You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by fm...@apache.org on 2013/07/26 13:22:06 UTC

[01/51] [partial] initial commit

Updated Branches:
  refs/heads/master [created] ff2b0a0ee


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumerTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumerTest.java
new file mode 100644
index 0000000..af660e3
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumerTest.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.servicedocument.AtomInfo;
+import org.apache.olingo.odata2.api.servicedocument.Categories;
+import org.apache.olingo.odata2.api.servicedocument.Category;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Fixed;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+import org.apache.olingo.odata2.api.servicedocument.Workspace;
+
+/**
+ * @author SAP AG
+ */
+public class AtomServiceDocumentConsumerTest {
+  private static final String NAMESPACE_SAP = "http://www.sap.com/Data";
+  private static final String PREFIX_SAP = "sap";
+
+  @Test
+  public void testServiceDocument() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    ServiceDocument svcDocument = svcDocumentParser.readServiceDokument(createStreamReader("/svcExample.xml"));
+    assertNotNull(svcDocument);
+    AtomInfo atomInfo = svcDocument.getAtomInfo();
+    assertNotNull(atomInfo);
+    assertNotNull(atomInfo.getWorkspaces());
+    for (Workspace workspace : atomInfo.getWorkspaces()) {
+      assertEquals("Data", workspace.getTitle().getText());
+      assertEquals(10, workspace.getCollections().size());
+      for (Collection collection : workspace.getCollections()) {
+        assertNotNull(collection.getHref());
+        if ("TypeOneEntityCollection".equals(collection.getHref())) {
+          assertEquals("TypeOneEntityCollection", collection.getTitle().getText());
+          assertFalse(collection.getCommonAttributes().getAttributes().isEmpty());
+          assertEquals("content-version", collection.getCommonAttributes().getAttributes().get(0).getName());
+          assertEquals(NAMESPACE_SAP, collection.getCommonAttributes().getAttributes().get(0).getNamespace());
+          assertEquals(PREFIX_SAP, collection.getCommonAttributes().getAttributes().get(0).getPrefix());
+          assertEquals("1", collection.getCommonAttributes().getAttributes().get(0).getText());
+          assertFalse(collection.getExtesionElements().isEmpty());
+          for (ExtensionElement extElement : collection.getExtesionElements()) {
+            assertEquals(PREFIX_SAP, extElement.getPrefix());
+            assertEquals("member-title", extElement.getName());
+            assertEquals(NAMESPACE_SAP, extElement.getNamespace());
+          }
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testExtensionsWithAttributes() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    ServiceDocument svcDocument = svcDocumentParser.readServiceDokument(createStreamReader("/svcExample.xml"));
+    assertNotNull(svcDocument);
+    AtomInfo atomInfo = svcDocument.getAtomInfo();
+    assertNotNull(atomInfo);
+    assertNotNull(atomInfo.getExtesionElements());
+    assertEquals(2, atomInfo.getExtesionElements().size());
+    for (ExtensionElement extElement : atomInfo.getExtesionElements()) {
+      assertEquals("link", extElement.getName());
+      assertEquals("atom", extElement.getPrefix());
+      assertEquals(2, extElement.getAttributes().size());
+      assertEquals("rel", extElement.getAttributes().get(0).getName());
+      assertEquals("http://localhost/odata/TEST_APPLICATION/", extElement.getAttributes().get(1).getText());
+      assertEquals("href", extElement.getAttributes().get(1).getName());
+    }
+
+  }
+
+  @Test
+  public void testServiceDocument2() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    ServiceDocument svcDocument = svcDocumentParser.readServiceDokument(createStreamReader("/svcAtomExample.xml"));
+    assertNotNull(svcDocument);
+    AtomInfo atomInfo = svcDocument.getAtomInfo();
+    assertNotNull(atomInfo);
+
+    assertEquals(2, atomInfo.getWorkspaces().size());
+
+    Workspace workspace = atomInfo.getWorkspaces().get(0);
+    assertEquals("Main Site", workspace.getTitle().getText());
+    assertEquals(2, workspace.getCollections().size());
+
+    workspace = atomInfo.getWorkspaces().get(1);
+    assertEquals("Sidebar Blog", workspace.getTitle().getText());
+    assertEquals(1, workspace.getCollections().size());
+    Collection collection = workspace.getCollections().get(0);
+    assertEquals("Remaindered Links", collection.getTitle().getText());
+
+    assertEquals(1, collection.getAcceptElements().size());
+    assertEquals("application/atom+xml;type=entry", collection.getAcceptElements().get(0).getValue());
+
+  }
+
+  @Test
+  public void testCategories() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    ServiceDocument svcDocument = svcDocumentParser.readServiceDokument(createStreamReader("/svcAtomExample.xml"));
+    assertNotNull(svcDocument);
+    AtomInfo atomInfo = svcDocument.getAtomInfo();
+    assertNotNull(atomInfo);
+
+    assertEquals(2, atomInfo.getWorkspaces().size());
+
+    Workspace workspace = atomInfo.getWorkspaces().get(0);
+    assertEquals(2, workspace.getCollections().size());
+    for (Collection collection : workspace.getCollections()) {
+      for (Categories categories : collection.getCategories()) {
+        assertEquals("http://example.com/cats/forMain.cats", categories.getHref());
+      }
+    }
+
+    workspace = atomInfo.getWorkspaces().get(1);
+    for (Collection collection : workspace.getCollections()) {
+      for (Categories categories : collection.getCategories()) {
+        assertEquals(Fixed.YES, categories.getFixed());
+        for (Category category : categories.getCategoryList()) {
+          assertEquals("http://example.org/extra-cats/", category.getScheme());
+        }
+      }
+    }
+
+  }
+
+  @Test
+  public void testNestedExtensions() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    ServiceDocument svcDocument = svcDocumentParser.readServiceDokument(createStreamReader("/svcAtomExample.xml"));
+    assertNotNull(svcDocument);
+    AtomInfo atomInfo = svcDocument.getAtomInfo();
+    assertNotNull(atomInfo);
+    assertNotNull(atomInfo.getExtesionElements());
+    for (ExtensionElement extElement : atomInfo.getExtesionElements()) {
+      for (ExtensionElement nestedExtElement : extElement.getElements()) {
+        if ("extension2".equals(nestedExtElement.getName())) {
+          assertFalse(nestedExtElement.getAttributes().isEmpty());
+          assertEquals("attributeValue", nestedExtElement.getAttributes().get(0).getText());
+          assertEquals("attr", nestedExtElement.getAttributes().get(0).getName());
+        } else if ("extension3".equals(nestedExtElement.getName())) {
+          assertTrue(nestedExtElement.getAttributes().isEmpty());
+          assertEquals("value", nestedExtElement.getText());
+        } else if ("extension4".equals(nestedExtElement.getName())) {
+          assertEquals("text", nestedExtElement.getText());
+          assertFalse(nestedExtElement.getAttributes().isEmpty());
+          assertEquals("attributeValue", nestedExtElement.getAttributes().get(0).getText());
+          assertEquals("attr", nestedExtElement.getAttributes().get(0).getName());
+        } else {
+          fail();
+        }
+      }
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testWithoutTitle() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    svcDocumentParser.readServiceDokument(createStreamReader("/svcDocWithoutTitle.xml"));
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testSvcWithoutWorkspaces() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    svcDocumentParser.readServiceDokument(createStreamReader("/invalidSvcExample.xml"));
+  }
+
+  @Test
+  public void testServiceDocument3() throws IOException, EntityProviderException {
+    AtomServiceDocumentConsumer svcDocumentParser = new AtomServiceDocumentConsumer();
+    ServiceDocument svcDocument = svcDocumentParser.readServiceDokument(createStreamReader("/serviceDocExample.xml"));
+    assertNotNull(svcDocument);
+    AtomInfo atomInfo = svcDocument.getAtomInfo();
+    assertNotNull(atomInfo);
+    for (Workspace workspace : atomInfo.getWorkspaces()) {
+      assertEquals("Data", workspace.getTitle().getText());
+      assertEquals(9, workspace.getCollections().size());
+      for (Collection collection : workspace.getCollections()) {
+        assertNotNull(collection.getHref());
+        if ("TravelagencyCollection".equals(collection.getHref())) {
+          assertEquals("TravelagencyCollection", collection.getTitle().getText());
+          assertEquals(2, collection.getCommonAttributes().getAttributes().size());
+          assertEquals("content-version", collection.getCommonAttributes().getAttributes().get(1).getName());
+          assertEquals(NAMESPACE_SAP, collection.getCommonAttributes().getAttributes().get(1).getNamespace());
+          assertEquals(PREFIX_SAP, collection.getCommonAttributes().getAttributes().get(1).getPrefix());
+          assertEquals("1", collection.getCommonAttributes().getAttributes().get(1).getText());
+          assertFalse(collection.getExtesionElements().isEmpty());
+          for (ExtensionElement extElement : collection.getExtesionElements()) {
+            if ("member-title".equals(extElement.getName())) {
+              assertEquals(PREFIX_SAP, extElement.getPrefix());
+              assertEquals(NAMESPACE_SAP, extElement.getNamespace());
+              assertEquals("Travelagency", extElement.getText());
+            } else if ("collectionLayout".equals(extElement.getName())) {
+              assertEquals("gp", extElement.getPrefix());
+              assertEquals("http://www.sap.com/Data/GP", extElement.getNamespace());
+              assertNotNull(extElement.getAttributes());
+              assertEquals(2, extElement.getAttributes().size());
+              assertEquals("display-order", extElement.getAttributes().get(0).getName());
+              assertEquals("0010", extElement.getAttributes().get(0).getText());
+              assertEquals("top-level", extElement.getAttributes().get(1).getName());
+              assertEquals("true", extElement.getAttributes().get(1).getText());
+            } else if ("link".equals(extElement.getName())) {
+              assertEquals(Edm.NAMESPACE_ATOM_2005, extElement.getNamespace());
+              assertEquals(4, extElement.getAttributes().size());
+              assertEquals("TravelagencyCollection/OpenSearchDescription.xml", extElement.getAttributes().get(0).getText());
+              assertEquals("href", extElement.getAttributes().get(0).getName());
+            } else {
+              fail();
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private XMLStreamReader createStreamReader(final String fileName) throws IOException, EntityProviderException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+    InputStream in = ClassLoader.class.getResourceAsStream(fileName);
+    if (in == null) {
+      throw new IOException("Requested file '" + fileName + "' was not found.");
+    }
+    XMLStreamReader streamReader;
+    try {
+      streamReader = factory.createXMLStreamReader(in);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON.addContent("Invalid Service Document"));
+    }
+
+    return streamReader;
+  }
+}


[08/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/resources/i18n_en.properties
----------------------------------------------------------------------
diff --git a/odata-core/src/main/resources/i18n_en.properties b/odata-core/src/main/resources/i18n_en.properties
new file mode 100644
index 0000000..d6d0654
--- /dev/null
+++ b/odata-core/src/main/resources/i18n_en.properties
@@ -0,0 +1,166 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# English translations
+#
+##################################
+# CommonExceptions (Should these exist?)
+##################################
+org.apache.olingo.odata2.api.exception.ODataMessageException.COMMON=Common exception
+
+##################################
+# UriParserExceptions
+##################################
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.MATCHPROBLEM=Could not match segment: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.NOTFOUND=Could not find an entity set or function import for '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.CONTAINERNOTFOUND=Could not find container with name: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.ENTITYNOTFOUND=Could not find entity with name: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.PROPERTYNOTFOUND=Could not find property with name: '%1$s'.
+
+org.apache.olingo.odata2.api.uri.UriSyntaxException.URISYNTAX=Invalid URI syntax.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.ENTITYSETINSTEADOFENTITY=Must be an entity set instead of an entity: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.NOTEXT=An exception occurred.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.NOMEDIARESOURCE=The requested resource is no media resource.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.NONAVIGATIONPROPERTY=Property '%1$s' must be a navigation property. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MISSINGPARAMETER=Missing parameter.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MISSINGKEYPREDICATENAME=Missing key predicate name for key: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.DUPLICATEKEYNAMES=Duplicate key names: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.EMPTYSEGMENT=No empty segment allowed.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MUSTNOTBELASTSEGMENT='%1$s' must not be the last segment. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MUSTBELASTSEGMENT='%1$s' must be the last segment.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDSEGMENT=Invalid segment: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDVALUE=Invalid value: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDNULLVALUE=Value for '%1$s' must not be null.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDNEGATIVEVALUE=Provided value '%1$s' must not be negative.  
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDRETURNTYPE=Invalid return type: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDPROPERTYTYPE=Invalid type for property: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDKEYPREDICATE=Invalid key predicate: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDSYSTEMQUERYOPTION=Invalid system query option: '%1$s'. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDFILTEREXPRESSION=Invalid filter expression: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDORDERBYEXPRESSION=Invalid order by expression: '%1$s'. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.LITERALFORMAT=Wrong literal format for literal: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.UNKNOWNLITERAL=Unknown literal: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INCOMPATIBLELITERAL=Format of '%1$s' is not compatible with '%2$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION=System query option '%1$s' is not compatible with the return type.
+
+##################################
+# EDMExceptions
+##################################
+org.apache.olingo.odata2.api.edm.EdmLiteralException.NOTEXT=An exception occurred.
+org.apache.olingo.odata2.api.edm.EdmLiteralException.LITERALFORMAT=Wrong literal format for literal: '%1$s'.
+org.apache.olingo.odata2.api.edm.EdmLiteralException.UNKNOWNLITERAL=Unknown literal: '%1$s'.
+
+org.apache.olingo.odata2.api.edm.EdmException.COMMON=An exception occurred.
+org.apache.olingo.odata2.api.edm.EdmException.PROVIDERPROBLEM=A problem has been detected in the metadata provided by the EDM provider.
+
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.COMMON=An exception occurred.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_KIND_MISSING=The literal kind is missing.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_KIND_NOT_SUPPORTED=The literal kind '%1$s' is not supported.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_NULL_NOT_ALLOWED=The metadata do not allow a null literal.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT=The literal '%1$s' is not formatted properly.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED=The metadata constraints '%2$s' do not match the literal '%1$s'.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE=The literal '%1$s' can not be converted into the type '%1$s'.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED=The type '%1$s' of the value object is not supported.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_NULL_NOT_ALLOWED=The metadata do not allow a null value.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT=The value object '%1$s' can not be formatted properly due to its content.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED=The metadata constraints '%2$s' do not allow to format the value '%1$s'.
+
+##################################
+# EPexceptions
+##################################
+org.apache.olingo.odata2.api.ep.EntityProviderException.COMMON=An exception occurred.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_STATE=Invalid consuming state for parsing with message '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_PROPERTY=Invalid property '%1$s' found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MISSING_PROPERTY=Property with name '%1$s' was not found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MISSING_ATTRIBUTE=Mandatory attribute '%1$s' was not found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.UNSUPPORTED_PROPERTY_TYPE=The given property type '%1$s' is not supported.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INLINECOUNT_INVALID=Invalid inline count found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.ILLEGAL_ARGUMENT=Illegal argument for method call with message '%1$s'.
+
+##################################
+# HttpExceptions
+##################################
+org.apache.olingo.odata2.api.exception.ODataHttpException.COMMON=Common exception
+
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.COMMON=Bad Request.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.NOTSUPPORTED=The request is not supported by the processor.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.URLTOOSHORT=The URL is too short.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.VERSIONERROR=The Data Services Request version '%1$s' is not supported for the request payload.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.PARSEVERSIONERROR=The Data Services Request version '%1$s' cannot be parsed.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.BODY=The request body is malformed.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.AMBIGUOUS_XMETHOD=Ambiguous X-HTTP-Method and X-HTTP-Method-Override header.
+
+org.apache.olingo.odata2.api.exception.ODataForbiddenException.COMMON=Forbidden
+
+org.apache.olingo.odata2.api.exception.ODataNotFoundException.MATRIX=Matrix parameter '%1$s' with path segment '%2$s' not found!
+org.apache.olingo.odata2.api.exception.ODataNotFoundException.ENTITY=Requested entity could not be found.
+
+org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException.DISPATCH=The request dispatcher does not allow the HTTP method used for the request.
+
+org.apache.olingo.odata2.api.exception.ODataNotAcceptableException.COMMON=The request can not be accepted.
+org.apache.olingo.odata2.api.exception.ODataNotAcceptableException.NOT_SUPPORTED_CONTENT_TYPE=Content type '%1$s' is not supported.
+
+org.apache.olingo.odata2.api.exception.ODataConflictException.COMMON=Conflict
+
+org.apache.olingo.odata2.api.exception.ODataPreconditionFailedException.COMMON=Precondition failed
+
+org.apache.olingo.odata2.api.exception.ODataUnsupportedMediaTypeException.COMMON=Unsupported media type
+
+org.apache.olingo.odata2.api.exception.ODataPreconditionRequiredException.COMMON=Precondition required
+
+org.apache.olingo.odata2.api.exception.ODataNotImplementedException.COMMON=Not implemented
+org.apache.olingo.odata2.api.exception.ODataNotImplementedException.TUNNELING=Method not recognized for X-HTTP-Method or X-HTTP-Method-Override header.
+
+org.apache.olingo.odata2.api.exception.ODataServiceUnavailableException.COMMON=Service Unavailable
+
+##################################
+# FilterParserExceptions
+##################################
+org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression.COMMON=Error while traversing a ODATA expression tree.
+
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMON=Error while parsing a ODATA expression.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING=Invalid token "%1$s" detected after parsing at position %2$s in "%3$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.TOKEN_UNDETERMINATED_STRING=Unterminated string literal at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR=Operator "%1$s" incompatible with operand types "%2$s" and "%3$s" at position %4$s in "%5$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.MISSING_CLOSING_PHARENTHESIS=Missing closing parenthesis ")" for opening parenthesis "(" at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.ERROR_IN_TOKENIZER=Error while tokenizing a ODATA expression on token '%1$s' at position '%2$s'.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AFTER_POS=Expression expected after position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AT_POS=Expression expected at position %1$s.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS=")" or "," expected after position %1$s.
+
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_EXACT=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires exact %4$s argument(s).
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_BETWEEN=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires between %4$s and %5$s arguments.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_X_OR_MORE=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires %4$s or more arguments.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_X_OR_LESS=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires maximal %4$s arguments.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_STRUCTURAL_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_A_PROPERTY=Leftside of method operator at position %1$s is not a property in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.PROPERTY_NAME_NOT_FOUND_IN_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_SORT_ORDER=Invalid sort order in OData orderby parser at position %1$s in %2$s.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_METHOD=Internal error in OData filter parser while parsing a method expression.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_PARENTHESIS=Internal error in OData filter parser while parsing a parenthesis expression.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_ACCESSING_EDM=Internal error in OData filter parser while accessing the EDM.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.INVALID_TYPE_COUNT=Internal error in OData filter parser while validating the allowed types.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.INVALID_TOKEN_AT    =Expect token '%1$s', but invalid token '%2$s' detected at position '%3$s'.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.INVALID_TOKENKIND_AT=Expect tokenkind '%1$s', but invalid tokenkind '%2$s'(with value:'%3$s' detected at position '%4$s'.
+
+org.apache.olingo.odata2.core.uri.expression.TokenizerExpectError.NO_TOKEN_AVAILABLE       =Expect token %1$s, but no token left in token list.
+org.apache.olingo.odata2.core.uri.expression.TokenizerExpectError.INVALID_TOKEN_AT         =Expect token '%1$s', but invalid token '%2$s' detected at position '%3$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerExpectError.INVALID_TOKENKIND_AT     =Expect tokenkind '%1$s', but invalid tokenkind '%2$s'(with value:'%3$s' detected at position '%4$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerException.TYPEDECTECTION_FAILED_ON_STRING=Type detection error for string like token '%1$s' at position '%2$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerException.TYPEDECTECTION_FAILED_ON_EDMTYPE=Type detection error for edmType like token '%1$s' at position '%2$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerException.UNKNOWN_CHARACTER=Unknown character '%1$s' at position '%2$s' detected.

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/resources/i18n_en_US.properties
----------------------------------------------------------------------
diff --git a/odata-core/src/main/resources/i18n_en_US.properties b/odata-core/src/main/resources/i18n_en_US.properties
new file mode 100644
index 0000000..593c033
--- /dev/null
+++ b/odata-core/src/main/resources/i18n_en_US.properties
@@ -0,0 +1,20 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# English translations
+#

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/META-INF/MANIFEST.MF b/odata-core/src/test/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..254272e
--- /dev/null
+++ b/odata-core/src/test/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ContentNegotiatorTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ContentNegotiatorTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ContentNegotiatorTest.java
new file mode 100644
index 0000000..2f9c53e
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ContentNegotiatorTest.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.core.uri.UriType;
+
+/**
+ * @author SAP AG
+ */
+public class ContentNegotiatorTest {
+  private void negotiateContentType(final List<ContentType> contentTypes, final List<ContentType> supportedTypes, final String expected) throws ODataException {
+    final ContentType contentType = new ContentNegotiator().contentNegotiation(contentTypes, supportedTypes);
+    assertEquals(expected, contentType.toContentTypeString());
+  }
+
+  @Test
+  public void contentNegotiationEmptyRequest() throws Exception {
+    negotiateContentType(
+        contentTypes(),
+        contentTypes("sup/111", "sup/222"),
+        "sup/111");
+  }
+
+  @Test
+  public void contentNegotiationConcreteRequest() throws Exception {
+    negotiateContentType(
+        contentTypes("sup/222"),
+        contentTypes("sup/111", "sup/222"),
+        "sup/222");
+  }
+
+  @Test(expected = ODataNotAcceptableException.class)
+  public void contentNegotiationNotSupported() throws Exception {
+    negotiateContentType(contentTypes("image/gif"), contentTypes("sup/111", "sup/222"), null);
+  }
+
+  @Test
+  public void contentNegotiationSupportedWildcard() throws Exception {
+    negotiateContentType(
+        contentTypes("image/gif"),
+        contentTypes("sup/111", "sup/222", "*/*"),
+        "image/gif");
+  }
+
+  @Test
+  public void contentNegotiationSupportedSubWildcard() throws Exception {
+    negotiateContentType(
+        contentTypes("image/gif"),
+        contentTypes("sup/111", "sup/222", "image/*"),
+        "image/gif");
+  }
+
+  @Test
+  public void contentNegotiationRequestWildcard() throws Exception {
+    negotiateContentType(
+        contentTypes("*/*"),
+        contentTypes("sup/111", "sup/222"),
+        "sup/111");
+  }
+
+  @Test
+  public void contentNegotiationRequestSubWildcard() throws Exception {
+    negotiateContentType(
+        contentTypes("sup/*", "*/*"),
+        contentTypes("bla/111", "sup/222"),
+        "sup/222");
+  }
+
+  @Test
+  public void contentNegotiationRequestSubtypeWildcard() throws Exception {
+    negotiateContentType(
+        contentTypes("sup2/*"),
+        contentTypes("sup1/111", "sup2/222", "sup2/333"),
+        "sup2/222");
+  }
+
+  @Test
+  public void contentNegotiationRequestResponseWildcard() throws Exception {
+    negotiateContentType(contentTypes("*/*"), contentTypes("*/*"), "*/*");
+  }
+
+  @Test
+  public void contentNegotiationManyRequests() throws Exception {
+    negotiateContentType(
+        contentTypes("bla/111", "bla/blub", "sub2/222"),
+        contentTypes("sub1/666", "sub2/222", "sub3/333"),
+        "sub2/222");
+  }
+
+  @Test(expected = ODataNotAcceptableException.class)
+  public void contentNegotiationCharsetNotSupported() throws Exception {
+    negotiateContentType(
+        contentTypes("text/plain;charset=iso-8859-1"),
+        contentTypes("sup/111", "sup/222"),
+        "sup/222");
+  }
+
+  @Test
+  public void contentNegotiationWithODataVerbose() throws Exception {
+    negotiateContentType(
+        contentTypes("text/plain;q=0.5", "application/json;odata=verbose;q=0.2", "*/*"),
+        contentTypes("application/json;charset=utf-8", "sup/222"),
+        "application/json;charset=utf-8");
+  }
+
+  @Test
+  public void contentNegotiationDefaultCharset() throws Exception {
+    negotiateContentTypeCharset("application/xml", "application/xml;charset=utf-8", false);
+  }
+
+  @Test
+  public void contentNegotiationDefaultCharsetAsDollarFormat() throws Exception {
+    negotiateContentTypeCharset("application/xml", "application/xml;charset=utf-8", true);
+  }
+
+  @Test
+  public void contentNegotiationSupportedCharset() throws Exception {
+    negotiateContentTypeCharset("application/xml; charset=utf-8", "application/xml;charset=utf-8", false);
+  }
+
+  @Test
+  public void contentNegotiationSupportedCharsetAsDollarFormat() throws Exception {
+    negotiateContentTypeCharset("application/xml; charset=utf-8", "application/xml;charset=utf-8", true);
+  }
+
+  private void negotiateContentTypeCharset(final String requestType, final String supportedType, final boolean asFormat) throws ODataException {
+    UriInfoImpl uriInfo = Mockito.mock(UriInfoImpl.class);
+    Mockito.when(uriInfo.getUriType()).thenReturn(UriType.URI1);
+    if (asFormat) {
+      Mockito.when(uriInfo.getFormat()).thenReturn(requestType);
+    }
+
+    List<String> acceptedContentTypes = Arrays.asList(requestType);
+    List<String> supportedContentTypes = Arrays.asList(supportedType);
+
+    ContentNegotiator negotiator = new ContentNegotiator();
+    String negotiatedContentType = negotiator.doContentNegotiation(uriInfo, acceptedContentTypes, supportedContentTypes);
+
+    assertEquals(supportedType, negotiatedContentType);
+  }
+
+  private List<ContentType> contentTypes(final String... contentType) {
+    List<ContentType> ctList = new ArrayList<ContentType>();
+    for (String ct : contentType) {
+      ctList.add(ContentType.create(ct));
+    }
+    return ctList;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/DispatcherTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/DispatcherTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/DispatcherTest.java
new file mode 100644
index 0000000..b38b86a
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/DispatcherTest.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.InputStream;
+import java.util.Arrays;
+
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.batch.BatchHandler;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.part.BatchProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityComplexPropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.MetadataProcessor;
+import org.apache.olingo.odata2.api.processor.part.ServiceDocumentProcessor;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.core.uri.UriType;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * Tests for request dispatching according to URI type and HTTP method.
+ * @author SAP AG
+ */
+public class DispatcherTest extends BaseTest {
+
+  public static ODataService getMockService() throws ODataException {
+    ServiceDocumentProcessor serviceDocument = mock(ServiceDocumentProcessor.class);
+    when(serviceDocument.readServiceDocument(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+
+    EntitySetProcessor entitySet = mock(EntitySetProcessor.class);
+    when(entitySet.readEntitySet(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entitySet.countEntitySet(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entitySet.createEntity(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyString())).thenAnswer(getAnswer());
+
+    EntityProcessor entity = mock(EntityProcessor.class);
+    when(entity.readEntity(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entity.existsEntity(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entity.deleteEntity(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entity.updateEntity(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyBoolean(), anyString())).thenAnswer(getAnswer());
+
+    EntityComplexPropertyProcessor entityComplexProperty = mock(EntityComplexPropertyProcessor.class);
+    when(entityComplexProperty.readEntityComplexProperty(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityComplexProperty.updateEntityComplexProperty(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyBoolean(), anyString())).thenAnswer(getAnswer());
+
+    EntitySimplePropertyProcessor entitySimpleProperty = mock(EntitySimplePropertyProcessor.class);
+    when(entitySimpleProperty.readEntitySimpleProperty(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entitySimpleProperty.updateEntitySimpleProperty(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyString())).thenAnswer(getAnswer());
+
+    EntitySimplePropertyValueProcessor entitySimplePropertyValue = mock(EntitySimplePropertyValueProcessor.class);
+    when(entitySimplePropertyValue.readEntitySimplePropertyValue(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entitySimplePropertyValue.deleteEntitySimplePropertyValue(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entitySimplePropertyValue.updateEntitySimplePropertyValue(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyString())).thenAnswer(getAnswer());
+
+    EntityLinkProcessor entityLink = mock(EntityLinkProcessor.class);
+    when(entityLink.readEntityLink(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityLink.existsEntityLink(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityLink.deleteEntityLink(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityLink.updateEntityLink(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyString())).thenAnswer(getAnswer());
+
+    EntityLinksProcessor entityLinks = mock(EntityLinksProcessor.class);
+    when(entityLinks.readEntityLinks(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityLinks.countEntityLinks(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityLinks.createEntityLink(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyString())).thenAnswer(getAnswer());
+
+    MetadataProcessor metadata = mock(MetadataProcessor.class);
+    when(metadata.readMetadata(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+
+    BatchProcessor batch = mock(BatchProcessor.class);
+    when(batch.executeBatch(any(BatchHandler.class), anyString(), any(InputStream.class))).thenAnswer(getAnswer());
+
+    FunctionImportProcessor functionImport = mock(FunctionImportProcessor.class);
+    when(functionImport.executeFunctionImport(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+
+    FunctionImportValueProcessor functionImportValue = mock(FunctionImportValueProcessor.class);
+    when(functionImportValue.executeFunctionImportValue(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+
+    EntityMediaProcessor entityMedia = mock(EntityMediaProcessor.class);
+    when(entityMedia.readEntityMedia(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityMedia.deleteEntityMedia(any(UriInfoImpl.class), anyString())).thenAnswer(getAnswer());
+    when(entityMedia.updateEntityMedia(any(UriInfoImpl.class), any(InputStream.class), anyString(), anyString())).thenAnswer(getAnswer());
+
+    ODataService service = mock(ODataService.class);
+    when(service.getServiceDocumentProcessor()).thenReturn(serviceDocument);
+    when(service.getEntitySetProcessor()).thenReturn(entitySet);
+    when(service.getEntityProcessor()).thenReturn(entity);
+    when(service.getEntityComplexPropertyProcessor()).thenReturn(entityComplexProperty);
+    when(service.getEntitySimplePropertyProcessor()).thenReturn(entitySimpleProperty);
+    when(service.getEntitySimplePropertyValueProcessor()).thenReturn(entitySimplePropertyValue);
+    when(service.getEntityLinkProcessor()).thenReturn(entityLink);
+    when(service.getEntityLinksProcessor()).thenReturn(entityLinks);
+    when(service.getMetadataProcessor()).thenReturn(metadata);
+    when(service.getBatchProcessor()).thenReturn(batch);
+    when(service.getFunctionImportProcessor()).thenReturn(functionImport);
+    when(service.getFunctionImportValueProcessor()).thenReturn(functionImportValue);
+    when(service.getEntityMediaProcessor()).thenReturn(entityMedia);
+
+    return service;
+  }
+
+  private static Answer<ODataResponse> getAnswer() {
+    return new Answer<ODataResponse>() {
+      @Override
+      public ODataResponse answer(final InvocationOnMock invocation) {
+        return mockResponse(invocation.getMethod().getName());
+      }
+    };
+  }
+
+  private static ODataResponse mockResponse(final String value) {
+    ODataResponse response = mock(ODataResponse.class);
+    when(response.getStatus()).thenReturn(HttpStatusCodes.PAYMENT_REQUIRED);
+    when(response.getEntity()).thenReturn(value);
+
+    return response;
+  }
+
+  private static UriInfoImpl mockUriInfo(final UriType uriType, final boolean isValue) throws EdmException {
+    UriInfoImpl uriInfo = mock(UriInfoImpl.class);
+    when(uriInfo.getUriType()).thenReturn(uriType);
+    when(uriInfo.isValue()).thenReturn(isValue);
+    return uriInfo;
+  }
+
+  private static void checkDispatch(final ODataHttpMethod method, final UriType uriType, final boolean isValue, final String expectedMethodName) throws ODataException {
+    ODataServiceFactory factory = mock(ODataServiceFactory.class);
+
+    final ODataResponse response = new Dispatcher(factory, getMockService())
+        .dispatch(method, mockUriInfo(uriType, isValue), null, "application/xml", "*/*");
+    assertEquals(expectedMethodName, response.getEntity());
+  }
+
+  private static void checkDispatch(final ODataHttpMethod method, final UriType uriType, final String expectedMethodName) throws ODataException {
+    checkDispatch(method, uriType, false, expectedMethodName);
+  }
+
+  private static void wrongDispatch(final ODataHttpMethod method, final UriType uriType) {
+    try {
+      checkDispatch(method, uriType, null);
+      fail("Expected ODataException not thrown");
+    } catch (ODataMethodNotAllowedException e) {
+      assertNotNull(e);
+    } catch (ODataException e) {
+      fail("Expected ODataMethodNotAllowedException not thrown");
+    }
+  }
+
+  private static void notSupportedDispatch(final ODataHttpMethod method, final UriType uriType) {
+    try {
+      checkDispatch(method, uriType, null);
+      fail("Expected ODataException not thrown");
+    } catch (ODataBadRequestException e) {
+      assertNotNull(e);
+    } catch (ODataException e) {
+      fail("Expected ODataBadRequestException not thrown");
+    }
+  }
+
+  @Test
+  public void dispatch() throws Exception {
+    checkDispatch(ODataHttpMethod.GET, UriType.URI0, "readServiceDocument");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI1, "readEntitySet");
+    checkDispatch(ODataHttpMethod.POST, UriType.URI1, "createEntity");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI2, "readEntity");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI2, "updateEntity");
+    checkDispatch(ODataHttpMethod.DELETE, UriType.URI2, "deleteEntity");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI2, "updateEntity");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI2, "updateEntity");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI3, "readEntityComplexProperty");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI3, "updateEntityComplexProperty");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI3, "updateEntityComplexProperty");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI3, "updateEntityComplexProperty");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI4, "readEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI4, "updateEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI4, "updateEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI4, "updateEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI4, true, "readEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI4, true, "updateEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.DELETE, UriType.URI4, true, "deleteEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI4, true, "updateEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI4, true, "updateEntitySimplePropertyValue");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI5, "readEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI5, "updateEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI5, "updateEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI5, "updateEntitySimpleProperty");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI5, true, "readEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI5, true, "updateEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.DELETE, UriType.URI5, true, "deleteEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI5, true, "updateEntitySimplePropertyValue");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI5, true, "updateEntitySimplePropertyValue");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI6A, "readEntity");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI6B, "readEntitySet");
+    checkDispatch(ODataHttpMethod.POST, UriType.URI6B, "createEntity");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI7A, "readEntityLink");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI7A, "updateEntityLink");
+    checkDispatch(ODataHttpMethod.DELETE, UriType.URI7A, "deleteEntityLink");
+    checkDispatch(ODataHttpMethod.PATCH, UriType.URI7A, "updateEntityLink");
+    checkDispatch(ODataHttpMethod.MERGE, UriType.URI7A, "updateEntityLink");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI7B, "readEntityLinks");
+    checkDispatch(ODataHttpMethod.POST, UriType.URI7B, "createEntityLink");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI8, "readMetadata");
+
+    checkDispatch(ODataHttpMethod.POST, UriType.URI9, "executeBatch");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI10, "executeFunctionImport");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI11, "executeFunctionImport");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI12, "executeFunctionImport");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI13, "executeFunctionImport");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI14, "executeFunctionImport");
+    checkDispatch(ODataHttpMethod.GET, UriType.URI14, true, "executeFunctionImportValue");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI15, "countEntitySet");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI16, "existsEntity");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI17, "readEntityMedia");
+    checkDispatch(ODataHttpMethod.PUT, UriType.URI17, "updateEntityMedia");
+    checkDispatch(ODataHttpMethod.DELETE, UriType.URI17, "deleteEntityMedia");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI50A, "existsEntityLink");
+
+    checkDispatch(ODataHttpMethod.GET, UriType.URI50B, "countEntityLinks");
+  }
+
+  @Test
+  public void dispatchNotAllowedCombinations() throws Exception {
+    wrongDispatch(null, UriType.URI0);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI0);
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI0);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI0);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI0);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI0);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI1);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI1);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI1);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI1);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI2);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI3);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI3);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI4);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI4);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI5);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI5);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI6A);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI6B);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI6B);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI6B);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI6B);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI7A);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI7B);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI7B);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI7B);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI7B);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI8);
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI8);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI8);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI8);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI8);
+
+    wrongDispatch(ODataHttpMethod.GET, UriType.URI9);
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI9);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI9);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI9);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI9);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI15);
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI15);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI15);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI15);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI15);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI16);
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI16);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI16);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI16);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI16);
+
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI17);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI17);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI17);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI50A);
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI50A);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI50A);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI50A);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI50A);
+
+    wrongDispatch(ODataHttpMethod.PUT, UriType.URI50B);
+    wrongDispatch(ODataHttpMethod.POST, UriType.URI50B);
+    wrongDispatch(ODataHttpMethod.DELETE, UriType.URI50B);
+    wrongDispatch(ODataHttpMethod.PATCH, UriType.URI50B);
+    wrongDispatch(ODataHttpMethod.MERGE, UriType.URI50B);
+  }
+
+  @Test
+  public void dispatchNotSupportedCombinations() throws Exception {
+    notSupportedDispatch(ODataHttpMethod.PUT, UriType.URI6A);
+    notSupportedDispatch(ODataHttpMethod.DELETE, UriType.URI6A);
+    notSupportedDispatch(ODataHttpMethod.PATCH, UriType.URI6A);
+    notSupportedDispatch(ODataHttpMethod.MERGE, UriType.URI6A);
+  }
+
+  private static void checkFeature(final UriType uriType, final boolean isValue, final Class<? extends ODataProcessor> feature) throws ODataException {
+    ODataServiceFactory factory = mock(ODataServiceFactory.class);
+    new Dispatcher(factory, getMockService());
+    assertEquals(feature, Dispatcher.mapUriTypeToProcessorFeature(mockUriInfo(uriType, isValue)));
+    assertEquals(feature, Dispatcher.mapUriTypeToProcessorFeature(mockUriInfo(uriType, isValue)));
+  }
+
+  @Test
+  public void processorFeature() throws Exception {
+    checkFeature(UriType.URI0, false, ServiceDocumentProcessor.class);
+    checkFeature(UriType.URI1, false, EntitySetProcessor.class);
+    checkFeature(UriType.URI2, false, EntityProcessor.class);
+    checkFeature(UriType.URI3, false, EntityComplexPropertyProcessor.class);
+    checkFeature(UriType.URI4, false, EntitySimplePropertyProcessor.class);
+    checkFeature(UriType.URI4, true, EntitySimplePropertyValueProcessor.class);
+    checkFeature(UriType.URI5, false, EntitySimplePropertyProcessor.class);
+    checkFeature(UriType.URI5, true, EntitySimplePropertyValueProcessor.class);
+    checkFeature(UriType.URI6A, false, EntityProcessor.class);
+    checkFeature(UriType.URI6B, false, EntitySetProcessor.class);
+    checkFeature(UriType.URI7A, false, EntityLinkProcessor.class);
+    checkFeature(UriType.URI7B, false, EntityLinksProcessor.class);
+    checkFeature(UriType.URI8, false, MetadataProcessor.class);
+    checkFeature(UriType.URI9, false, BatchProcessor.class);
+    checkFeature(UriType.URI10, false, FunctionImportProcessor.class);
+    checkFeature(UriType.URI11, false, FunctionImportProcessor.class);
+    checkFeature(UriType.URI12, false, FunctionImportProcessor.class);
+    checkFeature(UriType.URI13, false, FunctionImportProcessor.class);
+    checkFeature(UriType.URI14, false, FunctionImportProcessor.class);
+    checkFeature(UriType.URI14, true, FunctionImportValueProcessor.class);
+    checkFeature(UriType.URI15, false, EntitySetProcessor.class);
+    checkFeature(UriType.URI16, false, EntityProcessor.class);
+    checkFeature(UriType.URI17, false, EntityMediaProcessor.class);
+    checkFeature(UriType.URI50A, false, EntityLinkProcessor.class);
+    checkFeature(UriType.URI50B, false, EntityLinksProcessor.class);
+  }
+
+  @Test
+  public void contentNegotiationDefaultCharset() throws Exception {
+    negotiateContentTypeCharset("application/xml", "application/xml;charset=utf-8", false);
+  }
+
+  @Test
+  public void contentNegotiationDefaultCharsetAsDollarFormat() throws Exception {
+    negotiateContentTypeCharset("application/xml", "application/xml;charset=utf-8", true);
+  }
+
+  @Test
+  public void contentNegotiationSupportedCharset() throws Exception {
+    negotiateContentTypeCharset("application/xml;charset=utf-8", "application/xml;charset=utf-8", false);
+  }
+
+  @Test
+  public void contentNegotiationSupportedCharsetAsDollarFormat() throws Exception {
+    negotiateContentTypeCharset("application/xml;charset=utf-8", "application/xml;charset=utf-8", true);
+  }
+
+  @SuppressWarnings("unchecked")
+  private void negotiateContentTypeCharset(final String requestType, final String supportedType, final boolean asFormat)
+      throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException, ODataException {
+
+    ODataServiceFactory factory = mock(ODataServiceFactory.class);
+    ODataService service = Mockito.mock(ODataService.class);
+    Dispatcher dispatcher = new Dispatcher(factory, service);
+
+    UriInfoImpl uriInfo = new UriInfoImpl();
+    uriInfo.setUriType(UriType.URI1); // 
+    if (asFormat) {
+      uriInfo.setFormat(requestType);
+    }
+
+    Mockito.when(service.getSupportedContentTypes(Matchers.any(Class.class))).thenReturn(Arrays.asList(supportedType));
+    EntitySetProcessor processor = Mockito.mock(EntitySetProcessor.class);
+    ODataResponse response = Mockito.mock(ODataResponse.class);
+    Mockito.when(response.getContentHeader()).thenReturn(supportedType);
+    Mockito.when(processor.readEntitySet(uriInfo, supportedType)).thenReturn(response);
+    Mockito.when(service.getEntitySetProcessor()).thenReturn(processor);
+
+    InputStream content = null;
+    ODataResponse odataResponse = dispatcher.dispatch(ODataHttpMethod.GET, uriInfo, content, requestType, supportedType);
+    assertEquals(supportedType, odataResponse.getContentHeader());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataContextImplTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataContextImplTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataContextImplTest.java
new file mode 100644
index 0000000..8c3f040
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataContextImplTest.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+
+/**
+ * @author SAP AG
+ */
+public class ODataContextImplTest {
+
+  ODataContextImpl context;
+
+  @Before
+  public void before() {
+    ODataServiceFactory factory = mock(ODataServiceFactory.class);
+    ODataRequest request = mock(ODataRequest.class);
+
+    when(request.getMethod()).thenReturn(ODataHttpMethod.GET);
+    when(request.getPathInfo()).thenReturn(new PathInfoImpl());
+
+    context = new ODataContextImpl(request, factory);
+  }
+
+  @Test
+  public void httpMethod() {
+    context.setHttpMethod(ODataHttpMethod.GET.name());
+    assertEquals(ODataHttpMethod.GET.name(), context.getHttpMethod());
+  }
+
+  @Test
+  public void debugMode() {
+    context.setDebugMode(true);
+    assertTrue(context.isInDebugMode());
+  }
+
+  @Test
+  public void parentContext() {
+
+    assertFalse(context.isInBatchMode());
+    assertNull(context.getBatchParentContext());
+
+    ODataContext parentContext = mock(ODataContext.class);
+    context.setBatchParentContext(parentContext);
+
+    assertTrue(context.isInBatchMode());
+    assertNotNull(context.getBatchParentContext());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
new file mode 100644
index 0000000..bc68292
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataExceptionWrapperTest.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.ws.rs.core.MultivaluedHashMap;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataErrorCallback;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.core.rest.ODataErrorHandlerCallbackImpl;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class ODataExceptionWrapperTest extends BaseTest {
+
+  /**
+   * Wrap an exception and verify that {@link PathInfo} is available and filled with correct values.
+   * 
+   */
+  @Test
+  public void testCallbackPathInfoAvailable() throws Exception {
+    ODataContextImpl context = getMockedContext("http://localhost:80/test", "ODataServiceRoot");
+    ODataErrorCallback errorCallback = new ODataErrorCallback() {
+      @Override
+      public ODataResponse handleError(final ODataErrorContext context) throws ODataApplicationException {
+        PathInfo pathInfo = context.getPathInfo();
+        assertEquals("ODataServiceRoot", pathInfo.getServiceRoot().toString());
+        assertEquals("http://localhost:80/test", pathInfo.getRequestUri().toString());
+        return ODataResponse.entity("bla").status(HttpStatusCodes.BAD_REQUEST).contentHeader("text/html").build();
+      }
+    };
+    when(context.getServiceFactory()).thenReturn(new MapperServiceFactory(errorCallback));
+
+    //
+    Map<String, String> queryParameters = Collections.emptyMap();
+    List<String> acceptContentTypes = Arrays.asList("text/html");
+    ODataExceptionWrapper exceptionWrapper = createWrapper(context, queryParameters, acceptContentTypes);
+    ODataResponse response = exceptionWrapper.wrapInExceptionResponse(new Exception());
+
+    // verify
+    assertNotNull(response);
+    assertEquals(HttpStatusCodes.BAD_REQUEST.getStatusCode(), response.getStatus().getStatusCode());
+    String errorMessage = (String) response.getEntity();
+    assertEquals("bla", errorMessage);
+    String contentTypeHeader = response.getContentHeader();
+    assertEquals("text/html", contentTypeHeader);
+  }
+
+  private ODataExceptionWrapper createWrapper(final ODataContextImpl context, final Map<String, String> queryParameters, final List<String> acceptContentTypes) throws URISyntaxException {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(context, queryParameters, acceptContentTypes);
+
+    return exceptionWrapper;
+  }
+
+  private ODataContextImpl getMockedContext(final String requestUri, final String serviceRoot) throws ODataException, URISyntaxException {
+    ODataContextImpl context = Mockito.mock(ODataContextImpl.class);
+    PathInfoImpl pathInfo = new PathInfoImpl();
+    pathInfo.setRequestUri(new URI(requestUri));
+    pathInfo.setServiceRoot(new URI(serviceRoot));
+    when(context.getPathInfo()).thenReturn(pathInfo);
+    when(context.getRequestHeaders()).thenReturn(new MultivaluedHashMap<String, String>());
+    return context;
+  }
+
+  public static final class MapperServiceFactory extends ODataServiceFactory {
+    private ODataErrorCallback errorCallback;
+
+    public MapperServiceFactory(final ODataErrorCallback callback) {
+      errorCallback = callback;
+    }
+
+    @Override
+    public ODataService createService(final ODataContext ctx) throws ODataException {
+      return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+      if (callbackInterface == ODataErrorCallback.class) {
+        if (errorCallback == null) {
+          return (T) new ODataErrorHandlerCallbackImpl();
+        }
+        return (T) errorCallback;
+      }
+      // only error callbacks are handled here
+      return null;
+    }
+  }
+}


[30/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
new file mode 100644
index 0000000..8c870d5
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderReadProperties.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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.api.ep;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.callback.OnReadInlineContent;
+
+/**
+ * The {@link EntityProviderReadProperties} contains all necessary settings to read an entity with the {@link EntityProvider}.
+ * 
+ * The main settings are
+ * <ul>
+ * <li>the <code>mergeSemantic</code></li>
+ * <li>the <code>callback for inlined navigation properties</code></li>
+ * <li>and the <code>type mappings</code></li>
+ * </ul>
+ * 
+ * @author SAP AG
+ */
+public class EntityProviderReadProperties {
+  /** Callback which is necessary if entity contains inlined navigation properties. */
+  private OnReadInlineContent callback;
+  /**
+   * if merge is <code>true</code> the input content is in context of an <b>merge</b> (e.g. MERGE, PATCH) read request, 
+   * otherwise if <code>false</code> it is an <b>none merge</b> (e.g. CREATE) read request
+   */
+  private boolean merge;
+  /**
+   * typeMappings contains mappings from <code>edm property name</code> to <code>java class</code> which should be used 
+   * for a type mapping during read of content. If according <code>edm property</code> can not be read
+   * into given <code>java class</code> an {@link EntityProviderException} is thrown.
+   * Supported mappings are documented in {@link org.apache.olingo.odata2.api.edm.EdmSimpleType}.
+   */
+  final private Map<String, Object> typeMappings;
+  final private Map<String, String> validatedPrefix2NamespaceUri;
+
+  private EntityProviderReadProperties() {
+    typeMappings = new HashMap<String, Object>();
+    validatedPrefix2NamespaceUri = new HashMap<String, String>();
+  }
+
+  public static EntityProviderReadPropertiesBuilder init() {
+    return new EntityProviderReadPropertiesBuilder();
+  }
+
+  public static EntityProviderReadPropertiesBuilder initFrom(final EntityProviderReadProperties properties) {
+    return new EntityProviderReadPropertiesBuilder(properties);
+  }
+
+  public Map<String, String> getValidatedPrefixNamespaceUris() {
+    return Collections.unmodifiableMap(validatedPrefix2NamespaceUri);
+  }
+
+  public Map<String, Object> getTypeMappings() {
+    return Collections.unmodifiableMap(typeMappings);
+  }
+
+  public OnReadInlineContent getCallback() {
+    return callback;
+  }
+
+  public boolean getMergeSemantic() {
+    return merge;
+  }
+
+  /**
+   * @author SAP AG
+   */
+  public static class EntityProviderReadPropertiesBuilder {
+    private final EntityProviderReadProperties properties = new EntityProviderReadProperties();
+
+    public EntityProviderReadPropertiesBuilder() {}
+
+    public EntityProviderReadPropertiesBuilder(final EntityProviderReadProperties propertiesFrom) {
+      properties.merge = propertiesFrom.merge;
+      properties.callback = propertiesFrom.callback;
+      addValidatedPrefixes(propertiesFrom.validatedPrefix2NamespaceUri);
+      addTypeMappings(propertiesFrom.typeMappings);
+    }
+
+    public EntityProviderReadPropertiesBuilder mergeSemantic(final boolean mergeSemantic) {
+      properties.merge = mergeSemantic;
+      return this;
+    }
+
+    public EntityProviderReadPropertiesBuilder callback(final OnReadInlineContent callback) {
+      properties.callback = callback;
+      return this;
+    }
+
+    public EntityProviderReadPropertiesBuilder addValidatedPrefixes(final Map<String, String> prefix2NamespaceUri) {
+      if (prefix2NamespaceUri != null) {
+        properties.validatedPrefix2NamespaceUri.putAll(prefix2NamespaceUri);
+      }
+      return this;
+    }
+
+    public EntityProviderReadPropertiesBuilder addTypeMappings(final Map<String, Object> typeMappings) {
+      if (typeMappings != null) {
+        properties.typeMappings.putAll(typeMappings);
+      }
+      return this;
+    }
+
+    public EntityProviderReadProperties build() {
+      return properties;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
new file mode 100644
index 0000000..55be388
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderWriteProperties.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * 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.api.ep;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+
+/**
+ * {@link EntityProviderWriteProperties} contains all additional properties which are necessary to <b>write (serialize)</b> an
+ * {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry} into an specific format (e.g. <code>XML</code> or <code>JSON</code> or ...).
+ */
+public class EntityProviderWriteProperties {
+
+  private URI serviceRoot;
+  private String mediaResourceMimeType;
+  private InlineCount inlineCountType;
+  private Integer inlineCount;
+  private String nextLink;
+  private ExpandSelectTreeNode expandSelectTree;
+  private Map<String, ODataCallback> callbacks = Collections.emptyMap();
+  private URI selfLink;
+
+  private EntityProviderWriteProperties() {}
+
+  /**
+   * Gets the self link from an application. May be null.
+   * @return the self link
+   */
+  public final URI getSelfLink() {
+    return selfLink;
+  }
+
+  /**
+   * Gets the service root.
+   * @return the service root
+   */
+  public final URI getServiceRoot() {
+    return serviceRoot;
+  }
+
+  /**
+   * Gets the MIME type of the media resource.
+   * @return the MIME type of the media resource
+   */
+  public final String getMediaResourceMimeType() {
+    return mediaResourceMimeType;
+  }
+
+  /**
+  * Gets the type of the inlinecount request from the system query option.
+  * @return the type of the inlinecount request from the system query option
+  */
+  public final InlineCount getInlineCountType() {
+    return inlineCountType;
+  }
+
+  public final Map<String, ODataCallback> getCallbacks() {
+    return callbacks;
+  }
+
+  /**
+   * Gets the expand select tree data structure resulting from $expand and $select query options.
+   * @return a paresed tree structure representing the $expand and $select
+   */
+  public final ExpandSelectTreeNode getExpandSelectTree() {
+    return expandSelectTree;
+  }
+
+  /**
+  * Gets the inlinecount.
+   * @return the inlinecount as Integer
+   * @see #getInlineCountType
+   */
+  public final Integer getInlineCount() {
+    return inlineCount;
+  }
+
+  /**
+   * Gets the next link used for server-side paging of feeds.
+   * @return the next link
+   */
+  public final String getNextLink() {
+    return nextLink;
+  }
+
+  public static ODataEntityProviderPropertiesBuilder serviceRoot(final URI serviceRoot) {
+    return new ODataEntityProviderPropertiesBuilder().serviceRoot(serviceRoot);
+  }
+
+  public static class ODataEntityProviderPropertiesBuilder {
+    private final EntityProviderWriteProperties properties = new EntityProviderWriteProperties();
+
+    /**
+     * @param mediaResourceMimeType  the mediaResourceMimeType to set
+     */
+    public final ODataEntityProviderPropertiesBuilder mediaResourceMimeType(final String mediaResourceMimeType) {
+      properties.mediaResourceMimeType = mediaResourceMimeType;
+      return this;
+    }
+
+    /**
+     * @param inlineCountType  the inlineCountType to set
+     */
+    public final ODataEntityProviderPropertiesBuilder inlineCountType(final InlineCount inlineCountType) {
+      properties.inlineCountType = inlineCountType;
+      return this;
+    }
+
+    /**
+     * @param inlineCount  the inlineCount to set
+     */
+    public final ODataEntityProviderPropertiesBuilder inlineCount(final Integer inlineCount) {
+      properties.inlineCount = inlineCount;
+      return this;
+    }
+
+    /**
+     * @param serviceRoot
+     */
+    public final ODataEntityProviderPropertiesBuilder serviceRoot(final URI serviceRoot) {
+      properties.serviceRoot = serviceRoot;
+      return this;
+    }
+
+    /**
+     * @param nextLink Next link to render feeds with server side paging. Should usually contain a skiptoken.
+     */
+    public ODataEntityProviderPropertiesBuilder nextLink(final String nextLink) {
+      properties.nextLink = nextLink;
+      return this;
+    }
+
+    /**
+     * Build properties object.
+     * @return assembled properties object
+     */
+    public final EntityProviderWriteProperties build() {
+      return properties;
+    }
+
+    /**
+     * Set a expand select tree which results from $expand and $select query parameter. Usually the data structure is constructed 
+     * by the uri parser.
+     * @param expandSelectTree data structure
+     * @return properties builder
+     */
+    public ODataEntityProviderPropertiesBuilder expandSelectTree(final ExpandSelectTreeNode expandSelectTree) {
+      properties.expandSelectTree = expandSelectTree;
+      return this;
+    }
+
+    public ODataEntityProviderPropertiesBuilder callbacks(final Map<String, ODataCallback> callbacks) {
+      properties.callbacks = callbacks;
+      return this;
+    }
+
+    public ODataEntityProviderPropertiesBuilder selfLink(final URI selfLink) {
+      properties.selfLink = selfLink;
+      return this;
+    }
+
+    public ODataEntityProviderPropertiesBuilder fromProperties(final EntityProviderWriteProperties properties) {
+      this.properties.mediaResourceMimeType = properties.getMediaResourceMimeType();
+      this.properties.inlineCountType = properties.getInlineCountType();
+      this.properties.inlineCount = properties.getInlineCount();
+      this.properties.nextLink = properties.getNextLink();
+      this.properties.expandSelectTree = properties.getExpandSelectTree();
+      this.properties.callbacks = properties.getCallbacks();
+      this.properties.selfLink = properties.getSelfLink();
+      return this;
+    }
+
+  }
+
+  public static ODataEntityProviderPropertiesBuilder fromProperties(final EntityProviderWriteProperties properties) {
+    final ODataEntityProviderPropertiesBuilder b = EntityProviderWriteProperties.serviceRoot(properties.getServiceRoot());
+    b.fromProperties(properties);
+    return b;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnReadInlineContent.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnReadInlineContent.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnReadInlineContent.java
new file mode 100644
index 0000000..970e4d8
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnReadInlineContent.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+
+/**
+ * <p> 
+ * Callback interface for the deep insert read calls (read of <code><m:inline></code> content). 
+ * Typically the {@link #receiveReadProperties(EntityProviderReadProperties, EdmNavigationProperty)} method is called
+ * when an inline navigation property is found and will be read.
+ * </p> 
+ * <p> 
+ * The {@link #handleReadEntry(ReadEntryResult)} and {@link #handleReadFeed(ReadFeedResult)} methods are called 
+ * after the inline navigation property was read and deliver the read (de-serialized) entity or list of entities.
+ * If inlined navigation property is <code>nullable</code> and not set a {@link ReadEntryResult} is given with the 
+ * <code>navigationPropertyName</code> and a <code>NULL</code> entry set.
+ * </p>
+ * 
+ * @author SAP AG
+ */
+public interface OnReadInlineContent {
+
+  /**
+   * Receive (request) to be used {@link EntityProviderReadProperties} to read the found inline navigation property 
+   * (<code>><m:inline>...</m:inline></code>).
+   * 
+   * @param readProperties read properties which are used to read enclosing parent entity
+   * @param navigationProperty emd navigation property information of found inline navigation property
+   * @return read properties which are used to read (de-serialize) found inline navigation property
+   * @throws ODataApplicationException
+   */
+  EntityProviderReadProperties receiveReadProperties(EntityProviderReadProperties readProperties, EdmNavigationProperty navigationProperty) throws ODataApplicationException;
+
+  /**
+   * Handles reading (de-serialization) entry result.
+   * The given {@link ReadEntryResult} object contains all contextual information
+   * about the de-serialized inline navigation property and the entry as
+   * {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}.
+   *
+   * @param readEntryResult with contextual information about and de-serialized
+   *                        inlined navigation property as
+   *                        {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}
+   * @throws ODataApplicationException
+   */
+  void handleReadEntry(ReadEntryResult readEntryResult) throws ODataApplicationException;
+
+  /**
+   * Handles reading (de-serialization) entry result.
+   * The given {@link ReadFeedResult} object contains all contextual information
+   * about the de-serialized inline navigation property and the entry as
+   * a list of {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}.
+   *
+   * @param readFeedResult with contextual information about and de-serialized
+   *                       inlined navigation property as a list of
+   *                       {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}
+   * @throws ODataApplicationException
+   */
+  void handleReadFeed(ReadFeedResult readFeedResult) throws ODataApplicationException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteEntryContent.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteEntryContent.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteEntryContent.java
new file mode 100644
index 0000000..f4f3dcb
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteEntryContent.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+
+/**
+ * Callback interface for the $expand query option. 
+ * <p>If an expand clause for a navigation property which points to an entry is found this callback will be called.
+ * <br>Pointing to an entry means the navigation property has a multiplicity of 0..1 or 1..1.
+ * 
+ * @author SAP AG
+ *
+ */
+public interface OnWriteEntryContent extends ODataCallback {
+
+  /**
+   * Retrieves the data for an entry. See {@link WriteEntryCallbackContext} for details on the context and {@link WriteEntryCallbackResult} for details on the result of this method.
+   * @param context of this entry
+   * @return result - must not be null.
+   * @throws ODataApplicationException
+   */
+  WriteEntryCallbackResult retrieveEntryResult(WriteEntryCallbackContext context) throws ODataApplicationException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteFeedContent.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteFeedContent.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteFeedContent.java
new file mode 100644
index 0000000..f702c9e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/OnWriteFeedContent.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+
+/**
+ * Callback interface for the $expand query option. 
+ * <p>If an expand clause for a navigation property which points to a feed is found this callback will be called.
+ * <br>Pointing to an feed means the navigation property has a multiplicity of 0..* or 1..*.
+ * 
+ * @author SAP AG
+ *
+ */
+public interface OnWriteFeedContent extends ODataCallback {
+
+  /**
+   * Retrieves the data for a feed. See {@link WriteFeedCallbackContext} for details on the context and {@link WriteFeedCallbackResult} for details on the result of this method.
+   * @param context of this entry
+   * @return result - must not be null.
+   * @throws ODataApplicationException
+   */
+  WriteFeedCallbackResult retrieveFeedResult(WriteFeedCallbackContext context) throws ODataApplicationException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadEntryResult.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadEntryResult.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadEntryResult.java
new file mode 100644
index 0000000..ad96cf4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadEntryResult.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+
+/**
+ * A {@link ReadEntryResult} represents an inlined navigation property which points to an entry.
+ * The {@link ReadEntryResult} contains the {@link EntityProviderReadProperties} which were used for read, 
+ * the <code>navigationPropertyName</code> and the read/de-serialized inlined entity.
+ * If inlined navigation property is <code>nullable</code> the {@link ReadEntryResult} has the 
+ * <code>navigationPropertyName</code> and a <code>NULL</code> entry set.
+ * 
+ * @author SAP AG
+ *
+ */
+public class ReadEntryResult extends ReadResult {
+
+  private final ODataEntry entry;
+
+  /**
+   * Constructor.
+   * Parameters <b>MUST NOT BE NULL</b>.
+   * 
+   * @param properties read properties which are used to read enclosing parent entity
+   * @param navigationProperty emd navigation property information of found inline navigation property
+   * @param entry read entity as {@link ODataEntry}
+   */
+  public ReadEntryResult(final EntityProviderReadProperties properties, final EdmNavigationProperty navigationProperty, final ODataEntry entry) {
+    super(properties, navigationProperty);
+    this.entry = entry;
+  }
+
+  @Override
+  public ODataEntry getResult() {
+    return entry;
+  }
+
+  @Override
+  public boolean isFeed() {
+    return false;
+  }
+
+  @Override
+  public String toString() {
+    return super.toString() + "\n\t" + entry.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadFeedResult.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadFeedResult.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadFeedResult.java
new file mode 100644
index 0000000..c86d90d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadFeedResult.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+
+/**
+ * A {@link ReadFeedResult} represents an inlined navigation property which points to a feed (in the form of a list of
+ * {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry} instances).
+ * The {@link ReadFeedResult} contains the {@link EntityProviderReadProperties} which were used for read, 
+ * the <code>navigationPropertyName</code> and the read/de-serialized inlined entities.
+ * If inlined navigation property is <code>nullable</code> the {@link ReadFeedResult} has the 
+ * <code>navigationPropertyName</code> and a <code>NULL</code> entry set.
+ * 
+ * @author SAP AG
+ */
+public class ReadFeedResult extends ReadResult {
+
+  private final ODataFeed feed;
+
+  /**
+   * Constructor.
+   * Parameters <b>MUST NOT BE NULL</b>.
+   * 
+   * @param properties read properties which are used to read enclosing parent entity
+   * @param navigationProperty emd navigation property information of found inline navigation property
+   * @param entry read entities as list of {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}
+   */
+  public ReadFeedResult(final EntityProviderReadProperties properties, final EdmNavigationProperty navigationProperty, final ODataFeed entry) {
+    super(properties, navigationProperty);
+    feed = entry;
+  }
+
+  @Override
+  public ODataFeed getResult() {
+    return feed;
+  }
+
+  @Override
+  public boolean isFeed() {
+    return true;
+  }
+
+  @Override
+  public String toString() {
+    return super.toString() + "\n\t" + feed.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadResult.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadResult.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadResult.java
new file mode 100644
index 0000000..dd2d8a8
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/ReadResult.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+
+/**
+ * A {@link ReadResult} represents an inlined navigation property which points to an entry or feed.
+ * The {@link ReadResult} contains the {@link EntityProviderReadProperties} which were used for read, 
+ * the <code>navigationPropertyName</code>, the read/de-serialized inlined entity and information whether the inlined content
+ * is a <code>feed</code> (multiplicity of <code>1..m</code>) or a single <code>entry</code> (multiplicity of <code>0..1</code> or <code>1..1</code>).
+ * If inlined navigation property is <code>nullable</code> the {@link ReadResult} has the 
+ * <code>navigationPropertyName</code> and a <code>NULL</code> entry set.
+ * 
+ * @author SAP AG
+ */
+public abstract class ReadResult {
+
+  protected final EntityProviderReadProperties readProperties;
+  protected final EdmNavigationProperty navigationProperty;
+
+  /**
+   * Constructor.
+   * Parameters <b>MUST NOT BE NULL</b>.
+   * 
+   * @param readProperties read properties which are used to read enclosing parent entity
+   * @param navigationProperty emd navigation property information of found inline navigation property
+   */
+  public ReadResult(final EntityProviderReadProperties readProperties, final EdmNavigationProperty navigationProperty) {
+    this.readProperties = readProperties;
+    this.navigationProperty = navigationProperty;
+  }
+
+  /**
+   * @return read properties which were used to read enclosing parent entity
+   */
+  public EntityProviderReadProperties getReadProperties() {
+    return readProperties;
+  }
+
+  /**
+   * @return emd navigation property information of found inline navigation property
+   */
+  public EdmNavigationProperty getNavigationProperty() {
+    return navigationProperty;
+  }
+
+  /**
+   * Common access method to read result.
+   * 
+   * @return an {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}
+   *         for the case of an single read entry or a list of
+   *         {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry ODataEntry}
+   *         in the case of an read feed.
+   */
+  public abstract Object getResult();
+
+  @Override
+  public String toString() {
+    return this.getClass().getSimpleName() + " [readProperties=" + readProperties + ", navigationProperty=" + navigationProperty + "]";
+  }
+
+  /**
+   * Return whether this entry is a <code>feed</code> (multiplicity of <code>1..m</code>) 
+   * or a single <code>entry</code> (multiplicity of <code>0..1</code> or <code>1..1</code>).
+   * 
+   * @return <code>true</code> for a feed and <code>false</code> for an entry
+   */
+  public abstract boolean isFeed();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallback.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallback.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallback.java
new file mode 100644
index 0000000..3021e67
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallback.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+
+/**
+ * <p>Interface that must be implemented in order to provide tombstone support.</p>
+ * <p>The callback implementing this interface is registered at the
+ * {@link org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties EntityProviderWriteProperties}
+ * using the callback key of this class.</p>
+ * @author SAP AG
+ */
+public interface TombstoneCallback extends ODataCallback {
+
+  /**
+   * The key to be used when registering the callback at the
+   * {@link org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties EntityProviderWriteProperties}
+   */
+  public static final String CALLBACK_KEY_TOMBSTONE = "~tombstoneCallback";
+  public static final String PREFIX_TOMBSTONE = "at";
+  public static final String NAMESPACE_TOMBSTONE = "http://purl.org/atompub/tombstones/1.0";
+
+  @Deprecated
+  public static final String REL_DELTA = "delta";
+
+  /**
+   * <p>This method is called after all entries have been serialized.</p>
+   * <p>The returned {@link TombstoneCallbackResult} must contain all deleted entries,
+   * in the form of List{@literal <}Map{@literal <}property name, property value{@literal >}{@literal >},
+   * which should be serialized.</p>
+   * <p>A map representing a deleted entry
+   * <ul><li><b>MUST</b> contain all properties which are part of the key for this entry.</li>
+   * <li><b>MAY</b> contain the property which is mapped on SyndicationUpdated.
+   * The provided value here will result in the value of the "when" attribute
+   * of the deleted entry.</li></ul></p>
+   * <p>The provided delta link will be serialized at the end of the feed document.</p>
+   */
+  TombstoneCallbackResult getTombstoneCallbackResult();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallbackResult.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallbackResult.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallbackResult.java
new file mode 100644
index 0000000..9836780
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/TombstoneCallbackResult.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Objects of this class are a container for the result of the {@link TombstoneCallback}.
+ * @author SAP AG
+ *
+ */
+public class TombstoneCallbackResult {
+
+  private List<Map<String, Object>> deletedEntriesData;
+  private String deltaLink;
+
+  /**
+   * A map representing a deleted entry <b>MUST</b> contain all properties which are part of the key for this entry.
+   * <br>A map representing a deleted entry <b>MAY</b> contain the property which is mapped on SyndicationUpdated. The provided value here will result in the value of the "when" attribute of the deleted entry. 
+   * @return deleted entries in the form of List{@literal <}Map{@literal <}property name, property value{@literal >}{@literal >}
+   */
+  public List<Map<String, Object>> getDeletedEntriesData() {
+    return deletedEntriesData;
+  }
+
+  /**
+   * Sets the data for all deleted entries
+   * @param deletedEntriesData
+   */
+  public void setDeletedEntriesData(final List<Map<String, Object>> deletedEntriesData) {
+    this.deletedEntriesData = deletedEntriesData;
+  }
+
+  /**
+   * @return delta link as String
+   */
+  public String getDeltaLink() {
+    return deltaLink;
+  }
+
+  /**
+   * Sets the delta link to retrieve a delta. 
+   * @param deltaLink
+   */
+  public void setDeltaLink(final String deltaLink) {
+    this.deltaLink = deltaLink;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteCallbackContext.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteCallbackContext.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteCallbackContext.java
new file mode 100644
index 0000000..4281de7
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteCallbackContext.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+
+/**
+ * Wrapper for {@link WriteEntryCallbackContext} and {@link WriteFeedCallbackContext}.
+ * @org.apache.olingo.odata2.DoNotImplement 
+ * @author SAP AG
+ */
+public abstract class WriteCallbackContext {
+  private EdmEntitySet sourceEntitySet;
+  private EdmNavigationProperty navigationProperty;
+  private Map<String, Object> entryData;
+  private ExpandSelectTreeNode currentNode;
+
+  /**
+   * Current means the node pointing to the target entity set
+   * @return the current node of the expand select tree
+   */
+  public ExpandSelectTreeNode getCurrentExpandSelectTreeNode() {
+    return currentNode;
+  }
+
+  /**
+   * Do Not Call This Method!
+   * @param currentNode
+   */
+  public void setCurrentExpandSelectTreeNode(final ExpandSelectTreeNode currentNode) {
+    this.currentNode = currentNode;
+  }
+
+  /**
+   * Returns entity set which contains an entry that should be expanded
+   * @return source entity set
+   */
+  public EdmEntitySet getSourceEntitySet() {
+    return sourceEntitySet;
+  }
+
+  /**
+   * Do Not Call This Method!
+   * @param entitySet
+   */
+  public void setSourceEntitySet(final EdmEntitySet entitySet) {
+    sourceEntitySet = entitySet;
+  }
+
+  /**
+   * Navigation property which is contained in the expand clause.
+   * @return navigation property pointing to the entity which has to be expanded.
+   */
+  public EdmNavigationProperty getNavigationProperty() {
+    return navigationProperty;
+  }
+
+  /**
+   * Do Not Call This Method!
+   * @param navigationProperty
+   */
+  public void setNavigationProperty(final EdmNavigationProperty navigationProperty) {
+    this.navigationProperty = navigationProperty;
+  }
+
+  /**
+   * Source entry data which was just serialized.
+   * @return data of the source entry
+   */
+  public Map<String, Object> getEntryData() {
+    return entryData;
+  }
+
+  /**
+   * Do Not Call This Method!
+   * @param entryData
+   */
+  public void setEntryData(final Map<String, Object> entryData) {
+    this.entryData = entryData;
+  }
+
+  /**
+   * @return the key of the current entry as a Map<String,Object>
+   * @throws EntityProviderException in case of an {@link EdmException}
+   */
+  public Map<String, Object> extractKeyFromEntryData() throws EntityProviderException {
+    HashMap<String, Object> key = new HashMap<String, Object>();
+    try {
+      for (String keyPropertyName : sourceEntitySet.getEntityType().getKeyPropertyNames()) {
+        key.put(keyPropertyName, entryData.get(keyPropertyName));
+      }
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return key;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackContext.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackContext.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackContext.java
new file mode 100644
index 0000000..3955dab
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackContext.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+/**
+ * Context given if the target of an expand is an entry. It contains the source entity set, the navigation property pointing to the entry which has to be expanded, the current expand select tree node and the data of the source entry.
+ * @author SAP AG
+ *
+ */
+public class WriteEntryCallbackContext extends WriteCallbackContext {}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackResult.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackResult.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackResult.java
new file mode 100644
index 0000000..cfc5d88
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteEntryCallbackResult.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+
+/**
+ * Result of a callback. It contains the data of the entry which is to be expanded as well as the properties of this entry.
+ * @author SAP AG
+ */
+public class WriteEntryCallbackResult {
+
+  EntityProviderWriteProperties inlineProperties;
+  Map<String, Object> oneEntryData;
+
+  /**
+   * @return the inline properties
+   */
+  public EntityProviderWriteProperties getInlineProperties() {
+    return inlineProperties;
+  }
+
+  /**
+   * Sets the inline properties for this entry
+   * @param inlineProperties
+   */
+  public void setInlineProperties(final EntityProviderWriteProperties inlineProperties) {
+    this.inlineProperties = inlineProperties;
+  }
+
+  /**
+   * @return the data for the entry as a map
+   */
+  public Map<String, Object> getEntryData() {
+    return oneEntryData;
+  }
+
+  /**
+   * @param data for the entry as a map
+   */
+  public void setEntryData(final Map<String, Object> data) {
+    oneEntryData = data;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackContext.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackContext.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackContext.java
new file mode 100644
index 0000000..ab30e4c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackContext.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import java.net.URI;
+
+/**
+ * Context given if the target of an expand is a feed. It contains the source entity set, the navigation property pointing to the entry which has to be expanded, the current expand select tree node and the data of the source entry.
+ * @author SAP AG
+ *
+ */
+public class WriteFeedCallbackContext extends WriteCallbackContext {
+
+  private URI selfLink;
+
+  /**
+   * Sets the self Link for this feed.
+   * @param selfLink
+   */
+  public void setSelfLink(final URI selfLink) {
+    this.selfLink = selfLink;
+  }
+
+  /**
+   * This self link is the same as the link displayed for the navigation property e.g. Rooms(1)/nr_Buildings.
+   * @return the self link calculated by the library
+   */
+  public URI getSelfLink() {
+    return selfLink;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackResult.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackResult.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackResult.java
new file mode 100644
index 0000000..8c3878e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/WriteFeedCallbackResult.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.api.ep.callback;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+
+/**
+ * Result of a callback. It contains the data of the feed which is to be expanded as well as the BaseUri of the feed. Further callbacks for this feed can also be set.
+ * @author SAP AG
+ *
+ */
+public class WriteFeedCallbackResult {
+
+  EntityProviderWriteProperties inlineProperties;
+  List<Map<String, Object>> feedData;
+
+  /**
+   * @return the inline provider properties
+   */
+  public EntityProviderWriteProperties getInlineProperties() {
+    return inlineProperties;
+  }
+
+  /**
+   * Sets the properties for the inline data. MUST NOT BE NULL.
+   * @param inlineProperties
+   */
+  public void setInlineProperties(final EntityProviderWriteProperties inlineProperties) {
+    this.inlineProperties = inlineProperties;
+  }
+
+  /**
+   * @return the feed data as a list of maps
+   */
+  public List<Map<String, Object>> getFeedData() {
+    return feedData;
+  }
+
+  /**
+   * Sets the feed data as a list of maps.
+   * @param feedData
+   */
+  public void setFeedData(final List<Map<String, Object>> feedData) {
+    this.feedData = feedData;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/package-info.java
new file mode 100644
index 0000000..b25eab4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/callback/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Entity Provider Callbacks<p>
+ * These callbacks will be used to support the $expand query option. Callbacks have to implement the {@link org.apache.olingo.odata2.api.ODataCallback} as a marker. 
+ * <br>To support an expanded entry the {@link org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent} interface has to be implemented.
+ * <br>To support an expanded feed the {@link org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent} interface has to be implemented.
+ * 
+ * <p>All callbacks are registered for a navigation property in a HashMap<String as navigation property name, callback for this navigation property> and will only be called if a matching $expand clause is found.
+ */
+package org.apache.olingo.odata2.api.ep.callback;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/EntryMetadata.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/EntryMetadata.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/EntryMetadata.java
new file mode 100644
index 0000000..39ea767
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/EntryMetadata.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.api.ep.entry;
+
+import java.util.List;
+
+/**
+ * {@link EntryMetadata} contains all metadata for an {@link ODataEntry}.
+ */
+public interface EntryMetadata {
+
+  /**
+   * Gets the URI of this entry.
+   * 
+   * @return the URI
+   */
+  public abstract String getUri();
+
+  /**
+   * Gets the association URIs for a given navigation property.
+   * 
+   * @param navigationPropertyName the name of the navigation property
+   * @return the list of URIs for the given navigation property
+   */
+  public abstract List<String> getAssociationUris(String navigationPropertyName);
+
+  /**
+   * Gets the entity tag for this entry.
+   * 
+   * @return the entity tag
+   */
+  public abstract String getEtag();
+
+  /**
+   * Gets the ID of this entry.
+   * 
+   * @return the ID
+   */
+  public abstract String getId();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/MediaMetadata.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/MediaMetadata.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/MediaMetadata.java
new file mode 100644
index 0000000..2d9da48
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/MediaMetadata.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.ep.entry;
+
+/**
+ * {@link MediaMetadata} contains all metadata for media related entries.
+ */
+public interface MediaMetadata {
+
+  /**
+   * Get <code>edit link</code>.
+   * 
+   * @return <code>edit link</code>.
+   */
+  public abstract String getEditLink();
+
+  /**
+   * Get <code>content type</code> in as specified in 
+   * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616 Section 14</a>.
+   * 
+   * @return <code>content type</code>.
+   */
+  public abstract String getContentType();
+
+  /**
+   * Get <code>etag</code>.
+   * 
+   * @return <code>etag</code>.
+   */
+  public abstract String getEtag();
+
+  /**
+   * Get <code>source link</code>.
+   * 
+   * @return <code>source link</code>.
+   */
+  public abstract String getSourceLink();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/ODataEntry.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/ODataEntry.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/ODataEntry.java
new file mode 100644
index 0000000..78401bc
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/ODataEntry.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.api.ep.entry;
+
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+
+/**
+ * An {@link ODataEntry} contains all <b>properties</b> (in form of a {@link Map}) and possible <b>metadata</b> 
+ * (in form of {@link MediaMetadata} and/or {@link EntryMetadata}) for an entry.
+ * 
+ */
+public interface ODataEntry {
+
+  /**
+   * Properties of this {@link ODataEntry} in form of a <b>property name</b> to <b>property value</b> map.
+   * 
+   * @return a <b>property name</b> to <b>property value</b> map.
+   */
+  public Map<String, Object> getProperties();
+
+  /**
+   * Get {@link MediaMetadata} for this {@link ODataEntry} if available.
+   * 
+   * @return {@link MediaMetadata} for this {@link ODataEntry} if available.
+   */
+  public MediaMetadata getMediaMetadata();
+
+  /**
+   * Get {@link EntryMetadata} for this {@link ODataEntry} if available.
+   * 
+   * @return {@link EntryMetadata} for this {@link ODataEntry} if available.
+   */
+  public EntryMetadata getMetadata();
+
+  /**
+   * If this {@link ODataEntry} contains properties of an inline navigation property this method
+   * returns <code>true</code>. 
+   * Otherwise if this {@link ODataEntry} only contains it own properties this method
+   * returns <code>false</code>.
+   * 
+   * @return <code>true</code> if inline navigation properties are contained, otherwise <code>false</code>.
+   */
+  public boolean containsInlineEntry();
+
+  /**
+   * Gets the expand select tree data structure which can be used for <code>$expand</code> query option.
+   * 
+   * @return parsed tree structure representing the $expand
+   */
+  public ExpandSelectTreeNode getExpandSelectTree();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/package-info.java
new file mode 100644
index 0000000..1b99ceb
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/entry/package-info.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Entity Provider Entries<p>
+ * 
+ * The <b>org.apache.olingo.odata2.api.ep.entry</b> package contains all classes related and necessary for an {@link org.apache.olingo.odata2.api.ep.entry.ODataEntry}.
+ * <p>
+ */
+package org.apache.olingo.odata2.api.ep.entry;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/FeedMetadata.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/FeedMetadata.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/FeedMetadata.java
new file mode 100644
index 0000000..2200d5c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/FeedMetadata.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.api.ep.feed;
+
+/**
+ * {@link FeedMetadata} objects contain metadata information about one feed.
+ * @author SAP AG
+ *
+ */
+public interface FeedMetadata {
+
+  /**
+   * @return inlineCount may be null if no inlineCount is set.
+   */
+  public Integer getInlineCount();
+
+  /**
+   * @return nextLink may be null if no next link is set
+   */
+  public String getNextLink();
+
+  /**
+   * @return deltaLink may be null if no delta link is set
+   */
+  public String getDeltaLink();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/ODataFeed.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/ODataFeed.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/ODataFeed.java
new file mode 100644
index 0000000..0403b83
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/ODataFeed.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.api.ep.feed;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+
+/**
+ * An {@link ODataFeed} object contains a list of {@link ODataEntry}s and the metadata associated with this feed.
+ * @author SAP AG
+ *
+ */
+public interface ODataFeed {
+
+  /**
+   * The returned list may be empty but never null.
+   * @return list of {@link ODataEntry}s
+   */
+  public List<ODataEntry> getEntries();
+
+  /**
+   * @return {@link FeedMetadata} object
+   */
+  public FeedMetadata getFeedMetadata();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/package-info.java
new file mode 100644
index 0000000..abee895
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/feed/package-info.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Entity Provider Feed<p>
+ * 
+ * The <b>org.apache.olingo.odata2.api.ep.feed</b> package contains all classes related and necessary for an {@link org.apache.olingo.odata2.api.ep.feed.ODataFeed}.
+ * <p>
+ */
+package org.apache.olingo.odata2.api.ep.feed;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/package-info.java
new file mode 100644
index 0000000..ce381f9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/package-info.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Entity Provider<p>
+ * 
+ * The <b>org.apache.olingo.odata2.api.ep</b> package contains all classes related and necessary to provide an {@link org.apache.olingo.odata2.api.ep.EntityProvider}.
+ * <p>
+ * An {@link org.apache.olingo.odata2.api.ep.EntityProvider} provides all necessary <b>read</b> and <b>write</b> methods for accessing 
+ * the entities defined in an <code>Entity Data Model</code>.
+ * Therefore this library provides (in its <code>core</code> packages) as convenience basic {@link org.apache.olingo.odata2.api.ep.EntityProvider} 
+ * for accessing entities in the <b>XML</b> and <b>JSON</b> format.
+ * <p>
+ * For support of additional formats it is recommended to handle those directly within an implementation of a 
+ * <code>ODataProcessor</code> (it is possible but <b>not recommended</b> to implement an own 
+ * {@link org.apache.olingo.odata2.api.ep.EntityProvider} for support of additional formats).
+ */
+package org.apache.olingo.odata2.api.ep;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/MessageReference.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/MessageReference.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/MessageReference.java
new file mode 100644
index 0000000..2e8b31b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/MessageReference.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * APPLICATION DEVELOPERS: Please use {@link ODataApplicationException} to throw custom exceptions. This class is used inside the library only. 
+ * <p>A {@link MessageReference} references to the used message for an
+ * {@link ODataMessageException} and its sub classes. It supports
+ * internationalization and translation of exception messages.
+ * <br>Theses classes  contain a {@link MessageReference} object which
+ * can be mapped to a related key and message text in the resource bundles.
+ * @author SAP AG
+ */
+public abstract class MessageReference {
+
+  protected final String key;
+  protected List<Object> content = null;
+
+  private MessageReference(final String key) {
+    this(key, null);
+  }
+
+  private MessageReference(final String key, final List<Object> content) {
+    this.key = key;
+    this.content = content;
+  }
+
+  /**
+   * Creates a {@link MessageReference} for given <code>class</code> and <code>key</code>.
+   * This combination of <code>class</code> and <code>key</code> has to be provided
+   * by a resource bundle.
+   * @param clazz {@link ODataMessageException} for which this {@link MessageReference}
+   *              should be used
+   * @param key   unique key (in context of {@link ODataMessageException}) for reference
+   *              to message text in resource bundle
+   * @return created {@link MessageReference}
+   */
+  public static MessageReference create(final Class<? extends ODataException> clazz, final String key) {
+    return new SimpleMessageReference(clazz.getName() + "." + key);
+  }
+
+  public MessageReference create() {
+    return new SingleMessageReference(key);
+  }
+
+  /**
+   * Returns message key.
+   */
+  public String getKey() {
+    return key;
+  }
+
+  /**
+   * Adds given content to message reference.
+   */
+  public MessageReference addContent(final Object... content) {
+    if (this.content == null) {
+      return new SimpleMessageReference(key, content);
+    } else {
+      final List<Object> mergedContent = new ArrayList<Object>(this.content.size() + content.length);
+      mergedContent.addAll(this.content);
+      mergedContent.addAll(Arrays.asList(content));
+      return new SimpleMessageReference(key, mergedContent);
+    }
+  }
+
+  /**
+   * Receives content for this {@link MessageReference}.
+   * Beware that returned list is immutable.
+   */
+  public List<?> getContent() {
+    if (content == null) {
+      return Collections.emptyList();
+    } else {
+      return Collections.unmodifiableList(content);
+    }
+  }
+
+  /**
+   * Simple inner class for realization of {@link MessageReference} interface.
+   */
+  private static class SimpleMessageReference extends MessageReference {
+    public SimpleMessageReference(final String implKey) {
+      super(implKey);
+    }
+
+    public SimpleMessageReference(final String implKey, final List<Object> content) {
+      super(implKey, content);
+    }
+
+    public SimpleMessageReference(final String implKey, final Object... content) {
+      super(implKey, Arrays.asList(content));
+    }
+  }
+
+  private static class SingleMessageReference extends MessageReference {
+    public SingleMessageReference(final String implKey) {
+      super(implKey);
+    }
+
+    public SingleMessageReference(final String implKey, final List<Object> content) {
+      super(implKey, content);
+    }
+
+    public SingleMessageReference(final String implKey, final Object... content) {
+      super(implKey, Arrays.asList(content));
+    }
+
+    @Override
+    public MessageReference addContent(final Object... content) {
+
+      if (this.content == null) {
+        this.content = new ArrayList<Object>();
+      }
+
+      this.content.addAll(Arrays.asList(content));
+      return this;
+    }
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((key == null) ? 0 : key.hashCode());
+    return result;
+  }
+
+  /**
+   * {@link MessageReference}s are equal if their message keys have the same value.
+   * @return <code>true</code> if both instances are equal, otherwise <code>false</code>.
+   */
+  @Override
+  public boolean equals(final Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    MessageReference other = (MessageReference) obj;
+    if (key == null) {
+      if (other.key != null) {
+        return false;
+      }
+    } else if (!key.equals(other.key)) {
+      return false;
+    }
+    return true;
+  }
+}


[16/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntityConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntityConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntityConsumer.java
new file mode 100644
index 0000000..f65938b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntityConsumer.java
@@ -0,0 +1,239 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties.EntityProviderReadPropertiesBuilder;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+
+/**
+ * Xml entity (content type dependent) consumer for reading input (from <code>content</code>).
+ * 
+ * @author SAP AG
+ */
+public class XmlEntityConsumer {
+
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  public XmlEntityConsumer() throws EntityProviderException {
+    super();
+  }
+
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createStaxReader(content);
+
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      XmlFeedConsumer xfc = new XmlFeedConsumer();
+      return xfc.readFeed(reader, eia, properties);
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      XmlEntryConsumer xec = new XmlEntryConsumer();
+      reader = createStaxReader(content);
+
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      ODataEntry result = xec.readEntry(reader, eia, properties);
+      return result;
+    } catch (EntityProviderException e) {
+      cachedException = e;
+      throw cachedException;
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public Map<String, Object> readProperty(final EdmProperty edmProperty, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    XmlPropertyConsumer xec = new XmlPropertyConsumer();
+
+    try {
+      reader = createStaxReader(content);
+      Map<String, Object> result = xec.readProperty(reader, edmProperty, properties.getMergeSemantic(), properties.getTypeMappings());
+      return result;
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public Object readPropertyValue(final EdmProperty edmProperty, final InputStream content) throws EntityProviderException {
+    return readPropertyValue(edmProperty, content, null);
+  }
+
+  public Object readPropertyValue(final EdmProperty edmProperty, final InputStream content, final Class<?> typeMapping) throws EntityProviderException {
+    try {
+      final Map<String, Object> result;
+      EntityProviderReadPropertiesBuilder propertiesBuilder = EntityProviderReadProperties.init().mergeSemantic(false);
+      if (typeMapping == null) {
+        result = readProperty(edmProperty, content, propertiesBuilder.build());
+      } else {
+        Map<String, Object> typeMappings = new HashMap<String, Object>();
+        typeMappings.put(edmProperty.getName(), typeMapping);
+        result = readProperty(edmProperty, content, propertiesBuilder.addTypeMappings(typeMappings).build());
+      }
+      return result.get(edmProperty.getName());
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  public String readLink(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    XmlLinkConsumer xlc = new XmlLinkConsumer();
+
+    try {
+      reader = createStaxReader(content);
+      return xlc.readLink(reader, entitySet);
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public List<String> readLinks(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+    XMLStreamReader reader = null;
+    EntityProviderException cachedException = null;
+    XmlLinkConsumer xlc = new XmlLinkConsumer();
+
+    try {
+      reader = createStaxReader(content);
+      return xlc.readLinks(reader, entitySet);
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (XMLStreamException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  private XMLStreamReader createStaxReader(final Object content) throws XMLStreamException, EntityProviderException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+
+    if (content == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Got not supported NULL object as content to de-serialize."));
+    }
+
+    if (content instanceof InputStream) {
+      XMLStreamReader streamReader = factory.createXMLStreamReader((InputStream) content, DEFAULT_CHARSET);
+      // 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 = streamReader.getCharacterEncodingScheme();
+      if (characterEncodingInContent != null && !DEFAULT_CHARSET.equalsIgnoreCase(characterEncodingInContent)) {
+        throw new EntityProviderException(EntityProviderException.UNSUPPORTED_CHARACTER_ENCODING.addContent(characterEncodingInContent));
+      }
+      return streamReader;
+    }
+    throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+        .addContent("Found not supported content of class '" + content.getClass() + "' to de-serialize."));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntryConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntryConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntryConsumer.java
new file mode 100644
index 0000000..881d8c7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlEntryConsumer.java
@@ -0,0 +1,684 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+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.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityTypeMapping;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+
+/**
+ * Atom/XML format reader/consumer for entries.
+ * 
+ * {@link XmlEntryConsumer} instance can be reused for several {@link #readEntry(XMLStreamReader, EntityInfoAggregator, EntityProviderReadProperties)} calls
+ * but be aware that the instance and their <code>readEntry*</code> methods are <b>NOT THREAD SAFE</b>.
+ * @author SAP AG
+ */
+public class XmlEntryConsumer {
+
+  private Map<String, String> foundPrefix2NamespaceUri;
+  private ODataEntryImpl readEntryResult;
+  private Map<String, Object> properties;
+  private MediaMetadataImpl mediaMetadata;
+  private EntryMetadataImpl entryMetadata;
+  private ExpandSelectTreeNodeImpl expandSelectTree;
+  private EntityTypeMapping typeMappings;
+  private String currentHandledStartTagName;
+
+  public ODataEntry readEntry(final XMLStreamReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    try {
+      initialize(readProperties);
+
+      while (reader.hasNext() && !isEntryEndTag(reader)) {
+        reader.nextTag();
+        if (reader.isStartElement()) {
+          handleStartedTag(reader, eia, readProperties);
+        }
+      }
+
+      if (!readProperties.getMergeSemantic()) {
+        validateMandatoryPropertiesAvailable(eia, readEntryResult);
+      }
+
+      return readEntryResult;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private boolean isEntryEndTag(final XMLStreamReader reader) {
+    return reader.isEndElement()
+        && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())
+        && FormatXml.ATOM_ENTRY.equals(reader.getLocalName());
+  }
+
+  /**
+   * Initialize the {@link XmlEntryConsumer} to be ready for read of an entry.
+   * 
+   * @param readProperties
+   * @throws EntityProviderException
+   */
+  private void initialize(final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    properties = new HashMap<String, Object>();
+    mediaMetadata = new MediaMetadataImpl();
+    entryMetadata = new EntryMetadataImpl();
+    expandSelectTree = new ExpandSelectTreeNodeImpl();
+    foundPrefix2NamespaceUri = new HashMap<String, String>();
+
+    readEntryResult = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, expandSelectTree);
+    typeMappings = EntityTypeMapping.create(readProperties.getTypeMappings());
+    foundPrefix2NamespaceUri.putAll(readProperties.getValidatedPrefixNamespaceUris());
+  }
+
+  /**
+   * Validates that all mandatory properties are found and set at the {@link #readEntryResult} entity.
+   * If a mandatory property is missing an {@link EntityProviderException} is thrown.
+   * 
+   * @param eia entity info which contains the information which properties are mandatory
+   * @param entry entry for which the mandatory properties are validated
+   * @throws EntityProviderException if a mandatory property is missing
+   */
+  private void validateMandatoryPropertiesAvailable(final EntityInfoAggregator eia, final ODataEntryImpl entry) throws EntityProviderException {
+    Collection<EntityPropertyInfo> propertyInfos = new ArrayList<EntityPropertyInfo>(eia.getPropertyInfos());
+    propertyInfos.removeAll(eia.getKeyPropertyInfos());
+    Map<String, Object> data = entry.getProperties();
+
+    for (EntityPropertyInfo entityPropertyInfo : propertyInfos) {
+      boolean mandatory = entityPropertyInfo.isMandatory();
+      if (mandatory && !data.containsKey(entityPropertyInfo.getName())) {
+        throw new EntityProviderException(EntityProviderException.MISSING_PROPERTY.addContent(entityPropertyInfo.getName()));
+      }
+    }
+  }
+
+  private void handleStartedTag(final XMLStreamReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties)
+      throws EntityProviderException, XMLStreamException, EdmException {
+
+    currentHandledStartTagName = reader.getLocalName();
+
+    if (FormatXml.ATOM_ID.equals(currentHandledStartTagName)) {
+      readId(reader);
+    } else if (FormatXml.ATOM_ENTRY.equals(currentHandledStartTagName)) {
+      readEntry(reader);
+    } else if (FormatXml.ATOM_LINK.equals(currentHandledStartTagName)) {
+      readLink(reader, eia, readProperties);
+    } else if (FormatXml.ATOM_CONTENT.equals(currentHandledStartTagName)) {
+      readContent(reader, eia);
+    } else if (FormatXml.M_PROPERTIES.equals(currentHandledStartTagName)) {
+      readProperties(reader, eia);
+    } else if (!readProperties.getMergeSemantic()) {
+      readCustomElement(reader, currentHandledStartTagName, eia);
+    } else {
+      skipStartedTag(reader);
+    }
+  }
+
+  private void readCustomElement(final XMLStreamReader reader, final String tagName, final EntityInfoAggregator eia) throws EdmException, EntityProviderException, XMLStreamException {
+    EntityPropertyInfo targetPathInfo = eia.getTargetPathInfo(tagName);
+    NamespaceContext nsctx = reader.getNamespaceContext();
+
+    boolean skipTag = true;
+    if (!Edm.NAMESPACE_ATOM_2005.equals(reader.getName().getNamespaceURI())) {
+
+      if (targetPathInfo != null) {
+        final String customPrefix = targetPathInfo.getCustomMapping().getFcNsPrefix();
+        final String customNamespaceURI = targetPathInfo.getCustomMapping().getFcNsUri();
+
+        if (customPrefix != null && customNamespaceURI != null) {
+          String xmlPrefix = nsctx.getPrefix(customNamespaceURI);
+          String xmlNamespaceUri = reader.getNamespaceURI(customPrefix);
+
+          if (customNamespaceURI.equals(xmlNamespaceUri) && customPrefix.equals(xmlPrefix)) {
+            skipTag = false;
+            reader.require(XMLStreamConstants.START_ELEMENT, customNamespaceURI, tagName);
+            reader.next();
+            reader.require(XMLStreamConstants.CHARACTERS, null, null);
+            final String text = reader.getText();
+            reader.nextTag();
+            reader.require(XMLStreamConstants.END_ELEMENT, customNamespaceURI, tagName);
+
+            final EntityPropertyInfo propertyInfo = getValidatedPropertyInfo(eia, tagName);
+            final Class<?> typeMapping = typeMappings.getMappingClass(propertyInfo.getName());
+            final EdmSimpleType type = (EdmSimpleType) propertyInfo.getType();
+            final Object value = type.valueOfString(text, EdmLiteralKind.DEFAULT, propertyInfo.getFacets(),
+                typeMapping == null ? type.getDefaultType() : typeMapping);
+            properties.put(tagName, value);
+          }
+        }
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(tagName));
+      }
+    }
+
+    if (skipTag) {
+      skipStartedTag(reader);
+    }
+  }
+
+  /**
+   * Skip the tag to which the {@link XMLStreamReader} currently points.
+   * Therefore it is read until an end element tag with current local name is found.
+   * 
+   * @param reader
+   * @throws XMLStreamException
+   */
+  private void skipStartedTag(final XMLStreamReader reader) throws XMLStreamException {
+    final String name = reader.getLocalName();
+    int read = 1;
+    while (read > 0 && reader.hasNext()) {
+      reader.next();
+      if (reader.hasName() && name.equals(reader.getLocalName())) {
+        if (reader.isEndElement()) {
+          read--;
+        } else if (reader.isStartElement()) {
+          read++;
+        }
+      }
+    }
+  }
+
+  private void readEntry(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ENTRY);
+
+    extractNamespacesFromTag(reader);
+    final String etag = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_ETAG);
+    entryMetadata.setEtag(etag);
+  }
+
+  private void extractNamespacesFromTag(final XMLStreamReader reader) throws EntityProviderException {
+    // collect namespaces
+    int namespaceCount = reader.getNamespaceCount();
+    for (int i = 0; i < namespaceCount; i++) {
+      String namespacePrefix = reader.getNamespacePrefix(i);
+      String namespaceUri = reader.getNamespaceURI(i);
+
+      foundPrefix2NamespaceUri.put(namespacePrefix, namespaceUri);
+    }
+  }
+
+  private void checkAllMandatoryNamespacesAvailable() throws EntityProviderException {
+    if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_D_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_D_2007_08));
+    } else if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_M_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_M_2007_08));
+    } else if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_ATOM_2005)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_ATOM_2005));
+    }
+  }
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @throws EntityProviderException
+   * @throws XMLStreamException
+   * @throws EdmException
+   */
+  private void readLink(final XMLStreamReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) throws EntityProviderException, XMLStreamException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_LINK);
+
+    final String rel = reader.getAttributeValue(null, FormatXml.ATOM_REL);
+    final String uri = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+    final String type = reader.getAttributeValue(null, FormatXml.ATOM_TYPE);
+    final String etag = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_ETAG);
+
+    // read to next tag to check if <link> contains any further tags
+    reader.nextTag();
+
+    if (reader.isEndElement()) {
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_LINK);
+
+      if (rel == null || uri == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(
+            FormatXml.ATOM_HREF + "' and/or '" + FormatXml.ATOM_REL).addContent(FormatXml.ATOM_LINK));
+      } else if (rel.startsWith(Edm.NAMESPACE_REL_2007_08)) {
+        final String navigationPropertyName = rel.substring(Edm.NAMESPACE_REL_2007_08.length());
+        entryMetadata.putAssociationUri(navigationPropertyName, uri);
+      } else if (rel.equals(Edm.LINK_REL_EDIT_MEDIA)) {
+        mediaMetadata.setEditLink(uri);
+        mediaMetadata.setEtag(etag);
+      }
+    } else {
+      if (rel != null && rel.startsWith(Edm.NAMESPACE_REL_2007_08)) {
+        readInlineContent(reader, eia, readProperties, type, rel);
+      }
+    }
+  }
+
+  /**
+   * Inline content was found and {@link XMLStreamReader} already points to <m:inline> tag.
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @param atomLinkType the atom <code>type</code> attribute value of the <code>link</code> tag
+   * @param atomLinkRel the atom <code>rel</code> attribute value of the <code>link</code> tag
+   * @throws XMLStreamException
+   * @throws EntityProviderException
+   * @throws EdmException
+   */
+  private void readInlineContent(final XMLStreamReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties,
+      final String atomLinkType, final String atomLinkRel)
+      throws XMLStreamException, EntityProviderException, EdmException {
+
+    //
+    String navigationPropertyName = atomLinkRel.substring(Edm.NAMESPACE_REL_2007_08.length());
+
+    EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+    EdmEntitySet entitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+    EntityInfoAggregator inlineEia = EntityInfoAggregator.create(entitySet);
+
+    final EntityProviderReadProperties inlineProperties = createInlineProperties(readProperties, navigationProperty);
+
+    // validations
+    boolean isFeed = isInlineFeedValidated(reader, eia, atomLinkType, navigationPropertyName);
+
+    List<ODataEntry> inlineEntries = new ArrayList<ODataEntry>();
+
+    while (!(reader.isEndElement() && Edm.NAMESPACE_M_2007_08.equals(reader.getNamespaceURI()) && FormatXml.M_INLINE.equals(reader.getLocalName()))) {
+
+      if (reader.isStartElement() && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI()) && FormatXml.ATOM_ENTRY.equals(reader.getLocalName())) {
+        XmlEntryConsumer xec = new XmlEntryConsumer();
+        ODataEntry inlineEntry = xec.readEntry(reader, inlineEia, inlineProperties);
+        inlineEntries.add(inlineEntry);
+      }
+      // next tag
+      reader.next();
+    }
+
+    updateExpandSelectTree(navigationPropertyName, inlineEntries);
+    updateReadProperties(readProperties, navigationPropertyName, navigationProperty, isFeed, inlineEntries);
+
+    reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+  }
+
+  /**
+   * Updates the read properties ({@link #properties}) for this {@link ReadEntryResult} ({@link #readEntryResult}).
+   * 
+   * @param readProperties
+   * @param navigationPropertyName
+   * @param navigationProperty
+   * @param isFeed
+   * @param inlineEntries
+   * @throws EntityProviderException 
+   */
+  private void updateReadProperties(final EntityProviderReadProperties readProperties, final String navigationPropertyName,
+      final EdmNavigationProperty navigationProperty, final boolean isFeed, final List<ODataEntry> inlineEntries) throws EntityProviderException {
+    Object entry = extractODataEntity(isFeed, inlineEntries);
+    OnReadInlineContent callback = readProperties.getCallback();
+    if (callback == null) {
+      readEntryResult.setContainsInlineEntry(true);
+      properties.put(navigationPropertyName, entry);
+    } else {
+      doCallback(readProperties, navigationProperty, callback, isFeed, entry);
+    }
+  }
+
+  /**
+   * Updates the expand select tree ({@link #expandSelectTree}) for this {@link ReadEntryResult} ({@link #readEntryResult}).
+   * 
+   * @param navigationPropertyName
+   * @param inlineEntries
+   * @throws EntityProviderException 
+   */
+  private void updateExpandSelectTree(final String navigationPropertyName, final List<ODataEntry> inlineEntries) throws EntityProviderException {
+    expandSelectTree.setExpanded();
+    ExpandSelectTreeNodeImpl subNode = getExpandSelectTreeNode(inlineEntries);
+    expandSelectTree.putLink(navigationPropertyName, subNode);
+  }
+
+  /**
+   * Get the {@link ExpandSelectTreeNodeImpl} from the <code>inlineEntries</code> or if none exists create a new
+   * {@link ExpandSelectTreeNodeImpl}.
+   * 
+   * @param inlineEntries entries which are checked for existing {@link ExpandSelectTreeNodeImpl}
+   * @return {@link ExpandSelectTreeNodeImpl} from the <code>inlineEntries</code> or if none exists create a new {@link ExpandSelectTreeNodeImpl}.
+   * @throws EntityProviderException if an unsupported {@link ExpandSelectTreeNode} implementation was found.
+   */
+  private ExpandSelectTreeNodeImpl getExpandSelectTreeNode(final List<ODataEntry> inlineEntries) throws EntityProviderException {
+    if (inlineEntries.isEmpty()) {
+      return new ExpandSelectTreeNodeImpl();
+    } else {
+      ExpandSelectTreeNode inlinedEntryEstNode = inlineEntries.get(0).getExpandSelectTree();
+      if (inlinedEntryEstNode instanceof ExpandSelectTreeNodeImpl) {
+        return (ExpandSelectTreeNodeImpl) inlinedEntryEstNode;
+      } else {
+        throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+            .addContent("Unsupported implementation for " + ExpandSelectTreeNode.class + " found."));
+      }
+    }
+  }
+
+  /**
+   * Get a list of {@link ODataEntry}, an empty list, a single {@link ODataEntry} or <code>NULL</code> based on 
+   * <code>isFeed</code> value and <code>inlineEntries</code> content.
+   * 
+   * @param isFeed
+   * @param inlineEntries
+   * @return
+   */
+  private Object extractODataEntity(final boolean isFeed, final List<ODataEntry> inlineEntries) {
+    if (isFeed) {
+      //TODO: fill metadata correctly with inline count and inline next link. Both are currently ignored.
+      return new ODataFeedImpl(inlineEntries, new FeedMetadataImpl());
+    } else if (!inlineEntries.isEmpty()) {
+      return inlineEntries.get(0);
+    }
+    return null;
+  }
+
+  /**
+   * Do the callback based on given parameters.
+   * 
+   * @param readProperties
+   * @param navigationProperty
+   * @param callback
+   * @param isFeed
+   * @param entry
+   * @throws EntityProviderException
+   */
+  private void doCallback(final EntityProviderReadProperties readProperties, final EdmNavigationProperty navigationProperty,
+      final OnReadInlineContent callback, final boolean isFeed, final Object content) throws EntityProviderException {
+
+    try {
+      if (isFeed) {
+        ReadFeedResult callbackInfo = new ReadFeedResult(readProperties, navigationProperty, (ODataFeed) content);
+        callback.handleReadFeed(callbackInfo);
+      } else {
+        ReadEntryResult callbackInfo = new ReadEntryResult(readProperties, navigationProperty, (ODataEntry) content);
+        callback.handleReadEntry(callbackInfo);
+      }
+    } catch (ODataApplicationException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  /**
+   * Create {@link EntityProviderReadProperties} which can be used for reading of inline properties/entrys of navigation links within
+   * this current read entry.
+   * 
+   * @param readProperties
+   * @param navigationProperty
+   * @return
+   * @throws EntityProviderException 
+   */
+  private EntityProviderReadProperties createInlineProperties(final EntityProviderReadProperties readProperties, final EdmNavigationProperty navigationProperty) throws EntityProviderException {
+    final OnReadInlineContent callback = readProperties.getCallback();
+
+    EntityProviderReadProperties currentReadProperties = EntityProviderReadProperties.initFrom(readProperties).addValidatedPrefixes(foundPrefix2NamespaceUri).build();
+    if (callback == null) {
+      return currentReadProperties;
+    } else {
+      try {
+        return callback.receiveReadProperties(currentReadProperties, navigationProperty);
+      } catch (ODataApplicationException e) {
+        throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      }
+    }
+  }
+
+  /**
+   * <p>
+   * Inline content was found and {@link XMLStreamReader} already points to <code><m:inline> tag</code>.
+   * <br/>
+   * <b>ATTENTION</b>: If {@link XMLStreamReader} does not point to the <code><m:inline> tag</code> an exception is thrown.
+   * </p>
+   * <p>
+   * Check whether it is an inline <code>Feed</code> or <code>Entry</code> and validate that...
+   * <ul>
+   * <li>...{@link FormatXml#M_INLINE} tag is correctly set.</li>
+   * <li>...based on {@link EdmMultiplicity} of {@link EdmNavigationProperty} all tags are correctly set.</li>
+   * <li>...{@link FormatXml#ATOM_TYPE} tag is correctly set and according to {@link FormatXml#ATOM_ENTRY} or {@link FormatXml#ATOM_FEED} to following tags are available.</li>
+   * </ul>
+   * 
+   * For the case that one of above validations fail an {@link EntityProviderException} is thrown.
+   * If validation was successful <code>true</code> is returned for <code>Feed</code> and <code>false</code> for <code>Entry</code>
+   * multiplicity.
+   * </p>
+   * 
+   * @param reader xml content reader which already points to <code><m:inline> tag</code>
+   * @param eia all necessary information about the entity 
+   * @param type the atom type attribute value of the <code>link</code> tag
+   * @param navigationPropertyName the navigation property name of the entity
+   * @return <code>true</code> for <code>Feed</code> and <code>false</code> for <code>Entry</code>
+   * @throws EntityProviderException is thrown if at least one validation fails.
+   * @throws EdmException if edm access fails
+   */
+  private boolean isInlineFeedValidated(final XMLStreamReader reader, final EntityInfoAggregator eia, final String type, final String navigationPropertyName) throws EntityProviderException, EdmException {
+    boolean isFeed = false;
+    try {
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      //
+      ContentType cType = ContentType.parse(type);
+      if (cType == null) {
+        throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"));
+      }
+
+      EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+      EdmMultiplicity navigationMultiplicity = navigationProperty.getMultiplicity();
+
+      switch (navigationMultiplicity) {
+      case MANY:
+        validateFeedTags(reader, cType);
+        isFeed = true;
+        break;
+      case ONE:
+      case ZERO_TO_ONE:
+        validateEntryTags(reader, cType);
+        break;
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("xml data"), e);
+    }
+    return isFeed;
+  }
+
+  private void validateEntryTags(final XMLStreamReader reader, final ContentType cType) throws XMLStreamException, EntityProviderException {
+    if (FormatXml.ATOM_ENTRY.equals(cType.getParameters().get(FormatXml.ATOM_TYPE))) {
+      int next = reader.nextTag();
+      if (XMLStreamConstants.START_ELEMENT == next) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ENTRY);
+      } else {
+        reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("entry"));
+    }
+  }
+
+  private void validateFeedTags(final XMLStreamReader reader, final ContentType cType) throws XMLStreamException, EntityProviderException {
+    if (FormatXml.ATOM_FEED.equals(cType.getParameters().get(FormatXml.ATOM_TYPE))) {
+      int next = reader.nextTag();
+      if (XMLStreamConstants.START_ELEMENT == next) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_FEED);
+      } else {
+        reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_INLINE_CONTENT.addContent("feed"));
+    }
+  }
+
+  private void readContent(final XMLStreamReader reader, final EntityInfoAggregator eia) throws EntityProviderException, XMLStreamException, EdmException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CONTENT);
+
+    extractNamespacesFromTag(reader);
+
+    checkAllMandatoryNamespacesAvailable();
+
+    final String contentType = reader.getAttributeValue(null, FormatXml.ATOM_TYPE);
+    final String sourceLink = reader.getAttributeValue(null, FormatXml.ATOM_SRC);
+
+    reader.nextTag();
+
+    if (reader.isStartElement() && reader.getLocalName().equals(FormatXml.M_PROPERTIES)) {
+      readProperties(reader, eia);
+    } else if (reader.isEndElement()) {
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CONTENT);
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE
+          .addContent("Expected closing 'content' or starting 'properties' but found '" + reader.getLocalName() + "'."));
+    }
+
+    mediaMetadata.setContentType(contentType);
+    mediaMetadata.setSourceLink(sourceLink);
+  }
+
+  private void readId(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ID);
+    reader.next();
+    if (reader.isCharacters()) {
+      entryMetadata.setId(reader.getText());
+    }
+    reader.nextTag();
+    reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_ID);
+  }
+
+  private void readProperties(final XMLStreamReader reader, final EntityInfoAggregator entitySet) throws XMLStreamException, EdmException, EntityProviderException {
+    // validate namespace
+    checkAllMandatoryNamespacesAvailable();
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES);
+    if (entitySet.getEntityType().hasStream()) {
+      // external properties
+      checkCurrentHandledStartTag(FormatXml.M_PROPERTIES);
+    } else {
+      // inline properties
+      checkCurrentHandledStartTag(FormatXml.ATOM_CONTENT);
+    }
+
+    EntityPropertyInfo property;
+    XmlPropertyConsumer xpc = new XmlPropertyConsumer();
+
+    String closeTag = null;
+    boolean run = true;
+    reader.next();
+
+    while (run) {
+      if (reader.isStartElement() && closeTag == null) {
+        closeTag = reader.getLocalName();
+        if (isEdmNamespaceProperty(reader)) {
+          if (properties.containsKey(closeTag)) {
+            throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(closeTag));
+          }
+          property = getValidatedPropertyInfo(entitySet, closeTag);
+          final Object value = xpc.readStartedElement(reader, property, typeMappings);
+          properties.put(closeTag, value);
+          closeTag = null;
+        }
+      } else if (reader.isEndElement()) {
+        if (reader.getLocalName().equals(closeTag)) {
+          closeTag = null;
+        } else if (Edm.NAMESPACE_M_2007_08.equals(reader.getNamespaceURI()) && FormatXml.M_PROPERTIES.equals(reader.getLocalName())) {
+          run = false;
+        }
+      }
+      reader.next();
+    }
+  }
+
+  /**
+   * Check if the {@link #currentHandledStartTagName} is the same as the <code>expectedTagName</code>.
+   * If tag name is not as expected or if {@link #currentHandledStartTagName} is not set an {@link EntityProviderException} is thrown.
+   * 
+   * @param expectedTagName expected name for {@link #currentHandledStartTagName}
+   * @throws EntityProviderException if tag name is not as expected or if {@link #currentHandledStartTagName} is <code>NULL</code>.
+   */
+  private void checkCurrentHandledStartTag(final String expectedTagName) throws EntityProviderException {
+    if (currentHandledStartTagName == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("No current handled start tag name set."));
+    } else if (!currentHandledStartTagName.equals(expectedTagName)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_PARENT_TAG.addContent(expectedTagName).addContent(currentHandledStartTagName));
+    }
+  }
+
+  /**
+   * Checks if property of currently read tag in {@link XMLStreamReader} is defined in 
+   * <code>edm properties namespace</code> {@value Edm#NAMESPACE_D_2007_08}.
+   * 
+   * If no namespace uri definition is found for namespace prefix of property (<code>tag</code>) an exception is thrown.
+   * 
+   * @param reader {@link XMLStreamReader} with position at to checked tag
+   * @return <code>true</code> if property is in <code>edm properties namespace</code>, otherwise <code>false</code>.
+   * @throws EntityProviderException If no namespace uri definition is found for namespace prefix of property (<code>tag</code>).
+   */
+  private boolean isEdmNamespaceProperty(final XMLStreamReader reader) throws EntityProviderException {
+    final String nsUri = reader.getNamespaceURI();
+    if (nsUri == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(reader.getLocalName()));
+    } else {
+      return Edm.NAMESPACE_D_2007_08.equals(nsUri);
+    }
+  }
+
+  /**
+   * Get validated {@link EntityPropertyInfo} for property with given <code>name</code>.
+   * If validation fails an {@link EntityProviderException} is thrown.
+   * 
+   * Currently this is the case if no {@link EntityPropertyInfo} if found for given <code>name</code>.
+   * 
+   * @param entitySet
+   * @param name
+   * @return valid {@link EntityPropertyInfo} (which is never <code>NULL</code>).
+   * @throws EntityProviderException
+   */
+  private EntityPropertyInfo getValidatedPropertyInfo(final EntityInfoAggregator entitySet, final String name) throws EntityProviderException {
+    EntityPropertyInfo info = entitySet.getPropertyInfo(name);
+    if (info == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(name));
+    }
+    return info;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlFeedConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlFeedConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlFeedConsumer.java
new file mode 100644
index 0000000..b15c1f0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlFeedConsumer.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+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.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Atom/XML format reader/consumer for feeds.
+ * 
+ * {@link XmlFeedConsumer} instance use {@link XmlEntryConsumer#readEntry(XMLStreamReader, EntityInfoAggregator, EntityProviderReadProperties)} 
+ * for read/consume of several entries.
+ * 
+ * @author SAP AG
+ */
+public class XmlFeedConsumer {
+
+  /**
+   * 
+   * @param reader
+   * @param eia
+   * @param readProperties
+   * @return {@link ODataFeed} object
+   * @throws EntityProviderException
+   */
+  public ODataFeed readFeed(final XMLStreamReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    try {
+      // read xml tag
+      reader.require(XMLStreamConstants.START_DOCUMENT, null, null);
+      reader.nextTag();
+
+      // read feed tag
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_FEED);
+      Map<String, String> foundPrefix2NamespaceUri = extractNamespacesFromTag(reader);
+      foundPrefix2NamespaceUri.putAll(readProperties.getValidatedPrefixNamespaceUris());
+      checkAllMandatoryNamespacesAvailable(foundPrefix2NamespaceUri);
+      EntityProviderReadProperties entryReadProperties =
+          EntityProviderReadProperties.initFrom(readProperties).addValidatedPrefixes(foundPrefix2NamespaceUri).build();
+
+      // read feed data (metadata and entries)
+      return readFeedData(reader, eia, entryReadProperties);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  /**
+   * Read all feed specific data (like <code>inline count</code> and <code>next link</code>) as well as all feed entries (<code>entry</code>).
+   * 
+   * @param reader
+   * @param eia
+   * @param entryReadProperties
+   * @return
+   * @throws XMLStreamException
+   * @throws EntityProviderException
+   */
+  private ODataFeed readFeedData(final XMLStreamReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties entryReadProperties) throws XMLStreamException, EntityProviderException {
+    FeedMetadataImpl metadata = new FeedMetadataImpl();
+    XmlEntryConsumer xec = new XmlEntryConsumer();
+    List<ODataEntry> results = new ArrayList<ODataEntry>();
+
+    while (reader.hasNext() && !isFeedEndTag(reader)) {
+      if (FormatXml.ATOM_ENTRY.equals(reader.getLocalName())) {
+        ODataEntry entry = xec.readEntry(reader, eia, entryReadProperties);
+        results.add(entry);
+      } else if (FormatXml.M_COUNT.equals(reader.getLocalName())) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_M_2007_08, FormatXml.M_COUNT);
+
+        reader.next();
+        if (reader.hasText()) {
+          String inlineCountString = reader.getText();
+          try {
+            int inlineCountNumber = Integer.valueOf(inlineCountString);
+            if (inlineCountNumber >= 0) {
+              metadata.setInlineCount(inlineCountNumber);
+            } else {
+              throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(inlineCountNumber));
+            }
+          } catch (NumberFormatException e) {
+            throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(""), e);
+          }
+        }
+      } else if (FormatXml.ATOM_LINK.equals(reader.getLocalName())) {
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_LINK);
+
+        final String rel = reader.getAttributeValue(null, FormatXml.ATOM_REL);
+        if (FormatXml.ATOM_NEXT_LINK.equals(rel)) {
+          final String uri = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+          metadata.setNextLink(uri);
+        } else if (FormatXml.ATOM_DELTA_LINK.equals(rel)) {
+          final String uri = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+          metadata.setDeltaLink(uri);
+        }
+
+        reader.next();
+      } else {
+        reader.next();
+      }
+      readTillNextStartTag(reader);
+    }
+    return new ODataFeedImpl(results, metadata);
+  }
+
+  private void readTillNextStartTag(final XMLStreamReader reader) throws XMLStreamException {
+    while (reader.hasNext() && !reader.isStartElement()) {
+      reader.next();
+    }
+  }
+
+  private boolean isFeedEndTag(final XMLStreamReader reader) {
+    return reader.isEndElement()
+        && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())
+        && FormatXml.ATOM_FEED.equals(reader.getLocalName());
+  }
+
+  /**
+   * 
+   * @param reader
+   * @return 
+   * @throws EntityProviderException
+   */
+  private Map<String, String> extractNamespacesFromTag(final XMLStreamReader reader) throws EntityProviderException {
+    // collect namespaces
+    Map<String, String> foundPrefix2NamespaceUri = new HashMap<String, String>();
+    int namespaceCount = reader.getNamespaceCount();
+    for (int i = 0; i < namespaceCount; i++) {
+      String namespacePrefix = reader.getNamespacePrefix(i);
+      String namespaceUri = reader.getNamespaceURI(i);
+
+      foundPrefix2NamespaceUri.put(namespacePrefix, namespaceUri);
+    }
+    return foundPrefix2NamespaceUri;
+  }
+
+  /**
+   * 
+   * @param foundPrefix2NamespaceUri 
+   * @throws EntityProviderException
+   */
+  private void checkAllMandatoryNamespacesAvailable(final Map<String, String> foundPrefix2NamespaceUri) throws EntityProviderException {
+    if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_D_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_D_2007_08));
+    } else if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_M_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_M_2007_08));
+    } else if (!foundPrefix2NamespaceUri.containsValue(Edm.NAMESPACE_ATOM_2005)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_ATOM_2005));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlLinkConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlLinkConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlLinkConsumer.java
new file mode 100644
index 0000000..d419c5b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlLinkConsumer.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * @author SAP AG
+ */
+public class XmlLinkConsumer {
+
+  /**
+   * Reads single link with format {@code <uri>http://somelink</uri>}.
+   * @param reader
+   * @param entitySet
+   * @return link as string object
+   * @throws EntityProviderException
+   */
+  public String readLink(final XMLStreamReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+    try {
+      reader.next();
+      return readLink(reader);
+    } catch (final XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private String readLink(final XMLStreamReader reader) throws XMLStreamException {
+    return readTag(reader, Edm.NAMESPACE_D_2007_08, FormatXml.D_URI);
+  }
+
+  private String readTag(final XMLStreamReader reader, final String namespaceURI, final String localName) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, namespaceURI, localName);
+
+    reader.next();
+    reader.require(XMLStreamConstants.CHARACTERS, null, null);
+    final String result = reader.getText();
+
+    reader.nextTag();
+    reader.require(XMLStreamConstants.END_ELEMENT, namespaceURI, localName);
+
+    return result;
+  }
+
+  /**
+   * Reads multiple links with format 
+   * <pre>
+   * {@code
+   * <links>
+   *  <uri>http://somelink</uri>
+   *  <uri>http://anotherLink</uri>
+   *  <uri>http://somelink/yetAnotherLink</uri>
+   * </links>
+   * }
+   * </pre>
+   * @param reader
+   * @param entitySet
+   * @return list of string based links
+   * @throws EntityProviderException
+   */
+  public List<String> readLinks(final XMLStreamReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+    try {
+      List<String> links = new ArrayList<String>();
+
+      reader.next();
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_D_2007_08, FormatXml.D_LINKS);
+
+      reader.nextTag();
+      while (!reader.isEndElement()) {
+        if (reader.getLocalName().equals(FormatXml.M_COUNT)) {
+          readTag(reader, Edm.NAMESPACE_M_2007_08, FormatXml.M_COUNT);
+        } else {
+          final String link = readLink(reader);
+          links.add(link);
+        }
+        reader.nextTag();
+      }
+
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_D_2007_08, FormatXml.D_LINKS);
+
+      return links;
+    } catch (final XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlPropertyConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlPropertyConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlPropertyConsumer.java
new file mode 100644
index 0000000..d44c6c5
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/XmlPropertyConsumer.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+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.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityTypeMapping;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * @author SAP AG
+ */
+public class XmlPropertyConsumer {
+
+  public static final String TRUE = "true";
+
+  public Map<String, Object> readProperty(final XMLStreamReader reader, final EdmProperty property, final boolean merge) throws EntityProviderException {
+    return readProperty(reader, property, merge, null);
+  }
+
+  public Map<String, Object> readProperty(final XMLStreamReader reader, final EdmProperty property, final boolean merge, final Map<String, Object> typeMappings) throws EntityProviderException {
+    EntityPropertyInfo eia = EntityInfoAggregator.create(property);
+
+    try {
+      reader.next();
+
+      Object value = readStartedElement(reader, eia, EntityTypeMapping.create(typeMappings));
+
+      if (eia.isComplex() && merge) {
+        mergeWithDefaultValues(value, eia);
+      }
+
+      Map<String, Object> result = new HashMap<String, Object>();
+      result.put(eia.getName(), value);
+      return result;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private void mergeWithDefaultValues(final Object value, final EntityPropertyInfo epi) throws EntityProviderException {
+    if (!(value instanceof Map)) {
+      throw new EntityProviderException(EntityProviderException.COMMON);
+    }
+    if (!epi.isComplex()) {
+      throw new EntityProviderException(EntityProviderException.COMMON);
+    }
+
+    mergeComplexWithDefaultValues((Map<String, Object>) value, (EntityComplexPropertyInfo) epi);
+  }
+
+  private void mergeComplexWithDefaultValues(final Map<String, Object> complexValue, final EntityComplexPropertyInfo ecpi) {
+    for (EntityPropertyInfo info : ecpi.getPropertyInfos()) {
+      Object obj = complexValue.get(info.getName());
+      if (obj == null) {
+        if (info.isComplex()) {
+          Map<String, Object> defaultValue = new HashMap<String, Object>();
+          mergeComplexWithDefaultValues(defaultValue, ecpi);
+          complexValue.put(info.getName(), defaultValue);
+        } else {
+          EdmFacets facets = info.getFacets();
+          if (facets != null) {
+            complexValue.put(info.getName(), facets.getDefaultValue());
+          }
+        }
+      }
+    }
+  }
+
+  protected Object readStartedElement(final XMLStreamReader reader, final EntityPropertyInfo propertyInfo, final EntityTypeMapping typeMappings) throws EntityProviderException, EdmException {
+    Map<String, Object> name2Value = new HashMap<String, Object>();
+    Object result = null;
+
+    try {
+      reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_D_2007_08, propertyInfo.getName());
+      final String nullAttribute = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_NULL);
+
+      if (TRUE.equals(nullAttribute)) {
+        reader.nextTag();
+      } else if (propertyInfo.isComplex()) {
+        final String typeAttribute = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, FormatXml.M_TYPE);
+        String expectedTypeAttributeValue = propertyInfo.getType().getNamespace() + Edm.DELIMITER + propertyInfo.getType().getName();
+        if (typeAttribute != null && !expectedTypeAttributeValue.equals(typeAttribute)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_COMPLEX_TYPE.addContent(expectedTypeAttributeValue).addContent(typeAttribute));
+        }
+
+        reader.nextTag();
+        while (reader.hasNext() && !reader.isEndElement()) {
+          String childName = reader.getLocalName();
+          EntityPropertyInfo childProperty = getChildProperty(childName, propertyInfo);
+          if (childProperty == null) {
+            throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(childName));
+          }
+          Object value = readStartedElement(reader, childProperty, typeMappings.getEntityTypeMapping(propertyInfo.getName()));
+          name2Value.put(childName, value);
+          reader.nextTag();
+        }
+      } else {
+        Class<?> mapping = typeMappings.getMappingClass(propertyInfo.getName());
+        result = convert(propertyInfo, reader.getElementText(), mapping);
+      }
+      reader.require(XMLStreamConstants.END_ELEMENT, Edm.NAMESPACE_D_2007_08, propertyInfo.getName());
+
+      // if reading finished check which result must be returned
+      if (result != null) {
+        return result;
+      } else if (!name2Value.isEmpty()) {
+        return name2Value;
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return null;
+  }
+
+  private EntityPropertyInfo getChildProperty(final String childPropertyName, final EntityPropertyInfo property) throws EdmException, EntityProviderException {
+    if (property.isComplex()) {
+      EntityComplexPropertyInfo complex = (EntityComplexPropertyInfo) property;
+      return complex.getPropertyInfo(childPropertyName);
+    }
+    throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(
+        "Expected complex property but found simple for property with name '" + property.getName() + "'"));
+  }
+
+  private Object convert(final EntityPropertyInfo property, final String value, final Class<?> typeMapping) throws EdmException, EntityProviderException {
+    if (!property.isComplex()) {
+      EdmSimpleType type = (EdmSimpleType) property.getType();
+      return type.valueOfString(value, EdmLiteralKind.DEFAULT, property.getFacets(),
+          typeMapping == null ? type.getDefaultType() : typeMapping);
+    }
+    throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(
+        "Expected simple property but found complex for property with name '" + property.getName() + "'"));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/EntryMetadataImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/EntryMetadataImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/EntryMetadataImpl.java
new file mode 100644
index 0000000..a4b1fbd
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/EntryMetadataImpl.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.ep.entry;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.entry.EntryMetadata;
+
+/**
+ * @author SAP AG
+ */
+public class EntryMetadataImpl implements EntryMetadata {
+  private String id;
+  private String etag;
+  private String uri;
+  private Map<String, List<String>> associationUris = new HashMap<String, List<String>>();
+
+  @Override
+  public String getId() {
+    return id;
+  }
+
+  public void setId(final String id) {
+    this.id = id;
+  }
+
+  @Override
+  public String getEtag() {
+    return etag;
+  }
+
+  public void setEtag(final String etag) {
+    this.etag = etag;
+  }
+
+  @Override
+  public String getUri() {
+    return uri;
+  }
+
+  public void setUri(final String uri) {
+    this.uri = uri;
+  }
+
+  @Override
+  public List<String> getAssociationUris(final String navigationPropertyName) {
+    final List<String> uris = associationUris.get(navigationPropertyName);
+    if (uris == null) {
+      return Collections.emptyList();
+    } else {
+      return Collections.unmodifiableList(uris);
+    }
+  }
+
+  public void putAssociationUri(final String navigationPropertyName, final String uri) {
+    List<String> uris = associationUris.get(navigationPropertyName);
+    if (uris == null) {
+      uris = new ArrayList<String>();
+    }
+    uris.add(uri);
+    associationUris.put(navigationPropertyName, uris);
+  }
+
+  @Override
+  public String toString() {
+    return "EntryMetadataImpl [id=" + id + ", etag=" + etag + ", uri=" + uri + ", associationUris=" + associationUris + "]";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/MediaMetadataImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/MediaMetadataImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/MediaMetadataImpl.java
new file mode 100644
index 0000000..2d8d436
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/MediaMetadataImpl.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.ep.entry;
+
+import org.apache.olingo.odata2.api.ep.entry.MediaMetadata;
+
+/**
+ * @author SAP AG
+ */
+public class MediaMetadataImpl implements MediaMetadata {
+
+  private String sourceLink;
+  private String etag;
+  private String contentType;
+  private String editLink;
+
+  @Override
+  public String getSourceLink() {
+    return sourceLink;
+  }
+
+  @Override
+  public String getEtag() {
+    return etag;
+  }
+
+  @Override
+  public String getContentType() {
+    return contentType;
+  }
+
+  @Override
+  public String getEditLink() {
+    return editLink;
+  }
+
+  public void setSourceLink(final String sourceLink) {
+    this.sourceLink = sourceLink;
+  }
+
+  public void setEtag(final String etag) {
+    this.etag = etag;
+  }
+
+  public void setContentType(final String contentType) {
+    this.contentType = contentType;
+  }
+
+  public void setEditLink(final String editLink) {
+    this.editLink = editLink;
+  }
+
+  @Override
+  public String toString() {
+    return "MediaMetadataImpl [sourceLink=" + sourceLink + ", etag=" + etag + ", contentType=" + contentType + ", editLink=" + editLink + "]";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/ODataEntryImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/ODataEntryImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/ODataEntryImpl.java
new file mode 100644
index 0000000..2a94a68
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/entry/ODataEntryImpl.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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.ep.entry;
+
+import java.util.Map;
+
+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.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class ODataEntryImpl implements ODataEntry {
+
+  private final Map<String, Object> data;
+  private final EntryMetadata entryMetadata;
+  private final MediaMetadata mediaMetadata;
+  private final ExpandSelectTreeNode expandSelectTree;
+  private boolean containsInlineEntry;
+
+  public ODataEntryImpl(final Map<String, Object> data, final MediaMetadata mediaMetadata, final EntryMetadata entryMetadata, final ExpandSelectTreeNodeImpl expandSelectTree) {
+    this(data, mediaMetadata, entryMetadata, expandSelectTree, false);
+  }
+
+  public ODataEntryImpl(final Map<String, Object> data, final MediaMetadata mediaMetadata, final EntryMetadata entryMetadata, final ExpandSelectTreeNode expandSelectTree, final boolean containsInlineEntry) {
+    this.data = data;
+    this.entryMetadata = entryMetadata;
+    this.mediaMetadata = mediaMetadata;
+    this.expandSelectTree = expandSelectTree;
+    this.containsInlineEntry = containsInlineEntry;
+  }
+
+  @Override
+  public Map<String, Object> getProperties() {
+    return data;
+  }
+
+  @Override
+  public MediaMetadata getMediaMetadata() {
+    return mediaMetadata;
+  }
+
+  @Override
+  public EntryMetadata getMetadata() {
+    return entryMetadata;
+  }
+
+  @Override
+  public boolean containsInlineEntry() {
+    return containsInlineEntry;
+  }
+
+  @Override
+  public ExpandSelectTreeNode getExpandSelectTree() {
+    return expandSelectTree;
+  }
+
+  public void setContainsInlineEntry(final boolean containsInlineEntry) {
+    this.containsInlineEntry = containsInlineEntry;
+  }
+
+  @Override
+  public String toString() {
+    return "ODataEntryImpl [data=" + data + ", "
+        + "entryMetadata=" + entryMetadata + ", "
+        + "mediaMetadata=" + mediaMetadata + ", "
+        + "expandSelectTree=" + expandSelectTree + ", "
+        + "containsInlineEntry=" + containsInlineEntry + "]";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/FeedMetadataImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/FeedMetadataImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/FeedMetadataImpl.java
new file mode 100644
index 0000000..3f18298
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/FeedMetadataImpl.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.ep.feed;
+
+import org.apache.olingo.odata2.api.ep.feed.FeedMetadata;
+
+public class FeedMetadataImpl implements FeedMetadata {
+
+  private Integer inlineCount = null;
+  private String nextLink = null;
+  private String deltaLink;
+
+  public void setInlineCount(final int inlineCount) {
+    this.inlineCount = inlineCount;
+  }
+
+  @Override
+  public Integer getInlineCount() {
+    return inlineCount;
+  }
+
+  public void setNextLink(final String nextLink) {
+    this.nextLink = nextLink;
+  }
+
+  @Override
+  public String getNextLink() {
+    return nextLink;
+  }
+
+  public void setDeltaLink(final String deltaLink) {
+    this.deltaLink = deltaLink;
+  }
+
+  @Override
+  public String getDeltaLink() {
+    return deltaLink;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/ODataFeedImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/ODataFeedImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/ODataFeedImpl.java
new file mode 100644
index 0000000..9dd0328
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/feed/ODataFeedImpl.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.ep.feed;
+
+import java.util.List;
+
+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;
+
+public class ODataFeedImpl implements ODataFeed {
+
+  private final List<ODataEntry> entries;
+  private final FeedMetadata feedMetadata;
+
+  public ODataFeedImpl(final List<ODataEntry> entries, final FeedMetadata feedMetadata) {
+    this.entries = entries;
+    this.feedMetadata = feedMetadata;
+
+  }
+
+  @Override
+  public List<ODataEntry> getEntries() {
+    return entries;
+  }
+
+  @Override
+  public FeedMetadata getFeedMetadata() {
+    return feedMetadata;
+  }
+
+}


[27/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/AtomInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/AtomInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/AtomInfo.java
new file mode 100644
index 0000000..86f2cff
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/AtomInfo.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+/**
+ * A AtomInfo
+ * <p>AtomInfo represents the structure of Service Document according RFC 5023 (for ATOM format) 
+ * @author SAP AG
+ */
+public interface AtomInfo {
+
+  /**
+   * Get the list of workspaces
+   * 
+   * @return a list of {@link Workspace}
+   */
+  public List<Workspace> getWorkspaces();
+
+  /**
+   * Get common attributes
+   * 
+   * @return {@link CommonAttributes}
+   */
+  public CommonAttributes getCommonAttributes();
+
+  /**
+   * Get the list of extension elements
+   * 
+   * @return a list of {@link ExtensionElement}
+   */
+  public List<ExtensionElement> getExtesionElements();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Categories.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Categories.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Categories.java
new file mode 100644
index 0000000..5923636
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Categories.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+/**
+ * A Categories element
+ * <p>Categories element provides a list of the categories that can be applied to the members of a Collection
+ * <p>If the "href" attribute is provided, the Categories element MUST be empty and MUST NOT have the "fixed" or "scheme" attributes
+ * @author SAP AG
+ */
+
+public interface Categories {
+
+  /**
+   * Get the IRI reference identifying a Category Document
+   * 
+   * @return href as String
+   */
+  public String getHref();
+
+  /**
+   * Get the attribute fixed that indicates whether the list of categories is a fixed or an open set
+   * 
+   * @return {@link Fixed}
+   */
+  public Fixed getFixed();
+
+  /**
+   * Get the scheme
+   * 
+   * @return scheme as String
+   */
+  public String getScheme();
+
+  /**
+   * Get the list of categories
+   * 
+   * @return list of {@link Category}
+   */
+  public List<Category> getCategoryList();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Category.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Category.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Category.java
new file mode 100644
index 0000000..a4d3553
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Category.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+/**
+ * A Category element
+ * <p>Category element 
+ * @author SAP AG
+ */
+public interface Category {
+  /**
+   * Get the scheme
+   * 
+   * @return scheme as String
+   */
+  public String getScheme();
+
+  /**
+   * Get the term
+   * 
+   * @return term as String
+   */
+  public String getTerm();
+
+  /**
+   * Get common attributes
+   * 
+   * @return {@link CommonAttributes}
+   */
+  public CommonAttributes getCommonAttributes();
+
+  /**
+   * Get the label
+   * 
+   * @return label as String
+   */
+  public String getLabel();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Collection.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Collection.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Collection.java
new file mode 100644
index 0000000..60f48e1
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Collection.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+/**
+ * A Collection
+ * <p>Collection element describes a Collection
+ * @author SAP AG
+ */
+public interface Collection {
+  /**
+   * Get the human-readable title for the Collection
+   * 
+   * @return {@link Title}
+   */
+  public Title getTitle();
+
+  /**
+   * Get the "href" attribute, whose value gives IRI of the Collection
+   * 
+   * @return href as String
+   */
+  public String getHref();
+
+  /**
+   * Get common attributes
+   * 
+   * @return {@link CommonAttributes}
+   */
+  public CommonAttributes getCommonAttributes();
+
+  /**
+   * Get the media range that specifies a type of representation 
+   * that can be POSTed to a Collection
+   * @return a list of {@link Accept}
+   */
+  public List<Accept> getAcceptElements();
+
+  /**
+   *
+   * 
+   * @return a list of {@link Categories}
+   */
+  public List<Categories> getCategories();
+
+  /**
+   * Get the list of extension elements
+   * 
+   * @return a list of {@link ExtensionElement}
+   */
+  public List<ExtensionElement> getExtesionElements();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/CommonAttributes.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/CommonAttributes.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/CommonAttributes.java
new file mode 100644
index 0000000..bc22f15
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/CommonAttributes.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+/**
+ * A CommonAttributes
+ * @author SAP AG
+ */
+public interface CommonAttributes {
+  /**
+   * Get the a base URI 
+   * 
+   * @return base as String
+   */
+  public String getBase();
+
+  /**
+   * Get the natural language for the element
+   * 
+   * @return language as String
+   */
+  public String getLang();
+
+  /**
+   * Get the list of any attributes
+   * 
+   * @return list of {@link ExtensionAttribute}
+   */
+  public List<ExtensionAttribute> getAttributes();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionAttribute.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionAttribute.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionAttribute.java
new file mode 100644
index 0000000..c946f00
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionAttribute.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+/**
+ * A ExtensionAttribute
+ * <p>ExtensionAttribute is an attribute of an extension element
+ * @author SAP AG
+ */
+public interface ExtensionAttribute {
+  /**
+   * Get the namespace 
+   * 
+   * @return namespace as String
+   */
+  public String getNamespace();
+
+  /**
+   * Get the prefix of the attribute
+   * 
+   * @return prefix as String
+   */
+  public String getPrefix();
+
+  /**
+   * Get the local name of the attribute
+   * 
+   * @return name as String
+   */
+  public String getName();
+
+  /**
+   * Get the text
+   * 
+   * @return text as String
+   */
+  public String getText();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionElement.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionElement.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionElement.java
new file mode 100644
index 0000000..1797f79
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ExtensionElement.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+/**
+ * A ExtensionElement
+ * <p>ExtensionElement is an element that is defined in any namespace except 
+ * the namespace "app"
+ * @author SAP AG
+ */
+public interface ExtensionElement {
+  /**
+   * Get the namespace 
+   * 
+   * @return namespace as String
+   */
+  public String getNamespace();
+
+  /**
+   * Get the prefix of the element
+   * 
+   * @return prefix as String
+   */
+  public String getPrefix();
+
+  /**
+   * Get the local name of the element
+   * 
+   * @return name as String
+   */
+  public String getName();
+
+  /**
+   * Get the text
+   * 
+   * @return text as String
+   */
+  public String getText();
+
+  /**
+   * Get nested elements
+   * 
+   * @return a list of {@link ExtensionElement}
+   */
+  public List<ExtensionElement> getElements();
+
+  /**
+   * Get attributes
+   * 
+   * @return a list of {@link ExtensionAttribute}
+   */
+  public List<ExtensionAttribute> getAttributes();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Fixed.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Fixed.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Fixed.java
new file mode 100644
index 0000000..5b28ee5
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Fixed.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+/**
+* Fixed
+* <p>Fixed indicates whether the list of categories is a fixed or an open set
+* Fixed can either be yes or no
+* @author SAP AG
+*/
+public enum Fixed {
+  YES, NO;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocument.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocument.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocument.java
new file mode 100644
index 0000000..b978820
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocument.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+
+/**
+ * A Service document
+ * <p>Service document lists all EntitySets
+ * @author SAP AG
+ */
+public interface ServiceDocument {
+  /**
+   * Get the list of the EntitySets
+   * 
+   * @return a list of {@link EdmEntitySetInfo}
+   */
+  public List<EdmEntitySetInfo> getEntitySetsInfo() throws EntityProviderException;
+
+  /**
+   * Get additional information if the service document is in atom format 
+   * 
+   * @return {@link AtomInfo} or null
+   */
+  public AtomInfo getAtomInfo();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParser.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParser.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParser.java
new file mode 100644
index 0000000..3f35736
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParser.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.io.InputStream;
+
+/**
+ * @author SAP AG
+ */
+public interface ServiceDocumentParser {
+  public ServiceDocument parseXml(InputStream in) throws ServiceDocumentParserException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParserException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParserException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParserException.java
new file mode 100644
index 0000000..2c27d3f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/ServiceDocumentParserException.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+/**
+ * @author SAP AG
+ */
+public class ServiceDocumentParserException extends Exception {
+
+  private static final long serialVersionUID = 1L;
+
+  public ServiceDocumentParserException(final String message) {
+    super(message);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Title.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Title.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Title.java
new file mode 100644
index 0000000..05c219c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Title.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+/**
+ * A Title element
+ * <p>Title element gives a human-readable title
+ * @author SAP AG
+ */
+public interface Title {
+  /**
+   * @return text as String
+   */
+  public String getText();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Workspace.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Workspace.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Workspace.java
new file mode 100644
index 0000000..656b34e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Workspace.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+import java.util.List;
+
+/**
+ * A Workspace element
+ * <p>Workspaces are server-defined groups of Collections. 
+ * @author SAP AG
+ */
+public interface Workspace {
+  /**
+   * Get the human-readable title for the Workspace
+   * 
+   * @return {@link Title}
+   */
+  public Title getTitle();
+
+  /**
+   * Get the list of the Collections
+   * 
+   * @return a list of {@link Collection}
+   */
+  public List<Collection> getCollections();
+
+  /**
+   * Get common attributes
+   * 
+   * @return {@link CommonAttributes}
+   */
+  public CommonAttributes getCommonAttributes();
+
+  /**
+   * Get the list of extension elements
+   * 
+   * @return a list of {@link ExtensionElement}
+   */
+  public List<ExtensionElement> getExtesionElements();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/ExpandSelectTreeNode.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/ExpandSelectTreeNode.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/ExpandSelectTreeNode.java
new file mode 100644
index 0000000..7475457
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/ExpandSelectTreeNode.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+
+/**
+ * Expression tree node with information about selected properties and to be expanded links.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface ExpandSelectTreeNode {
+
+  /**
+   * Determines whether all properties (including navigation properties) have been selected.
+   */
+  public boolean isAll();
+
+  /**
+   * <p>Gets the list of explicitly selected {@link EdmProperty properties}.</p>
+   * <p>This list does not contain any navigation properties.
+   * It is empty if {@link #isAll()} returns <code>true</code>.</p>
+   * @return List of selected properties
+   */
+  public List<EdmProperty> getProperties();
+
+  /**
+   * Gets the links that have to be included or expanded.
+   * @return a Map from EdmNavigationProperty Name to its related {@link ExpandSelectTreeNode};
+   *         if that node is <code>null</code>, a deferred link has been requested,
+   *         otherwise the link must be expanded with information found in that node
+   */
+  public Map<String, ExpandSelectTreeNode> getLinks();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/KeyPredicate.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/KeyPredicate.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/KeyPredicate.java
new file mode 100644
index 0000000..6142e67
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/KeyPredicate.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+
+/**
+ * Key predicate, consisting of a simple-type property and its value as String literal
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface KeyPredicate {
+
+  /**
+   * <p>Gets the literal String in default representation.</p>
+   * <p>The description for {@link org.apache.olingo.odata2.api.edm.EdmLiteral} has some motivation for using
+   * this representation.</p> 
+   * @return String literal in default (<em>not</em> URI) representation
+   * @see org.apache.olingo.odata2.api.edm.EdmLiteralKind
+   */
+  public String getLiteral();
+
+  /**
+   * Gets the key property.
+   * @return {@link EdmProperty} simple-type property
+   */
+  public EdmProperty getProperty();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationPropertySegment.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationPropertySegment.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationPropertySegment.java
new file mode 100644
index 0000000..08a528e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationPropertySegment.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+
+/**
+ * Navigation property segment, consisting of a navigation property and its
+ * target entity set.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface NavigationPropertySegment {
+
+  /**
+   * Gets the navigation property.
+   * @return {@link EdmNavigationProperty} navigation property
+   */
+  public EdmNavigationProperty getNavigationProperty();
+
+  /**
+   * Gets the target entity set.
+   * @return {@link EdmEntitySet} the target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationSegment.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationSegment.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationSegment.java
new file mode 100644
index 0000000..daf22c8
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/NavigationSegment.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+
+/**
+ * Navigation segment, consisting of a navigation property, its target entity set,
+ * and, optionally, a list of key predicates to determine a single entity out of
+ * the target entity set.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface NavigationSegment {
+
+  /**
+   * Gets the navigation property.
+   * @return {@link EdmNavigationProperty} navigation property of this navigation segment
+   */
+  public EdmNavigationProperty getNavigationProperty();
+
+  /**
+   * Gets the target entity set.
+   * @return {@link EdmEntitySet} entity set of this navigation segment
+   */
+  public EdmEntitySet getEntitySet();
+
+  /**
+   * Gets the key predicate for the target entity set.
+   * @return List of {@link KeyPredicate}: key predicate of this navigation segment
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathInfo.java
new file mode 100644
index 0000000..e4f2409
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathInfo.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.api.uri;
+
+import java.net.URI;
+import java.util.List;
+
+/**
+ * Object to keep OData URI information.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface PathInfo {
+
+  /**
+   * Gets preceding path segments.
+   * @return List of path segments
+   */
+  List<PathSegment> getPrecedingSegments();
+
+  /**
+   * Gets OData path segments as immutable list.
+   * @return List of path segments
+   */
+  List<PathSegment> getODataSegments();
+
+  /**
+   * Gets the root URI of this service.
+   * @return absolute base URI of the request
+   */
+  URI getServiceRoot();
+
+  /**
+   * Get the absolute request URI including any query parameters.
+   * @return the absolute request URI
+   */
+  URI getRequestUri();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathSegment.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathSegment.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathSegment.java
new file mode 100644
index 0000000..0629b19
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/PathSegment.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>URI path segment consisting of an URI path element and URI matrix parameters.</p>
+ * <p>Example URI:
+ * <pre>{@code //moremaps.com/map/color;mul=50,25;long=20;scale=32000}</pre>
+ * where <code>color</code> is a path segment,
+ * <code>mul</code>, <code>long</code>, and <code>scale</code> are matrix parameters,
+ * and the matrix parameter <code>mul</code> has a multi-value list.</p> 
+ *
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface PathSegment {
+
+  /**
+   * Gets a URI path element. In the example above, <code>color</code> will be an element.
+   * @return a URI path element
+   */
+  String getPath();
+
+  /**
+   * <p>Gets the matrix parameters of this path segment.</p>
+   * <p>In the {@link PathSegment} example, <code>mul</code>, <code>long</code>,
+   * and <code>scale</code> are matrix parameters.</p>
+   * @return an immutable map of matrix parameters and their values
+   */
+  Map<String, List<String>> getMatrixParameters();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/SelectItem.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/SelectItem.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/SelectItem.java
new file mode 100644
index 0000000..ae3a52d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/SelectItem.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+
+/**
+ * An item of a $select system query option.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface SelectItem {
+
+  /**
+   * <code>true</code> if select=*
+   * @return <code>true</code> if select=*
+   */
+  public boolean isStar();
+
+  /**
+   * Gets the EDM property.
+   * @return {@link EdmProperty} property of this select item
+   */
+  public EdmProperty getProperty();
+
+  /**
+   * Gets the navigation-property segments for this select item.
+   * @return List of {@link NavigationPropertySegment} for this select item or Collection.EmptyList
+   */
+  public List<NavigationPropertySegment> getNavigationPropertySegments();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriInfo.java
new file mode 100644
index 0000000..ce60329
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriInfo.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetComplexPropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetMediaResourceUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetMetadataUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetServiceDocumentUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetSimplePropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Structured parts of the request URI - the result of URI parsing.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ * @see UriParser
+ */
+public interface UriInfo extends GetServiceDocumentUriInfo,
+    GetEntitySetUriInfo, GetEntityUriInfo,
+    GetComplexPropertyUriInfo, GetSimplePropertyUriInfo,
+    GetEntityLinkUriInfo, GetEntitySetLinksUriInfo,
+    GetMetadataUriInfo,
+    GetFunctionImportUriInfo,
+    GetEntitySetCountUriInfo, GetEntityCountUriInfo,
+    GetMediaResourceUriInfo,
+    GetEntityLinkCountUriInfo, GetEntitySetLinksCountUriInfo,
+    PutMergePatchUriInfo, PostUriInfo, DeleteUriInfo {
+
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  @Override
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  @Override
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  @Override
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  @Override
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target type of the request: an entity type, a simple type, or a complex type.
+   * @return {@link EdmType} the target type
+   */
+  @Override
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  @Override
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  @Override
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  @Override
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the path used to select a (simple or complex) property of an entity,
+   * or an empty list if no property is accessed.
+   * @return List of {@link EdmProperty}
+   */
+  @Override
+  public List<EdmProperty> getPropertyPath();
+
+  /**
+   * Determines whether $count has been used in the request URI.
+   * @return whether $count has been used
+   */
+  @Override
+  public boolean isCount();
+
+  /**
+   * Determines whether $value has been used in the request URI.
+   * @return whether $value has been used
+   */
+  @Override
+  public boolean isValue();
+
+  /**
+   * Determines whether $links has been used in the request URI.
+   * @return whether $links has been used
+   */
+  @Override
+  public boolean isLinks();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  @Override
+  public String getFormat();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  @Override
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the value of the $inlinecount system query option.
+   * @return {@link InlineCount} the inline count or null
+   */
+  @Override
+  public InlineCount getInlineCount();
+
+  /**
+   * Gets the value of the $orderby system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the order-by expression or null
+   */
+  @Override
+  public OrderByExpression getOrderBy();
+
+  /**
+   * Gets the value of the $skiptoken system query option.
+   * @return skip token or null
+   */
+  @Override
+  public String getSkipToken();
+
+  /**
+   * Gets the value of the $skip system query option.
+   * @return skip or null
+   */
+  @Override
+  public Integer getSkip();
+
+  /**
+   * Gets the value of the $top system query option.
+   * @return top or null
+   */
+  @Override
+  public Integer getTop();
+
+  /**
+   * Gets the value of the $expand system query option as a list of
+   * lists of navigation-property segments, or an empty list if not used.
+   * @return List of a list of {@link NavigationPropertySegment} to be expanded
+   */
+  @Override
+  public List<ArrayList<NavigationPropertySegment>> getExpand();
+
+  /**
+   * Gets the value of the $select system query option as a list of select items,
+   * or an empty list if not used.
+   * @return List of {@link SelectItem} to be selected
+   */
+  @Override
+  public List<SelectItem> getSelect();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  @Override
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  @Override
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriNotMatchingException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriNotMatchingException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriNotMatchingException.java
new file mode 100644
index 0000000..4ff467b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriNotMatchingException.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+
+/**
+ * URI-parsing exception resulting in a 404 Not Found response.
+ * @author SAP AG
+ */
+public class UriNotMatchingException extends ODataNotFoundException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference MATCHPROBLEM = createMessageReference(UriNotMatchingException.class, "MATCHPROBLEM");
+  public static final MessageReference NOTFOUND = createMessageReference(UriNotMatchingException.class, "NOTFOUND");
+  public static final MessageReference CONTAINERNOTFOUND = createMessageReference(UriNotMatchingException.class, "CONTAINERNOTFOUND");
+  public static final MessageReference ENTITYNOTFOUND = createMessageReference(UriNotMatchingException.class, "ENTITYNOTFOUND");
+  public static final MessageReference PROPERTYNOTFOUND = createMessageReference(UriNotMatchingException.class, "PROPERTYNOTFOUND");
+
+  public UriNotMatchingException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public UriNotMatchingException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public UriNotMatchingException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, errorCode);
+  }
+
+  public UriNotMatchingException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriParser.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriParser.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriParser.java
new file mode 100644
index 0000000..5cca5f4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriParser.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+
+/**
+ * Wrapper for UriParser functionality.
+ * @author SAP AG
+ */
+public abstract class UriParser {
+
+  /**
+   * Parses path segments and query parameters for the given EDM.
+   * @param edm Entity Data Model
+   * @param pathSegments list of path segments
+   * @param queryParameters query parameters
+   * @return {@link UriInfo} information about the parsed URI
+   * @throws ODataException
+   */
+  public static UriInfo parse(final Edm edm, final List<PathSegment> pathSegments, final Map<String, String> queryParameters) throws ODataException {
+    return RuntimeDelegate.getUriParser(edm).parse(pathSegments, queryParameters);
+  }
+
+  /**
+   * Parses path segments and query parameters.
+   * @param pathSegments list of path segments
+   * @param queryParameters query parameters
+   * @return {@link UriInfo} information about the parsed URI
+   * @throws UriSyntaxException
+   * @throws UriNotMatchingException
+   * @throws EdmException
+   */
+  public abstract UriInfo parse(List<PathSegment> pathSegments, Map<String, String> queryParameters) throws UriSyntaxException, UriNotMatchingException, EdmException;
+
+  /**
+   * Parses a $filter expression string and create an expression tree.
+   * <p>The current expression parser supports expressions as defined in the
+   * OData specification 2.0 with the following restrictions:
+   * <ul>
+   *   <li>the methods "cast", "isof" and "replace" are not supported</li>
+   * </ul></p>
+   *
+   * <p>The expression parser can be used with providing an Entity Data Model (EDM)
+   * and without providing it. When an EDM is provided the expression parser will be
+   * as strict as possible. That means:
+   * <ul>
+   *   <li>All properties used in the expression must be defined inside the EDM,</li>
+   *   <li>the types of EDM properties will be checked against the lists of allowed
+   *       types per method and per binary or unary operator, respectively</li>
+   * </ul>
+   * If no EDM is provided the expression parser performs a lax validation:
+   * <ul>
+   *   <li>The properties used in the expression are not looked up inside the EDM
+   *       and the type of the expression node representing the property will be "null",</li>
+   *   <li>expression nodes with EDM type "null" are not considered during the parameter
+   *       type validation, so the return type of the parent expression node will
+   *       also become "null".</li>
+   * </ul>
+   * @param edm        entity data model of the accessed OData service 
+   * @param edmType    EDM type of the OData entity/complex type/... addressed by the URL
+   * @param expression $filter expression string to be parsed
+   * @return           expression tree which can be traversed with help of the interfaces
+   *                   {@link org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor ExpressionVisitor}
+   *                   and {@link org.apache.olingo.odata2.api.uri.expression.Visitable Visitable}
+   * @throws ExpressionParserException thrown due to errors while parsing the $filter expression string
+   * @throws ODataMessageException     for extensibility
+   */
+  public static FilterExpression parseFilter(final Edm edm, final EdmEntityType edmType, final String expression) throws ExpressionParserException, ODataMessageException {
+    return RuntimeDelegate.getUriParser(edm).parseFilterString(edmType, expression);
+  }
+
+  /**
+   * Parses a $filter expression string and create an expression tree.
+   * <p>The current expression parser supports expressions as defined in the
+   * OData specification 2.0 with the following restrictions:
+   * <ul>
+   *   <li>the methods "cast", "isof" and "replace" are not supported</li>
+   * </ul></p>
+   *
+   * <p>The expression parser can be used with providing an Entity Data Model (EDM)
+   * and without providing it. When an EDM is provided the expression parser will be
+   * as strict as possible. That means:
+   * <ul>
+   *   <li>All properties used in the expression must be defined inside the EDM,</li>
+   *   <li>the types of EDM properties will be checked against the lists of allowed
+   *       types per method and per binary or unary operator, respectively</li>
+   * </ul>
+   * If no EDM is provided the expression parser performs a lax validation:
+   * <ul>
+   *   <li>The properties used in the expression are not looked up inside the EDM
+   *       and the type of the expression node representing the property will be "null",</li>
+   *   <li>expression nodes with EDM type "null" are not considered during the parameter
+   *       type validation, so the return type of the parent expression node will
+   *       also become "null".</li>
+   * </ul>
+   * @param edmType    EDM type of the OData entity/complex type/... addressed by the URL
+   * @param expression $filter expression string to be parsed
+   * @return           expression tree which can be traversed with help of the interfaces
+   *                   {@link org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor ExpressionVisitor}
+   *                   and {@link org.apache.olingo.odata2.api.uri.expression.Visitable Visitable}
+   * @throws ExpressionParserException thrown due to errors while parsing the $filter expression string
+   * @throws ODataMessageException     for extensibility
+   */
+  public abstract FilterExpression parseFilterString(EdmEntityType edmType, String expression) throws ExpressionParserException, ODataMessageException;
+
+  /**
+   * Parses a $orderby expression string and creates an expression tree.
+   * @param edm        EDM model of the accessed OData service 
+   * @param edmType    EDM type of the OData entity/complex type/... addressed by the URL
+   * @param expression $orderby expression string to be parsed
+   * @return           expression tree which can be traversed with help of the interfaces
+   *                   {@link org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor ExpressionVisitor}
+   *                   and {@link org.apache.olingo.odata2.api.uri.expression.Visitable Visitable}
+   * @throws ExpressionParserException thrown due to errors while parsing the $orderby expression string
+   * @throws ODataMessageException     used for extensibility
+   */
+  public static OrderByExpression parseOrderBy(final Edm edm, final EdmEntityType edmType, final String expression) throws ExpressionParserException, ODataMessageException {
+    return RuntimeDelegate.getUriParser(edm).parseOrderByString(edmType, expression);
+  }
+
+  /**
+   * Parses a $orderby expression string and creates an expression tree.
+   * @param edmType    EDM type of the OData entity/complex type/... addressed by the URL
+   * @param expression $orderby expression string to be parsed
+   * @return           expression tree which can be traversed with help of the interfaces
+   *                   {@link org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor ExpressionVisitor}
+   *                   and {@link org.apache.olingo.odata2.api.uri.expression.Visitable Visitable}
+   * @throws ExpressionParserException thrown due to errors while parsing the $orderby expression string
+   * @throws ODataMessageException     used for extensibility
+   */
+  public abstract OrderByExpression parseOrderByString(EdmEntityType edmType, String expression) throws ExpressionParserException, ODataMessageException;
+
+  /**
+   * Creates an optimized expression tree out of $expand and $select expressions. 
+   * @param select List of {@link SelectItem select items}
+   * @param expand List of Lists of {@link NavigationPropertySegment navigation property segments}
+   * @return       expression tree of type {@link ExpandSelectTreeNode}
+   * @throws EdmException
+   */
+  public static ExpandSelectTreeNode createExpandSelectTree(final List<SelectItem> select, final List<ArrayList<NavigationPropertySegment>> expand) throws EdmException {
+    return RuntimeDelegate.getUriParser(null).buildExpandSelectTree(select, expand);
+  }
+
+  /**
+   * Creates an optimized expression tree out of $expand and $select expressions. 
+   * @param select List of {@link SelectItem select items}
+   * @param expand List of Lists of {@link NavigationPropertySegment navigation property segments}
+   * @return       expression tree of type {@link ExpandSelectTreeNode}
+   * @throws EdmException
+   */
+  public abstract ExpandSelectTreeNode buildExpandSelectTree(List<SelectItem> select, List<ArrayList<NavigationPropertySegment>> expand) throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriSyntaxException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriSyntaxException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriSyntaxException.java
new file mode 100644
index 0000000..e5da915
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/UriSyntaxException.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.api.uri;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+
+/**
+ * Exception for violation of the OData URI construction rules,
+ * resulting in a 400 Bad Request response.
+ * @author SAP AG
+ */
+public class UriSyntaxException extends ODataBadRequestException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference URISYNTAX = createMessageReference(UriSyntaxException.class, "URISYNTAX");
+  public static final MessageReference ENTITYSETINSTEADOFENTITY = createMessageReference(UriSyntaxException.class, "ENTITYSETINSTEADOFENTITY");
+  public static final MessageReference NOTEXT = createMessageReference(UriSyntaxException.class, "NOTEXT");
+  public static final MessageReference NOMEDIARESOURCE = createMessageReference(UriSyntaxException.class, "NOMEDIARESOURCE");
+  public static final MessageReference NONAVIGATIONPROPERTY = createMessageReference(UriSyntaxException.class, "NONAVIGATIONPROPERTY");
+  public static final MessageReference MISSINGPARAMETER = createMessageReference(UriSyntaxException.class, "MISSINGPARAMETER");
+  public static final MessageReference MISSINGKEYPREDICATENAME = createMessageReference(UriSyntaxException.class, "MISSINGKEYPREDICATENAME");
+  public static final MessageReference DUPLICATEKEYNAMES = createMessageReference(UriSyntaxException.class, "DUPLICATEKEYNAMES");
+  public static final MessageReference EMPTYSEGMENT = createMessageReference(UriSyntaxException.class, "EMPTYSEGMENT");
+  public static final MessageReference MUSTNOTBELASTSEGMENT = createMessageReference(UriSyntaxException.class, "MUSTNOTBELASTSEGMENT");
+  public static final MessageReference MUSTBELASTSEGMENT = createMessageReference(UriSyntaxException.class, "MUSTBELASTSEGMENT");
+  public static final MessageReference INVALIDSEGMENT = createMessageReference(UriSyntaxException.class, "INVALIDSEGMENT");
+  public static final MessageReference INVALIDVALUE = createMessageReference(UriSyntaxException.class, "INVALIDVALUE");
+  public static final MessageReference INVALIDNULLVALUE = createMessageReference(UriSyntaxException.class, "INVALIDNULLVALUE");
+  public static final MessageReference INVALIDNEGATIVEVALUE = createMessageReference(UriSyntaxException.class, "INVALIDNEGATIVEVALUE");
+  public static final MessageReference INVALIDRETURNTYPE = createMessageReference(UriSyntaxException.class, "INVALIDRETURNTYPE");
+  public static final MessageReference INVALIDPROPERTYTYPE = createMessageReference(UriSyntaxException.class, "INVALIDPROPERTYTYPE");
+  public static final MessageReference INVALIDKEYPREDICATE = createMessageReference(UriSyntaxException.class, "INVALIDKEYPREDICATE");
+  public static final MessageReference INVALIDSYSTEMQUERYOPTION = createMessageReference(UriSyntaxException.class, "INVALIDSYSTEMQUERYOPTION");
+  public static final MessageReference INVALIDFILTEREXPRESSION = createMessageReference(UriSyntaxException.class, "INVALIDFILTEREXPRESSION");
+  public static final MessageReference INVALIDORDERBYEXPRESSION = createMessageReference(UriSyntaxException.class, "INVALIDORDERBYEXPRESSION");
+  public static final MessageReference LITERALFORMAT = createMessageReference(UriSyntaxException.class, "LITERALFORMAT");
+  public static final MessageReference UNKNOWNLITERAL = createMessageReference(UriSyntaxException.class, "UNKNOWNLITERAL");
+  public static final MessageReference INCOMPATIBLELITERAL = createMessageReference(UriSyntaxException.class, "INCOMPATIBLELITERAL");
+  public static final MessageReference INCOMPATIBLESYSTEMQUERYOPTION = createMessageReference(UriSyntaxException.class, "INCOMPATIBLESYSTEMQUERYOPTION");
+
+  public UriSyntaxException(final MessageReference MessageReference) {
+    super(MessageReference);
+  }
+
+  public UriSyntaxException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public UriSyntaxException(final MessageReference MessageReference, final String errorCode) {
+    super(MessageReference, errorCode);
+  }
+
+  public UriSyntaxException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryExpression.java
new file mode 100644
index 0000000..4f823c6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryExpression.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Represents a binary expression node in the expression tree returned by the methods 
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <br> 
+ * <br>
+ * A binary expression node is inserted in the expression tree for any valid
+ * ODATA binary operator in {@link BinaryOperator} (e.g. for "and", "div", "eg", ... )
+ * <br>
+ * @author SAP AG
+ */
+public interface BinaryExpression extends CommonExpression {
+  /**
+    * @return Operator object that represents the used operator
+    * @see BinaryOperator
+    */
+  public BinaryOperator getOperator();
+
+  /**
+   * @return Expression sub tree of the left operand
+   */
+  public CommonExpression getLeftOperand();
+
+  /**
+   * @return Expression sub tree of the right operand
+   */
+  public CommonExpression getRightOperand();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryOperator.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryOperator.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryOperator.java
new file mode 100644
index 0000000..2aa9a75
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/BinaryOperator.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Enumerations for supported binary operators of the ODATA expression parser 
+ * for ODATA version 2.0 (with some restrictions)
+ * @author SAP AG
+*/
+public enum BinaryOperator {
+  AND("and"), OR("or"), EQ("eq"), NE("ne"), LT("lt"), LE("le"), GT("gt"), GE("ge"), ADD("add"), SUB("sub"), MUL("mul"), DIV("div"), MODULO("mod"),
+
+  /**
+   * Property access operator. E.g. $filter=address/city eq "Sydney"
+   */
+  PROPERTY_ACCESS("/", "property access");
+
+  private String uriSyntax;
+  private String stringRespresentation;
+
+  private BinaryOperator(final String uriSyntax) {
+    this.uriSyntax = uriSyntax;
+    stringRespresentation = uriSyntax;
+  }
+
+  private BinaryOperator(final String syntax, final String stringRespresentation) {
+    uriSyntax = syntax;
+    this.stringRespresentation = stringRespresentation;
+  }
+
+  /** 
+   * @return Operator name for usage in text
+   */
+  @Override
+  public String toString() {
+    return stringRespresentation;
+  }
+
+  /**
+   * @return URI literal of the binary operator as used in the URL. 
+   */
+  public String toUriLiteral() {
+    return uriSyntax;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/CommonExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/CommonExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/CommonExpression.java
new file mode 100644
index 0000000..fc6be63
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/CommonExpression.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+/**
+ * Parent class of all classes used to build the expression tree returned by 
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <br>
+ * <br>
+ * <p>This interface defines the default methods for all expression tree nodes 
+ * <br>
+ * <br>
+ * @author SAP AG
+ */
+public interface CommonExpression extends Visitable {
+  /**
+   * @return Kind of this expression
+   * @see ExpressionKind
+   */
+  ExpressionKind getKind();
+
+  /**
+   * @return The return type of the value represented with 
+   * this expression. For example the {@link #getEdmType()} method
+   * for an expression representing the "concat" method will return always 
+   * "Edm.String".<br>
+   * <br>
+   * <p>This type information is set while parsing the $filter or $orderby 
+   * expressions and used to do a first validation of the expression.
+   * For calculating operators like "add, sub, mul" this type
+   * information is purely based on input and output types of the 
+   * operator as defined in the OData specification.
+   * So for $filter=2 add 7 the {@link #getEdmType()} method of the binary expression 
+   * will return Edm.Byte and not Edm.Int16 because the parser performs no real 
+   * addition.<br>
+   * <br>
+   * <p>However, the application may change this type while evaluating the 
+   * expression tree.
+   */
+  EdmType getEdmType();
+
+  /**
+   * Set the edmType of this expression node
+   * @param edmType Type to be set
+   * @return A self reference for method chaining"
+   */
+  CommonExpression setEdmType(EdmType edmType);
+
+  /**
+   * Returns the URI literal which lead to the creation of this expression.
+   * @return URI literal
+   */
+  String getUriLiteral();
+}


[37/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEdmMockData.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEdmMockData.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEdmMockData.java
new file mode 100644
index 0000000..4efbc2b
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEdmMockData.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.EntityType.EntityTypeA;
+
+public interface JPAEdmMockData {
+  /*
+   * Edm Complex Type Mock Data
+   */
+  public interface ComplexType {
+
+    public interface ComplexTypeA {
+      public static final String name = "ComplexTypeA";
+      public static final Class<ComplexTypeA> clazz = ComplexTypeA.class;
+
+      public interface Property {
+        public static final String PROPERTY_A = "A";
+        public static final String PROPERTY_B = "B";
+        public static final String PROPERTY_C = "C";
+      }
+
+    }
+
+    public interface ComplexTypeB {
+      public static final String name = "ComplexTypeB";
+
+      public interface Property {
+        public static final String PROPERTY_D = "D";
+        public static final String PROPERTY_E = "E";
+      }
+
+    }
+  }
+
+  public interface EntityType
+  {
+    public interface EntityTypeA
+    {
+      public static final String name = "SalesOrderHeader";
+      public static final Class<EntityTypeA> entityClazz = EntityTypeA.class;
+
+      public interface Property
+      {
+        public static final String PROPERTY_A = SimpleType.SimpleTypeA.NAME;
+
+      }
+
+    }
+  }
+
+  public interface SimpleType
+  {
+    public interface SimpleTypeA
+    {
+      public static final String NAME = "SOID";
+      public static final Class<String> clazz = String.class;
+      public static final Class<EntityTypeA> declaringClazz = EntityType.EntityTypeA.class;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableMock.java
new file mode 100644
index 0000000..fdff58b
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableMock.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+public class JPAEmbeddableMock<X> implements EmbeddableType<X> {
+
+  @Override
+  public Attribute<? super X, ?> getAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<? super X, ?>> getAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<? super X, ?> getCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<? super X, E> getCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public Attribute<X, ?> getDeclaredAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<X, ?>> getDeclaredAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<X, ?> getDeclaredCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<X, E> getDeclaredCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<X, ?> getDeclaredList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<X, E> getDeclaredList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<X, ?, ?> getDeclaredMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<X, K, V> getDeclaredMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<X, ?> getDeclaredSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<X, E> getDeclaredSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<X, ?> getDeclaredSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<? super X, ?> getList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<? super X, E> getList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<? super X, ?, ?> getMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<? super X, K, V> getMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<? super X, ?> getSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<? super X, E> getSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<? super X, ?> getSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<? super X, Y> getSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public Class<X> getJavaType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Type.PersistenceType getPersistenceType() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableTypeMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableTypeMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableTypeMock.java
new file mode 100644
index 0000000..4bef724
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEmbeddableTypeMock.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+public class JPAEmbeddableTypeMock<X> implements EmbeddableType<X> {
+
+  @Override
+  public Attribute<? super X, ?> getAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<? super X, ?>> getAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<? super X, ?> getCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<? super X, E> getCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public Attribute<X, ?> getDeclaredAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<X, ?>> getDeclaredAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<X, ?> getDeclaredCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<X, E> getDeclaredCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<X, ?> getDeclaredList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<X, E> getDeclaredList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<X, ?, ?> getDeclaredMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<X, K, V> getDeclaredMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<X, ?> getDeclaredSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<X, E> getDeclaredSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<X, ?> getDeclaredSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<? super X, ?> getList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<? super X, E> getList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<? super X, ?, ?> getMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<? super X, K, V> getMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<? super X, ?> getSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<? super X, E> getSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<? super X, ?> getSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<? super X, Y> getSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public Class<X> getJavaType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Type.PersistenceType getPersistenceType() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEntityTypeMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEntityTypeMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEntityTypeMock.java
new file mode 100644
index 0000000..27fea5c
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAEntityTypeMock.java
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.IdentifiableType;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type;
+
+public abstract class JPAEntityTypeMock<X> implements EntityType<X> {
+
+  @Override
+  public <Y> SingularAttribute<X, Y> getDeclaredId(final Class<Y> arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<X, Y> getDeclaredVersion(final Class<Y> arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<? super X, Y> getId(final Class<Y> arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<? super X, ?>> getIdClassAttributes() {
+    return null;
+  }
+
+  @Override
+  public Type<?> getIdType() {
+    return null;
+  }
+
+  @Override
+  public IdentifiableType<? super X> getSupertype() {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<? super X, Y> getVersion(final Class<Y> arg0) {
+    return null;
+  }
+
+  @Override
+  public boolean hasSingleIdAttribute() {
+    return false;
+  }
+
+  @Override
+  public boolean hasVersionAttribute() {
+    return false;
+  }
+
+  @Override
+  public Attribute<? super X, ?> getAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<? super X, ?>> getAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<? super X, ?> getCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<? super X, E> getCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public Attribute<X, ?> getDeclaredAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<X, ?>> getDeclaredAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<X, ?> getDeclaredCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<X, E> getDeclaredCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<X, ?> getDeclaredList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<X, E> getDeclaredList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<X, ?, ?> getDeclaredMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<X, K, V> getDeclaredMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<X, ?> getDeclaredSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<X, E> getDeclaredSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<X, ?> getDeclaredSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<? super X, ?> getList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<? super X, E> getList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<? super X, ?, ?> getMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<? super X, K, V> getMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<? super X, ?> getSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<? super X, E> getSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<? super X, ?> getSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<? super X, Y> getSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public Class<X> getJavaType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Type.PersistenceType getPersistenceType() {
+    return null;
+  }
+
+  @Override
+  public Class<X> getBindableJavaType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Bindable.BindableType getBindableType() {
+    return null;
+  }
+
+  @Override
+  public String getName() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAJavaMemberMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAJavaMemberMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAJavaMemberMock.java
new file mode 100644
index 0000000..217275c
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAJavaMemberMock.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Member;
+
+import javax.persistence.JoinColumns;
+
+public class JPAJavaMemberMock implements Member, AnnotatedElement, Annotation {
+
+  @Override
+  public Class<?> getDeclaringClass() {
+    return null;
+  }
+
+  @Override
+  public String getName() {
+    return null;
+  }
+
+  @Override
+  public int getModifiers() {
+    return 0;
+  }
+
+  @Override
+  public boolean isSynthetic() {
+    return false;
+  }
+
+  @Override
+  public boolean isAnnotationPresent(
+      final Class<? extends Annotation> annotationClass) {
+    return false;
+  }
+
+  @Override
+  public Annotation[] getAnnotations() {
+    return null;
+  }
+
+  @Override
+  public Annotation[] getDeclaredAnnotations() {
+    return null;
+  }
+
+  @Override
+  public Class<? extends Annotation> annotationType() {
+    return JoinColumns.class;
+  }
+
+  @Override
+  public <T extends Annotation> T getAnnotation(final Class<T> annotationClass) {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAManagedTypeMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAManagedTypeMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAManagedTypeMock.java
new file mode 100644
index 0000000..520ba8e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAManagedTypeMock.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+
+public class JPAManagedTypeMock<X> implements ManagedType<X> {
+
+  @Override
+  public Class<X> getJavaType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Type.PersistenceType getPersistenceType() {
+    return null;
+  }
+
+  @Override
+  public Attribute<? super X, ?> getAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<? super X, ?>> getAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<? super X, ?> getCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<? super X, E> getCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public Attribute<X, ?> getDeclaredAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<Attribute<X, ?>> getDeclaredAttributes() {
+    return null;
+  }
+
+  @Override
+  public CollectionAttribute<X, ?> getDeclaredCollection(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> CollectionAttribute<X, E> getDeclaredCollection(final String arg0,
+      final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<X, ?> getDeclaredList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<X, E> getDeclaredList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<X, ?, ?> getDeclaredMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<X, K, V> getDeclaredMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<X, ?, ?>> getDeclaredPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<X, ?> getDeclaredSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<X, E> getDeclaredSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<X, ?> getDeclaredSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<X, Y> getDeclaredSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<X, ?>> getDeclaredSingularAttributes() {
+    return null;
+  }
+
+  @Override
+  public ListAttribute<? super X, ?> getList(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> ListAttribute<? super X, E> getList(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public MapAttribute<? super X, ?, ?> getMap(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <K, V> MapAttribute<? super X, K, V> getMap(final String arg0,
+      final Class<K> arg1, final Class<V> arg2) {
+    return null;
+  }
+
+  @Override
+  public Set<PluralAttribute<? super X, ?, ?>> getPluralAttributes() {
+    return null;
+  }
+
+  @Override
+  public SetAttribute<? super X, ?> getSet(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <E> SetAttribute<? super X, E> getSet(final String arg0, final Class<E> arg1) {
+    return null;
+  }
+
+  @Override
+  public SingularAttribute<? super X, ?> getSingularAttribute(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public <Y> SingularAttribute<? super X, Y> getSingularAttribute(
+      final String arg0, final Class<Y> arg1) {
+    return null;
+  }
+
+  @Override
+  public Set<SingularAttribute<? super X, ?>> getSingularAttributes() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAMetaModelMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAMetaModelMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAMetaModelMock.java
new file mode 100644
index 0000000..8772efb
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAMetaModelMock.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.Set;
+
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.Metamodel;
+
+public class JPAMetaModelMock implements Metamodel {
+
+  @Override
+  public <X> EmbeddableType<X> embeddable(final Class<X> arg0) {
+    return null;
+  }
+
+  @Override
+  public <X> EntityType<X> entity(final Class<X> arg0) {
+    return null;
+  }
+
+  @Override
+  public Set<EmbeddableType<?>> getEmbeddables() {
+    return null;
+  }
+
+  @Override
+  public Set<EntityType<?>> getEntities() {
+    return null;
+  }
+
+  @Override
+  public Set<ManagedType<?>> getManagedTypes() {
+    return null;
+  }
+
+  @Override
+  public <X> ManagedType<X> managedType(final Class<X> arg0) {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPASingularAttributeMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPASingularAttributeMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPASingularAttributeMock.java
new file mode 100644
index 0000000..75be01a
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPASingularAttributeMock.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.lang.reflect.Member;
+
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type;
+
+public class JPASingularAttributeMock<X, T> implements SingularAttribute<X, T> {
+
+  @Override
+  public ManagedType<X> getDeclaringType() {
+    return null;
+  }
+
+  @Override
+  public Member getJavaMember() {
+    return null;
+  }
+
+  @Override
+  public Class<T> getJavaType() {
+    return null;
+  }
+
+  @Override
+  public String getName() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Attribute.PersistentAttributeType getPersistentAttributeType() {
+    return null;
+  }
+
+  @Override
+  public boolean isAssociation() {
+    return false;
+  }
+
+  @Override
+  public boolean isCollection() {
+    return false;
+  }
+
+  @Override
+  public Class<T> getBindableJavaType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Bindable.BindableType getBindableType() {
+    return null;
+  }
+
+  @Override
+  public Type<T> getType() {
+    return null;
+  }
+
+  @Override
+  public boolean isId() {
+    return false;
+  }
+
+  @Override
+  public boolean isOptional() {
+    return false;
+  }
+
+  @Override
+  public boolean isVersion() {
+    return false;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEndTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEndTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEndTest.java
new file mode 100644
index 0000000..8930e62
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEndTest.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import javax.persistence.metamodel.Attribute;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.SimpleType;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.SimpleType.SimpleTypeA;
+
+public class JPAEdmAssociationEndTest extends JPAEdmTestModelView {
+
+  private final static int VARIANT1 = 1;
+  private final static int VARIANT2 = 2;
+  private final static int VARIANT3 = 3;
+
+  private static int variant;
+
+  private static final String PUNIT_NAME = "salesorderprocessing";
+  private static JPAEdmAssociationEnd objJPAEdmAssociationEnd = null;
+  private static JPAEdmAssociationEndTest objJPAEdmAssociationEndTest = null;
+
+  @BeforeClass
+  public static void setup() {
+    objJPAEdmAssociationEndTest = new JPAEdmAssociationEndTest();
+    objJPAEdmAssociationEnd = new JPAEdmAssociationEnd(
+        objJPAEdmAssociationEndTest, objJPAEdmAssociationEndTest);
+    try {
+      objJPAEdmAssociationEnd.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBuilder() {
+    JPAEdmBuilder builder = objJPAEdmAssociationEnd.getBuilder();
+    assertNotNull(builder);
+
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmAssociationEnd.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmAssociationEnd.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetAssociationEnd1() {
+    AssociationEnd associationEnd = objJPAEdmAssociationEnd
+        .getEdmAssociationEnd1();
+    assertEquals(associationEnd.getType().getName(), "SOID");
+  }
+
+  @Test
+  public void testGetAssociationEnd2() {
+    AssociationEnd associationEnd = objJPAEdmAssociationEnd
+        .getEdmAssociationEnd2();
+    assertEquals(associationEnd.getType().getName(), "String");
+  }
+
+  @Test
+  public void testCompare() {
+    assertTrue(objJPAEdmAssociationEnd.compare(
+        getAssociationEnd("SOID", 1), getAssociationEnd("String", 1)));
+    assertFalse(objJPAEdmAssociationEnd.compare(
+        getAssociationEnd("String", 2), getAssociationEnd("SOID", 1)));
+  }
+
+  @Test
+  public void testBuildAssociationEnd()
+  {
+    assertEquals("SOID", objJPAEdmAssociationEnd.getEdmAssociationEnd1().getType().getName());
+    assertEquals(new FullQualifiedName("salesorderprocessing", "SOID"), objJPAEdmAssociationEnd.getEdmAssociationEnd1().getType());
+    assertTrue(objJPAEdmAssociationEnd.isConsistent());
+
+  }
+
+  private AssociationEnd getAssociationEnd(final String typeName, final int variant) {
+    AssociationEnd associationEnd = new AssociationEnd();
+    associationEnd.setType(getFullQualifiedName(typeName));
+    if (variant == VARIANT1) {
+      associationEnd.setMultiplicity(EdmMultiplicity.MANY);
+    } else if (variant == VARIANT2) {
+      associationEnd.setMultiplicity(EdmMultiplicity.ONE);
+    } else if (variant == VARIANT3) {
+      associationEnd.setMultiplicity(EdmMultiplicity.ZERO_TO_ONE);
+    }
+    else {
+      associationEnd.setMultiplicity(EdmMultiplicity.MANY);//
+    }
+    return associationEnd;
+  }
+
+  private FullQualifiedName getFullQualifiedName(final String typeName) {
+    FullQualifiedName fullQualifiedName = new FullQualifiedName(PUNIT_NAME,
+        typeName);
+    return fullQualifiedName;
+  }
+
+  private Attribute<?, ?> getJPAAttributeLocal() {
+    AttributeMock<Object, String> attr = new AttributeMock<Object, String>();
+    return attr;
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return getJPAAttributeLocal();
+  }
+
+  @Override
+  public String getpUnitName() {
+    return PUNIT_NAME;
+  }
+
+  @Override
+  public EntityType getEdmEntityType() {
+    EntityType entityType = new EntityType();
+    entityType.setName(SimpleTypeA.NAME);
+    return entityType;
+  }
+
+  // The inner class which gives us an replica of the jpa attribute
+  @SuppressWarnings("hiding")
+  public class AttributeMock<Object, String> extends JPAAttributeMock<Object, String> {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) SimpleType.SimpleTypeA.clazz;
+    }
+
+    @Override
+    public PersistentAttributeType getPersistentAttributeType() {
+      if (variant == VARIANT1) {
+        return PersistentAttributeType.ONE_TO_MANY;
+      } else if (variant == VARIANT2) {
+        return PersistentAttributeType.ONE_TO_ONE;
+      } else if (variant == VARIANT3) {
+        return PersistentAttributeType.MANY_TO_ONE;
+      } else {
+        return PersistentAttributeType.MANY_TO_MANY;
+      }
+
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSetTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSetTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSetTest.java
new file mode 100644
index 0000000..a2ac371
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSetTest.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPAEdmAssociationSetTest extends JPAEdmTestModelView {
+
+  private JPAEdmAssociationSetTest objJPAEdmAssociationSetTest;
+  private JPAEdmAssociationSet objJPAEdmAssociationSet;
+
+  @Before
+  public void setUp() {
+    objJPAEdmAssociationSetTest = new JPAEdmAssociationSetTest();
+    objJPAEdmAssociationSet = new JPAEdmAssociationSet(objJPAEdmAssociationSetTest);
+    try {
+      objJPAEdmAssociationSet.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmAssociationSet.getBuilder());
+  }
+
+  @Test
+  public void testGetConsistentEdmAssociationSetList() {
+    assertNotNull(objJPAEdmAssociationSet.getConsistentEdmAssociationSetList());
+  }
+
+  @Test
+  public void testGetEdmAssociationSet() {
+    assertNotNull(objJPAEdmAssociationSet.getEdmAssociationSet());
+  }
+
+  @Test
+  public void testGetEdmAssociation() {
+    assertNotNull(objJPAEdmAssociationSet.getEdmAssociation());
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertTrue(objJPAEdmAssociationSet.isConsistent());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmAssociationSet.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmAssociationSet.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmAssociationView getJPAEdmAssociationView() {
+    return this;
+  }
+
+  @Override
+  public AssociationSet getEdmAssociationSet() {
+    AssociationSet associationSet = new AssociationSet();
+    associationSet.setEnd1(new AssociationSetEnd());
+    associationSet.setEnd2(new AssociationSetEnd());
+
+    return associationSet;
+  }
+
+  @Override
+  public List<Association> getConsistentEdmAssociationList() {
+    return getEdmAssociationListLocal();
+  }
+
+  @Override
+  public List<AssociationSet> getConsistentEdmAssociationSetList() {
+
+    List<AssociationSet> associationSetList = new ArrayList<AssociationSet>();
+    associationSetList.add(getEdmAssociationSet());
+    associationSetList.add(getEdmAssociationSet());
+
+    return associationSetList;
+  }
+
+  @Override
+  public List<EntitySet> getConsistentEdmEntitySetList() {
+    return getEntitySetListLocal();
+  }
+
+  @Override
+  public boolean isConsistent() {
+    return true;
+  }
+
+  @Override
+  public Schema getEdmSchema() {
+    Schema schema = new Schema();
+    schema.setNamespace("salesordereprocessing");
+    return schema;
+  }
+
+  private List<EntitySet> getEntitySetListLocal() {
+    List<EntitySet> entitySetList = new ArrayList<EntitySet>();
+
+    EntitySet entitySet = new EntitySet();
+    entitySet.setName("SalesOrderHeader");
+    entitySet.setEntityType(new FullQualifiedName("salesorderprocessing", "SOID"));
+
+    EntitySet entitySet2 = new EntitySet();
+    entitySet2.setName("SalesOrderItem");
+    entitySet2.setEntityType(new FullQualifiedName("salesorderprocessing", "SOID"));
+
+    entitySetList.add(entitySet);
+    entitySetList.add(entitySet2);
+    return entitySetList;
+  }
+
+  private List<Association> getEdmAssociationListLocal() {
+    List<Association> associationList = new ArrayList<Association>();
+
+    Association association = new Association();
+    association.setName("Assoc_SalesOrderHeader_SalesOrderItem");
+    association.setEnd1(new AssociationEnd().setType(new FullQualifiedName("salesorderprocessing", "String")).setRole("SalesOrderHeader"));
+    association.setEnd2(new AssociationEnd().setType(new FullQualifiedName("salesorderprocessing", "SalesOrderItem")).setRole("SalesOrderItem"));
+
+    associationList.add(association);
+    return associationList;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationTest.java
new file mode 100644
index 0000000..857c246
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationTest.java
@@ -0,0 +1,438 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
+import javax.persistence.metamodel.Attribute;
+
+import org.easymock.EasyMock;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.SimpleType;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.SimpleType.SimpleTypeA;
+
+public class JPAEdmAssociationTest extends JPAEdmTestModelView {
+
+  private static JPAEdmAssociation objAssociation = null;
+  private static String ASSOCIATION_NAME = "SalesOrderHeader_String";
+  private static JPAEdmAssociationTest localView = null;
+  private static final String PUNIT_NAME = "salesorderprocessing";
+  private int variant;
+
+  @BeforeClass
+  public static void setup() {
+    localView = new JPAEdmAssociationTest();
+    objAssociation = new JPAEdmAssociation(localView, localView, localView, 1);
+    try {
+      objAssociation.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Override
+  public AssociationEnd getEdmAssociationEnd1() {
+    AssociationEnd associationEnd = new AssociationEnd();
+    associationEnd.setType(new FullQualifiedName("salesorderprocessing",
+        "SalesOrderHeader"));
+    associationEnd.setRole("SalesOrderHeader");
+    associationEnd.setMultiplicity(EdmMultiplicity.ONE);
+    return associationEnd;
+  }
+
+  @Override
+  public AssociationEnd getEdmAssociationEnd2() {
+    AssociationEnd associationEnd = new AssociationEnd();
+    associationEnd.setType(new FullQualifiedName("salesorderprocessing",
+        "String"));
+    associationEnd.setRole("String");
+    associationEnd.setMultiplicity(EdmMultiplicity.MANY);
+    return associationEnd;
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    Association association = new Association();
+    association.setEnd1(new AssociationEnd().setType(new FullQualifiedName(
+        "salesorderprocessing", "SalesOrderHeader")));
+    association.setEnd2(new AssociationEnd().setType(new FullQualifiedName(
+        "salesorderprocessing", "String")));
+
+    return association;
+  }
+
+  @Override
+  public boolean isExists() {
+    return true;
+  }
+
+  @Override
+  public JPAEdmReferentialConstraintView getJPAEdmReferentialConstraintView() {
+    JPAEdmReferentialConstraint refConstraintView = new JPAEdmReferentialConstraint(
+        localView, localView, localView);
+    return refConstraintView;
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return getJPAAttributeLocal();
+  }
+
+  @Override
+  public String getpUnitName() {
+    return PUNIT_NAME;
+  }
+
+  @Override
+  public EntityType getEdmEntityType() {
+    EntityType entityType = new EntityType();
+    entityType.setName(SimpleTypeA.NAME);
+    return entityType;
+  }
+
+  // The inner class which gives us an replica of the jpa attribute
+  @SuppressWarnings("hiding")
+  private class AttributeMock<Object, String> extends JPAAttributeMock<Object, String> {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) SimpleType.SimpleTypeA.clazz;
+    }
+
+    @Override
+    public PersistentAttributeType getPersistentAttributeType() {
+      if (variant == 1) {
+        return PersistentAttributeType.ONE_TO_MANY;
+      } else if (variant == 2) {
+        return PersistentAttributeType.ONE_TO_ONE;
+      } else if (variant == 2) {
+        return PersistentAttributeType.MANY_TO_ONE;
+      } else {
+        return PersistentAttributeType.MANY_TO_MANY;
+      }
+
+    }
+  }
+
+  private Attribute<?, ?> getJPAAttributeLocal() {
+    AttributeMock<Object, String> attr = new AttributeMock<Object, String>();
+    return attr;
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objAssociation.getBuilder());
+  }
+
+  @Test
+  public void testGetEdmAssociation() {
+    assertNotNull(objAssociation.getEdmAssociation());
+    assertEquals(objAssociation.getEdmAssociation().getName(),
+        ASSOCIATION_NAME);
+  }
+
+  @Test
+  public void testGetConsistentEdmAssociationList() {
+    assertTrue(objAssociation.getConsistentEdmAssociationList().size() > 0);
+  }
+
+  @Override
+  public String getEdmRelationShipName() {
+    return "Association_SalesOrderHeader_String";
+  }
+
+  @Test
+  public void testSearchAssociation1() {
+    class TestAssociationEndView extends JPAEdmTestModelView {
+      @Override
+      public String getEdmRelationShipName() {
+        return "SalesOrderHeader_String1";
+      }
+
+      private Attribute<?, ?> getJPAAttributeLocal() {
+        AttributeMock<Object, String> attr = new AttributeMock<Object, String>();
+        return attr;
+      }
+
+      @Override
+      public Attribute<?, ?> getJPAAttribute() {
+        return getJPAAttributeLocal();
+      }
+
+      @Override
+      public String getJoinColumnName() {
+        return "SO_ID";
+      }
+
+      @Override
+      public String getJoinColumnReferenceColumnName() {
+        return "DEMO_ID";
+      }
+
+      @Override
+      public String getMappedByName() {
+        return "demo";
+      }
+
+      @Override
+      public String getOwningPropertyName() {
+        return "salesOrder";
+      }
+
+      @Override
+      public int getNumberOfAssociationsWithSimilarEndPoints(
+          final JPAEdmAssociationEndView view) {
+        return 1;
+      }
+
+      @Override
+      public String getpUnitName() {
+        return "salesorderprocessing";
+      }
+
+      @Override
+      public EntityType getEdmEntityType() {
+        EntityType entityType = new EntityType();
+        entityType.setName("SalesOrderHeader");
+        return entityType;
+      }
+
+      @SuppressWarnings("hiding")
+      class AttributeMock<Object, String> extends
+          JPAAttributeMock<Object, String> {
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Class<String> getJavaType() {
+          return (Class<String>) SimpleType.SimpleTypeA.clazz;
+        }
+
+        @Override
+        public PersistentAttributeType getPersistentAttributeType() {
+
+          return PersistentAttributeType.ONE_TO_MANY;
+
+        }
+
+        @Override
+        public Member getJavaMember() {
+          return new AnnotatedElementMock();
+        }
+
+        @Override
+        public java.lang.String getName() {
+          // TODO Auto-generated method stub
+          return super.getName();
+        }
+
+        class AnnotatedElementMock implements AnnotatedElement, Member {
+
+          @Override
+          public boolean isAnnotationPresent(
+              final Class<? extends Annotation> annotationClass) {
+            return true;
+          }
+
+          @SuppressWarnings("unchecked")
+          @Override
+          public Annotation getAnnotation(@SuppressWarnings("rawtypes") final Class annotationClass) {
+            if (annotationClass.equals(JoinColumn.class)) {
+              JoinColumn joinColumn = EasyMock.createMock(JoinColumn.class);
+              EasyMock.expect(joinColumn.name()).andStubReturn("SO_ID");
+              EasyMock.expect(joinColumn.referencedColumnName()).andStubReturn("DEMO_ID");
+              EasyMock.replay(joinColumn);
+              return joinColumn;
+            }
+            else {
+              OneToMany oneToMany = EasyMock.createMock(OneToMany.class);
+              EasyMock.expect(oneToMany.mappedBy()).andStubReturn("demo");
+              EasyMock.replay(oneToMany);
+              return oneToMany;
+            }
+          }
+
+          @Override
+          public Annotation[] getAnnotations() {
+            return null;
+          }
+
+          @Override
+          public Annotation[] getDeclaredAnnotations() {
+            return null;
+          }
+
+          @Override
+          public Class<?> getDeclaringClass() {
+            // TODO Auto-generated method stub
+            return null;
+          }
+
+          @Override
+          public java.lang.String getName() {
+            // TODO Auto-generated method stub
+            return null;
+          }
+
+          @Override
+          public int getModifiers() {
+            // TODO Auto-generated method stub
+            return 0;
+          }
+
+          @Override
+          public boolean isSynthetic() {
+            // TODO Auto-generated method stub
+            return false;
+          }
+
+        }
+
+      }
+    }
+    TestAssociationEndView objJPAEdmAssociationEndTest = new TestAssociationEndView();
+    JPAEdmAssociationEnd objJPAEdmAssociationEnd = new JPAEdmAssociationEnd(
+        objJPAEdmAssociationEndTest, objJPAEdmAssociationEndTest);
+    try {
+      objJPAEdmAssociationEnd.getBuilder().build();
+      Field field = objAssociation.getClass().getDeclaredField("associationEndMap");
+      field.setAccessible(true);
+      Map<String, JPAEdmAssociationEndView> associationEndMap = new HashMap<String, JPAEdmAssociationEndView>();
+      associationEndMap.put("SalesOrderHeader_String", objJPAEdmAssociationEnd);
+      field.set(objAssociation, associationEndMap);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    assertEquals("SalesOrderHeader_String", objAssociation.searchAssociation(objJPAEdmAssociationEnd).getName());
+
+  }
+
+  @Test
+  public void testAddJPAEdmAssociationView() {
+
+    class LocalJPAAssociationView extends JPAEdmTestModelView {
+      @Override
+      public AssociationEnd getEdmAssociationEnd1() {
+        AssociationEnd associationEnd = new AssociationEnd();
+        associationEnd.setType(new FullQualifiedName(
+            "salesorderprocessing", "SalesOrderHeader"));
+        associationEnd.setRole("SalesOrderHeader");
+        associationEnd.setMultiplicity(EdmMultiplicity.ONE);
+        return associationEnd;
+      }
+
+      @Override
+      public AssociationEnd getEdmAssociationEnd2() {
+        AssociationEnd associationEnd = new AssociationEnd();
+        associationEnd.setType(new FullQualifiedName(
+            "salesorderprocessing", "SalesOrderItem"));
+        associationEnd.setRole("SalesOrderItem");
+        associationEnd.setMultiplicity(EdmMultiplicity.MANY);
+        return associationEnd;
+      }
+
+      @Override
+      public Association getEdmAssociation() {
+        Association association = new Association();
+        association.setEnd1(new AssociationEnd()
+            .setType(new FullQualifiedName("salesorderprocessing",
+                "SalesOrderHeader")));
+        association.setEnd2(new AssociationEnd()
+            .setType(new FullQualifiedName("salesorderprocessing",
+                "SalesOrderItem")));
+
+        return association;
+      }
+    }
+    LocalJPAAssociationView assocViewObj = new LocalJPAAssociationView();
+    JPAEdmAssociation objLocalAssociation = new JPAEdmAssociation(
+        assocViewObj, assocViewObj, assocViewObj, 1);
+    try {
+      objLocalAssociation.getBuilder().build();
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    objAssociation.addJPAEdmAssociationView(objLocalAssociation, localView);
+
+  }
+
+  @Test
+  public void testAddJPAEdmRefConstraintView() {
+
+    localView = new JPAEdmAssociationTest();
+    objAssociation = new JPAEdmAssociation(localView, localView, localView, 1);
+    try {
+      objAssociation.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    objAssociation.addJPAEdmRefConstraintView(localView);
+    assertTrue(objAssociation.getConsistentEdmAssociationList()
+        .size() > 0);
+  }
+
+  @Test
+  public void testGetJPAEdmReferentialConstraintView() {
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImplTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImplTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImplTest.java
new file mode 100644
index 0000000..6e92aa0
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImplTest.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+
+public class JPAEdmBaseViewImplTest extends JPAEdmTestModelView {
+
+  private JPAEdmBaseViewImplTest objJPAEdmBaseViewImplTest;
+  private JPAEdmBaseViewImpl objJPAEdmBaseViewImpl;
+
+  @Before
+  public void setUp() {
+    objJPAEdmBaseViewImplTest = new JPAEdmBaseViewImplTest();
+    objJPAEdmBaseViewImpl = new JPAEdmBaseViewImpl(objJPAEdmBaseViewImplTest) {
+
+      @Override
+      public JPAEdmBuilder getBuilder() {
+        return null;
+      }
+    };
+
+    objJPAEdmBaseViewImpl = new JPAEdmBaseViewImpl(getJPAMetaModel(), getpUnitName()) {
+
+      @Override
+      public JPAEdmBuilder getBuilder() {
+        return null;
+      }
+    };
+
+  }
+
+  @Test
+  public void testGetpUnitName() {
+    assertTrue(objJPAEdmBaseViewImpl.getpUnitName().equals("salesorderprocessing"));
+  }
+
+  @Test
+  public void testGetJPAMetaModel() {
+    assertNotNull(objJPAEdmBaseViewImpl.getJPAMetaModel());
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertTrue(objJPAEdmBaseViewImpl.isConsistent());
+  }
+
+  @Test
+  public void testClean() {
+    objJPAEdmBaseViewImpl.clean();
+    assertFalse(objJPAEdmBaseViewImpl.isConsistent());
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAMetaModelMock();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexTypeTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexTypeTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexTypeTest.java
new file mode 100644
index 0000000..88f1210
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexTypeTest.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEmbeddableMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPASingularAttributeMock;
+
+public class JPAEdmComplexTypeTest extends JPAEdmTestModelView {
+
+  private static JPAEdmComplexType objComplexType = null;
+  private static JPAEdmComplexTypeTest localView = null;
+
+  @BeforeClass
+  public static void setup() {
+    localView = new JPAEdmComplexTypeTest();
+    objComplexType = new JPAEdmComplexType(localView);
+    try {
+      objComplexType.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @SuppressWarnings("rawtypes")
+  @Override
+  public EmbeddableType<?> getJPAEmbeddableType() {
+    @SuppressWarnings("hiding")
+    class JPAComplexAttribute<Long> extends JPAEmbeddableMock<Long>
+    {
+
+      @SuppressWarnings("unchecked")
+      @Override
+      public Class<Long> getJavaType() {
+
+        return (Class<Long>) java.lang.Long.class;
+      }
+
+    }
+    return new JPAComplexAttribute();
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAEdmMetaModel();
+  }
+
+  @Test
+  public void testGetBuilder() {
+
+    assertNotNull(objComplexType.getBuilder());
+  }
+
+  @Test
+  public void testGetEdmComplexType() {
+    assertEquals(objComplexType.getEdmComplexType().getName(), "String");
+  }
+
+  @Test
+  public void testSearchComplexTypeString() {
+    assertNotNull(objComplexType.searchEdmComplexType("java.lang.String"));
+
+  }
+
+  @Test
+  public void testGetJPAEmbeddableType() {
+    assertTrue(objComplexType.getJPAEmbeddableType().getAttributes().size() > 0);
+
+  }
+
+  @Test
+  public void testGetConsistentEdmComplexTypes() {
+    assertTrue(objComplexType.getConsistentEdmComplexTypes().size() > 0);
+  }
+
+  @Test
+  public void testSearchComplexTypeFullQualifiedName() {
+    assertNotNull(objComplexType.searchEdmComplexType(new FullQualifiedName("salesorderprocessing", "String")));
+
+  }
+
+  @Test
+  public void testSearchComplexTypeFullQualifiedNameNegative()
+  {
+    assertNull(objComplexType.searchEdmComplexType(new FullQualifiedName("salesorderprocessing", "lang.String")));
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objComplexType.getBuilder();
+    JPAEdmBuilder builder2 = objComplexType.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testAddCompleTypeView() {
+    localView = new JPAEdmComplexTypeTest();
+    objComplexType = new JPAEdmComplexType(localView);
+    try {
+      objComplexType.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    objComplexType.addJPAEdmCompleTypeView(localView);
+    assertTrue(objComplexType.getConsistentEdmComplexTypes()
+        .size() > 1);
+  }
+
+  @Test
+  public void testExpandEdmComplexType() {
+    ComplexType complexType = new ComplexType();
+    List<Property> properties = new ArrayList<Property>();
+    JPAEdmMapping mapping1 = new JPAEdmMappingImpl();
+    mapping1.setJPAColumnName("LINEITEMID");
+    ((Mapping) mapping1).setInternalName("LineItemKey.LiId");
+    JPAEdmMapping mapping2 = new JPAEdmMappingImpl();
+    mapping2.setJPAColumnName("LINEITEMNAME");
+    ((Mapping) mapping2).setInternalName("LineItemKey.LiName");
+    properties.add(new SimpleProperty().setName("LIID").setMapping((Mapping) mapping1));
+    properties.add(new SimpleProperty().setName("LINAME").setMapping((Mapping) mapping2));
+    complexType.setProperties(properties);
+    List<Property> expandedList = null;
+    try
+    {
+      objComplexType.expandEdmComplexType(complexType, expandedList, "SalesOrderItemKey");
+    } catch (ClassCastException e)
+    {
+      assertTrue(false);
+    }
+    assertTrue(true);
+
+  }
+
+  @Test
+  public void testComplexTypeCreation()
+  {
+    try {
+      objComplexType.getBuilder().build();
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals(objComplexType.pUnitName, "salesorderprocessing");
+  }
+
+  private class JPAEdmMetaModel extends JPAMetaModelMock
+  {
+    Set<EmbeddableType<?>> embeddableSet;
+
+    public JPAEdmMetaModel() {
+      embeddableSet = new HashSet<EmbeddableType<?>>();
+    }
+
+    @Override
+    public Set<EmbeddableType<?>> getEmbeddables() {
+      embeddableSet.add(new JPAEdmEmbeddable<String>());
+      return embeddableSet;
+    }
+
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEmbeddable<String> extends JPAEmbeddableMock<String>
+  {
+
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet()
+    {
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SOID"));
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmAttribute<Object, String> extends JPASingularAttributeMock<Object, String>
+  {
+
+    @Override
+    public PersistentAttributeType getPersistentAttributeType() {
+      return PersistentAttributeType.BASIC;
+    }
+
+    Class<String> clazz;
+    java.lang.String attributeName;
+
+    public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+      this.clazz = javaType;
+      this.attributeName = name;
+
+    }
+
+    @Override
+    public Class<String> getJavaType() {
+      return clazz;
+    }
+
+    @Override
+    public java.lang.String getName() {
+      return this.attributeName;
+    }
+
+    @Override
+    public boolean isId() {
+      return false;
+    }
+
+  }
+}


[12/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CollectionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CollectionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CollectionImpl.java
new file mode 100644
index 0000000..5467e79
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CollectionImpl.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.servicedocument.Accept;
+import org.apache.olingo.odata2.api.servicedocument.Categories;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.CommonAttributes;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Title;
+
+/**
+ * @author SAP AG
+ */
+public class CollectionImpl implements Collection {
+  private Title title;
+  private String href;
+  private List<Accept> acceptElements;
+  private List<Categories> categories;
+  private CommonAttributes attributes;
+  private List<ExtensionElement> extensionElements;
+
+  @Override
+  public CommonAttributes getCommonAttributes() {
+    return attributes;
+  }
+
+  @Override
+  public Title getTitle() {
+    return title;
+  }
+
+  @Override
+  public String getHref() {
+    return href;
+  }
+
+  @Override
+  public List<Accept> getAcceptElements() {
+    return acceptElements;
+  }
+
+  @Override
+  public List<Categories> getCategories() {
+    return categories;
+  }
+
+  @Override
+  public List<ExtensionElement> getExtesionElements() {
+    return extensionElements;
+  }
+
+  public CollectionImpl setTitle(final Title title) {
+    this.title = title;
+    return this;
+  }
+
+  public CollectionImpl setHref(final String href) {
+    this.href = href;
+    return this;
+  }
+
+  public CollectionImpl setAcceptElements(final List<Accept> acceptElements) {
+    this.acceptElements = acceptElements;
+    return this;
+  }
+
+  public CollectionImpl setCategories(final List<Categories> categories) {
+    this.categories = categories;
+    return this;
+  }
+
+  public CollectionImpl setCommonAttributes(final CommonAttributes attributes) {
+    this.attributes = attributes;
+    return this;
+  }
+
+  public CollectionImpl setExtesionElements(final List<ExtensionElement> elements) {
+    extensionElements = elements;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CommonAttributesImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CommonAttributesImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CommonAttributesImpl.java
new file mode 100644
index 0000000..ec1a1fe
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CommonAttributesImpl.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.servicedocument.CommonAttributes;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionAttribute;
+
+/**
+ * @author SAP AG
+ */
+public class CommonAttributesImpl implements CommonAttributes {
+  private String base;
+  private String lang;
+  private List<ExtensionAttribute> attributes;
+
+  @Override
+  public String getBase() {
+    return base;
+  }
+
+  @Override
+  public String getLang() {
+    return lang;
+  }
+
+  @Override
+  public List<ExtensionAttribute> getAttributes() {
+    return Collections.unmodifiableList(attributes);
+  }
+
+  public CommonAttributesImpl setBase(final String base) {
+    this.base = base;
+    return this;
+  }
+
+  public CommonAttributesImpl setLang(final String lang) {
+    this.lang = lang;
+    return this;
+  }
+
+  public CommonAttributesImpl setAttributes(final List<ExtensionAttribute> attributes) {
+    this.attributes = attributes;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionAttributeImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionAttributeImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionAttributeImpl.java
new file mode 100644
index 0000000..08a1c8f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionAttributeImpl.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import org.apache.olingo.odata2.api.servicedocument.ExtensionAttribute;
+
+/**
+ * @author SAP AG
+ */
+public class ExtensionAttributeImpl implements ExtensionAttribute {
+  private String namespace;
+  private String prefix;
+  private String name;
+  private String text;
+
+  @Override
+  public String getNamespace() {
+    return namespace;
+  }
+
+  @Override
+  public String getPrefix() {
+    return prefix;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  public ExtensionAttributeImpl setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  public ExtensionAttributeImpl setPrefix(final String prefix) {
+    this.prefix = prefix;
+    return this;
+  }
+
+  public ExtensionAttributeImpl setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  public ExtensionAttributeImpl setText(final String text) {
+    this.text = text;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionElementImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionElementImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionElementImpl.java
new file mode 100644
index 0000000..fc1ee15
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ExtensionElementImpl.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.servicedocument.ExtensionAttribute;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+
+/**
+ * @author SAP AG
+ */
+public class ExtensionElementImpl implements ExtensionElement {
+  private String namespace;
+  private String prefix;
+  private String name;
+  private String text;
+  private List<ExtensionElement> anyElements;
+  private List<ExtensionAttribute> attributes;
+
+  @Override
+  public String getNamespace() {
+    return namespace;
+  }
+
+  @Override
+  public String getPrefix() {
+    return prefix;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  @Override
+  public List<ExtensionElement> getElements() {
+    return anyElements;
+  }
+
+  @Override
+  public List<ExtensionAttribute> getAttributes() {
+    return attributes;
+  }
+
+  public ExtensionElementImpl setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  public ExtensionElementImpl setPrefix(final String prefix) {
+    this.prefix = prefix;
+    return this;
+  }
+
+  public ExtensionElementImpl setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  public ExtensionElementImpl setText(final String text) {
+    this.text = text;
+    return this;
+
+  }
+
+  public ExtensionElementImpl setElements(final List<ExtensionElement> anyElements) {
+    this.anyElements = anyElements;
+    return this;
+  }
+
+  public ExtensionElementImpl setAttributes(final List<ExtensionAttribute> attributes) {
+    this.attributes = attributes;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ServiceDocumentImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ServiceDocumentImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ServiceDocumentImpl.java
new file mode 100644
index 0000000..2eb3ff7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/ServiceDocumentImpl.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.servicedocument;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.servicedocument.AtomInfo;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+
+/**
+ * @author SAP AG
+ */
+public class ServiceDocumentImpl implements ServiceDocument {
+  private AtomInfo atomInfo;
+  private List<EdmEntitySetInfo> entitySets = new ArrayList<EdmEntitySetInfo>();
+
+  public ServiceDocumentImpl setEntitySetsInfo(final List<EdmEntitySetInfo> entitySets) {
+    this.entitySets = entitySets;
+    return this;
+  }
+
+  @Override
+  public List<EdmEntitySetInfo> getEntitySetsInfo() throws EntityProviderException {
+    return entitySets;
+  }
+
+  @Override
+  public AtomInfo getAtomInfo() {
+    return atomInfo;
+  }
+
+  public void setAtomInfo(final AtomInfo atomInfo) {
+    this.atomInfo = atomInfo;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/TitleImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/TitleImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/TitleImpl.java
new file mode 100644
index 0000000..5fc6c3c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/TitleImpl.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import org.apache.olingo.odata2.api.servicedocument.Title;
+
+/**
+ * @author SAP AG
+ */
+public class TitleImpl implements Title {
+  private String text;
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  public TitleImpl setText(final String text) {
+    this.text = text;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/WorkspaceImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/WorkspaceImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/WorkspaceImpl.java
new file mode 100644
index 0000000..fa44081
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/WorkspaceImpl.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.CommonAttributes;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Title;
+import org.apache.olingo.odata2.api.servicedocument.Workspace;
+
+/**
+ * @author SAP AG
+ */
+public class WorkspaceImpl implements Workspace {
+  private Title title;
+  private List<Collection> collections;
+  private CommonAttributes attributes;
+  private List<ExtensionElement> extensionElements;
+
+  @Override
+  public Title getTitle() {
+    return title;
+  }
+
+  @Override
+  public List<Collection> getCollections() {
+    return collections;
+  }
+
+  @Override
+  public CommonAttributes getCommonAttributes() {
+    return attributes;
+  }
+
+  @Override
+  public List<ExtensionElement> getExtesionElements() {
+    return extensionElements;
+  }
+
+  public WorkspaceImpl setTitle(final Title title) {
+    this.title = title;
+    return this;
+  }
+
+  public WorkspaceImpl setCollections(final List<Collection> collections) {
+    this.collections = collections;
+    return this;
+  }
+
+  public WorkspaceImpl setAttributes(final CommonAttributes attributes) {
+    this.attributes = attributes;
+    return this;
+  }
+
+  public WorkspaceImpl setExtesionElements(final List<ExtensionElement> elements) {
+    extensionElements = elements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeCreator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeCreator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeCreator.java
new file mode 100644
index 0000000..9120d14
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeCreator.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl.AllKinds;
+
+/**
+ * @author SAP AG
+ */
+public class ExpandSelectTreeCreator {
+
+  private List<SelectItem> initialSelect;
+  private List<ArrayList<NavigationPropertySegment>> initialExpand;
+
+  public ExpandSelectTreeCreator(final List<SelectItem> select, final List<ArrayList<NavigationPropertySegment>> expand) {
+    if (select != null) {
+      initialSelect = select;
+    } else {
+      initialSelect = Collections.emptyList();
+    }
+
+    if (expand != null) {
+      initialExpand = expand;
+    } else {
+      initialExpand = Collections.emptyList();
+    }
+  }
+
+  public ExpandSelectTreeNodeImpl create() throws EdmException {
+
+    //Initial node
+    ExpandSelectTreeNodeImpl root = new ExpandSelectTreeNodeImpl();
+    if (!initialSelect.isEmpty()) {
+      //Create a full expand tree
+      createSelectTree(root);
+    } else {
+      //If no select is given the root node is explicitly selected for all expand clauses
+      root.setExplicitlySelected();
+    }
+    //Merge in the expand tree
+    mergeExpandTree(root);
+
+    //consolidate the tree
+    consolidate(root);
+    return root;
+  }
+
+  private void consolidate(final ExpandSelectTreeNodeImpl node) {
+    switch (node.getAllKind()) {
+    case EXPLICITLYTRUE:
+    case IMPLICITLYTRUE:
+      consolidateTrueNode(node);
+      break;
+    case FALSE:
+      consolidateFalseNode(node);
+    }
+
+  }
+
+  private void consolidateFalseNode(final ExpandSelectTreeNodeImpl node) {
+    Iterator<Map.Entry<String, ExpandSelectTreeNode>> iterator = node.getLinks().entrySet().iterator();
+    while (iterator.hasNext()) {
+      Map.Entry<String, ExpandSelectTreeNode> entry = iterator.next();
+      ExpandSelectTreeNodeImpl subNode = (ExpandSelectTreeNodeImpl) entry.getValue();
+      if (!subNode.isExpanded()) {
+        node.putLink(entry.getKey(), null);
+      } else {
+        consolidate(subNode);
+      }
+    }
+  }
+
+  private void consolidateTrueNode(final ExpandSelectTreeNodeImpl node) {
+    Map<String, ExpandSelectTreeNode> links = node.getLinks();
+    Set<Entry<String, ExpandSelectTreeNode>> linkEntries = links.entrySet();
+    List<String> toRemove = new ArrayList<String>();
+
+    for (Entry<String, ExpandSelectTreeNode> entry : linkEntries) {
+      ExpandSelectTreeNodeImpl subNode = (ExpandSelectTreeNodeImpl) entry.getValue();
+      if (subNode.isExpanded() && node.isExplicitlySelected()) {
+        subNode.setExplicitlySelected();
+        consolidate(subNode);
+      } else if (subNode.isExpanded()) {
+        consolidate(subNode);
+      } else {
+        toRemove.add(entry.getKey());
+      }
+    }
+
+    //
+    for (String key : toRemove) {
+      node.removeLink(key);
+    }
+  }
+
+  private void createSelectTree(final ExpandSelectTreeNodeImpl root) throws EdmException {
+    for (SelectItem item : initialSelect) {
+      ExpandSelectTreeNodeImpl actualNode = root;
+
+      for (NavigationPropertySegment navSegement : item.getNavigationPropertySegments()) {
+        actualNode = addSelectNode(actualNode, navSegement.getNavigationProperty().getName());
+      }
+
+      if (item.getProperty() != null) {
+        actualNode.addProperty(item.getProperty());
+      } else if (item.isStar()) {
+        actualNode.setAllExplicitly();
+      } else {
+        //The actual node is a navigation property and has no property or star so it is explicitly selected
+        actualNode.setExplicitlySelected();
+      }
+    }
+  }
+
+  private ExpandSelectTreeNodeImpl addSelectNode(final ExpandSelectTreeNodeImpl actualNode, final String navigationPropertyName) {
+    Map<String, ExpandSelectTreeNode> links = actualNode.getLinks();
+    if (!links.containsKey(navigationPropertyName)) {
+      ExpandSelectTreeNodeImpl subNode = new ExpandSelectTreeNodeImpl();
+      actualNode.putLink(navigationPropertyName, subNode);
+      if (actualNode.isExplicitlySelected()) {
+        //if a node was explicitly selected all sub nodes are explicitly selected
+        subNode.setExplicitlySelected();
+      } else {
+        if (actualNode.getAllKind() == AllKinds.IMPLICITLYTRUE) {
+          actualNode.setAllKindFalse();
+        }
+      }
+      return subNode;
+    } else {
+      return (ExpandSelectTreeNodeImpl) links.get(navigationPropertyName);
+    }
+  }
+
+  private void mergeExpandTree(final ExpandSelectTreeNodeImpl root) throws EdmException {
+    for (ArrayList<NavigationPropertySegment> singleExpand : initialExpand) {
+      ExpandSelectTreeNodeImpl actualNode = root;
+      for (NavigationPropertySegment navSegment : singleExpand) {
+        actualNode = addExpandNode(actualNode, navSegment.getNavigationProperty().getName());
+        if (actualNode == null) {
+          break;
+        }
+      }
+    }
+
+  }
+
+  private ExpandSelectTreeNodeImpl addExpandNode(final ExpandSelectTreeNodeImpl actualNode, final String navigationPropertyName) {
+    Map<String, ExpandSelectTreeNode> links = actualNode.getLinks();
+    if (!links.containsKey(navigationPropertyName)) {
+      if (actualNode.isExplicitlySelected() || (actualNode.isExplicitlySelected() && actualNode.isExpanded())) {
+        ExpandSelectTreeNodeImpl subNode = new ExpandSelectTreeNodeImpl();
+        subNode.setExpanded();
+        subNode.setExplicitlySelected();
+        actualNode.putLink(navigationPropertyName, subNode);
+        return subNode;
+      } else {
+        return null;
+      }
+    } else {
+      ExpandSelectTreeNodeImpl subNode = (ExpandSelectTreeNodeImpl) links.get(navigationPropertyName);
+      subNode.setExpanded();
+      return subNode;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeNodeImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeNodeImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeNodeImpl.java
new file mode 100644
index 0000000..bc49590
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/ExpandSelectTreeNodeImpl.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class ExpandSelectTreeNodeImpl implements ExpandSelectTreeNode {
+
+  public enum AllKinds {
+    IMPLICITLYTRUE(true), EXPLICITLYTRUE(true), FALSE(false);
+
+    private boolean booleanRepresentation;
+
+    private AllKinds(final boolean booleanRepresentation) {
+      this.booleanRepresentation = booleanRepresentation;
+    }
+
+    public boolean getBoolean() {
+      return booleanRepresentation;
+    }
+  }
+
+  private AllKinds isAll = AllKinds.IMPLICITLYTRUE;
+  private boolean isExplicitlySelected = false;
+  private boolean isExpanded = false;
+  private final List<EdmProperty> properties = new ArrayList<EdmProperty>();
+  private final Map<String, ExpandSelectTreeNodeImpl> links = new HashMap<String, ExpandSelectTreeNodeImpl>();
+
+  @Override
+  public boolean isAll() {
+    return isAll.getBoolean();
+  }
+
+  @Override
+  public List<EdmProperty> getProperties() {
+    return properties;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public Map<String, ExpandSelectTreeNode> getLinks() {
+    return (Map<String, ExpandSelectTreeNode>) ((Map<String, ? extends ExpandSelectTreeNode>) Collections.unmodifiableMap(links));
+  }
+
+  public void putLink(final String name, final ExpandSelectTreeNodeImpl node) {
+    links.put(name, node);
+  }
+
+  public void removeLink(final String name) {
+    links.remove(name);
+  }
+
+  public boolean isExplicitlySelected() {
+    return isExplicitlySelected;
+  }
+
+  public void setExplicitlySelected() {
+    isExplicitlySelected = true;
+    setAllExplicitly();
+  }
+
+  public boolean isExpanded() {
+    return isExpanded;
+  }
+
+  public void setExpanded() {
+    isExpanded = true;
+  }
+
+  public void addProperty(final EdmProperty property) {
+    if (property != null && isAll != AllKinds.EXPLICITLYTRUE && !properties.contains(property)) {
+      properties.add(property);
+      isAll = AllKinds.FALSE;
+    }
+  }
+
+  public void setAllExplicitly() {
+    properties.clear();
+    isAll = AllKinds.EXPLICITLYTRUE;
+  }
+
+  public AllKinds getAllKind() {
+    return isAll;
+  }
+
+  public void setAllKindFalse() {
+    isAll = AllKinds.FALSE;
+  }
+
+  public String toJsonString() {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .name("all").unquotedValue(Boolean.toString(isAll())).separator()
+          .name("properties")
+          .beginArray();
+      boolean first = true;
+      for (EdmProperty property : properties) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        jsonStreamWriter.stringValueRaw(property.getName());
+      }
+      jsonStreamWriter.endArray().separator()
+          .name("links")
+          .beginArray();
+      first = true;
+      for (Map.Entry<String, ExpandSelectTreeNodeImpl> entry : links.entrySet()) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        final String nodeString = entry.getValue() == null ? null : entry.getValue().toJsonString();
+        jsonStreamWriter.beginObject()
+            .name(entry.getKey()).unquotedValue(nodeString)
+            .endObject();
+      }
+      jsonStreamWriter.endArray()
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      throw new ODataRuntimeException("IOException: ", e);
+    } catch (final EdmException e) {
+      throw new ODataRuntimeException("EdmException: ", e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/KeyPredicateImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/KeyPredicateImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/KeyPredicateImpl.java
new file mode 100644
index 0000000..c7b3386
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/KeyPredicateImpl.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.uri;
+
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+
+/**
+ * @author SAP AG
+ */
+public class KeyPredicateImpl implements KeyPredicate {
+
+  public KeyPredicateImpl(final String literal, final EdmProperty property) {
+    super();
+    this.literal = literal;
+    this.property = property;
+  }
+
+  private String literal;
+  private EdmProperty property;
+
+  @Override
+  public String getLiteral() {
+    return literal;
+  }
+
+  public void setValue(final String value) {
+    literal = value;
+  }
+
+  @Override
+  public EdmProperty getProperty() {
+    return property;
+  }
+
+  public void setProperty(final EdmProperty property) {
+    this.property = property;
+  }
+
+  @Override
+  public String toString() {
+    return "KeyPredicate: literal=" + literal + ", propertyName=" + property;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationPropertySegmentImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationPropertySegmentImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationPropertySegmentImpl.java
new file mode 100644
index 0000000..0f1ebe7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationPropertySegmentImpl.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.uri;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+
+/**
+ * @author SAP AG
+ */
+public class NavigationPropertySegmentImpl implements NavigationPropertySegment {
+
+  private EdmNavigationProperty navigationProperty;
+  private EdmEntitySet targetEntitySet;
+
+  @Override
+  public EdmNavigationProperty getNavigationProperty() {
+    return navigationProperty;
+  }
+
+  public void setNavigationProperty(final EdmNavigationProperty navigationProperty) {
+    this.navigationProperty = navigationProperty;
+  }
+
+  @Override
+  public EdmEntitySet getTargetEntitySet() {
+    return targetEntitySet;
+  }
+
+  public void setTargetEntitySet(final EdmEntitySet targetEntitySet) {
+    this.targetEntitySet = targetEntitySet;
+  }
+
+  @Override
+  public String toString() {
+    return "Navigation Property: " + navigationProperty + ", Target Entity Set: " + targetEntitySet;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationSegmentImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationSegmentImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationSegmentImpl.java
new file mode 100644
index 0000000..ce4a935
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/NavigationSegmentImpl.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * @author SAP AG
+ */
+public class NavigationSegmentImpl implements NavigationSegment {
+
+  private EdmNavigationProperty navigationProperty;
+  private EdmEntitySet targetEntitySet;
+  private List<KeyPredicate> keyPredicates = Collections.emptyList();
+
+  @Override
+  public List<KeyPredicate> getKeyPredicates() {
+    return keyPredicates;
+  }
+
+  public void setKeyPredicates(final List<KeyPredicate> keyPredicates) {
+    this.keyPredicates = keyPredicates;
+  }
+
+  @Override
+  public EdmNavigationProperty getNavigationProperty() {
+    return navigationProperty;
+  }
+
+  public void setNavigationProperty(final EdmNavigationProperty edmNavigationProperty) {
+    navigationProperty = edmNavigationProperty;
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet() {
+    return targetEntitySet;
+  }
+
+  public void setEntitySet(final EdmEntitySet edmEntitySet) {
+    targetEntitySet = edmEntitySet;
+  }
+
+  @Override
+  public String toString() {
+    return "Navigation Property: " + navigationProperty + ", "
+        + "Target Entity Set: " + targetEntitySet + ", "
+        + "Key Predicates: " + keyPredicates;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SelectItemImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SelectItemImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SelectItemImpl.java
new file mode 100644
index 0000000..b25879b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SelectItemImpl.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+
+/**
+ * @author SAP AG
+ */
+public class SelectItemImpl implements SelectItem {
+
+  private List<NavigationPropertySegment> navigationPropertySegments = Collections.emptyList();
+  private EdmProperty property;
+  private boolean star;
+
+  @Override
+  public boolean isStar() {
+    return star;
+  }
+
+  public void setStar(final boolean star) {
+    this.star = star;
+  }
+
+  @Override
+  public EdmProperty getProperty() {
+    return property;
+  }
+
+  public void setProperty(final EdmProperty property) {
+    this.property = property;
+  }
+
+  public void addNavigationPropertySegment(final NavigationPropertySegment segment) {
+    if (navigationPropertySegments.equals(Collections.EMPTY_LIST)) {
+      navigationPropertySegments = new ArrayList<NavigationPropertySegment>();
+    }
+
+    navigationPropertySegments.add(segment);
+  }
+
+  @Override
+  public List<NavigationPropertySegment> getNavigationPropertySegments() {
+    return navigationPropertySegments;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SystemQueryOption.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SystemQueryOption.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SystemQueryOption.java
new file mode 100644
index 0000000..e30bee7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/SystemQueryOption.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.uri;
+
+/**
+ * @author SAP AG
+ */
+public enum SystemQueryOption {
+  $format, $filter, $inlinecount, $orderby, $skiptoken, $skip, $top, $expand, $select;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriInfoImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriInfoImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriInfoImpl.java
new file mode 100644
index 0000000..9db2427
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriInfoImpl.java
@@ -0,0 +1,324 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+
+/**
+ * @author SAP AG
+ */
+public class UriInfoImpl implements UriInfo {
+
+  private UriType uriType;
+
+  private EdmEntityContainer entityContainer;
+  private EdmEntitySet startEntitySet;
+  private EdmEntitySet targetEntitySet;
+  private EdmFunctionImport functionImport;
+  private EdmType targetType;
+  private List<KeyPredicate> keyPredicates = Collections.emptyList();
+  private List<NavigationSegment> navigationSegments = Collections.emptyList();
+  private List<EdmProperty> propertyPath = Collections.emptyList();
+  private boolean count;
+  private boolean value;
+  private boolean links;
+
+  private String format;
+  private FilterExpression filter;
+  private InlineCount inlineCount;
+  private OrderByExpression orderBy;
+  private String skipToken;
+  private Integer skip;
+  private Integer top;
+  private List<ArrayList<NavigationPropertySegment>> expand = Collections.emptyList();
+  private List<SelectItem> select = Collections.emptyList();
+  private Map<String, EdmLiteral> functionImportParameters = Collections.emptyMap();
+  private Map<String, String> customQueryOptions = Collections.emptyMap();
+
+  public UriType getUriType() {
+    return uriType;
+  }
+
+  public void setUriType(final UriType uriType) {
+    this.uriType = uriType;
+  }
+
+  public void setEntityContainer(final EdmEntityContainer entityContainer) {
+    this.entityContainer = entityContainer;
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() {
+    return entityContainer;
+  }
+
+  public void setStartEntitySet(final EdmEntitySet edmEntitySet) {
+    startEntitySet = edmEntitySet;
+  }
+
+  @Override
+  public EdmEntitySet getStartEntitySet() {
+    return startEntitySet;
+  }
+
+  public void setTargetEntitySet(final EdmEntitySet targetEntitySet) {
+    this.targetEntitySet = targetEntitySet;
+  }
+
+  @Override
+  public EdmEntitySet getTargetEntitySet() {
+    return targetEntitySet;
+  }
+
+  public void setFunctionImport(final EdmFunctionImport functionImport) {
+    this.functionImport = functionImport;
+  }
+
+  @Override
+  public EdmFunctionImport getFunctionImport() {
+    return functionImport;
+  }
+
+  public void setTargetType(final EdmType targetType) {
+    this.targetType = targetType;
+  }
+
+  @Override
+  public EdmType getTargetType() {
+    return targetType;
+  }
+
+  public void setKeyPredicates(final List<KeyPredicate> keyPredicates) {
+    this.keyPredicates = keyPredicates;
+  }
+
+  @Override
+  public List<KeyPredicate> getKeyPredicates() {
+    return keyPredicates;
+  }
+
+  @Override
+  public List<KeyPredicate> getTargetKeyPredicates() {
+    return navigationSegments.isEmpty() ?
+        keyPredicates :
+        navigationSegments.get(navigationSegments.size() - 1).getKeyPredicates();
+  }
+
+  public void addNavigationSegment(final NavigationSegment navigationSegment) {
+    if (navigationSegments.equals(Collections.EMPTY_LIST)) {
+      navigationSegments = new ArrayList<NavigationSegment>();
+    }
+
+    navigationSegments.add(navigationSegment);
+  }
+
+  @Override
+  public List<NavigationSegment> getNavigationSegments() {
+    return navigationSegments;
+  }
+
+  public void addProperty(final EdmProperty property) {
+    if (propertyPath.equals(Collections.EMPTY_LIST)) {
+      propertyPath = new ArrayList<EdmProperty>();
+    }
+
+    propertyPath.add(property);
+  }
+
+  @Override
+  public List<EdmProperty> getPropertyPath() {
+    return propertyPath;
+  }
+
+  public void setCount(final boolean count) {
+    this.count = count;
+  }
+
+  @Override
+  public boolean isCount() {
+    return count;
+  }
+
+  public void setValue(final boolean value) {
+    this.value = value;
+  }
+
+  @Override
+  public boolean isValue() {
+    return value;
+  }
+
+  public void setLinks(final boolean links) {
+    this.links = links;
+  }
+
+  @Override
+  public boolean isLinks() {
+    return links;
+  }
+
+  public void setFormat(final String contentType) {
+    format = contentType;
+  }
+
+  @Override
+  public String getFormat() {
+    return format;
+  }
+
+  public void setFilter(final FilterExpression filter) {
+    this.filter = filter;
+  }
+
+  @Override
+  public FilterExpression getFilter() {
+    return filter;
+  }
+
+  public void setInlineCount(final InlineCount inlineCount) {
+    this.inlineCount = inlineCount;
+  }
+
+  @Override
+  public InlineCount getInlineCount() {
+    return inlineCount;
+  }
+
+  public void setOrderBy(final OrderByExpression orderBy) {
+    this.orderBy = orderBy;
+  }
+
+  @Override
+  public OrderByExpression getOrderBy() {
+    return orderBy;
+  }
+
+  public void setSkipToken(final String skipToken) {
+    this.skipToken = skipToken;
+  }
+
+  @Override
+  public String getSkipToken() {
+    return skipToken;
+  }
+
+  public void setSkip(final Integer skip) {
+    this.skip = skip;
+  }
+
+  @Override
+  public Integer getSkip() {
+    return skip;
+  }
+
+  public void setTop(final Integer top) {
+    this.top = top;
+  }
+
+  @Override
+  public Integer getTop() {
+    return top;
+  }
+
+  public void setExpand(final List<ArrayList<NavigationPropertySegment>> expand) {
+    this.expand = expand;
+  }
+
+  @Override
+  public List<ArrayList<NavigationPropertySegment>> getExpand() {
+    return expand;
+  }
+
+  public void setSelect(final List<SelectItem> select) {
+    this.select = select;
+  }
+
+  @Override
+  public List<SelectItem> getSelect() {
+    return select;
+  }
+
+  public void addFunctionImportParameter(final String name, final EdmLiteral value) {
+    if (functionImportParameters.equals(Collections.EMPTY_MAP)) {
+      functionImportParameters = new HashMap<String, EdmLiteral>();
+    }
+
+    functionImportParameters.put(name, value);
+  }
+
+  @Override
+  public Map<String, EdmLiteral> getFunctionImportParameters() {
+    return functionImportParameters;
+  }
+
+  @Override
+  public Map<String, String> getCustomQueryOptions() {
+    return customQueryOptions;
+  }
+
+  public void setCustomQueryOptions(final Map<String, String> customQueryOptions) {
+    this.customQueryOptions = customQueryOptions;
+  }
+
+  @Override
+  public String toString() {
+    return "UriParserResult: uriType=" + uriType + ", "
+        + "entityContainer=" + entityContainer + ", "
+        + "entitySet=" + startEntitySet + ", "
+        + "targetEntitySet=" + targetEntitySet + ", "
+        + "functionImport=" + functionImport + ", "
+        + "targetType=" + targetType + ", "
+        + "keyPredicates=" + keyPredicates + ", "
+        + "navigationSegments=" + navigationSegments + ", "
+        + "propertyPath=" + propertyPath + ", "
+        + "isCount=" + count + ", "
+        + "isValue=" + value + ", "
+        + "isLinks=" + links + ", "
+        + "contentType=" + format + ", "
+        + "filter=" + filter + ", "
+        + "inlineCount=" + inlineCount + ", "
+        + "orderBy=" + orderBy + ", "
+        + "skipToken=" + skipToken + ", "
+        + "skip=" + skip + ", "
+        + "top=" + top + ", "
+        + "expand=" + expand + ", "
+        + "select=" + select + ", "
+        + "functionImportParameters=" + functionImportParameters + ", "
+        + "customQueryOptions=" + customQueryOptions;
+  }
+}


[14/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlCollectionEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlCollectionEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlCollectionEntityProducer.java
new file mode 100644
index 0000000..93beaa1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlCollectionEntityProducer.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Provider for writing a collection of simple-type or complex-type instances
+ * @author SAP AG
+ */
+public class XmlCollectionEntityProducer {
+
+  public static void append(final XMLStreamWriter writer, final EntityPropertyInfo propertyInfo, final List<?> data) throws EntityProviderException {
+    try {
+      writer.writeStartElement(propertyInfo.getName());
+      writer.writeDefaultNamespace(Edm.NAMESPACE_D_2007_08);
+      if (propertyInfo.isComplex()) {
+        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+      }
+      XmlPropertyEntityProducer provider = new XmlPropertyEntityProducer();
+      for (final Object propertyData : data) {
+        provider.append(writer, FormatXml.D_ELEMENT, propertyInfo, propertyData);
+      }
+      writer.writeEndElement();
+      writer.flush();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlErrorDocumentProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlErrorDocumentProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlErrorDocumentProducer.java
new file mode 100644
index 0000000..a94f395
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlErrorDocumentProducer.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.Locale;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+public class XmlErrorDocumentProducer {
+
+  public void writeErrorDocument(final XMLStreamWriter writer, final String errorCode, final String message, final Locale locale, final String innerError) throws XMLStreamException {
+    writer.writeStartDocument();
+    writer.writeStartElement(FormatXml.M_ERROR);
+    writer.writeDefaultNamespace(Edm.NAMESPACE_M_2007_08);
+    writer.writeStartElement(FormatXml.M_CODE);
+    if (errorCode != null) {
+      writer.writeCharacters(errorCode);
+    }
+    writer.writeEndElement();
+    writer.writeStartElement(FormatXml.M_MESSAGE);
+    if (locale != null) {
+      writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_LANG, getLocale(locale));
+    } else {
+      writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_LANG, "");
+    }
+    if (message != null) {
+      writer.writeCharacters(message);
+    }
+    writer.writeEndElement();
+
+    if (innerError != null) {
+      writer.writeStartElement(FormatXml.M_INNER_ERROR);
+      writer.writeCharacters(innerError);
+      writer.writeEndElement();
+    }
+
+    writer.writeEndDocument();
+  }
+
+  /**
+   * Gets language and country as defined in RFC 4646 based on {@link Locale}.
+   */
+  private String getLocale(final Locale locale) {
+    if (locale.getCountry().isEmpty()) {
+      return locale.getLanguage();
+    } else {
+      return locale.getLanguage() + "-" + locale.getCountry();
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinkEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinkEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinkEntityProducer.java
new file mode 100644
index 0000000..b3d4b4d
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinkEntityProducer.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+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.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Provider for writing a single link.
+ * @author SAP AG
+ */
+public class XmlLinkEntityProducer {
+
+  private final EntityProviderWriteProperties properties;
+
+  public XmlLinkEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final XMLStreamWriter writer, final EntityInfoAggregator entityInfo, final Map<String, Object> data, final boolean isRootElement) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.D_URI);
+      if (isRootElement) {
+        writer.writeDefaultNamespace(Edm.NAMESPACE_D_2007_08);
+      }
+      if (properties.getServiceRoot() != null) {
+        writer.writeCharacters(properties.getServiceRoot().toASCIIString());
+      }
+      writer.writeCharacters(AtomEntryEntityProducer.createSelfLink(entityInfo, data, null));
+      writer.writeEndElement();
+      writer.flush();
+    } catch (final XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinksEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinksEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinksEntityProducer.java
new file mode 100644
index 0000000..f361718
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlLinksEntityProducer.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+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.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Provider for writing a collection of links
+ * @author SAP AG
+ */
+public class XmlLinksEntityProducer {
+
+  private final EntityProviderWriteProperties properties;
+
+  public XmlLinksEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final XMLStreamWriter writer, final EntityInfoAggregator entityInfo, final List<Map<String, Object>> data) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.D_LINKS);
+      writer.writeDefaultNamespace(Edm.NAMESPACE_D_2007_08);
+      if (properties.getInlineCount() != null) {
+        writer.writeStartElement(Edm.PREFIX_M, FormatXml.M_COUNT, Edm.NAMESPACE_M_2007_08);
+        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+        writer.writeCharacters(properties.getInlineCount().toString());
+        writer.writeEndElement();
+      }
+      XmlLinkEntityProducer provider = new XmlLinkEntityProducer(properties);
+      for (final Map<String, Object> entityData : data) {
+        provider.append(writer, entityInfo, entityData, false);
+      }
+      writer.writeEndElement();
+      writer.flush();
+    } catch (final XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlMetadataProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlMetadataProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlMetadataProducer.java
new file mode 100644
index 0000000..265c092
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlMetadataProducer.java
@@ -0,0 +1,591 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.CustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.provider.DataServices;
+import org.apache.olingo.odata2.api.edm.provider.Documentation;
+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.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.OnDelete;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraintRole;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.api.edm.provider.Using;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+public class XmlMetadataProducer {
+
+  public static void writeMetadata(final DataServices metadata, final XMLStreamWriter xmlStreamWriter, Map<String, String> predefinedNamespaces) throws EntityProviderException {
+
+    try {
+      xmlStreamWriter.writeStartDocument();
+      xmlStreamWriter.setPrefix(Edm.PREFIX_EDMX, Edm.NAMESPACE_EDMX_2007_06);
+      xmlStreamWriter.setPrefix(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+      xmlStreamWriter.setDefaultNamespace(Edm.NAMESPACE_EDM_2008_09);
+
+      xmlStreamWriter.writeStartElement(Edm.NAMESPACE_EDMX_2007_06, "Edmx");
+      xmlStreamWriter.writeAttribute("Version", "1.0");
+      xmlStreamWriter.writeNamespace(Edm.PREFIX_EDMX, Edm.NAMESPACE_EDMX_2007_06);
+
+      xmlStreamWriter.writeStartElement(Edm.NAMESPACE_EDMX_2007_06, "DataServices");
+      xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "DataServiceVersion", metadata.getDataServiceVersion());
+      xmlStreamWriter.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+
+      if (predefinedNamespaces != null) {
+        for (Map.Entry<String, String> entry : predefinedNamespaces.entrySet()) {
+          xmlStreamWriter.writeNamespace(entry.getKey(), entry.getValue());
+        }
+      } else {
+        predefinedNamespaces = new HashMap<String, String>();
+      }
+
+      Collection<Schema> schemas = metadata.getSchemas();
+      if (schemas != null) {
+        for (Schema schema : schemas) {
+          xmlStreamWriter.writeStartElement("Schema");
+          if (schema.getAlias() != null) {
+            xmlStreamWriter.writeAttribute("Alias", schema.getAlias());
+          }
+          xmlStreamWriter.writeAttribute("Namespace", schema.getNamespace());
+          xmlStreamWriter.writeDefaultNamespace(Edm.NAMESPACE_EDM_2008_09);
+
+          writeAnnotationAttributes(schema.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+          Collection<Using> usings = schema.getUsings();
+          if (usings != null) {
+            for (Using using : usings) {
+              xmlStreamWriter.writeStartElement("Using");
+              xmlStreamWriter.writeAttribute("Namespace", using.getNamespace());
+              xmlStreamWriter.writeAttribute("Alias", using.getAlias());
+              writeAnnotationAttributes(using.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+              writeDocumentation(using.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+              writeAnnotationElements(using.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+              xmlStreamWriter.writeEndElement();
+            }
+          }
+
+          Collection<EntityType> entityTypes = schema.getEntityTypes();
+          if (entityTypes != null) {
+            for (EntityType entityType : entityTypes) {
+              xmlStreamWriter.writeStartElement("EntityType");
+              xmlStreamWriter.writeAttribute("Name", entityType.getName());
+              if (entityType.getBaseType() != null) {
+                xmlStreamWriter.writeAttribute("BaseType", entityType.getBaseType().toString());
+              }
+              if (entityType.isAbstract()) {
+                xmlStreamWriter.writeAttribute("Abstract", "true");
+              }
+              if (entityType.isHasStream()) {
+                xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "HasStream", "true");
+              }
+
+              writeCustomizableFeedMappings(entityType.getCustomizableFeedMappings(), xmlStreamWriter);
+
+              writeAnnotationAttributes(entityType.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+              writeDocumentation(entityType.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+              Key key = entityType.getKey();
+              if (key != null) {
+                xmlStreamWriter.writeStartElement("Key");
+
+                writeAnnotationAttributes(key.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                Collection<PropertyRef> propertyRefs = entityType.getKey().getKeys();
+                for (PropertyRef propertyRef : propertyRefs) {
+                  xmlStreamWriter.writeStartElement("PropertyRef");
+
+                  writeAnnotationAttributes(propertyRef.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                  xmlStreamWriter.writeAttribute("Name", propertyRef.getName());
+
+                  writeAnnotationElements(propertyRef.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                  xmlStreamWriter.writeEndElement();
+                }
+
+                writeAnnotationElements(key.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                xmlStreamWriter.writeEndElement();
+              }
+
+              Collection<Property> properties = entityType.getProperties();
+              if (properties != null) {
+                writeProperties(properties, predefinedNamespaces, xmlStreamWriter);
+              }
+
+              Collection<NavigationProperty> navigationProperties = entityType.getNavigationProperties();
+              if (navigationProperties != null) {
+                for (NavigationProperty navigationProperty : navigationProperties) {
+                  xmlStreamWriter.writeStartElement("NavigationProperty");
+                  xmlStreamWriter.writeAttribute("Name", navigationProperty.getName());
+                  xmlStreamWriter.writeAttribute("Relationship", navigationProperty.getRelationship().toString());
+                  xmlStreamWriter.writeAttribute("FromRole", navigationProperty.getFromRole());
+                  xmlStreamWriter.writeAttribute("ToRole", navigationProperty.getToRole());
+
+                  writeAnnotationAttributes(navigationProperty.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                  writeDocumentation(navigationProperty.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+                  writeAnnotationElements(navigationProperty.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                  xmlStreamWriter.writeEndElement();
+                }
+              }
+
+              writeAnnotationElements(entityType.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+              xmlStreamWriter.writeEndElement();
+            }
+          }
+
+          Collection<ComplexType> complexTypes = schema.getComplexTypes();
+          if (complexTypes != null) {
+            for (ComplexType complexType : complexTypes) {
+              xmlStreamWriter.writeStartElement("ComplexType");
+              xmlStreamWriter.writeAttribute("Name", complexType.getName());
+              if (complexType.getBaseType() != null) {
+                xmlStreamWriter.writeAttribute("BaseType", complexType.getBaseType().toString());
+              }
+              if (complexType.isAbstract()) {
+                xmlStreamWriter.writeAttribute("Abstract", "true");
+              }
+
+              writeAnnotationAttributes(complexType.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+              writeDocumentation(complexType.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+              Collection<Property> properties = complexType.getProperties();
+              if (properties != null) {
+                writeProperties(properties, predefinedNamespaces, xmlStreamWriter);
+              }
+
+              writeAnnotationElements(complexType.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+              xmlStreamWriter.writeEndElement();
+            }
+          }
+
+          Collection<Association> associations = schema.getAssociations();
+          if (associations != null) {
+            for (Association association : associations) {
+              xmlStreamWriter.writeStartElement("Association");
+              xmlStreamWriter.writeAttribute("Name", association.getName());
+
+              writeAnnotationAttributes(association.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+              writeDocumentation(association.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+              writeAssociationEnd(association.getEnd1(), predefinedNamespaces, xmlStreamWriter);
+              writeAssociationEnd(association.getEnd2(), predefinedNamespaces, xmlStreamWriter);
+
+              ReferentialConstraint referentialConstraint = association.getReferentialConstraint();
+              if (referentialConstraint != null) {
+                xmlStreamWriter.writeStartElement("ReferentialConstraint");
+                writeAnnotationAttributes(referentialConstraint.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+                writeDocumentation(referentialConstraint.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+                ReferentialConstraintRole principal = referentialConstraint.getPrincipal();
+                xmlStreamWriter.writeStartElement("Principal");
+                xmlStreamWriter.writeAttribute("Role", principal.getRole());
+                writeAnnotationAttributes(principal.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                for (PropertyRef propertyRef : principal.getPropertyRefs()) {
+                  xmlStreamWriter.writeStartElement("PropertyRef");
+                  xmlStreamWriter.writeAttribute("Name", propertyRef.getName());
+                  xmlStreamWriter.writeEndElement();
+                }
+                writeAnnotationElements(principal.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+                xmlStreamWriter.writeEndElement();
+
+                ReferentialConstraintRole dependent = referentialConstraint.getDependent();
+                xmlStreamWriter.writeStartElement("Dependent");
+                xmlStreamWriter.writeAttribute("Role", dependent.getRole());
+                writeAnnotationAttributes(dependent.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                for (PropertyRef propertyRef : dependent.getPropertyRefs()) {
+                  xmlStreamWriter.writeStartElement("PropertyRef");
+                  xmlStreamWriter.writeAttribute("Name", propertyRef.getName());
+                  xmlStreamWriter.writeEndElement();
+                }
+                writeAnnotationElements(dependent.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+                xmlStreamWriter.writeEndElement();
+
+                writeAnnotationElements(referentialConstraint.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+                xmlStreamWriter.writeEndElement();
+              }
+
+              writeAnnotationElements(association.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+              xmlStreamWriter.writeEndElement();
+            }
+          }
+
+          Collection<EntityContainer> entityContainers = schema.getEntityContainers();
+          if (entityContainers != null) {
+            for (EntityContainer entityContainer : entityContainers) {
+              xmlStreamWriter.writeStartElement("EntityContainer");
+              xmlStreamWriter.writeAttribute("Name", entityContainer.getName());
+              if (entityContainer.getExtendz() != null) {
+                xmlStreamWriter.writeAttribute("Extends", entityContainer.getExtendz());
+              }
+              if (entityContainer.isDefaultEntityContainer()) {
+                xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "IsDefaultEntityContainer", "true");
+              }
+
+              writeAnnotationAttributes(entityContainer.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+              writeDocumentation(entityContainer.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+              Collection<EntitySet> entitySets = entityContainer.getEntitySets();
+              if (entitySets != null) {
+                for (EntitySet entitySet : entitySets) {
+                  xmlStreamWriter.writeStartElement("EntitySet");
+                  xmlStreamWriter.writeAttribute("Name", entitySet.getName());
+                  xmlStreamWriter.writeAttribute("EntityType", entitySet.getEntityType().toString());
+
+                  writeAnnotationAttributes(entitySet.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                  writeDocumentation(entitySet.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+                  writeAnnotationElements(entitySet.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                  xmlStreamWriter.writeEndElement();
+                }
+              }
+
+              Collection<AssociationSet> associationSets = entityContainer.getAssociationSets();
+              if (associationSets != null) {
+                for (AssociationSet associationSet : associationSets) {
+                  xmlStreamWriter.writeStartElement("AssociationSet");
+                  xmlStreamWriter.writeAttribute("Name", associationSet.getName());
+                  xmlStreamWriter.writeAttribute("Association", associationSet.getAssociation().toString());
+
+                  writeAnnotationAttributes(associationSet.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                  writeDocumentation(associationSet.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+                  writeAssociationSetEnd(associationSet.getEnd1(), predefinedNamespaces, xmlStreamWriter);
+                  writeAssociationSetEnd(associationSet.getEnd2(), predefinedNamespaces, xmlStreamWriter);
+
+                  writeAnnotationElements(associationSet.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                  xmlStreamWriter.writeEndElement();
+                }
+              }
+
+              Collection<FunctionImport> functionImports = entityContainer.getFunctionImports();
+              if (functionImports != null) {
+                for (FunctionImport functionImport : functionImports) {
+                  xmlStreamWriter.writeStartElement("FunctionImport");
+                  xmlStreamWriter.writeAttribute("Name", functionImport.getName());
+                  if (functionImport.getReturnType() != null) {
+                    xmlStreamWriter.writeAttribute("ReturnType", functionImport.getReturnType().toString());
+                  }
+                  if (functionImport.getEntitySet() != null) {
+                    xmlStreamWriter.writeAttribute("EntitySet", functionImport.getEntitySet());
+                  }
+                  if (functionImport.getHttpMethod() != null) {
+                    xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "HttpMethod", functionImport.getHttpMethod());
+                  }
+
+                  writeAnnotationAttributes(functionImport.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                  writeDocumentation(functionImport.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+                  Collection<FunctionImportParameter> functionImportParameters = functionImport.getParameters();
+                  if (functionImportParameters != null) {
+                    for (FunctionImportParameter functionImportParameter : functionImportParameters) {
+                      xmlStreamWriter.writeStartElement("Parameter");
+                      xmlStreamWriter.writeAttribute("Name", functionImportParameter.getName());
+                      xmlStreamWriter.writeAttribute("Type", functionImportParameter.getType().getFullQualifiedName().toString());
+                      if (functionImportParameter.getMode() != null) {
+                        xmlStreamWriter.writeAttribute("Mode", functionImportParameter.getMode());
+                      }
+
+                      writeFacets(xmlStreamWriter, functionImportParameter.getFacets());
+
+                      writeAnnotationAttributes(functionImportParameter.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+                      writeDocumentation(functionImportParameter.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+                      writeAnnotationElements(functionImportParameter.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                      xmlStreamWriter.writeEndElement();
+                    }
+                  }
+
+                  writeAnnotationElements(functionImport.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+                  xmlStreamWriter.writeEndElement();
+                }
+              }
+
+              writeAnnotationElements(entityContainer.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+              xmlStreamWriter.writeEndElement();
+            }
+          }
+
+          writeAnnotationElements(schema.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+          xmlStreamWriter.writeEndElement();
+        }
+      }
+
+      xmlStreamWriter.writeEndElement();
+      xmlStreamWriter.writeEndElement();
+      xmlStreamWriter.writeEndDocument();
+
+      xmlStreamWriter.flush();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (FactoryConfigurationError e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private static void writeCustomizableFeedMappings(final CustomizableFeedMappings customizableFeedMappings, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    if (customizableFeedMappings != null) {
+      if (customizableFeedMappings.getFcKeepInContent() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "FC_KeepInContent", customizableFeedMappings.getFcKeepInContent().toString().toLowerCase(Locale.ROOT));
+      }
+      if (customizableFeedMappings.getFcContentKind() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "FC_ContentKind", customizableFeedMappings.getFcContentKind().toString());
+      }
+      if (customizableFeedMappings.getFcNsPrefix() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "FC_NsPrefix", customizableFeedMappings.getFcNsPrefix());
+      }
+      if (customizableFeedMappings.getFcNsUri() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "FC_NsUri", customizableFeedMappings.getFcNsUri());
+      }
+      if (customizableFeedMappings.getFcSourcePath() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "FC_SourcePath", customizableFeedMappings.getFcSourcePath());
+      }
+      if (customizableFeedMappings.getFcTargetPath() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "FC_TargetPath", customizableFeedMappings.getFcTargetPath().toString());
+      }
+    }
+  }
+
+  private static void writeProperties(final Collection<Property> properties, final Map<String, String> predefinedNamespaces, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    for (Property property : properties) {
+      xmlStreamWriter.writeStartElement("Property");
+      xmlStreamWriter.writeAttribute("Name", property.getName());
+      if (property instanceof SimpleProperty) {
+        xmlStreamWriter.writeAttribute("Type", ((SimpleProperty) property).getType().getFullQualifiedName().toString());
+      } else if (property instanceof ComplexProperty) {
+        xmlStreamWriter.writeAttribute("Type", ((ComplexProperty) property).getType().toString());
+      } else {
+        throw new ODataRuntimeException();
+      }
+
+      writeFacets(xmlStreamWriter, property.getFacets());
+
+      if (property.getMimeType() != null) {
+        xmlStreamWriter.writeAttribute(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08, "MimeType", property.getMimeType());
+      }
+
+      writeCustomizableFeedMappings(property.getCustomizableFeedMappings(), xmlStreamWriter);
+
+      writeAnnotationAttributes(property.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+      writeDocumentation(property.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+      writeAnnotationElements(property.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+      xmlStreamWriter.writeEndElement();
+    }
+  }
+
+  private static void writeFacets(final XMLStreamWriter xmlStreamWriter, final EdmFacets facets) throws XMLStreamException {
+    if (facets != null) {
+      if (facets.isNullable() != null) {
+        xmlStreamWriter.writeAttribute("Nullable", facets.isNullable().toString().toLowerCase(Locale.ROOT));
+      }
+      if (facets.getDefaultValue() != null) {
+        xmlStreamWriter.writeAttribute("DefaultValue", facets.getDefaultValue());
+      }
+      if (facets.getMaxLength() != null) {
+        xmlStreamWriter.writeAttribute("MaxLength", facets.getMaxLength().toString());
+      }
+      if (facets.isFixedLength() != null) {
+        xmlStreamWriter.writeAttribute("FixedLength", facets.isFixedLength().toString().toLowerCase(Locale.ROOT));
+      }
+      if (facets.getPrecision() != null) {
+        xmlStreamWriter.writeAttribute("Precision", facets.getPrecision().toString());
+      }
+      if (facets.getScale() != null) {
+        xmlStreamWriter.writeAttribute("Scale", facets.getScale().toString());
+      }
+      if (facets.isUnicode() != null) {
+        xmlStreamWriter.writeAttribute("Unicode", facets.isUnicode().toString());
+      }
+      if (facets.getCollation() != null) {
+        xmlStreamWriter.writeAttribute("Collation", facets.getCollation());
+      }
+      if (facets.getConcurrencyMode() != null) {
+        xmlStreamWriter.writeAttribute("ConcurrencyMode", facets.getConcurrencyMode().toString());
+      }
+    }
+  }
+
+  private static void writeAssociationEnd(final AssociationEnd end, final Map<String, String> predefinedNamespaces, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    xmlStreamWriter.writeStartElement("End");
+    xmlStreamWriter.writeAttribute("Type", end.getType().toString());
+    xmlStreamWriter.writeAttribute("Multiplicity", end.getMultiplicity().toString());
+    if (end.getRole() != null) {
+      xmlStreamWriter.writeAttribute("Role", end.getRole());
+    }
+
+    writeAnnotationAttributes(end.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+    writeDocumentation(end.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+
+    OnDelete onDelete = end.getOnDelete();
+    if (onDelete != null) {
+      xmlStreamWriter.writeStartElement("OnDelete");
+      xmlStreamWriter.writeAttribute("Action", onDelete.getAction().toString());
+      writeAnnotationAttributes(onDelete.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+      writeDocumentation(onDelete.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+      writeAnnotationElements(onDelete.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+      xmlStreamWriter.writeEndElement();
+    }
+
+    writeAnnotationElements(end.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+
+    xmlStreamWriter.writeEndElement();
+  }
+
+  private static void writeAssociationSetEnd(final AssociationSetEnd end, final Map<String, String> predefinedNamespaces, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    xmlStreamWriter.writeStartElement("End");
+    xmlStreamWriter.writeAttribute("EntitySet", end.getEntitySet().toString());
+    if (end.getRole() != null) {
+      xmlStreamWriter.writeAttribute("Role", end.getRole());
+    }
+    writeAnnotationAttributes(end.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+    writeDocumentation(end.getDocumentation(), predefinedNamespaces, xmlStreamWriter);
+    writeAnnotationElements(end.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+    xmlStreamWriter.writeEndElement();
+  }
+
+  private static void writeDocumentation(final Documentation documentation, final Map<String, String> predefinedNamespaces, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    if (documentation != null) {
+      xmlStreamWriter.writeStartElement("Documentation");
+      writeAnnotationAttributes(documentation.getAnnotationAttributes(), predefinedNamespaces, null, xmlStreamWriter);
+
+      xmlStreamWriter.writeStartElement("Summary");
+      xmlStreamWriter.writeCharacters(documentation.getSummary());
+      xmlStreamWriter.writeEndElement();
+
+      xmlStreamWriter.writeStartElement("LongDescription");
+      xmlStreamWriter.writeCharacters(documentation.getLongDescription());
+      xmlStreamWriter.writeEndElement();
+
+      writeAnnotationElements(documentation.getAnnotationElements(), predefinedNamespaces, xmlStreamWriter);
+      xmlStreamWriter.writeEndElement();
+    }
+  }
+
+  private static void writeAnnotationAttributes(final Collection<AnnotationAttribute> annotationAttributes, final Map<String, String> predefinedNamespaces, ArrayList<String> setNamespaces, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    if (annotationAttributes != null) {
+      if (setNamespaces == null) {
+        setNamespaces = new ArrayList<String>();
+      }
+      for (AnnotationAttribute annotationAttribute : annotationAttributes) {
+        if (annotationAttribute.getNamespace() != null) {
+          xmlStreamWriter.writeAttribute(annotationAttribute.getPrefix(), annotationAttribute.getNamespace(), annotationAttribute.getName(), annotationAttribute.getText());
+          if (setNamespaces.contains(annotationAttribute.getNamespace()) == false && predefinedNamespaces.containsValue(annotationAttribute.getNamespace()) == false) {
+            xmlStreamWriter.writeNamespace(annotationAttribute.getPrefix(), annotationAttribute.getNamespace());
+            setNamespaces.add(annotationAttribute.getNamespace());
+          }
+        } else {
+          xmlStreamWriter.writeAttribute(annotationAttribute.getName(), annotationAttribute.getText());
+        }
+      }
+    }
+  }
+
+  private static void writeAnnotationElements(final Collection<AnnotationElement> annotationElements, final Map<String, String> predefinedNamespaces, final XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
+    if (annotationElements != null) {
+      for (AnnotationElement annotationElement : annotationElements) {
+        ArrayList<String> setNamespaces = new ArrayList<String>();
+        if (annotationElement.getNamespace() != null) {
+          if (annotationElement.getPrefix() != null) {
+            xmlStreamWriter.writeStartElement(annotationElement.getPrefix(), annotationElement.getName(), annotationElement.getNamespace());
+            if (!predefinedNamespaces.containsValue(annotationElement.getNamespace())) {
+              xmlStreamWriter.writeNamespace(annotationElement.getPrefix(), annotationElement.getNamespace());
+              setNamespaces.add(annotationElement.getNamespace());
+            }
+          } else {
+            xmlStreamWriter.writeStartElement("", annotationElement.getName(), annotationElement.getNamespace());
+            if (!predefinedNamespaces.containsValue(annotationElement.getNamespace())) {
+              xmlStreamWriter.writeNamespace("", annotationElement.getNamespace());
+              setNamespaces.add(annotationElement.getNamespace());
+            }
+          }
+        } else {
+          xmlStreamWriter.writeStartElement(annotationElement.getName());
+        }
+
+        writeAnnotationAttributes(annotationElement.getAttributes(), predefinedNamespaces, setNamespaces, xmlStreamWriter);
+
+        if (annotationElement.getChildElements() != null) {
+          writeAnnotationElements(annotationElement.getChildElements(), predefinedNamespaces, xmlStreamWriter);
+        } else {
+          if (annotationElement.getText() != null) {
+            xmlStreamWriter.writeCharacters(annotationElement.getText());
+          }
+        }
+
+        xmlStreamWriter.writeEndElement();
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlPropertyEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlPropertyEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlPropertyEntityProducer.java
new file mode 100644
index 0000000..930f2f6
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/XmlPropertyEntityProducer.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Internal EntityProvider for simple and complex EDM properties which are pre-analyzed as {@link EntityPropertyInfo}.
+ * @author SAP AG
+ */
+public class XmlPropertyEntityProducer {
+
+  /**
+   * Append {@link Object} <code>value</code> based on {@link EntityPropertyInfo} to {@link XMLStreamWriter}
+   * in an already existing XML structure inside the d namespace.
+   * 
+   * @param writer
+   * @param name  Name of the outer XML tag
+   * @param propertyInfo
+   * @param value
+   * @throws EntityProviderException
+   */
+  public void append(final XMLStreamWriter writer, final String name, final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    try {
+      writer.writeStartElement(Edm.NAMESPACE_D_2007_08, name);
+
+      if (propertyInfo.isComplex()) {
+        appendProperty(writer, (EntityComplexPropertyInfo) propertyInfo, value);
+      } else {
+        appendProperty(writer, propertyInfo, value);
+      }
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  public void appendCustomProperty(final XMLStreamWriter writer, final String name, final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    try {
+      if (!propertyInfo.isComplex()) {
+        writeStartElementWithCustomNamespace(writer, propertyInfo, name);
+        appendProperty(writer, propertyInfo, value);
+        writer.writeEndElement();
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  /**
+   * Append {@link Object} <code>value</code> based on {@link EntityPropertyInfo} to {@link XMLStreamWriter}
+   * as a stand-alone XML structure, including writing of default namespace declarations.
+   * The name of the outermost XML element comes from the {@link EntityPropertyInfo}.
+   * 
+   * @param writer
+   * @param propertyInfo
+   * @param value
+   * @throws EntityProviderException
+   */
+  public void append(final XMLStreamWriter writer, final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    try {
+      writer.writeStartElement(propertyInfo.getName());
+      writer.writeDefaultNamespace(Edm.NAMESPACE_D_2007_08);
+      writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+
+      if (propertyInfo.isComplex()) {
+        appendProperty(writer, (EntityComplexPropertyInfo) propertyInfo, value);
+      } else {
+        appendProperty(writer, propertyInfo, value);
+      }
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  /**
+   * 
+   * @param writer
+   * @param propertyInfo
+   * @param value
+   * @throws XMLStreamException
+   * @throws EdmException
+   * @throws EntityProviderException
+   */
+  private void appendProperty(final XMLStreamWriter writer, final EntityComplexPropertyInfo propertyInfo, final Object value) throws XMLStreamException, EdmException, EntityProviderException {
+
+    if (value == null) {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.ATOM_NULL, FormatXml.ATOM_VALUE_TRUE);
+    } else {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.ATOM_TYPE, getFqnTypeName(propertyInfo));
+      List<EntityPropertyInfo> propertyInfos = propertyInfo.getPropertyInfos();
+      for (EntityPropertyInfo childPropertyInfo : propertyInfos) {
+        Object childValue = extractChildValue(value, childPropertyInfo.getName());
+        append(writer, childPropertyInfo.getName(), childPropertyInfo, childValue);
+      }
+    }
+  }
+
+  /**
+   * Returns full qualified name of a type of a given PropertyInfo.
+   * @return Full qualified name
+   */
+  private String getFqnTypeName(final EntityComplexPropertyInfo propertyInfo) throws EdmException {
+    return propertyInfo.getType().getNamespace() + Edm.DELIMITER + propertyInfo.getType().getName();
+  }
+
+  /**
+   * If <code>value</code> is a {@link Map} the element with given <code>name</code> as key is returned.
+   * If <code>value</code> is NOT a {@link Map} its {@link String#valueOf(Object)} result is returned.
+   * 
+   * @param value
+   * @param name
+   * @return name or result (see above)
+   */
+  private Object extractChildValue(final Object value, final String name) {
+    if (value instanceof Map) {
+      Map<?, ?> map = (Map<?, ?>) value;
+      return map.get(name);
+    }
+    return String.valueOf(value);
+  }
+
+  /**
+   * Appends a simple-property value to the XML stream.
+   * @param writer the XML stream writer
+   * @param prop property informations
+   * @param value the value of the property
+   * @throws XMLStreamException
+   * @throws EdmException
+   */
+  private void appendProperty(final XMLStreamWriter writer, final EntityPropertyInfo prop, final Object value) throws XMLStreamException, EdmException {
+    Object contentValue = value;
+    String mimeType = null;
+    if (prop.getMimeType() != null) {
+      mimeType = prop.getMimeType();
+    } else if (prop.getMapping() != null && prop.getMapping().getMimeType() != null) {
+      mimeType = (String) extractChildValue(value, prop.getMapping().getMimeType());
+      contentValue = extractChildValue(value, prop.getName());
+    }
+
+    if (mimeType != null) {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.M_MIME_TYPE, mimeType);
+    }
+
+    final EdmSimpleType type = (EdmSimpleType) prop.getType();
+    final String valueAsString = type.valueToString(contentValue, EdmLiteralKind.DEFAULT, prop.getFacets());
+    if (valueAsString == null) {
+      writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.ATOM_NULL, FormatXml.ATOM_VALUE_TRUE);
+    } else {
+      writer.writeCharacters(valueAsString);
+    }
+  }
+
+  /**
+   * 
+   * @param writer
+   * @param prop
+   * @param name
+   * @throws XMLStreamException
+   * @throws EntityProviderException
+   */
+  private void writeStartElementWithCustomNamespace(final XMLStreamWriter writer, final EntityPropertyInfo prop, final String name) throws XMLStreamException, EntityProviderException {
+    EdmCustomizableFeedMappings mapping = prop.getCustomMapping();
+    String nsPrefix = mapping.getFcNsPrefix();
+    String nsUri = mapping.getFcNsUri();
+    if (nsUri == null || nsPrefix == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(name));
+    }
+    writer.writeStartElement(nsPrefix, name, nsUri);
+    writer.writeNamespace(nsPrefix, nsUri);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/CircleStreamBuffer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/CircleStreamBuffer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/CircleStreamBuffer.java
new file mode 100644
index 0000000..759b374
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/CircleStreamBuffer.java
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * 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.ep.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.Queue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * Circular stream buffer to write/read into/from one single buffer.
+ * With support of {@link InputStream} and {@link OutputStream} access to buffered data.
+ * 
+ * @author SAP AG
+ */
+public class CircleStreamBuffer {
+
+  private static final int NEW_BUFFER_RESIZE_FACTOR = 2;
+  private static final int READ_EOF = -1;
+  private static final int DEFAULT_CAPACITY = 8192;
+  private static final int MAX_CAPACITY = DEFAULT_CAPACITY * 32;
+
+  private int currentAllocateCapacity = DEFAULT_CAPACITY;
+
+  private boolean writeMode = true;
+  private boolean writeClosed = false;
+  private boolean readClosed = false;
+
+  private Queue<ByteBuffer> bufferQueue = new LinkedBlockingQueue<ByteBuffer>();
+  private ByteBuffer currentWriteBuffer;
+
+  private InternalInputStream inStream;
+  private InternalOutputStream outStream;
+
+  /**
+   * Creates a {@link CircleStreamBuffer} with default buffer size.
+   */
+  public CircleStreamBuffer() {
+    this(DEFAULT_CAPACITY);
+  }
+
+  /**
+   * Create a {@link CircleStreamBuffer} with given buffer size in bytes.
+   * 
+   * @param bufferSize
+   */
+  public CircleStreamBuffer(final int bufferSize) {
+    currentAllocateCapacity = bufferSize;
+    createNewWriteBuffer();
+    inStream = new InternalInputStream(this);
+    outStream = new InternalOutputStream(this);
+  }
+
+  /**
+   * Get {@link InputStream} for data read access.
+   * 
+   * @return the stream
+   */
+  public InputStream getInputStream() {
+    return inStream;
+  }
+
+  /**
+   * Get {@link OutputStream} for write data.
+   * 
+   * @return the stream
+   */
+  public OutputStream getOutputStream() {
+    return outStream;
+  }
+
+  // #############################################
+  // #
+  // # Common parts
+  // #
+  // #############################################
+
+  /**
+   * Closes the write (input) part of the {@link CircleStreamBuffer}.
+   * After this call the buffer can only be read out.
+   */
+  public void closeWrite() {
+    writeClosed = true;
+  }
+
+  /**
+   * Closes the read (output) part of the {@link CircleStreamBuffer}.
+   * After this call it is possible to write into the buffer (but can never be read out).
+   */
+  public void closeRead() {
+    readClosed = true;
+    // clear references to byte buffers
+    ByteBuffer buffer = bufferQueue.poll();
+    while (buffer != null) {
+      buffer.clear();
+      buffer = bufferQueue.poll();
+    }
+  }
+
+  /**
+   * Closes write and read part (and hence the complete buffer).
+   */
+  public void close() {
+    closeWrite();
+    closeRead();
+  }
+
+  private int remaining() throws IOException {
+    if (writeMode) {
+      return currentWriteBuffer.remaining();
+    } else {
+      ByteBuffer toRead = getReadBuffer();
+      if (toRead == null) {
+        return 0;
+      }
+      return toRead.remaining();
+    }
+  }
+
+  // #############################################
+  // #
+  // # Reading parts
+  // #
+  // #############################################
+
+  private ByteBuffer getReadBuffer() throws IOException {
+    if (readClosed) {
+      throw new IOException("Tried to read from closed stream.");
+    }
+
+    boolean next = false;
+    ByteBuffer tmp = null;
+    if (writeMode) {
+      writeMode = false;
+      next = true;
+    } else {
+      tmp = bufferQueue.peek();
+      if (tmp != null && !tmp.hasRemaining()) {
+        tmp = bufferQueue.poll();
+        next = true;
+      }
+    }
+
+    if (next) {
+      tmp = bufferQueue.peek();
+      if (tmp != null) {
+        tmp.flip();
+      }
+      tmp = getReadBuffer();
+    }
+
+    return tmp;
+  }
+
+  private int read(final byte[] b, final int off, final int len) throws IOException {
+    ByteBuffer readBuffer = getReadBuffer();
+    if (readBuffer == null) {
+      return READ_EOF;
+    }
+
+    int toReadLength = readBuffer.remaining();
+    if (len < toReadLength) {
+      toReadLength = len;
+    }
+    readBuffer.get(b, off, toReadLength);
+    return toReadLength;
+  }
+
+  private int read() throws IOException {
+    ByteBuffer readBuffer = getReadBuffer();
+    if (readBuffer == null) {
+      return READ_EOF;
+    }
+
+    return readBuffer.get();
+  }
+
+  // #############################################
+  // #
+  // # Writing parts
+  // #
+  // #############################################
+
+  private void write(final byte[] data, final int off, final int len) throws IOException {
+    ByteBuffer writeBuffer = getWriteBuffer(len);
+    writeBuffer.put(data, off, len);
+  }
+
+  private ByteBuffer getWriteBuffer(final int size) throws IOException {
+    if (writeClosed) {
+      throw new IOException("Tried to write into closed stream.");
+    }
+
+    if (writeMode) {
+      if (remaining() < size) {
+        createNewWriteBuffer(size);
+      }
+    } else {
+      writeMode = true;
+      createNewWriteBuffer();
+    }
+
+    return currentWriteBuffer;
+  }
+
+  private void write(final int b) throws IOException {
+    ByteBuffer writeBuffer = getWriteBuffer(1);
+    writeBuffer.put((byte) b);
+  }
+
+  private void createNewWriteBuffer() {
+    createNewWriteBuffer(currentAllocateCapacity);
+  }
+
+  /**
+   * Creates a new buffer (per {@link #allocateBuffer(int)}) with the requested capacity as minimum capacity, add the new allocated
+   * buffer to the {@link #bufferQueue} and set it as {@link #currentWriteBuffer}.
+   * 
+   * @param requestedCapacity minimum capacity for new allocated buffer
+   */
+  private void createNewWriteBuffer(final int requestedCapacity) {
+    ByteBuffer b = allocateBuffer(requestedCapacity);
+    bufferQueue.add(b);
+    currentWriteBuffer = b;
+  }
+
+  /**
+   * 
+   * @param requestedCapacity
+   * @return the buffer
+   */
+  private ByteBuffer allocateBuffer(final int requestedCapacity) {
+    int allocateCapacity = requestedCapacity;
+    if (allocateCapacity < currentAllocateCapacity) {
+      allocateCapacity = currentAllocateCapacity * NEW_BUFFER_RESIZE_FACTOR;
+    }
+    if (allocateCapacity > MAX_CAPACITY) {
+      allocateCapacity = MAX_CAPACITY;
+    }
+    // update current
+    currentAllocateCapacity = allocateCapacity;
+    return ByteBuffer.allocate(allocateCapacity);
+  }
+
+  // #############################################
+  // #
+  // # Inner classes (streams)
+  // #
+  // #############################################
+
+  /**
+   * 
+   */
+  private static class InternalInputStream extends InputStream {
+
+    private final CircleStreamBuffer inBuffer;
+
+    public InternalInputStream(final CircleStreamBuffer csBuffer) {
+      inBuffer = csBuffer;
+    }
+
+    @Override
+    public int available() throws IOException {
+      return inBuffer.remaining();
+    }
+
+    @Override
+    public int read() throws IOException {
+      return inBuffer.read();
+    }
+
+    @Override
+    public int read(final byte[] b, final int off, final int len) throws IOException {
+      return inBuffer.read(b, off, len);
+    }
+
+    @Override
+    public void close() throws IOException {
+      inBuffer.closeRead();
+    }
+  }
+
+  /**
+   * 
+   */
+  private static class InternalOutputStream extends OutputStream {
+    private final CircleStreamBuffer outBuffer;
+
+    public InternalOutputStream(final CircleStreamBuffer csBuffer) {
+      outBuffer = csBuffer;
+    }
+
+    @Override
+    public void write(final int b) throws IOException {
+      outBuffer.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b, final int off, final int len) throws IOException {
+      outBuffer.write(b, off, len);
+    }
+
+    @Override
+    public void close() throws IOException {
+      outBuffer.closeWrite();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatJson.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatJson.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatJson.java
new file mode 100644
index 0000000..f1a3d67
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatJson.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.ep.util;
+
+/**
+ * String constants for formatting and parsing of JSON.
+ * @author SAP AG
+ */
+public class FormatJson {
+
+  public static final String D = "d";
+  public static final String RESULTS = "results";
+  public static final String COUNT = "__count";
+  public static final String METADATA = "__metadata";
+  public static final String DEFERRED = "__deferred";
+  public static final String ID = "id";
+  public static final String CONTENT_TYPE = "content_type";
+  public static final String MEDIA_SRC = "media_src";
+  public static final String MEDIA_ETAG = "media_etag";
+  public static final String EDIT_MEDIA = "edit_media";
+  public static final String PROPERTIES = "properties";
+  public static final String URI = "uri";
+  public static final String NULL = "null";
+  public static final String TRUE = "true";
+  public static final String FALSE = "false";
+  public static final String TYPE = "type";
+  public static final String ETAG = "etag";
+  public static final String ENTITY_SETS = "EntitySets";
+  public static final String NEXT = "__next";
+  public static final String ERROR = "error";
+  public static final String CODE = "code";
+  public static final String MESSAGE = "message";
+  public static final String LANG = "lang";
+  public static final String VALUE = "value";
+  public static final String INNER_ERROR = "innererror";
+  public static final String DELTA = "__delta";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatXml.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatXml.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatXml.java
new file mode 100644
index 0000000..52ee8d1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/FormatXml.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.ep.util;
+
+/**
+ * String constants for formatting and parsing of XML.
+ * @author SAP AG
+ */
+public class FormatXml {
+
+  public static final String XML_HEADER_NO = "no";
+  public static final String XML_HEADER_FULL = "full";
+  public static final String XML_HEADER_WITHOUT_ENCODING = "without encoding";
+  public static final String XML_BASE = "base";
+  public static final String XML_LANG = "lang";
+
+  public static final String M_PROPERTIES = "properties";
+  public static final String M_MIME_TYPE = "MimeType";
+
+  public static final String M_ETAG = "etag";
+  public static final String M_COUNT = "count";
+  public static final String M_TYPE = "type";
+  public static final String M_NULL = "null";
+  public static final String M_INLINE = "inline";
+
+  public static final String M_ERROR = "error";
+  public static final String M_CODE = "code";
+  public static final String M_MESSAGE = "message";
+  public static final String M_INNER_ERROR = "innererror";
+
+  public static final String D_ELEMENT = "element";
+  public static final String D_LINKS = "links";
+  public static final String D_URI = "uri";
+
+  public static final String APP_SERVICE = "service";
+  public static final String APP_WORKSPACE = "workspace";
+  public static final String APP_COLLECTION = "collection";
+  public static final String APP_ACCEPT = "accept";
+  public static final String APP_CATEGORIES = "categories";
+  public static final String APP_CATEGORIES_FIXED = "fixed";
+  public static final String APP_CATEGORIES_SCHEME = "scheme";
+
+  public static final String ATOM_FEED = "feed";
+  public static final String ATOM_ENTRY = "entry";
+  public static final String ATOM_LINK = "link";
+  public static final String ATOM_REL = "rel";
+  public static final String ATOM_HREF = "href";
+  public static final String ATOM_SRC = "src";
+  public static final String ATOM_TITLE = "title";
+  public static final String ATOM_TITLE_DEFAULT = "Default";
+  public static final String ATOM_TEXT = "text";
+  public static final String ATOM_TYPE = "type";
+  public static final String ATOM_UPDATED = "updated";
+  public static final String ATOM_ID = "id";
+  public static final String ATOM_AUTHOR = "author";
+  public static final String ATOM_AUTHOR_NAME = "name";
+  public static final String ATOM_AUTHOR_EMAIL = "email";
+  public static final String ATOM_AUTHOR_URI = "uri";
+  public static final String ATOM_SUMMARY = "summary";
+  public static final String ATOM_CONTRIBUTOR = "contributor";
+  public static final String ATOM_CONTRIBUTOR_NAME = "name";
+  public static final String ATOM_CONTRIBUTOR_EMAIL = "email";
+  public static final String ATOM_CONTRIBUTOR_URI = "uri";
+  public static final String ATOM_PUBLISHED = "published";
+  public static final String ATOM_RIGHTS = "rights";
+  public static final String ATOM_CATEGORY = "category";
+  public static final String ATOM_CATEGORY_TERM = "term";
+  public static final String ATOM_CATEGORY_SCHEME = "scheme";
+  public static final String ATOM_CATEGORY_LABEL = "label";
+  public static final String ATOM_CONTENT = "content";
+  public static final String ATOM_NULL = "null";
+  public static final String ATOM_VALUE_TRUE = "true";
+  public static final String ATOM_NEXT_LINK = "next";
+  public static final String ATOM_DELTA_LINK = "delta";
+  public static final String ATOM_TOMBSTONE_REF = "ref";
+  public static final String ATOM_TOMBSTONE_WHEN = "when";
+  public static final String ATOM_TOMBSTONE_DELETED_ENTRY = "deleted-entry";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonStreamWriter.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonStreamWriter.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonStreamWriter.java
new file mode 100644
index 0000000..185d32a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonStreamWriter.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.ep.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Writes JSON output.
+ * @author SAP AG
+ */
+public class JsonStreamWriter {
+  private final Writer writer;
+
+  public JsonStreamWriter(final Writer writer) {
+    this.writer = writer;
+  }
+
+  public JsonStreamWriter beginObject() throws IOException {
+    writer.append('{');
+    return this;
+  }
+
+  public JsonStreamWriter endObject() throws IOException {
+    writer.append('}');
+    return this;
+  }
+
+  public JsonStreamWriter beginArray() throws IOException {
+    writer.append('[');
+    return this;
+  }
+
+  public JsonStreamWriter endArray() throws IOException {
+    writer.append(']');
+    return this;
+  }
+
+  public JsonStreamWriter name(final String name) throws IOException {
+    writer.append('"').append(name).append('"').append(':');
+    return this;
+  }
+
+  public JsonStreamWriter unquotedValue(final String value) throws IOException {
+    writer.append(value == null ? FormatJson.NULL : value);
+    return this;
+  }
+
+  public JsonStreamWriter stringValueRaw(final String value) throws IOException {
+    if (value == null) {
+      writer.append(FormatJson.NULL);
+    } else {
+      writer.append('"').append(value).append('"');
+    }
+    return this;
+  }
+
+  public JsonStreamWriter stringValue(final String value) throws IOException {
+    if (value == null) {
+      writer.append(FormatJson.NULL);
+    } else {
+      writer.append('"');
+      escape(value);
+      writer.append('"');
+    }
+    return this;
+  }
+
+  public JsonStreamWriter namedStringValueRaw(final String name, final String value) throws IOException {
+    name(name);
+    stringValueRaw(value);
+    return this;
+  }
+
+  public JsonStreamWriter namedStringValue(final String name, final String value) throws IOException {
+    name(name);
+    stringValue(value);
+    return this;
+  }
+
+  public JsonStreamWriter separator() throws IOException {
+    writer.append(',');
+    return this;
+  }
+
+  /**
+   * Writes the JSON-escaped form of a Java String value according to RFC 4627.
+   * @param value the Java String
+   * @throws IOException if an I/O error occurs
+   */
+  protected void escape(final String value) throws IOException {
+    // RFC 4627 says: "All Unicode characters may be placed within the
+    // quotation marks except for the characters that must be escaped:
+    // quotation mark, reverse solidus, and the control characters
+    // (U+0000 through U+001F)."
+    // All output here is done on character basis which should be faster
+    // than writing Strings.
+    for (int i = 0; i < value.length(); i++) {
+      final char c = value.charAt(i);
+      switch (c) {
+      case '\\':
+        writer.append('\\').append(c);
+        break;
+      case '"':
+        writer.append('\\').append(c);
+        break;
+      case '\b':
+        writer.append('\\').append('b');
+        break;
+      case '\t':
+        writer.append('\\').append('t');
+        break;
+      case '\n':
+        writer.append('\\').append('n');
+        break;
+      case '\f':
+        writer.append('\\').append('f');
+        break;
+      case '\r':
+        writer.append('\\').append('r');
+        break;
+      case '\u0000':
+      case '\u0001':
+      case '\u0002':
+      case '\u0003':
+      case '\u0004':
+      case '\u0005':
+      case '\u0006':
+      case '\u0007':
+      case '\u000B':
+      case '\u000E':
+      case '\u000F':
+      case '\u0010':
+      case '\u0011':
+      case '\u0012':
+      case '\u0013':
+      case '\u0014':
+      case '\u0015':
+      case '\u0016':
+      case '\u0017':
+      case '\u0018':
+      case '\u0019':
+      case '\u001A':
+      case '\u001B':
+      case '\u001C':
+      case '\u001D':
+      case '\u001E':
+      case '\u001F':
+        final int lastHexDigit = c % 0x10;
+        writer.append('\\').append('u').append('0').append('0')
+            .append(c >= '\u0010' ? '1' : '0')
+            .append((char) ((lastHexDigit > 9 ? 'A' : '0') + lastHexDigit % 10));
+        break;
+      default:
+        writer.append(c);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonUtils.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonUtils.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonUtils.java
new file mode 100644
index 0000000..53542ab
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/util/JsonUtils.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.ep.util;
+
+import java.io.IOException;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+
+public class JsonUtils {
+
+  public static int startJson(final JsonReader reader) throws EntityProviderException {
+    //The enclosing "d" and "results" are optional - so we cannot check for the presence
+    //but we have to read over them in case they are present.
+    JsonToken token;
+    try {
+      token = reader.peek();
+      int openJsonObjects = 0;
+      if (JsonToken.BEGIN_OBJECT == token) {
+        reader.beginObject();
+        openJsonObjects++;
+        token = reader.peek();
+        if (JsonToken.NAME == token) {
+          String name = reader.nextName();
+          if (!("d".equals(name) ^ "results".equals(name))) {
+            //TODO I18N
+            throw new EntityProviderException(EntityProviderException.COMMON, name + " not expected, only d or results");
+          }
+        }
+
+        token = reader.peek();
+        if (JsonToken.BEGIN_OBJECT == token) {
+          reader.beginObject();
+          openJsonObjects++;
+        } else if (JsonToken.BEGIN_ARRAY == token) {
+          //TODO I18N
+          throw new EntityProviderException(EntityProviderException.COMMON, "Array not expected");
+        }
+      }
+
+      return openJsonObjects;
+    } catch (IOException e) {
+      //TODO I18N
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  public static boolean endJson(final JsonReader reader, final int openJsonObjects) throws IOException, EntityProviderException {
+
+    for (int closedJsonObjects = 0; closedJsonObjects < openJsonObjects; closedJsonObjects++) {
+      reader.endObject();
+    }
+    return reader.peek() == JsonToken.END_DOCUMENT;
+  }
+}


[45/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilder.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilder.java
new file mode 100644
index 0000000..271455d
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilder.java
@@ -0,0 +1,545 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+
+import javax.persistence.Column;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
+import javax.persistence.metamodel.PluralAttribute;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmBaseView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmComplexType;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmMappingImpl;
+
+public class JPAEdmNameBuilder {
+  private static final String ENTITY_CONTAINER_SUFFIX = "Container";
+  private static final String ENTITY_SET_SUFFIX = "s";
+  private static final String ASSOCIATIONSET_SUFFIX = "Set";
+  private static final String NAVIGATION_NAME = "Details";
+  private static final String UNDERSCORE = "_";
+
+  public static FullQualifiedName build(final JPAEdmBaseView view, final String name) {
+    FullQualifiedName fqName = new FullQualifiedName(buildNamespace(view),
+        name);
+    return fqName;
+  }
+
+  /*
+   * ************************************************************************
+   * EDM EntityType Name - RULES
+   * ************************************************************************
+   * EDM Entity Type Name = JPA Entity Name EDM Entity Type Internal Name =
+   * JPA Entity Name
+   * ************************************************************************
+   * EDM Entity Type Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmEntityTypeView view) {
+
+    EntityType edmEntityType = view.getEdmEntityType();
+    String jpaEntityName = view.getJPAEntityType().getName();
+    JPAEdmMappingModelAccess mappingModelAccess = view
+        .getJPAEdmMappingModelAccess();
+    String edmEntityTypeName = null;
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      edmEntityTypeName = mappingModelAccess
+          .mapJPAEntityType(jpaEntityName);
+    }
+
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    mapping.setJPAType(view.getJPAEntityType().getJavaType());
+
+    if (edmEntityTypeName == null) {
+      edmEntityTypeName = jpaEntityName;
+    }
+    //Setting the mapping object
+    edmEntityType.setMapping(((Mapping) mapping)
+        .setInternalName(jpaEntityName));
+
+    edmEntityType.setName(edmEntityTypeName);
+
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Schema Name - RULES
+   * ************************************************************************
+   * Java Persistence Unit name is set as Schema's Namespace
+   * ************************************************************************
+   * EDM Schema Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmSchemaView view)
+      throws ODataJPAModelException {
+    view.getEdmSchema().setNamespace(buildNamespace(view));
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Property Name - RULES
+   * ************************************************************************
+   * OData Property Names are represented in Camel Case. The first character
+   * of JPA Attribute Name is converted to an UpperCase Character and set as
+   * OData Property Name. JPA Attribute Name is set as Internal Name for OData
+   * Property. The Column name (annotated as @Column(name="x")) is set as
+   * column name in the mapping object.
+   * ************************************************************************
+   * EDM Property Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmPropertyView view, final boolean isComplexMode) {
+    Attribute<?, ?> jpaAttribute = view.getJPAAttribute();
+    String jpaAttributeName = jpaAttribute.getName();
+    String propertyName = null;
+
+    JPAEdmMappingModelAccess mappingModelAccess = view
+        .getJPAEdmMappingModelAccess();
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      if (isComplexMode) {
+        propertyName = mappingModelAccess
+            .mapJPAEmbeddableTypeAttribute(view
+                .getJPAEdmComplexTypeView()
+                .getJPAEmbeddableType().getJavaType()
+                .getSimpleName(), jpaAttributeName);
+      } else {
+        propertyName = mappingModelAccess.mapJPAAttribute(
+            view.getJPAEdmEntityTypeView().getJPAEntityType()
+                .getName(), jpaAttributeName);
+      }
+    }
+    if (propertyName == null) {
+      propertyName = Character.toUpperCase(jpaAttributeName.charAt(0))
+          + jpaAttributeName.substring(1);
+    }
+
+    view.getEdmSimpleProperty().setName(propertyName);
+
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    ((Mapping) mapping).setInternalName(jpaAttributeName);
+
+    AnnotatedElement annotatedElement = (AnnotatedElement) jpaAttribute
+        .getJavaMember();
+    if (annotatedElement != null) {
+      Column column = annotatedElement.getAnnotation(Column.class);
+      if (column != null) {
+        mapping.setJPAColumnName(column.name());
+      }
+    } else {
+      ManagedType<?> managedType = jpaAttribute.getDeclaringType();
+      if (managedType != null) {
+        Class<?> clazz = managedType.getJavaType();
+        try {
+          Field field = clazz.getDeclaredField(jpaAttributeName);
+          Column column = field.getAnnotation(Column.class);
+          if (column != null) {
+            mapping.setJPAColumnName(column.name());
+          }
+        } catch (SecurityException e) {
+
+        } catch (NoSuchFieldException e) {
+
+        }
+      }
+
+    }
+    view.getEdmSimpleProperty().setMapping((Mapping) mapping);
+  }
+
+  /*
+   * ************************************************************************
+   * EDM EntityContainer Name - RULES
+   * ************************************************************************
+   * Entity Container Name = EDM Namespace + Literal "Container"
+   * ************************************************************************
+   * EDM EntityContainer Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmEntityContainerView view) {
+    view.getEdmEntityContainer().setName(
+        buildNamespace(view) + ENTITY_CONTAINER_SUFFIX);
+  }
+
+  /*
+   * ************************************************************************
+   * EDM EntitySet Name - RULES
+   * ************************************************************************
+   * Entity Set Name = JPA Entity Type Name + Literal "s"
+   * ************************************************************************
+   * EDM EntitySet Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmEntitySetView view,
+      final JPAEdmEntityTypeView entityTypeView) {
+    FullQualifiedName fQname = view.getEdmEntitySet().getEntityType();
+    JPAEdmMappingModelAccess mappingModelAccess = view
+        .getJPAEdmMappingModelAccess();
+    String entitySetName = null;
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      Mapping mapping = entityTypeView.getEdmEntityType().getMapping();
+      if (mapping != null) {
+        entitySetName = mappingModelAccess.mapJPAEntitySet(mapping
+            .getInternalName());
+      }
+    }
+
+    if (entitySetName == null) {
+      entitySetName = fQname.getName() + ENTITY_SET_SUFFIX;
+    }
+
+    view.getEdmEntitySet().setName(entitySetName);
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Complex Type Name - RULES
+   * ************************************************************************
+   * Complex Type Name = JPA Embeddable Type Simple Name.
+   * ************************************************************************
+   * EDM Complex Type Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmComplexType view) {
+
+    JPAEdmMappingModelAccess mappingModelAccess = view
+        .getJPAEdmMappingModelAccess();
+    String jpaEmbeddableTypeName = view.getJPAEmbeddableType()
+        .getJavaType().getSimpleName();
+    String edmComplexTypeName = null;
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      edmComplexTypeName = mappingModelAccess
+          .mapJPAEmbeddableType(jpaEmbeddableTypeName);
+    }
+
+    if (edmComplexTypeName == null) {
+      edmComplexTypeName = jpaEmbeddableTypeName;
+    }
+
+    view.getEdmComplexType().setName(edmComplexTypeName);
+
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Complex Property Name - RULES
+   * ************************************************************************
+   * The first character of JPA complex attribute name is converted to
+   * uppercase. The modified JPA complex attribute name is assigned as EDM
+   * complex property name. The unmodified JPA complex attribute name is
+   * assigned as internal name.
+   * ************************************************************************
+   * EDM Complex Property Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmComplexPropertyView complexView,
+      final JPAEdmPropertyView propertyView) {
+
+    ComplexProperty complexProperty = complexView.getEdmComplexProperty();
+
+    String jpaAttributeName = propertyView.getJPAAttribute().getName();
+    String jpaEntityTypeName = propertyView.getJPAEdmEntityTypeView()
+        .getJPAEntityType().getName();
+
+    JPAEdmMappingModelAccess mappingModelAccess = complexView
+        .getJPAEdmMappingModelAccess();
+    String propertyName = null;
+
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      propertyName = mappingModelAccess.mapJPAAttribute(
+          jpaEntityTypeName, jpaAttributeName);
+    }
+
+    if (propertyName == null) {
+      propertyName = Character.toUpperCase(jpaAttributeName.charAt(0))
+          + jpaAttributeName.substring(1);
+    }
+    // change for navigation property issue
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    ((Mapping) mapping).setInternalName(jpaAttributeName);
+    mapping.setJPAType(propertyView.getJPAAttribute().getJavaType());
+    complexProperty.setMapping((Mapping) mapping);
+
+    complexProperty.setName(propertyName);
+
+  }
+
+  public static void build(final JPAEdmComplexPropertyView complexView, final String parentComplexTypeName)
+  {
+    ComplexProperty complexProperty = complexView.getEdmComplexProperty();
+
+    JPAEdmMappingModelAccess mappingModelAccess = complexView.getJPAEdmMappingModelAccess();
+    JPAEdmPropertyView propertyView = ((JPAEdmPropertyView) complexView);
+    String jpaAttributeName = propertyView.getJPAAttribute().getName();
+    String propertyName = null;
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      propertyName = mappingModelAccess.mapJPAEmbeddableTypeAttribute(
+          parentComplexTypeName, jpaAttributeName);
+    }
+    if (propertyName == null) {
+      propertyName = Character.toUpperCase(jpaAttributeName.charAt(0))
+          + jpaAttributeName.substring(1);
+    }
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    ((Mapping) mapping).setInternalName(jpaAttributeName);
+    mapping.setJPAType(propertyView.getJPAAttribute().getJavaType());
+    complexProperty.setMapping((Mapping) mapping);
+    complexProperty.setName(propertyName);
+
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Association End Name - RULES
+   * ************************************************************************
+   * Association End name = Namespace + Entity Type Name
+   * ************************************************************************
+   * EDM Association End Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmAssociationEndView assocaitionEndView,
+      final JPAEdmEntityTypeView entityTypeView, final JPAEdmPropertyView propertyView) {
+
+    String namespace = buildNamespace(assocaitionEndView);
+
+    String name = entityTypeView.getEdmEntityType().getName();
+    FullQualifiedName fQName = new FullQualifiedName(namespace, name);
+    assocaitionEndView.getEdmAssociationEnd1().setType(fQName);
+
+    name = null;
+    String jpaEntityTypeName = null;
+    try {
+
+      PluralAttribute<?, ?, ?> jpattr = (PluralAttribute<?, ?, ?>) propertyView
+          .getJPAAttribute();
+
+      jpaEntityTypeName = jpattr.getElementType().getJavaType()
+          .getSimpleName();
+
+    } catch (Exception e) {
+      jpaEntityTypeName = propertyView.getJPAAttribute().getJavaType()
+          .getSimpleName();
+    }
+
+    JPAEdmMappingModelAccess mappingModelAccess = assocaitionEndView
+        .getJPAEdmMappingModelAccess();
+
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      name = mappingModelAccess.mapJPAEntityType(jpaEntityTypeName);
+    }
+
+    if (name == null) {
+      name = jpaEntityTypeName;
+    }
+
+    fQName = new FullQualifiedName(namespace, name);
+    assocaitionEndView.getEdmAssociationEnd2().setType(fQName);
+
+  }
+
+  private static String buildNamespace(final JPAEdmBaseView view) {
+    JPAEdmMappingModelAccess mappingModelAccess = view
+        .getJPAEdmMappingModelAccess();
+    String namespace = null;
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      namespace = mappingModelAccess.mapJPAPersistenceUnit(view
+          .getpUnitName());
+    }
+    if (namespace == null) {
+      namespace = view.getpUnitName();
+    }
+
+    return namespace;
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Association Name - RULES
+   * ************************************************************************
+   * Association name = Association + End1 Name + End2 Name
+   * ************************************************************************
+   * EDM Association Name - RULES
+   * ************************************************************************
+   */
+
+  public static void build(final JPAEdmAssociationView view, final int count) {
+    Association association = view.getEdmAssociation();
+    String associationName = null;
+    String end1Name = association.getEnd1().getType().getName();
+    String end2Name = association.getEnd2().getType().getName();
+
+    if (end1Name.compareToIgnoreCase(end2Name) > 0) {
+      associationName = end2Name + UNDERSCORE + end1Name;
+    } else {
+      associationName = end1Name + UNDERSCORE + end2Name;
+    }
+    if (count > 1) {
+      associationName = associationName + Integer.toString(count - 1);
+    }
+    association.setName(associationName);
+
+  }
+
+  /*
+   * ************************************************************************
+   * EDM Association Set Name - RULES
+   * ************************************************************************
+   * Association Set name = Association Name + "Set"
+   * ************************************************************************
+   * EDM Association Set Name - RULES
+   * ************************************************************************
+   */
+  public static void build(final JPAEdmAssociationSetView view) {
+    AssociationSet associationSet = view.getEdmAssociationSet();
+
+    String name = view.getEdmAssociation().getName();
+    associationSet.setName(name + ASSOCIATIONSET_SUFFIX);
+
+  }
+
+  public static void build(final JPAEdmAssociationView associationView,
+      final JPAEdmPropertyView propertyView,
+      final JPAEdmNavigationPropertyView navPropertyView, final int count) {
+
+    String toName = null;
+    String fromName = null;
+    String navPropName = null;
+    NavigationProperty navProp = navPropertyView.getEdmNavigationProperty();
+    String namespace = buildNamespace(associationView);
+
+    Association association = associationView.getEdmAssociation();
+    navProp.setRelationship(new FullQualifiedName(namespace, association
+        .getName()));
+
+    FullQualifiedName associationEndTypeOne = association.getEnd1()
+        .getType();
+    FullQualifiedName associationEndTypeTwo = association.getEnd2()
+        .getType();
+
+    Attribute<?, ?> jpaAttribute = propertyView.getJPAAttribute();
+    navProp.setMapping(new Mapping().setInternalName(jpaAttribute.getName()));
+
+    String jpaEntityTypeName = propertyView.getJPAEdmEntityTypeView()
+        .getJPAEntityType().getName();
+    JPAEdmMappingModelAccess mappingModelAccess = navPropertyView
+        .getJPAEdmMappingModelAccess();
+
+    try {
+      PluralAttribute<?, ?, ?> jpattr = (PluralAttribute<?, ?, ?>) propertyView
+          .getJPAAttribute();
+
+      if (mappingModelAccess != null
+          && mappingModelAccess.isMappingModelExists()) {
+        toName = mappingModelAccess.mapJPAEntityType(jpattr
+            .getElementType().getJavaType().getSimpleName());
+        fromName = mappingModelAccess
+            .mapJPAEntityType(jpaEntityTypeName);
+        navPropName = mappingModelAccess.mapJPARelationship(
+            jpaEntityTypeName, jpattr.getName());
+      }
+      if (toName == null) {
+        toName = jpattr.getElementType().getJavaType().getSimpleName();
+      }
+      if (fromName == null) {
+        fromName = jpaEntityTypeName;
+      }
+
+      if (navPropName == null) {
+        navPropName = toName.concat(NAVIGATION_NAME);
+      }
+      if (count > 1) {
+        navPropName = navPropName + Integer.toString(count - 1);
+      }
+      navProp.setName(navPropName);
+
+      if (toName.equals(associationEndTypeOne.getName())) {
+        navProp.setFromRole(association.getEnd2().getRole());
+        navProp.setToRole(association.getEnd1().getRole());
+      } else if (toName.equals(associationEndTypeTwo.getName())) {
+        navProp.setToRole(association.getEnd2().getRole());
+        navProp.setFromRole(association.getEnd1().getRole());
+      }
+
+    } catch (Exception e) {
+      if (mappingModelAccess != null
+          && mappingModelAccess.isMappingModelExists()) {
+        navPropName = mappingModelAccess.mapJPARelationship(
+            jpaEntityTypeName, jpaAttribute.getName());
+        toName = mappingModelAccess.mapJPAEntityType(jpaAttribute
+            .getJavaType().getSimpleName());
+        fromName = mappingModelAccess
+            .mapJPAEntityType(jpaEntityTypeName);
+      }
+      if (toName == null) {
+        toName = jpaAttribute.getJavaType().getSimpleName();
+      }
+      if (fromName == null) {
+        fromName = jpaEntityTypeName;
+      }
+
+      if (navPropName == null) {
+        navPropName = toName.concat(NAVIGATION_NAME);
+      }
+      if (count > 1) {
+        navPropName = navPropName + Integer.toString(count - 1);
+      }
+      navProp.setName(navPropName);
+
+      if (toName.equals(associationEndTypeOne.getName())) {
+        navProp.setFromRole(association.getEnd2().getRole());
+        navProp.setToRole(association.getEnd1().getRole());
+      } else if (toName.equals(associationEndTypeTwo.getName())) {
+
+        navProp.setToRole(association.getEnd2().getRole());
+        navProp.setFromRole(association.getEnd1().getRole());
+      }
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertor.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertor.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertor.java
new file mode 100644
index 0000000..ae9eabc
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertor.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.metamodel.Attribute;
+
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+/**
+ * This class holds utility methods for Type conversions between JPA and OData Types.
+ * 
+ * @author SAP AG
+ *
+ */
+public class JPATypeConvertor {
+
+  /**
+   * This utility method converts a given jpa Type to equivalent
+   * EdmSimpleTypeKind for maintaining compatibility between Java and OData
+   * Types.
+   * 
+   * @param jpaType
+   *            The JPA Type input.
+   * @return The corresponding EdmSimpleTypeKind.
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException 
+   * 
+   * @see EdmSimpleTypeKind
+   */
+  public static EdmSimpleTypeKind convertToEdmSimpleType(final Class<?> jpaType, final Attribute<?, ?> currentAttribute) throws ODataJPAModelException {
+    if (jpaType.equals(String.class)) {
+      return EdmSimpleTypeKind.String;
+    }
+    else if (jpaType.equals(Long.class) || jpaType.equals(long.class)) {
+      return EdmSimpleTypeKind.Int64;
+    }
+    else if (jpaType.equals(Short.class) || jpaType.equals(short.class)) {
+      return EdmSimpleTypeKind.Int16;
+    }
+    else if (jpaType.equals(Integer.class) || jpaType.equals(int.class)) {
+      return EdmSimpleTypeKind.Int32;
+    }
+    else if (jpaType.equals(Double.class) || jpaType.equals(double.class)) {
+      return EdmSimpleTypeKind.Double;
+    }
+    else if (jpaType.equals(Float.class) || jpaType.equals(float.class)) {
+      return EdmSimpleTypeKind.Single;
+    }
+    else if (jpaType.equals(BigDecimal.class)) {
+      return EdmSimpleTypeKind.Decimal;
+    }
+    else if (jpaType.equals(byte[].class)) {
+      return EdmSimpleTypeKind.Binary;
+    }
+    else if (jpaType.equals(Byte.class) || jpaType.equals(byte.class)) {
+      return EdmSimpleTypeKind.Byte;
+    }
+    else if (jpaType.equals(Byte[].class)) {
+      return EdmSimpleTypeKind.Binary;
+    }
+    else if (jpaType.equals(Boolean.class) || jpaType.equals(boolean.class)) {
+      return EdmSimpleTypeKind.Boolean;
+    }
+    else if ((jpaType.equals(Date.class)) || (jpaType.equals(Calendar.class))) {
+      try {
+        if ((currentAttribute != null) && (currentAttribute.getDeclaringType().getJavaType().getDeclaredField(currentAttribute.getName()).getAnnotation(Temporal.class).value() == TemporalType.TIME)) {
+          return EdmSimpleTypeKind.Time;
+        } else {
+          return EdmSimpleTypeKind.DateTime;
+        }
+      } catch (NoSuchFieldException e) {
+        throw ODataJPAModelException
+            .throwException(ODataJPAModelException.GENERAL.addContent(e.getMessage()), e);
+      } catch (SecurityException e) {
+        throw ODataJPAModelException
+            .throwException(ODataJPAModelException.GENERAL.addContent(e.getMessage()), e);
+      }
+    }
+    else if (jpaType.equals(UUID.class)) {
+      return EdmSimpleTypeKind.Guid;
+    }
+    throw ODataJPAModelException.throwException(ODataJPAModelException.TYPE_NOT_SUPPORTED.addContent(jpaType.toString()), null);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequest.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequest.java
new file mode 100644
index 0000000..6297f67
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequest.java
@@ -0,0 +1,477 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+public class JPACreateRequest extends JPAWriteRequest {
+
+  private Metamodel metamodel;
+
+  public JPACreateRequest() {
+    super();
+    jpaEmbeddableKeyMap = new HashMap<String, HashMap<String, String>>();
+    jpaEmbeddableKeyObjectMap = new HashMap<String, Class<?>>();
+  }
+
+  public JPACreateRequest(final Metamodel metamodel) {
+    this();
+    this.metamodel = metamodel;
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T> List<T> process(final PostUriInfo postUriInfo, final InputStream content, final String requestContentType) throws ODataJPARuntimeException {
+    final EdmEntitySet entitySet = postUriInfo.getTargetEntitySet();
+    EdmEntityType entityType = null;
+    try {
+      entityType = entitySet.getEntityType();
+    } catch (EdmException e3) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e3.getMessage()), e3);
+    }
+    String entityName = null;
+    try {
+      if (entityType.getMapping() != null && entityType.getMapping().getInternalName() != null)
+      {
+        entityName = entityType.getMapping().getInternalName();
+      } else {
+        entityName = entityType.getName();
+      }
+    } catch (EdmException e1) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e1.getMessage()), e1);
+    }
+    Object jpaEntity = null;
+    Set<EntityType<?>> entityTypeSet = metamodel.getEntities();
+    String currentEntityName = null;
+    for (EntityType<?> entityTypeTemp : entityTypeSet) {
+      if (entityTypeTemp.getJavaType().getName().endsWith("." + entityName)) {
+        currentEntityName = entityTypeTemp.getName();
+        try {
+          jpaEntity = entityTypeTemp.getJavaType().newInstance();
+          break;
+        } catch (InstantiationException e) {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.GENERAL
+                  .addContent(e.getMessage()), e);
+        } catch (IllegalAccessException e) {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.GENERAL
+                  .addContent(e.getMessage()), e);
+        }
+      }
+    }
+
+    ODataEntry entryValues = null;
+    try {
+      entryValues = parseEntry(entitySet, content, requestContentType, true);
+    } catch (ODataBadRequestException e1) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e1.getMessage()), e1);
+    }
+
+    Map<String, Object> propertyValueMap = entryValues.getProperties();
+    parse2JPAEntityValueMap(jpaEntity, entityType, propertyValueMap, currentEntityName);
+
+    Map<EdmNavigationProperty, EdmEntitySet> navPropEntitySetMap = null;
+    try {
+      navPropEntitySetMap = createInlinedEntities(jpaEntity, entitySet, entryValues, currentEntityName);
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    List<T> objectList = new ArrayList<T>();
+    objectList.add((T) jpaEntity);
+    objectList.add((T) navPropEntitySetMap);
+    return objectList;
+  }
+
+  @SuppressWarnings("unchecked")
+  public final Object parse2JPAEntityValueMap(
+      final Object jpaEntity, final EdmStructuralType edmEntityType, final Map<String, Object> propertyValueMap, final String entityName)
+      throws ODataJPARuntimeException {
+
+    if (jpaEntity == null || edmEntityType == null || propertyValueMap == null || propertyValueMap.size() == 0) {
+      return null;
+    }
+
+    String jpaEntityAccessKey = jpaEntity.getClass().getName();
+
+    if (!jpaEntityAccessMap.containsKey(jpaEntityAccessKey)) {
+      jpaEntityAccessMap.put(jpaEntityAccessKey,
+          getSetters(jpaEntity, edmEntityType, true));
+    }
+
+    HashMap<String, Method> setters = jpaEntityAccessMap
+        .get(jpaEntityAccessKey);
+    HashMap<String, String> embeddableKeys = jpaEmbeddableKeyMap
+        .get(jpaEntityAccessKey);
+    String propertyName = null;
+    try {
+      for (String key : setters.keySet()) {
+
+        EdmProperty property = (EdmProperty) edmEntityType
+            .getProperty(key);
+        if (property.getMapping() != null && property.getMapping().getInternalName() != null) {
+          propertyName = property.getMapping().getInternalName();
+        } else {
+          propertyName = property.getName();
+        }
+        Method method = setters.get(key);
+        Object propertyValue = propertyValueMap.get(key);
+        if (propertyValue == null) {
+          continue;
+        }
+        if (propertyValue instanceof java.util.GregorianCalendar) {
+          propertyValue = ((java.util.GregorianCalendar) propertyValue).getTime();
+        }
+
+        if (method != null) {
+          if (property.getType().getKind().equals(EdmTypeKind.COMPLEX)) {
+            Object complexObject = jpaComplexObjectMap.get(propertyName);
+            parse2JPAEntityValueMap(complexObject, ((EdmComplexType) property.getType()),
+                (Map<String, Object>) propertyValue, propertyName);
+            setters.get(key).invoke(jpaEntity, complexObject);
+          } else {
+            setters.get(key).invoke(jpaEntity, propertyValue);
+          }
+        }
+      }
+
+      if (embeddableKeys != null) {
+        Object embeddableKeyObj = null;
+        Method method = null;
+        for (String embeddableKey : embeddableKeys.keySet()) {
+          String name = embeddableKeys.get(embeddableKey);
+          String[] nameParts = name.split("\\.");//$NON-NLS-1$
+          Object propertyValue = jpaEntity;
+          Class<?> propertyClass = null;
+
+          try {
+            for (EntityType<?> entity : metamodel.getEntities())
+            {
+              if (entity.getName().equals(entityName))
+              {
+                Attribute<?, ?> attribute = entity.getAttribute(nameParts[0].substring(3, 4).toLowerCase() + nameParts[0].substring(4));
+                propertyClass = attribute.getJavaType();
+                if (embeddableKeyObj == null) {
+                  try {
+                    embeddableKeyObj = propertyClass.newInstance();
+                  } catch (InstantiationException e) {
+                    throw ODataJPARuntimeException
+                        .throwException(ODataJPARuntimeException.GENERAL
+                            .addContent(e.getMessage()), e);
+                  }
+                }
+                break;
+              }
+            }
+
+            method = propertyValue.getClass().getMethod(
+                nameParts[0], propertyClass);
+            populateEmbeddableKey(embeddableKeyObj, embeddableKey, nameParts[1], propertyValueMap);
+          } catch (NoSuchMethodException e) {
+            throw ODataJPARuntimeException
+                .throwException(ODataJPARuntimeException.GENERAL
+                    .addContent(e.getMessage()), e);
+          }
+        }
+        propertyName = "Embeddable Key";//$NON-NLS-1$
+        method.invoke(jpaEntity, embeddableKeyObj);
+      }
+    } catch (SecurityException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.ERROR_JPQL_PARAM_VALUE
+              .addContent(propertyName), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    return jpaEntity;
+  }
+
+  private void populateEmbeddableKey(final Object embeddableKeyObject, final String key, final String setterName, final Map<String, Object> propertyValueMap) throws ODataJPARuntimeException {
+    Class<?> propertyClass = jpaEmbeddableKeyObjectMap.get(key);
+    Method method = null;
+    try {
+      method = embeddableKeyObject.getClass().getMethod(setterName, propertyClass);
+    } catch (NoSuchMethodException e1) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e1.getMessage()), e1);
+    } catch (SecurityException e1) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e1.getMessage()), e1);
+    }
+    try {
+      method.invoke(embeddableKeyObject, propertyValueMap.get(key));
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.ERROR_JPQL_KEY_VALUE
+              .addContent(key), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+  }
+
+  private <T> Map<EdmNavigationProperty, EdmEntitySet> createInlinedEntities(final T jpaEntity, final EdmEntitySet entitySet, final ODataEntry entryValues, final String jpaEntityName) throws ODataException {
+    if (jpaEntity == null) {
+      return null;
+    }
+    Map<String, Object> relatedPropertyValueMap = new HashMap<String, Object>();
+    Map<String, Class<?>> relatedClassMap = new HashMap<String, Class<?>>();
+    Map<EdmNavigationProperty, EdmEntitySet> navPropEntitySetMap = new HashMap<EdmNavigationProperty, EdmEntitySet>();
+    final EdmEntityType entityType = entitySet.getEntityType();
+    for (final String navigationPropertyName : entityType.getNavigationPropertyNames()) {
+      final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) entityType.getProperty(navigationPropertyName);
+      List<ODataEntry> relatedValueList = null;
+      if (entryValues.getProperties().get(navigationPropertyName) != null) {
+        relatedValueList = ((ODataFeed) entryValues.getProperties().get(navigationPropertyName)).getEntries();
+      }
+      List<Object> relatedDataList = null;
+      if (relatedValueList != null) {
+        relatedDataList = new ArrayList<Object>();
+        final EdmEntitySet relatedEntitySet = entitySet.getRelatedEntitySet(navigationProperty);
+
+        for (final ODataEntry relatedValues : relatedValueList) {
+
+          String entityName = null;
+          EdmEntityType relatedEntityType = relatedEntitySet.getEntityType();
+          try {
+            if (relatedEntityType.getMapping() != null && relatedEntityType.getMapping().getInternalName() != null)
+            {
+              entityName = relatedEntityType.getMapping().getInternalName();
+            } else {
+              entityName = relatedEntityType.getName();
+            }
+          } catch (EdmException e1) {
+            throw ODataJPARuntimeException
+                .throwException(ODataJPARuntimeException.GENERAL
+                    .addContent(e1.getMessage()), e1);
+          }
+
+          Object relatedData = null;
+          Set<EntityType<?>> entityTypeSet = metamodel.getEntities();
+          String currentEntityName = null;
+          for (EntityType<?> entityTypeTemp : entityTypeSet) {
+            if (entityTypeTemp.getJavaType().getName().endsWith("." + entityName)) {
+              currentEntityName = entityTypeTemp.getName();
+              try {
+                relatedClassMap.put(navigationProperty.getMapping().getInternalName(), entityTypeTemp.getJavaType());
+                relatedData = entityTypeTemp.getJavaType().newInstance();
+                break;
+              } catch (InstantiationException e) {
+                throw ODataJPARuntimeException
+                    .throwException(ODataJPARuntimeException.GENERAL
+                        .addContent(e.getMessage()), e);
+              } catch (IllegalAccessException e) {
+                throw ODataJPARuntimeException
+                    .throwException(ODataJPARuntimeException.GENERAL
+                        .addContent(e.getMessage()), e);
+              }
+            }
+          }
+          if (relatedValues != null && relatedEntitySet != null) {
+            relatedDataList.add(relatedData);
+            if (navPropEntitySetMap.get(navigationProperty) == null) {
+              navPropEntitySetMap.put(navigationProperty, relatedEntitySet);
+            }
+            parse2JPAEntityValueMap(relatedData, relatedEntitySet.getEntityType(), relatedValues.getProperties(), currentEntityName);
+          } else {
+            continue;
+          }
+          createInlinedEntities(relatedData, relatedEntitySet, relatedValues, currentEntityName);
+        }
+      }
+      relatedPropertyValueMap.put(navigationProperty.getMapping().getInternalName(), relatedDataList);
+    }
+    setNavigationProperties(jpaEntity, entitySet, relatedPropertyValueMap, jpaEntityName, relatedClassMap);
+    return navPropEntitySetMap;
+  }
+
+  @SuppressWarnings("unchecked")
+  private void setNavigationProperties(
+      final Object jpaEntity, final EdmEntitySet entitySet, final Map<String, Object> propertyValueMap, final String entityName, final Map<String, Class<?>> relatedClassMap) throws ODataJPARuntimeException {
+    if (jpaEntity == null || entitySet == null || propertyValueMap == null || propertyValueMap.size() == 0) {
+      return;
+    }
+    List<HashMap<?, ?>> mapList = getSettersForNavigationProperties(jpaEntity, entitySet, relatedClassMap);
+    HashMap<String, Method> setters = (HashMap<String, Method>) mapList.get(0);
+    HashMap<String, EdmMultiplicity> multiplicityMap = (HashMap<String, EdmMultiplicity>) mapList.get(1);
+    for (String key : setters.keySet()) {
+      Method method = setters.get(key);
+      List<Object> propertyValue = (List<Object>) propertyValueMap.get(key);
+      if (propertyValue == null || propertyValue.size() == 0) {
+        continue;
+      }
+      try {
+        if (multiplicityMap.get(key) == EdmMultiplicity.MANY) {
+          method.invoke(jpaEntity, propertyValue);
+        } else {
+          method.invoke(jpaEntity, propertyValue.get(0));
+        }
+      } catch (IllegalAccessException e) {
+        throw ODataJPARuntimeException
+            .throwException(ODataJPARuntimeException.GENERAL
+                .addContent(e.getMessage()), e);
+      } catch (IllegalArgumentException e) {
+        throw ODataJPARuntimeException
+            .throwException(ODataJPARuntimeException.GENERAL
+                .addContent(e.getMessage()), e);
+      } catch (InvocationTargetException e) {
+        throw ODataJPARuntimeException
+            .throwException(ODataJPARuntimeException.GENERAL
+                .addContent(e.getMessage()), e);
+      }
+    }
+
+  }
+
+  private List<HashMap<?, ?>> getSettersForNavigationProperties(final Object jpaEntity, final EdmEntitySet edmEntitySet, final Map<String, Class<?>> relatedClassMap) throws ODataJPARuntimeException {
+    List<HashMap<?, ?>> mapList = new ArrayList<HashMap<?, ?>>();
+    HashMap<String, Method> setters = new HashMap<String, Method>();
+    HashMap<String, EdmMultiplicity> multiplicityMap = new HashMap<String, EdmMultiplicity>();
+    EdmEntityType edmEntityType = null;
+    try {
+      edmEntityType = edmEntitySet.getEntityType();
+    } catch (EdmException e2) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e2.getMessage()), e2);
+    }
+
+    try {
+      for (final String navigationPropertyName : edmEntityType.getNavigationPropertyNames()) {
+        final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) edmEntityType.getProperty(navigationPropertyName);
+        String entityName = null;
+        try {
+          if (navigationProperty.getMapping() != null && navigationProperty.getMapping().getInternalName() != null)
+          {
+            entityName = navigationProperty.getMapping().getInternalName();
+          } else {
+            entityName = navigationProperty.getName();
+          }
+        } catch (EdmException e1) {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.GENERAL
+                  .addContent(e1.getMessage()), e1);
+        }
+        String name = getSetterName(entityName);
+
+        Class<?> propertyClass = null;
+        if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+          propertyClass = List.class;
+          multiplicityMap.put(entityName, EdmMultiplicity.MANY);
+        } else {
+          propertyClass = relatedClassMap.get(entityName);
+          if (propertyClass == null) {
+            continue;
+          }
+          multiplicityMap.put(entityName, EdmMultiplicity.ONE);
+        }
+        try {
+          setters.put(
+              entityName,
+              jpaEntity.getClass().getDeclaredMethod(name, propertyClass));
+        } catch (NoSuchMethodException e) {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.GENERAL
+                  .addContent(e.getMessage()), e);
+        } catch (SecurityException e) {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.GENERAL
+                  .addContent(e.getMessage()), e);
+        }
+      }
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    mapList.add(0, setters);
+    mapList.add(1, multiplicityMap);
+    return mapList;
+  }
+
+  private String getSetterName(final String navigationPropertyName)
+      throws ODataJPARuntimeException {
+    StringBuilder builder = new StringBuilder();
+    char c = Character.toUpperCase(navigationPropertyName.charAt(0));
+
+    builder.append("set").append(c).append(navigationPropertyName.substring(1)) //$NON-NLS-1$
+        .toString();
+    if (builder.length() > 0) {
+      return builder.toString();
+    } else {
+      return null;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPALink.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPALink.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPALink.java
new file mode 100644
index 0000000..c1a3e8c
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPALink.java
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.processor.core.jpa.ODataEntityParser;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntityParser;
+
+public class JPALink {
+
+  private ODataJPAContext context;
+  private JPAProcessor jpaProcessor;
+  private ODataEntityParser parser;
+  private Object targetJPAEntity;
+  private Object sourceJPAEntity;
+
+  public JPALink(final ODataJPAContext context) {
+    this.context = context;
+    jpaProcessor = ODataJPAFactory.createFactory().getJPAAccessFactory()
+        .getJPAProcessor(this.context);
+    parser = new ODataEntityParser(this.context);
+  }
+
+  public void setSourceJPAEntity(final Object jpaEntity) {
+    sourceJPAEntity = jpaEntity;
+  }
+
+  public void create(final PostUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType)
+      throws ODataJPARuntimeException, ODataJPAModelException {
+
+    EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
+    String targerEntitySetName;
+    EdmNavigationProperty navigationProperty = null;
+    try {
+      targerEntitySetName = targetEntitySet.getName();
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    List<UriInfo> uriInfoList = new ArrayList<UriInfo>();
+
+    if (((UriInfo) uriInfo).isLinks()) {
+      UriInfo getUriInfo = parser.parseLink(targetEntitySet, content, requestContentType);
+      uriInfoList = new ArrayList<UriInfo>();
+      uriInfoList.add(getUriInfo);
+      navigationProperty = uriInfo.getNavigationSegments().get(0).getNavigationProperty();
+    }
+    else
+    {
+      uriInfoList = parser.parseLinks(targetEntitySet, content, contentType);
+    }
+
+    if (uriInfoList == null) {
+      return;
+    }
+    try {
+      for (UriInfo getUriInfo : uriInfoList) {
+
+        if (!getUriInfo.getTargetEntitySet().getName().equals(targerEntitySetName))
+        {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.RELATIONSHIP_INVALID, null);
+        }
+        if (!((UriInfo) uriInfo).isLinks()) {
+          navigationProperty = getUriInfo.getNavigationSegments().get(0).getNavigationProperty();
+        }
+
+        targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
+        if (targetJPAEntity != null && ((UriInfo) uriInfo).isLinks()) {
+          getUriInfo = parser.parseLinkURI();
+          sourceJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
+          if (sourceJPAEntity == null) {
+            throw ODataJPARuntimeException
+                .throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND.
+                    addContent(getUriInfo.getTargetEntitySet().getName()), null);
+          }
+        }
+
+        JPAEntityParser entityParser = JPAEntityParser.create();
+        Method setMethod = entityParser.getAccessModifier(sourceJPAEntity,
+            navigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);
+
+        Method getMethod = entityParser.getAccessModifier(sourceJPAEntity,
+            navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
+
+        if (getMethod.getReturnType().getTypeParameters() != null) {
+          @SuppressWarnings("unchecked")
+          List<Object> relatedEntities = (List<Object>) getMethod.invoke(sourceJPAEntity);
+          relatedEntities.add(targetJPAEntity);
+          setMethod.invoke(sourceJPAEntity, relatedEntities);
+        } else {
+          setMethod.invoke(sourceJPAEntity, targetJPAEntity);
+        }
+      }
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+  }
+
+  public void delete() {}
+
+  public void save() {
+    EntityManager em = context.getEntityManager();
+    EntityTransaction tx = em.getTransaction();
+
+    if (!tx.isActive()) {
+      em.getTransaction().begin();
+      em.persist(sourceJPAEntity);
+      em.getTransaction().commit();
+    }
+
+  }
+
+  public void update(final PutMergePatchUriInfo putUriInfo, final InputStream content,
+      final String requestContentType, final String contentType) throws ODataJPARuntimeException, ODataJPAModelException {
+    UriInfo uriInfo = (UriInfo) putUriInfo;
+
+    EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
+    String targerEntitySetName;
+    EdmNavigationProperty navigationProperty = null;
+    try {
+      targerEntitySetName = targetEntitySet.getName();
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    List<UriInfo> uriInfoList = new ArrayList<UriInfo>();
+
+    if (((UriInfo) uriInfo).isLinks()) {
+      UriInfo getUriInfo = parser.parseLink(targetEntitySet, content, requestContentType);
+      uriInfoList = new ArrayList<UriInfo>();
+      uriInfoList.add(getUriInfo);
+      navigationProperty = uriInfo.getNavigationSegments().get(0).getNavigationProperty();
+    }
+    else
+    {
+      uriInfoList = parser.parseLinks(targetEntitySet, content, contentType);
+    }
+
+    if (uriInfoList == null) {
+      return;
+    }
+    try {
+      for (UriInfo getUriInfo : uriInfoList) {
+
+        if (!getUriInfo.getTargetEntitySet().getName().equals(targerEntitySetName))
+        {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.RELATIONSHIP_INVALID, null);
+        }
+        if (!((UriInfo) uriInfo).isLinks()) {
+          navigationProperty = getUriInfo.getNavigationSegments().get(0).getNavigationProperty();
+        }
+
+        targetJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
+        if (targetJPAEntity != null && ((UriInfo) uriInfo).isLinks()) {
+          getUriInfo = parser.parseLinkURI();
+          sourceJPAEntity = jpaProcessor.process((GetEntityUriInfo) getUriInfo);
+          if (sourceJPAEntity == null) {
+            throw ODataJPARuntimeException
+                .throwException(ODataJPARuntimeException.RESOURCE_X_NOT_FOUND.
+                    addContent(getUriInfo.getTargetEntitySet().getName()), null);
+          }
+        }
+
+        JPAEntityParser entityParser = JPAEntityParser.create();
+        Method setMethod = entityParser.getAccessModifier(sourceJPAEntity,
+            navigationProperty, JPAEntityParser.ACCESS_MODIFIER_SET);
+
+        Method getMethod = entityParser.getAccessModifier(sourceJPAEntity,
+            navigationProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
+
+        if (getMethod.getReturnType().getTypeParameters() != null && getMethod.getReturnType().getTypeParameters().length != 0) {
+          @SuppressWarnings("unchecked")
+          List<Object> relatedEntities = (List<Object>) getMethod.invoke(sourceJPAEntity);
+          relatedEntities.add(targetJPAEntity);
+          setMethod.invoke(sourceJPAEntity, relatedEntities);
+        } else {
+          setMethod.invoke(sourceJPAEntity, targetJPAEntity);
+        }
+      }
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequest.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequest.java
new file mode 100644
index 0000000..b8ae487
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequest.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+public class JPAUpdateRequest extends JPAWriteRequest {
+
+  public JPAUpdateRequest() {
+    super();
+  }
+
+  public void process(final Object jpaEntity, final PutMergePatchUriInfo putUriInfo, final InputStream content, final String requestContentType) throws ODataJPARuntimeException {
+
+    final EdmEntitySet entitySet = putUriInfo.getTargetEntitySet();
+    EdmEntityType entityType = null;
+    try {
+      entityType = entitySet.getEntityType();
+    } catch (EdmException e3) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e3.getMessage()), e3);
+    }
+
+    ODataEntry entryValues = null;
+    try {
+      entryValues = parseEntry(entitySet, content, requestContentType, false);
+    } catch (ODataBadRequestException e1) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e1.getMessage()), e1);
+    }
+    try {
+      Map<String, Object> propertValueMap = entryValues.getProperties();
+      parse2JPAEntityValueMap(jpaEntity, entityType, propertValueMap);
+    } catch (ODataJPARuntimeException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  public final Object parse2JPAEntityValueMap(
+      final Object jpaEntity, final EdmStructuralType edmEntityType, final Map<String, Object> propertyValueMap)
+      throws ODataJPARuntimeException {
+
+    if (jpaEntity == null || edmEntityType == null || propertyValueMap == null) {
+      return null;
+    }
+
+    String jpaEntityAccessKey = jpaEntity.getClass().getName();
+
+    if (!jpaEntityAccessMap.containsKey(jpaEntityAccessKey)) {
+      jpaEntityAccessMap.put(jpaEntityAccessKey,
+          getSetters(jpaEntity, edmEntityType, false));
+    }
+
+    HashMap<String, Method> setters = jpaEntityAccessMap
+        .get(jpaEntityAccessKey);
+    List<EdmProperty> keyProperties = null;
+    if (edmEntityType instanceof EdmEntityType) {
+      try {
+        keyProperties = ((EdmEntityType) edmEntityType).getKeyProperties();
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException
+            .throwException(ODataJPARuntimeException.GENERAL
+                .addContent(e.getMessage()), e);
+      }
+    }
+    boolean isKeyProperty = false;
+    String propertyName = null;
+    try {
+      for (String key : setters.keySet()) {
+        isKeyProperty = false;
+        if (keyProperties != null) {
+          for (EdmProperty keyProperty : keyProperties) {
+            if (keyProperty.getName().equalsIgnoreCase(key)) {
+              isKeyProperty = true;
+              break;
+            }
+          }
+          if (isKeyProperty) {
+            continue;
+          }
+        }
+        EdmProperty property = (EdmProperty) edmEntityType
+            .getProperty(key);
+        if (property.getMapping() != null && property.getMapping().getInternalName() != null) {
+          propertyName = property.getMapping().getInternalName();
+        } else {
+          propertyName = property.getName();
+        }
+        Method method = setters.get(key);
+        Object propertyValue = propertyValueMap.get(key);
+        if (propertyValue == null) {
+          continue;
+        }
+        if (propertyValue != null) {
+          if (propertyValue instanceof java.util.GregorianCalendar) {
+            propertyValue = ((java.util.GregorianCalendar) propertyValue).getTime();
+          }
+
+          if (method != null) {
+            if (property.getType().getKind().equals(EdmTypeKind.COMPLEX)) {
+              Object complexObject = jpaComplexObjectMap.get(propertyName);
+              parse2JPAEntityValueMap(complexObject, ((EdmComplexType) property.getType()),
+                  (Map<String, Object>) propertyValue);
+              setters.get(key).invoke(jpaEntity, complexObject);
+            } else {
+              setters.get(key).invoke(jpaEntity, propertyValue);
+            }
+          }
+        }
+
+      }
+    } catch (SecurityException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.ERROR_JPQL_PARAM_VALUE
+              .addContent(propertyName), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    return jpaEntity;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAWriteRequest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAWriteRequest.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAWriteRequest.java
new file mode 100644
index 0000000..d8fd6d4
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAWriteRequest.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+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.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.EdmTypeConvertor;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmMappingImpl;
+
+public class JPAWriteRequest {
+  protected HashMap<String, HashMap<String, Method>> jpaEntityAccessMap = null;
+  protected HashMap<String, Object> jpaComplexObjectMap = null;
+  protected HashMap<String, HashMap<String, String>> jpaEmbeddableKeyMap = null;
+  protected HashMap<String, Class<?>> jpaEmbeddableKeyObjectMap = null;
+
+  public JPAWriteRequest() {
+    jpaEntityAccessMap = new HashMap<String, HashMap<String, Method>>();
+    jpaComplexObjectMap = new HashMap<String, Object>();
+  }
+
+  protected HashMap<String, Method> getSetters(final Object jpaEntity,
+      final EdmStructuralType structuralType, final boolean isCreate) throws ODataJPARuntimeException {
+
+    HashMap<String, Method> setters = new HashMap<String, Method>();
+    HashMap<String, String> embeddableKey = new HashMap<String, String>();
+    try {
+      for (String propertyName : structuralType.getPropertyNames()) {
+
+        EdmProperty property = (EdmProperty) structuralType
+            .getProperty(propertyName);
+        Class<?> propertyClass = null;
+        try {
+          if (property.getMapping() != null && ((JPAEdmMappingImpl) property.getMapping()).getJPAType() != null) {
+            propertyClass = ((JPAEdmMappingImpl) property.getMapping()).getJPAType();
+            if (property.getType().getKind().equals(EdmTypeKind.COMPLEX)) {
+              try {
+                if (((JPAEdmMappingImpl) property.getMapping()).getInternalName() != null) {
+                  jpaComplexObjectMap.put(((JPAEdmMappingImpl) property.getMapping()).getInternalName(), propertyClass.newInstance());
+                } else {
+                  jpaComplexObjectMap.put(propertyName, propertyClass.newInstance());
+                }
+              } catch (InstantiationException e) {
+                throw ODataJPARuntimeException
+                    .throwException(ODataJPARuntimeException.GENERAL
+                        .addContent(e.getMessage()), e);
+              } catch (IllegalAccessException e) {
+                throw ODataJPARuntimeException
+                    .throwException(ODataJPARuntimeException.GENERAL
+                        .addContent(e.getMessage()), e);
+              }
+            }
+          } else {
+            propertyClass = EdmTypeConvertor.convertToJavaType(property.getType());
+          }
+        } catch (ODataJPAModelException e) {
+          throw ODataJPARuntimeException
+              .throwException(ODataJPARuntimeException.GENERAL
+                  .addContent(e.getMessage()), e);
+        }
+        String name = getSetterName(property);
+        String[] nameParts = name.split("\\.");
+        if (nameParts.length > 1) {
+          if (isCreate) {
+            jpaEmbeddableKeyObjectMap.put(propertyName, propertyClass);
+            embeddableKey.put(propertyName, name);
+          }
+        } else {
+          setters.put(
+              propertyName,
+              jpaEntity.getClass().getMethod(name, propertyClass));
+        }
+      }
+    } catch (NoSuchMethodException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (SecurityException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    if (isCreate && !embeddableKey.isEmpty()) {
+      jpaEmbeddableKeyMap.put(jpaEntity.getClass().getName(),
+          embeddableKey);
+    }
+    return setters;
+  }
+
+  private String getSetterName(final EdmProperty property)
+      throws ODataJPARuntimeException {
+    EdmMapping mapping = null;
+    String name = null;
+    try {
+      mapping = property.getMapping();
+      if (mapping == null || mapping.getInternalName() == null) {
+        name = property.getName();
+      } else {
+        name = mapping.getInternalName();
+      }
+
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    String[] nameParts = name.split("\\."); //$NON-NLS-1$
+    StringBuilder builder = new StringBuilder();
+
+    if (nameParts.length == 1) {
+      if (name != null) {
+        char c = Character.toUpperCase(name.charAt(0));
+
+        builder.append("set").append(c).append(name.substring(1)) //$NON-NLS-1$
+            .toString();
+      }
+    } else if (nameParts.length > 1) {
+
+      for (int i = 0; i < nameParts.length; i++) {
+        name = nameParts[i];
+        char c = Character.toUpperCase(name.charAt(0));
+        if (i == 0) {
+          builder.append("set").append(c).append(name.substring(1)); //$NON-NLS-1$
+        } else {
+          builder.append(".").append("set").append(c) //$NON-NLS-1$ //$NON-NLS-2$
+              .append(name.substring(1));
+        }
+      }
+    } else {
+      return null;
+    }
+
+    if (builder.length() > 0) {
+      return builder.toString();
+    } else {
+      return null;
+    }
+
+  }
+
+  protected ODataEntry parseEntry(final EdmEntitySet entitySet, final InputStream content, final String requestContentType, final boolean merge) throws ODataBadRequestException {
+    ODataEntry entryValues;
+    try {
+      EntityProviderReadProperties entityProviderProperties = EntityProviderReadProperties.init().mergeSemantic(merge).build();
+      entryValues = EntityProvider.readEntry(requestContentType, entitySet, content, entityProviderProperties);
+    } catch (EntityProviderException e) {
+      throw new ODataBadRequestException(ODataBadRequestException.BODY, e);
+    }
+    return entryValues;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProvider.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProvider.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProvider.java
new file mode 100644
index 0000000..edc3da9
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProvider.java
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.edm;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+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.EntityContainerInfo;
+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.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView;
+
+public class ODataJPAEdmProvider extends EdmProvider {
+
+  private ODataJPAContext oDataJPAContext;
+  private JPAEdmModelView jpaEdmModel;
+
+  private List<Schema> schemas;
+  private HashMap<String, EntityType> entityTypes;
+  private HashMap<String, EntityContainerInfo> entityContainerInfos;
+  private HashMap<String, ComplexType> complexTypes;
+  private HashMap<String, Association> associations;
+  private HashMap<String, FunctionImport> functionImports;
+
+  public ODataJPAEdmProvider() {
+    entityTypes = new HashMap<String, EntityType>();
+    entityContainerInfos = new HashMap<String, EntityContainerInfo>();
+    complexTypes = new HashMap<String, ComplexType>();
+    associations = new HashMap<String, Association>();
+    functionImports = new HashMap<String, FunctionImport>();
+  }
+
+  public ODataJPAEdmProvider(final ODataJPAContext oDataJPAContext) {
+    if (oDataJPAContext == null) {
+      throw new IllegalArgumentException(
+          ODataJPAException.ODATA_JPACTX_NULL);
+    }
+    entityTypes = new HashMap<String, EntityType>();
+    entityContainerInfos = new HashMap<String, EntityContainerInfo>();
+    complexTypes = new HashMap<String, ComplexType>();
+    associations = new HashMap<String, Association>();
+    functionImports = new HashMap<String, FunctionImport>();
+    jpaEdmModel = ODataJPAFactory.createFactory().getJPAAccessFactory()
+        .getJPAEdmModelView(oDataJPAContext);
+  }
+
+  public ODataJPAContext getODataJPAContext() {
+    return oDataJPAContext;
+  }
+
+  public void setODataJPAContext(final ODataJPAContext jpaContext) {
+    oDataJPAContext = jpaContext;
+  }
+
+  @Override
+  public EntityContainerInfo getEntityContainerInfo(final String name)
+      throws ODataException {
+
+    if (entityContainerInfos.containsKey(name)) {
+      return entityContainerInfos.get(name);
+    } else {
+
+      if (schemas == null) {
+        getSchemas();
+      }
+      List<EntityContainer> containerList = schemas.get(0).getEntityContainers();
+      if (containerList == null) return null;
+      for (EntityContainer container : containerList) {
+        if (name == null && container.isDefaultEntityContainer()) {
+          entityContainerInfos.put(name, container);
+          return container;
+        } else if (name != null && name.equals(container.getName())) {
+          return container;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EntityType getEntityType(final FullQualifiedName edmFQName)
+      throws ODataException {
+
+    String strEdmFQName = edmFQName.toString();
+
+    if (edmFQName != null) {
+      if (entityTypes.containsKey(strEdmFQName)) {
+        return entityTypes.get(strEdmFQName);
+      } else if (schemas == null) {
+        getSchemas();
+      }
+
+      String entityTypeNamespace = edmFQName.getNamespace();
+      String entityTypeName = edmFQName.getName();
+
+      for (Schema schema : schemas) {
+        String schemaNamespace = schema.getNamespace();
+        if (schemaNamespace.equals(entityTypeNamespace)) {
+          if (schema.getEntityTypes() == null) return null;
+          for (EntityType et : schema.getEntityTypes()) {
+            if (et.getName().equals(entityTypeName)) {
+              entityTypes.put(strEdmFQName, et);
+              return et;
+            }
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public ComplexType getComplexType(final FullQualifiedName edmFQName)
+      throws ODataException {
+
+    if (edmFQName != null) {
+      if (complexTypes.containsKey(edmFQName.toString())) {
+        return complexTypes.get(edmFQName.toString());
+      } else if (schemas == null) {
+        getSchemas();
+      }
+
+      for (Schema schema : schemas) {
+        if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+          if (schema.getComplexTypes() == null) return null;
+          for (ComplexType ct : schema.getComplexTypes()) {
+            if (ct.getName().equals(edmFQName.getName())) {
+              complexTypes.put(edmFQName.toString(), ct);
+              return ct;
+            }
+          }
+        }
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public Association getAssociation(final FullQualifiedName edmFQName)
+      throws ODataException {
+    if (edmFQName != null) {
+      if (associations.containsKey(edmFQName.toString())) {
+        return associations.get(edmFQName.toString());
+      } else if (schemas == null) {
+        getSchemas();
+      }
+
+      for (Schema schema : schemas) {
+        if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+          if (schema.getAssociations() == null) return null;
+          for (Association association : schema.getAssociations()) {
+            if (association.getName().equals(
+                edmFQName.getName())) {
+              associations.put(edmFQName.toString(),
+                  association);
+              return association;
+            }
+          }
+        }
+      }
+
+    }
+    return null;
+  }
+
+  @Override
+  public EntitySet getEntitySet(final String entityContainer, final String name)
+      throws ODataException {
+
+    EntitySet returnedSet = null;
+    EntityContainer container = null;
+    if (!entityContainerInfos.containsKey(entityContainer)) {
+      container = (EntityContainer) getEntityContainerInfo(entityContainer);
+    } else {
+      container = (EntityContainer) entityContainerInfos
+          .get(entityContainer);
+    }
+
+    if (container != null && name != null) {
+      for (EntitySet es : container.getEntitySets()) {
+        if (name.equals(es.getName())) {
+          returnedSet = es;
+          break;
+        }
+      }
+    }
+
+    return returnedSet;
+  }
+
+  @Override
+  public AssociationSet getAssociationSet(final String entityContainer,
+      final FullQualifiedName association, final String sourceEntitySetName,
+      final String sourceEntitySetRole) throws ODataException {
+
+    EntityContainer container = null;
+    if (!entityContainerInfos.containsKey(entityContainer)) {
+      container = (EntityContainer) getEntityContainerInfo(entityContainer);
+    } else {
+      container = (EntityContainer) entityContainerInfos
+          .get(entityContainer);
+    }
+
+    if (container != null && association != null && container.getAssociationSets() != null) {
+      for (AssociationSet as : container.getAssociationSets()) {
+        if (association.equals(as.getAssociation())) {
+          AssociationSetEnd end = as.getEnd1();
+          if (sourceEntitySetName.equals(end.getEntitySet())
+              && sourceEntitySetRole.equals(end.getRole())) {
+            return as;
+          } else {
+            end = as.getEnd2();
+            if (sourceEntitySetName.equals(end.getEntitySet())
+                && sourceEntitySetRole.equals(end.getRole())) {
+              return as;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public FunctionImport getFunctionImport(final String entityContainer, final String name)
+      throws ODataException {
+
+    if (functionImports.containsKey(name)) {
+      return functionImports.get(name);
+    }
+
+    EntityContainer container = null;
+    if (!entityContainerInfos.containsKey(entityContainer)) {
+      container = (EntityContainer) getEntityContainerInfo(entityContainer);
+    } else {
+      container = (EntityContainer) entityContainerInfos
+          .get(entityContainer);
+    }
+
+    if (container != null && name != null) {
+      if (container.getFunctionImports() == null) return null;
+      for (FunctionImport fi : container.getFunctionImports()) {
+        if (name.equals(fi.getName())) {
+          functionImports.put(name, fi);
+          return fi;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<Schema> getSchemas() throws ODataException {
+    if (schemas == null && jpaEdmModel != null) {
+      jpaEdmModel.getBuilder().build();
+      schemas = new ArrayList<Schema>();
+      schemas.add(jpaEdmModel.getEdmSchemaView().getEdmSchema());
+    }
+    if (jpaEdmModel == null) {
+
+      throw ODataJPAModelException.throwException(
+          ODataJPAModelException.BUILDER_NULL, null);
+    }
+
+    return schemas;
+
+  }
+
+}


[26/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExceptionVisitExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExceptionVisitExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExceptionVisitExpression.java
new file mode 100644
index 0000000..e24a845
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExceptionVisitExpression.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+
+/**
+ * Exception thrown while traversing/visiting a filter expression tree
+ * @author SAP AG
+ */
+public class ExceptionVisitExpression extends ODataMessageException {
+  private static final long serialVersionUID = 7701L;
+
+  public static final MessageReference COMMON = createMessageReference(ExceptionVisitExpression.class, "COMMON");
+
+  private CommonExpression filterTree;
+
+  public ExceptionVisitExpression() {
+    super(COMMON);
+  }
+
+  /**
+   * Create {@link ExceptionVisitExpression} with given {@link MessageReference}.
+   * 
+   * @param messageReference
+   *   references the message text (and additional values) of this {@link ExceptionVisitExpression}
+   */
+  public ExceptionVisitExpression(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  /**
+   * Create {@link ExceptionVisitExpression} with given {@link MessageReference} and cause {@link Throwable} which caused
+   * this {@link ExceptionVisitExpression}.
+   * 
+   * @param message
+   *   references the message text (and additional values) of this {@link ExceptionVisitExpression}
+   * @param cause
+   *   exception which caused this {@link ExceptionVisitExpression}
+   */
+  public ExceptionVisitExpression(final MessageReference message, final Throwable cause) {
+    super(message, cause);
+  }
+
+  /**
+   * Get erroneous filter for debug information
+   * @return Erroneous filter tree 
+   */
+  public CommonExpression getFilterTree() {
+    return filterTree;
+  }
+
+  /**
+   * Sets erroneous filter tree for debug information.
+   * @param filterTree Erroneous filter tree
+   */
+  public void setFilterTree(final CommonExpression filterTree) {
+    this.filterTree = filterTree;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionKind.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionKind.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionKind.java
new file mode 100644
index 0000000..9b22787
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionKind.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Enumeration describing all possible node types inside an expression tree
+ * @author SAP AG
+ */
+public enum ExpressionKind {
+  /**
+   * Used to mark the root node of a filter expression tree
+   * @see FilterExpression  
+   */
+  FILTER,
+  /**
+   * Literal expressions like "1.1d" or "'This is a string'"
+   * @see LiteralExpression 
+   */
+  LITERAL,
+
+  /**
+   * Unary operator expressions like "not" and "-"
+   * @see UnaryExpression
+   */
+  UNARY,
+
+  /**
+   * Binary operator expressions like "eq" and "or" 
+   * @see BinaryExpression
+   */
+  BINARY,
+
+  /**
+   * Method operator expressions like "substringof" and "concat" 
+   * @see MethodExpression
+   */
+  METHOD,
+
+  /**
+   * Member access expressions like "/" in "adress/street"
+   * @see MemberExpression 
+   */
+  MEMBER,
+
+  /**
+   * Property expressions like "age" 
+   * @see PropertyExpression
+   */
+  PROPERTY,
+
+  /**
+   * Order expressions like "age desc" 
+   * @see OrderExpression
+   */
+  ORDER,
+
+  /**
+   * Orderby expression like "age desc, name asc" 
+   * @see OrderByExpression
+   */
+  ORDERBY;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java
new file mode 100644
index 0000000..5816ea9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionParserException.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+
+/**
+ * Exception thrown while parsing a filter or orderby expression
+ * @author SAP AG
+ */
+public class ExpressionParserException extends ODataBadRequestException {
+  private static final long serialVersionUID = 7702L;
+
+  public static final MessageReference COMMON_ERROR = createMessageReference(ExpressionParserException.class, "COMMON");
+
+  //token related exception texts
+  public static final MessageReference ERROR_IN_TOKENIZER = createMessageReference(ExpressionParserException.class, "ERROR_IN_TOKENIZER");
+  public static final MessageReference TOKEN_UNDETERMINATED_STRING = createMessageReference(ExpressionParserException.class, "TOKEN_UNDETERMINATED_STRING");
+  public static final MessageReference INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING = createMessageReference(ExpressionParserException.class, "INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING");
+
+  //parsing
+  public static final MessageReference EXPRESSION_EXPECTED_AFTER_POS = createMessageReference(ExpressionParserException.class, "EXPRESSION_EXPECTED_AFTER_POS");
+  public static final MessageReference COMMA_OR_END_EXPECTED_AT_POS = createMessageReference(ExpressionParserException.class, "COMMA_OR_END_EXPECTED_AT_POS");
+  public static final MessageReference EXPRESSION_EXPECTED_AT_POS = createMessageReference(ExpressionParserException.class, "EXPRESSION_EXPECTED_AT_POS");
+  public static final MessageReference MISSING_CLOSING_PHARENTHESIS = createMessageReference(ExpressionParserException.class, "MISSING_CLOSING_PHARENTHESIS");
+  public static final MessageReference COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS = createMessageReference(ExpressionParserException.class, "COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS");
+  public static final MessageReference INVALID_METHOD_CALL = createMessageReference(ExpressionParserException.class, "INVALID_METHOD_CALL");
+  public static final MessageReference TYPE_EXPECTED_AT = createMessageReference(ExpressionParserException.class, "TYPE_EXPECTED_AT");
+
+  //validation exceptions texts - method
+  public static final MessageReference METHOD_WRONG_ARG_EXACT = createMessageReference(ExpressionParserException.class, "METHOD_WRONG_ARG_EXACT");
+  public static final MessageReference METHOD_WRONG_ARG_BETWEEN = createMessageReference(ExpressionParserException.class, "METHOD_WRONG_ARG_BETWEEN");
+  public static final MessageReference METHOD_WRONG_ARG_X_OR_MORE = createMessageReference(ExpressionParserException.class, "METHOD_WRONG_ARG_X_OR_MORE");
+  public static final MessageReference METHOD_WRONG_ARG_X_OR_LESS = createMessageReference(ExpressionParserException.class, "METHOD_WRONG_ARG_X_OR_LESS");
+  public static final MessageReference METHOD_WRONG_INPUT_TYPE = createMessageReference(ExpressionParserException.class, "METHOD_WRONG_INPUT_TYPE");
+
+  //validation exceptions texts - member
+  public static final MessageReference LEFT_SIDE_NOT_STRUCTURAL_TYPE = createMessageReference(ExpressionParserException.class, "LEFT_SIDE_NOT_STRUCTURAL_TYPE");
+  public static final MessageReference LEFT_SIDE_NOT_A_PROPERTY = createMessageReference(ExpressionParserException.class, "LEFT_SIDE_NOT_A_PROPERTY");
+  public static final MessageReference PROPERTY_NAME_NOT_FOUND_IN_TYPE = createMessageReference(ExpressionParserException.class, "PROPERTY_NAME_NOT_FOUND_IN_TYPE");
+
+  //validation exceptions texts - binary
+  public static final MessageReference INVALID_TYPES_FOR_BINARY_OPERATOR = createMessageReference(ExpressionParserException.class, "INVALID_TYPES_FOR_BINARY_OPERATOR");
+
+  //orderby  
+  public static final MessageReference INVALID_SORT_ORDER = createMessageReference(ExpressionParserException.class, "INVALID_SORT_ORDER");
+
+  //instance attributes
+  private CommonExpression filterTree;
+
+  //Constructors
+  public ExpressionParserException() {
+    super(COMMON_ERROR);
+  }
+
+  /**
+   * Create {@link ExpressionParserException} with given {@link MessageReference}.
+   * 
+   * @param messageReference
+   *   references the message text (and additional values) of this {@link ExpressionParserException}
+   */
+  public ExpressionParserException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  /**
+   * Create {@link ExpressionParserException} with given {@link MessageReference} and cause {@link Throwable} which caused
+   * this {@link ExpressionParserException}.
+   * 
+   * @param messageReference
+   *   References the message text (and additional values) of this {@link ExpressionParserException}
+   * @param cause
+   *   Exception which caused this {@link ExpressionParserException}
+   */
+  public ExpressionParserException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  /**
+   * Gets erroneous filter expression tree for debug information.
+   * @return erroneous filter tree 
+   */
+  public CommonExpression getFilterTree() {
+    return filterTree;
+  }
+
+  /**
+   * Sets erroneous filter tree for debug information.
+   * @param filterTree filter tree to be set
+   */
+  public void setFilterTree(final CommonExpression filterTree) {
+    this.filterTree = filterTree;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionVisitor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionVisitor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionVisitor.java
new file mode 100644
index 0000000..06c8c8d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/ExpressionVisitor.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+
+/**
+ * Interface {@link ExpressionVisitor} is used to traverse a $filter or $orderby expression tree.
+ * Any class instance implementing this interface can be passed to the method {@link Visitable#accept(ExpressionVisitor)}
+ * of an expression node to start the traversing. While traversing, the appropriate methods of the visitor implementation
+ * will be called.
+ * @author SAP AG
+ */
+public interface ExpressionVisitor {
+  /**
+   * Visits a filter expression
+   * @param filterExpression
+   *   The visited filter expression node
+   * @param expressionString
+   *   The $filter expression string used to build the filter expression tree   
+   * @param expression
+   *   The expression node representing the first <i>operator</i>,<i>method</i>,<i>literal</i> or <i>property</i> of the expression tree
+   * @return
+   *   The overall result of evaluating the whole filter expression tree    
+   */
+  Object visitFilterExpression(FilterExpression filterExpression, String expressionString, Object expression);
+
+  /**
+   * Visits a binary expression
+   * @param binaryExpression
+   *   The visited binary expression node
+   * @param operator
+   *   The operator used in the binary expression
+   * @param leftSide
+   *   The result of visiting the left expression node
+   * @param rightSide
+   *   The result of visiting the right expression node
+   * @return
+   *   Returns the result from evaluating operator, leftSide and rightSide 
+   */
+  Object visitBinary(BinaryExpression binaryExpression, BinaryOperator operator, Object leftSide, Object rightSide);
+
+  /**
+   * Visits a orderby expression
+   * @param orderByExpression
+   *   The visited orderby expression node
+   * @param expressionString
+   *   The $orderby expression string used to build the orderby expression tree   
+   * @param orders
+   *   The result of visiting the orders of the orderby expression
+   * @return
+   *   The overall result of evaluating the orderby expression tree  
+   */
+  Object visitOrderByExpression(OrderByExpression orderByExpression, String expressionString, List<Object> orders);
+
+  /**
+   * Visits a order expression
+   * @param orderExpression
+   *   The visited order expression node
+   * @param filterResult
+   *   The result of visiting the filter expression contained in the order
+   * @param sortOrder
+   *   The sort order
+   * @return
+   *   The overall result of evaluating the order
+   */
+  Object visitOrder(OrderExpression orderExpression, Object filterResult, SortOrder sortOrder);
+
+  /**
+   * Visits a literal expression 
+   * @param literal
+   *   The visited literal expression node
+   * @param edmLiteral
+   *   The detected EDM literal (value and type)  
+   * @return
+   *   The value of the literal 
+   */
+  Object visitLiteral(LiteralExpression literal, EdmLiteral edmLiteral);
+
+  /**
+   * Visits a method expression
+   * @param methodExpression
+   *   The visited method expression node
+   * @param method
+   *   The method used in the method expression
+   * @param parameters
+   *   The result of visiting the parameters of the method 
+   * @return
+   *   Returns the result from evaluating the method and the method parameters 
+   */
+  Object visitMethod(MethodExpression methodExpression, MethodOperator method, List<Object> parameters);
+
+  /**
+   * Visits a member expression (e.g. <path property>/<member property>)
+   * @param memberExpression
+   *   The visited member expression node
+   * @param path
+   *   The result of visiting the path property expression node (the left side of the property operator)
+   * @param property
+   *   The result of visiting the member property expression node
+   * @return
+  *    Returns the <b>value</b> of the corresponding property (which may be a single EDM value or a structured EDM value) 
+   */
+  Object visitMember(MemberExpression memberExpression, Object path, Object property);
+
+  /** 
+  * Visits a property expression
+  * @param propertyExpression
+  *   The visited property expression node
+  * @param uriLiteral
+  *   The URI literal of the property
+  * @param edmProperty
+  *   The EDM property matching the property name used in the expression String 
+  * @return
+  *   Returns the <b>value</b> of the corresponding property ( which may be a single EDM value or a structured EDM value)
+  */
+  Object visitProperty(PropertyExpression propertyExpression, String uriLiteral, EdmTyped edmProperty);
+
+  /**
+   * Visits a unary expression
+   * @param unaryExpression
+   *   The visited unary expression node
+   * @param operator
+   *   The operator used in the unary expression 
+   * @param operand
+   *   The result of visiting the operand expression node
+   * @return
+   *   Returns the result from evaluating operator and operand
+   */
+  Object visitUnary(UnaryExpression unaryExpression, UnaryOperator operator, Object operand);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/FilterExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/FilterExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/FilterExpression.java
new file mode 100644
index 0000000..7f3499c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/FilterExpression.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Represents a $filter expression in the expression tree returned by {@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}
+ * Used to define the <b>root</b> expression node in an $filter expression tree. 
+ * 
+ * @author SAP AG
+ */
+public interface FilterExpression extends CommonExpression {
+
+  /**
+   * @return Returns the $filter expression string used to build the expression tree
+   */
+  String getExpressionString();
+
+  /**
+   * @return Returns the expression node representing the first <i>operator</i>,<i>method</i>,<i>literal</i> or <i>property</i> of the expression tree
+   */
+  CommonExpression getExpression();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/LiteralExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/LiteralExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/LiteralExpression.java
new file mode 100644
index 0000000..74dc2a0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/LiteralExpression.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Represents a literal expression node in the expression tree returned by the methods:
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String) }</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String) }</li> 
+ * <br>
+ * <br>
+ * <p>A literal expression node is inserted in the expression tree for any token witch is no
+ * valid <i>operator</i>, <i>method</i> or <i>property</i>.
+ * <br>
+ * <br>
+ * <p><b>For example</b> the filter "$filter=age eq 12" will result in an expression tree
+ * with a literal expression node for "12".
+ * <br>
+ * <br>
+ * @author SAP AG
+ */
+public interface LiteralExpression extends CommonExpression {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MemberExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MemberExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MemberExpression.java
new file mode 100644
index 0000000..6f4f51b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MemberExpression.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Represents a member expression in the expression tree returned by the methods:
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li> 
+ * <br>
+ * <br>
+ * <p>A member expression node is inserted in the expression tree for any member operator ("/") 
+ * which is used to reference a property of an complex type or entity type.
+ * <br>
+ * <br>
+ * <p><b>For example:</b> The expression "address/city eq 'Heidelberg' will result in an expression tree
+ * containing a member expression node for accessing property "city" which is part of the 
+ * complex property "address". Method {@link #getPath()} will return a reference to the "address" property,
+ * method {@link #getProperty()} will return a refence to the "city" property.
+ * @author SAP AG
+ */
+public interface MemberExpression extends CommonExpression {
+  /**
+   * @return 
+   *   Returns the CommonExpression forming the path (the left side of '/') of the method operator.
+   *   For OData 2.0 the value returned by {@link #getPath()} is a {@link PropertyExpression}   
+   */
+  public CommonExpression getPath();
+
+  /**
+   * @return 
+   *   Return the CommonExpression forming the property (the right side of '/') of the method operator.
+   *   For OData 2.0 the value returned by {@link #getProperty()} is a {@link PropertyExpression}
+   */
+  public CommonExpression getProperty();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodExpression.java
new file mode 100644
index 0000000..574a587
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodExpression.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import java.util.List;
+
+/**
+ * Represents a method expression in the expression tree returned by the methods:
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String) }</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String) }</li> 
+ * <br>
+ * <br>
+ * <p>A method expression node is inserted in the expression tree for any valid
+ * OData method operator in {@link MethodOperator} (e.g. for "substringof", "concat", "year", ... )
+ * <br>
+ * <br>
+ * @author SAP AG
+ */
+public interface MethodExpression extends CommonExpression {
+
+  /**
+   * @return Returns the method object that represents the used method 
+   * @see MethodOperator
+   */
+  public MethodOperator getMethod();
+
+  /**
+   * @return Returns the number of provided method parameters
+   */
+  public int getParameterCount();
+
+  /**
+   * @return Returns a ordered list of expressions defining the input parameters for the used method
+   * @see CommonExpression
+   */
+  public List<CommonExpression> getParameters();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodOperator.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodOperator.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodOperator.java
new file mode 100644
index 0000000..71cc7f1
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/MethodOperator.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Enumerations for all supported methods of the ODATA expression parser 
+ * for ODATA version 2.0 (with some restrictions). 
+ * @author SAP AG
+ */
+public enum MethodOperator {
+  ENDSWITH("endswith"), INDEXOF("indexof"), STARTSWITH("startswith"), TOLOWER("tolower"), TOUPPER("toupper"), TRIM("trim"), SUBSTRING("substring"), SUBSTRINGOF("substringof"), CONCAT("concat"), LENGTH("length"), YEAR("year"), MONTH("month"), DAY("day"), HOUR("hour"), MINUTE("minute"), SECOND("second"), ROUND("round"), FLOOR("floor"), CEILING("ceiling");
+
+  private String syntax;
+  private String stringRespresentation;
+
+  private MethodOperator(final String syntax) {
+    this.syntax = syntax;
+    stringRespresentation = syntax;
+  }
+
+  /** 
+   * @return Operators name for usage in in text
+   */
+  @Override
+  public String toString() {
+    return stringRespresentation;
+  }
+
+  /**
+   * @return URI literal of the unary operator as used in the URL. 
+   */
+  public String toUriLiteral() {
+    return syntax;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderByExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderByExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderByExpression.java
new file mode 100644
index 0000000..8645a0c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderByExpression.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import java.util.List;
+
+/**
+ * Represents a $orderby expression in the expression tree returned by
+ * {@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String) }
+ * Used to define the <b>root</b> expression node in an $filter expression tree.
+ * 
+ * @author SAP AG
+ */
+public interface OrderByExpression extends CommonExpression {
+  /**
+   * @return Returns the $filter expression string used to build the expression tree
+   */
+  String getExpressionString();
+
+  /**
+   * @return 
+   *   Returns a ordered list of order expressions contained in the $orderby expression string
+   *   <p>
+   *   <b>For example</b>: The orderby expression build from "$orderby=name asc, age desc" 
+   *   would contain to order expression.  
+   */
+  public List<OrderExpression> getOrders();
+
+  /**
+   * @return Returns the count of order expressions contained in the $orderby expression string
+   */
+  public int getOrdersCount();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderExpression.java
new file mode 100644
index 0000000..4bd8a8b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/OrderExpression.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Represents a order expression in the expression tree returned by the method 
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String) }</li> 
+ * <br>
+ * <br>
+ * <p>A order expression node is inserted in the expression tree for any valid
+ * OData order. For example for "$orderby=age desc, name asc" two order expression node
+ * will be inserted into the expression tree
+ * <br>
+ * <br>
+ * @author SAP AG
+ */
+public interface OrderExpression extends CommonExpression {
+
+  /**
+   * @return Returns the sort order (ascending or descending) of the order expression  
+   */
+  SortOrder getSortOrder();
+
+  /**
+   * @return Returns the expression node which defines the data used to order the output
+   * send back to the client. In the simplest case this would be a {@link PropertyExpression}.
+   * @see CommonExpression
+   */
+  CommonExpression getExpression();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/PropertyExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/PropertyExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/PropertyExpression.java
new file mode 100644
index 0000000..534cc3a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/PropertyExpression.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+
+/**
+ * Represents a property expression in the expression tree returned by the methods:
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <br>
+ * <br>
+ * <p>A property expression node is inserted in the expression tree for any property.
+ * If an EDM is available during parsing the property is automatically verified 
+ * against the EDM.
+ * <br>
+ * <br>
+ * @author SAP AG
+ */
+public interface PropertyExpression extends CommonExpression {
+  /**
+   * @return the property name as used in the EDM
+   */
+  public String getPropertyName();
+
+  /**
+   * @return Returns the EDM property matching the property name used in the expression String.
+   *   This may be an instance of EdmProperty or EdmNavigationProperty
+   * @see EdmTyped    
+   */
+  public EdmTyped getEdmProperty();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/SortOrder.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/SortOrder.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/SortOrder.java
new file mode 100644
index 0000000..b23849d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/SortOrder.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Enumeration describing all possible sort orders used in an $orderby expression 
+ * @author SAP AG
+ */
+public enum SortOrder {
+
+  /**
+   * Sort order ascending 
+   */
+  asc("asc"),
+
+  /**
+   * Sort order descending 
+   */
+  desc("desc");
+
+  private String syntax;
+  private String stringRespresentation;
+
+  private SortOrder(final String syntax) {
+    this.syntax = syntax;
+    stringRespresentation = syntax;
+  }
+
+  /** 
+   * @return Operators name for usage in in text
+   */
+  @Override
+  public String toString() {
+    return stringRespresentation;
+  }
+
+  /**
+   * @return URI literal of the unary operator as used in the URL. 
+   */
+  public String toUriLiteral() {
+    return syntax;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryExpression.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryExpression.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryExpression.java
new file mode 100644
index 0000000..9c54c56
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryExpression.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Represents a unary expression node in the expression tree returned by the methods:
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseFilterString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li>
+ * <li>{@link org.apache.olingo.odata2.api.uri.UriParser#parseOrderByString(org.apache.olingo.odata2.api.edm.EdmEntityType, String)}</li> 
+ * <br>
+ * <br>
+ * <p>A unary expression node is inserted in the expression tree for any valid
+ * ODATA unary operator in {@link UnaryOperator} (e.g. for "not or "-" )
+ * <br>
+ * <br>
+ * @author SAP AG
+ */
+public interface UnaryExpression extends CommonExpression {
+
+  /**
+   * @return Returns the operator object that represents the used operator
+   * @see UnaryOperator
+   */
+  public UnaryOperator getOperator();
+
+  /**
+   * @return Returns the expression node of the operand of the unary operator
+   * @see CommonExpression
+   */
+  public CommonExpression getOperand();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryOperator.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryOperator.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryOperator.java
new file mode 100644
index 0000000..fbbf11f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/UnaryOperator.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+/**
+ * Enumerations for supported unary operators of the OData expression parser
+ * for OData version 2.0
+ * @author SAP AG 
+ */
+public enum UnaryOperator {
+  MINUS("-", "negation"), NOT("not");
+
+  private String syntax;
+  private String stringRespresentation;
+
+  private UnaryOperator(final String syntax) {
+    this.syntax = syntax;
+    stringRespresentation = syntax;
+  }
+
+  private UnaryOperator(final String syntax, final String stringRespresentation) {
+    this.syntax = syntax;
+    this.stringRespresentation = stringRespresentation;
+  }
+
+  /** 
+   * @return Methods name for usage in in text
+   */
+  @Override
+  public String toString() {
+    return stringRespresentation;
+  }
+
+  /**
+   * @return Syntax of the unary operator as used in the URL. 
+   */
+  public String toUriLiteral() {
+    return syntax;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/Visitable.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/Visitable.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/Visitable.java
new file mode 100644
index 0000000..3659aa7
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/Visitable.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.api.uri.expression;
+
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+
+/**
+ * The interface {@link Visitable} is part of the visitor pattern used to traverse 
+ * the expression tree build from a $filter expression string or $orderby expression string.
+ * It is implemented by each class used as node in an expression tree.
+ * @author SAP AG
+ * @see ExpressionVisitor
+ *
+ */
+public interface Visitable {
+
+  /**
+   * Method {@link #accept(ExpressionVisitor)} is called when traversing the expression tree. This method is invoked on each 
+   * expression used as node in an expression tree. The implementations should  
+   * behave as follows:
+   * <li>Call accept on all sub nodes and store the returned Objects
+   * <li>Call the appropriate method on the {@link ExpressionVisitor} instance and provide the stored objects to that instance 
+   * <li>Return the object which should be passed to the processing algorithm of the parent expression node
+   * <br>
+   * <br>
+   * @param visitor 
+   *   Object ( implementing {@link ExpressionVisitor}) whose methods are called during traversing a expression node of the expression tree.
+   * @return
+   *   Object which should be passed to the processing algorithm of the parent expression node  
+   * @throws ExceptionVisitExpression
+   *   Exception occurred the OData library while traversing the tree
+   * @throws ODataApplicationException
+   *   Exception thrown by the application who implemented the visitor  
+   */
+  Object accept(ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/package-info.java
new file mode 100644
index 0000000..0dd23e2
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/expression/package-info.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Expression Parser
+ * <p>This package contains all classes necessary to decribe an expression tree(e.g. a filter or order by tree)
+ * 
+ * <p>Trees can be traversed by implementing the {@link org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor} interface and calling the accept() method. 
+ * <br>Different types of expressions can be found in {@link org.apache.olingo.odata2.api.uri.expression.ExpressionKind}.
+ */
+package org.apache.olingo.odata2.api.uri.expression;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/DeleteUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/DeleteUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/DeleteUriInfo.java
new file mode 100644
index 0000000..cf742fc
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/DeleteUriInfo.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * Access to the parts of the request URI that are relevant for DELETE requests.
+ * @org.apache.olingo.odata2.DoNotImplement
+* @author SAP AG
+*/
+public interface DeleteUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target type of the request: an entity type, a simple type, or a complex type.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the path used to select a (simple or complex) property of an entity,
+   * or an empty list if no property is accessed.
+   * @return List of {@link EdmProperty}
+   */
+  public List<EdmProperty> getPropertyPath();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetComplexPropertyUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetComplexPropertyUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetComplexPropertyUriInfo.java
new file mode 100644
index 0000000..c8f2798
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetComplexPropertyUriInfo.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of complex properties.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetComplexPropertyUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target complex type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the path used to select a (simple or complex) property of an entity,
+   * or an empty list if no property is accessed.
+   * @return List of {@link EdmProperty}
+   */
+  public List<EdmProperty> getPropertyPath();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityCountUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityCountUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityCountUriInfo.java
new file mode 100644
index 0000000..c4ed2d9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityCountUriInfo.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the count of a single entity (also known as existence check).
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntityCountUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Determines whether $count has been used in the request URI.
+   * @return whether $count has been used
+   */
+  public boolean isCount();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkCountUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkCountUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkCountUriInfo.java
new file mode 100644
index 0000000..6f89fb5
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkCountUriInfo.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the number of links to a single entity (also known as existence check).
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntityLinkCountUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Determines whether $count has been used in the request URI.
+   * @return whether $count has been used
+   */
+  public boolean isCount();
+
+  /**
+   * Determines whether $links has been used in the request URI.
+   * @return whether $links has been used
+   */
+  public boolean isLinks();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkUriInfo.java
new file mode 100644
index 0000000..36afb71
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityLinkUriInfo.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the URI of a single entity.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntityLinkUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Determines whether $links has been used in the request URI.
+   * @return whether $links has been used
+   */
+  public boolean isLinks();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetCountUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetCountUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetCountUriInfo.java
new file mode 100644
index 0000000..a05af1f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetCountUriInfo.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the number of entities.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntitySetCountUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Determines whether $count has been used in the request URI.
+   * @return whether $count has been used
+   */
+  public boolean isCount();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the value of the $skip system query option.
+   * @return skip or null
+   */
+  public Integer getSkip();
+
+  /**
+   * Gets the value of the $top system query option.
+   * @return top or null
+   */
+  public Integer getTop();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}


[10/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java
new file mode 100644
index 0000000..cfbfb9b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserImpl.java
@@ -0,0 +1,856 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
+import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.UnaryOperator;
+import org.apache.olingo.odata2.core.edm.EdmBoolean;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class FilterParserImpl implements FilterParser {
+  /*do the static initialization*/
+  protected static Map<String, InfoBinaryOperator> availableBinaryOperators;
+  protected static Map<String, InfoMethod> availableMethods;
+  protected static Map<String, InfoUnaryOperator> availableUnaryOperators;
+
+  static {
+    initAvailTables();
+  }
+
+  /*instance attributes*/
+  protected EdmEntityType resourceEntityType = null;
+  protected TokenList tokenList = null;
+  protected String curExpression;
+
+  /**
+   * Creates a new FilterParser implementation
+   * @param resourceEntityType EntityType of the resource on which the filter is applied
+   */
+  public FilterParserImpl(final EdmEntityType resourceEntityType) {
+    this.resourceEntityType = resourceEntityType;
+  }
+
+  @Override
+  public FilterExpression parseFilterString(final String filterExpression) throws ExpressionParserException, ExpressionParserInternalError {
+    return parseFilterString(filterExpression, false);
+  }
+
+  public FilterExpression parseFilterString(final String filterExpression, final boolean allowOnlyBinary) throws ExpressionParserException, ExpressionParserInternalError {
+    CommonExpression node = null;
+    curExpression = filterExpression;
+    try {
+      // Throws TokenizerException and FilterParserException. FilterParserException is caught somewhere above 
+      tokenList = new Tokenizer(filterExpression).tokenize();
+      if (!tokenList.hasTokens()) {
+        return new FilterExpressionImpl(filterExpression);
+      }
+    } catch (TokenizerException tokenizerException) {
+      // Tested with TestParserExceptions.TestPMparseFilterString
+      throw FilterParserExceptionImpl.createERROR_IN_TOKENIZER(tokenizerException, curExpression);
+    }
+
+    try {
+      CommonExpression nodeLeft = readElement(null);
+      node = readElements(nodeLeft, 0);
+    } catch (ExpressionParserException filterParserException) {
+      // Add empty filterTree to Exception
+      // Tested for original throw point
+      filterParserException.setFilterTree(new FilterExpressionImpl(filterExpression));
+      throw filterParserException;
+    }
+
+    // Post check
+    if (tokenList.tokenCount() > tokenList.currentToken) //this indicates that not all tokens have been read
+    {
+      // Tested with TestParserExceptions.TestPMparseFilterString
+      throw FilterParserExceptionImpl.createINVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING(tokenList.elementAt(tokenList.currentToken), filterExpression);
+    }
+
+    // Create and return filterExpression node
+    if ((allowOnlyBinary == true) && (node.getEdmType() != null) && (node.getEdmType() != EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance())) {
+      // Tested with TestParserExceptions.testAdditionalStuff CASE 9
+      throw FilterParserExceptionImpl.createTYPE_EXPECTED_AT(EdmBoolean.getInstance(), node.getEdmType(), 1, curExpression);
+    }
+
+    return new FilterExpressionImpl(filterExpression, node);
+  }
+
+  protected CommonExpression readElements(final CommonExpression leftExpression, final int priority) throws ExpressionParserException, ExpressionParserInternalError {
+    CommonExpression leftNode = leftExpression;
+    CommonExpression rightNode;
+    BinaryExpression binaryNode;
+
+    ActualBinaryOperator operator = readBinaryOperator();
+    ActualBinaryOperator nextOperator;
+
+    while ((operator != null) && (operator.getOP().getPriority() >= priority)) {
+      tokenList.next(); //eat the operator
+      rightNode = readElement(leftNode, operator); //throws FilterParserException, FilterParserInternalError
+      if (rightNode == null) {
+        // Tested with TestParserExceptions.testAdditionalStuff CASE 10
+        throw FilterParserExceptionImpl.createEXPRESSION_EXPECTED_AFTER_POS(operator.getToken().getPosition() + operator.getToken().getUriLiteral().length(), curExpression);
+      }
+      nextOperator = readBinaryOperator();
+
+      // It must be "while" because for example in "Filter=a or c eq d and e eq f"
+      // after reading the "eq" operator the "and" operator must be consumed too. This is due to the fact that "and" has a higher priority than "or" 
+      while ((nextOperator != null) && (nextOperator.getOP().getPriority() > operator.getOP().getPriority())) {
+        //recurse until the a binary operator with a lower priority is detected 
+        rightNode = readElements(rightNode, nextOperator.getOP().getPriority());
+        nextOperator = readBinaryOperator();
+      }
+
+      // Although the member operator is also a binary operator, there is some special handling in the filterTree
+      if (operator.getOP().getOperator() == BinaryOperator.PROPERTY_ACCESS) {
+        binaryNode = new MemberExpressionImpl(leftNode, rightNode);
+      } else {
+        binaryNode = new BinaryExpressionImpl(operator.getOP(), leftNode, rightNode, operator.getToken());
+      }
+
+      try {
+        validateBinaryOperatorTypes(binaryNode);
+      } catch (ExpressionParserException expressionException) {
+        // Extend the error information
+        // Tested for original throw point
+        expressionException.setFilterTree(binaryNode);
+        throw expressionException;
+      }
+
+      leftNode = binaryNode;
+      operator = readBinaryOperator();
+    }
+
+    //Add special handling for expressions like $filter=notsupportedfunction('a')
+    //If this special handling is not in place the error text would be 
+    //-->Invalid token "(" detected after parsing at position 21 in "notsupportedfunction('a')".
+    //with this special handling we ensure that the error text would be
+
+    Token token = tokenList.lookToken();
+    if (token != null) {
+      if ((leftNode.getKind() == ExpressionKind.PROPERTY) && (tokenList.lookToken().getKind() == TokenKind.OPENPAREN)) {
+        // Tested with TestParserExceptions.testAdditionalStuff CASE 2
+        throw FilterParserExceptionImpl.createINVALID_METHOD_CALL(leftNode, tokenList.lookPrevToken(), curExpression);
+      }
+    }
+
+    return leftNode;
+  }
+
+  /**
+   * Reads the content between parenthesis. Its is expected that the current token is of kind {@link TokenKind#OPENPAREN}
+   * because it MUST be check in the calling method ( when read the method name and the '(' is read).  
+   * @return An expression which reflects the content within the parenthesis
+   * @throws ExpressionParserException
+   *   While reading the elements in the parenthesis an error occurred
+   * @throws TokenizerMessage 
+   *   The next token did not match the expected token
+   */
+  protected CommonExpression readParenthesis() throws ExpressionParserException, ExpressionParserInternalError {
+    // The existing of a '(' is verified BEFORE this method is called --> so it's a internal error
+    Token openParenthesis = tokenList.expectToken(TokenKind.OPENPAREN, true);
+
+    CommonExpression firstExpression = readElement(null);
+    CommonExpression parenthesisExpression = readElements(firstExpression, 0);
+
+    // check for ')'
+    try {
+      tokenList.expectToken(TokenKind.CLOSEPAREN); //TokenizerMessage
+    } catch (TokenizerExpectError e) {
+      // Internal parsing error, even if there are no more token (then there should be a different exception).
+      // Tested with TestParserExceptions.TestPMreadParenthesis
+      throw FilterParserExceptionImpl.createMISSING_CLOSING_PHARENTHESIS(openParenthesis.getPosition(), curExpression, e);
+    }
+    return parenthesisExpression;
+  }
+
+  /**
+   * Read the parameters of a method expression
+   * @param methodInfo
+   *   Signature information about the method whose parameters should be read
+   * @param methodExpression
+   *   Method expression to which the read parameters are added 
+   * @return
+   *   The method expression input parameter 
+   * @throws ExpressionParserException
+   * @throws ExpressionParserInternalError 
+   * @throws TokenizerExpectError 
+   *   The next token did not match the expected token
+   */
+  protected MethodExpression readParameters(final InfoMethod methodInfo, final MethodExpressionImpl methodExpression, final Token methodToken) throws ExpressionParserException, ExpressionParserInternalError {
+    CommonExpression expression;
+    boolean expectAnotherExpression = false;
+    boolean readComma = true;
+
+    // The existing of a '(' is verified BEFORE this method is called --> so it's a internal error
+    Token openParenthesis = tokenList.expectToken(TokenKind.OPENPAREN, true); //throws FilterParserInternalError
+
+    Token token = tokenList.lookToken();
+    if (token == null) {
+      //Tested with TestParserExceptions.TestPMreadParameters CASE 1 e.g. "$filter=concat("
+      throw FilterParserExceptionImpl.createEXPRESSION_EXPECTED_AFTER_POS(openParenthesis, curExpression);
+    }
+
+    while (token.getKind() != TokenKind.CLOSEPAREN) {
+      if (readComma == false) {
+        //Tested with TestParserExceptions.TestPMreadParameters CASE 12 e.g. "$filter=concat('a' 'b')"
+        throw FilterParserExceptionImpl.createCOMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS(tokenList.lookPrevToken(), curExpression);
+      }
+      expression = readElement(null);
+      if (expression != null) {
+        expression = readElements(expression, 0);
+      }
+
+      if ((expression == null) && (expectAnotherExpression == true)) {
+        //Tested with TestParserExceptions.TestPMreadParameters CASE 4 e.g. "$filter=concat(,"
+        throw FilterParserExceptionImpl.createEXPRESSION_EXPECTED_AFTER_POS(token, curExpression);
+      } else if (expression != null) //parameter list may be empty
+      {
+        methodExpression.appendParameter(expression);
+      }
+
+      token = tokenList.lookToken();
+      if (token == null) {
+        //Tested with TestParserExceptions.TestPMreadParameters CASE 2 e.g. "$filter=concat(123"
+        throw FilterParserExceptionImpl.createCOMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS(tokenList.lookPrevToken(), curExpression);
+      }
+
+      if (token.getKind() == TokenKind.COMMA) {
+        expectAnotherExpression = true;
+        if (expression == null) {
+          //Tested with TestParserExceptions.TestPMreadParameters CASE 3 e.g. "$filter=concat(,"
+          throw FilterParserExceptionImpl.createEXPRESSION_EXPECTED_AT_POS(token, curExpression);
+        }
+
+        tokenList.expectToken(",", true);
+        readComma = true;
+      } else {
+        readComma = false;
+      }
+    }
+
+    // because the while loop above only exits if a ')' has been found it is an  
+    // internal error if there is not ')'
+    tokenList.expectToken(TokenKind.CLOSEPAREN, true);
+
+    //---check parameter count
+    int count = methodExpression.getParameters().size();
+    if ((methodInfo.getMinParameter() > -1) && (count < methodInfo.getMinParameter())) {
+      //Tested with TestParserExceptions.TestPMreadParameters CASE 12
+      throw FilterParserExceptionImpl.createMETHOD_WRONG_ARG_COUNT(methodExpression, methodToken, curExpression);
+    }
+
+    if ((methodInfo.getMaxParameter() > -1) && (count > methodInfo.getMaxParameter())) {
+      //Tested with TestParserExceptions.TestPMreadParameters CASE 15
+      throw FilterParserExceptionImpl.createMETHOD_WRONG_ARG_COUNT(methodExpression, methodToken, curExpression);
+    }
+
+    return methodExpression;
+  }
+
+  protected CommonExpression readElement(final CommonExpression leftExpression) throws ExpressionParserException, ExpressionParserInternalError {
+    return readElement(leftExpression, null);
+  }
+
+  /**
+   * Reads: Unary operators, Methods, Properties, ...
+   * but not binary operators which are handelt in {@link #readElements(CommonExpression, int)}
+   * @param leftExpression 
+   *   Used while parsing properties. In this case ( e.g. parsing "a/b") the property "a" ( as leftExpression of "/") is relevant 
+   *   to verify whether the property "b" exists inside the edm
+   * @return a CommonExpression
+   * @throws ExpressionParserException
+   * @throws ExpressionParserInternalError 
+   * @throws TokenizerMessage 
+   */
+  protected CommonExpression readElement(final CommonExpression leftExpression, final ActualBinaryOperator leftOperator) throws ExpressionParserException, ExpressionParserInternalError {
+    CommonExpression node = null;
+    Token token;
+    Token lookToken;
+    lookToken = tokenList.lookToken();
+    if (lookToken == null) {
+      return null;
+    }
+
+    switch (lookToken.getKind()) {
+    case OPENPAREN:
+      node = readParenthesis();
+      return node;
+    case CLOSEPAREN: // ')'  finishes a parenthesis (it is no extra token)" +
+    case COMMA: //. " ','  is a separator for function parameters (it is no extra token)" +
+      return null;
+    default:
+      // continue
+    }
+
+    //-->Check if the token is a unary operator
+    InfoUnaryOperator unaryOperator = isUnaryOperator(lookToken);
+    if (unaryOperator != null) {
+      return readUnaryoperator(lookToken, unaryOperator);
+    }
+
+    //---expect the look ahead token
+    token = tokenList.expectToken(lookToken.getUriLiteral(), true);
+    lookToken = tokenList.lookToken();
+
+    //-->Check if the token is a method 
+    //To avoid name clashes between method names and property names we accept here only method names if a "(" follows.
+    //Hence the parser accepts a property named "concat"
+    InfoMethod methodOperator = isMethod(token, lookToken);
+    if (methodOperator != null) {
+      return readMethod(token, methodOperator);
+    }
+
+    //-->Check if token is a terminal 
+    //is a terminal e.g. a Value like an EDM.String 'hugo' or  125L or 1.25D" 
+    if (token.getKind() == TokenKind.SIMPLE_TYPE) {
+      LiteralExpression literal = new LiteralExpressionImpl(token.getUriLiteral(), token.getJavaLiteral());
+      return literal;
+    }
+
+    //-->Check if token is a property, e.g. "name" or "address"
+    if (token.getKind() == TokenKind.LITERAL) {
+      PropertyExpressionImpl property = new PropertyExpressionImpl(token.getUriLiteral(), token.getJavaLiteral());
+      validateEdmProperty(leftExpression, property, token, leftOperator);
+      return property;
+    }
+
+    // not Tested, should not occur 
+    throw ExpressionParserInternalError.createCOMMON();
+  }
+
+  protected CommonExpression readUnaryoperator(final Token lookToken, final InfoUnaryOperator unaryOperator) throws ExpressionParserException, ExpressionParserInternalError {
+    tokenList.expectToken(lookToken.getUriLiteral(), true);
+
+    CommonExpression operand = readElement(null);
+    UnaryExpression unaryExpression = new UnaryExpressionImpl(unaryOperator, operand);
+    validateUnaryOperatorTypes(unaryExpression); //throws ExpressionInvalidOperatorTypeException
+
+    return unaryExpression;
+  }
+
+  protected CommonExpression readMethod(final Token token, final InfoMethod methodOperator) throws ExpressionParserException, ExpressionParserInternalError {
+    MethodExpressionImpl method = new MethodExpressionImpl(methodOperator);
+
+    readParameters(methodOperator, method, token);
+    validateMethodTypes(method, token); //throws ExpressionInvalidOperatorTypeException
+
+    return method;
+  }
+
+  protected ActualBinaryOperator readBinaryOperator() {
+    InfoBinaryOperator operator = null;
+    Token token = tokenList.lookToken();
+    if (token == null) {
+      return null;
+    }
+    if ((token.getKind() == TokenKind.SYMBOL) && (token.getUriLiteral().equals("/"))) {
+      operator = availableBinaryOperators.get(token.getUriLiteral());
+    } else if (token.getKind() == TokenKind.LITERAL) {
+      operator = availableBinaryOperators.get(token.getUriLiteral());
+    }
+
+    if (operator == null) {
+      return null;
+    }
+
+    return new ActualBinaryOperator(operator, token);
+  }
+
+  /**
+   * Check if a token is a UnaryOperator ( e.g. "not" or "-" ) 
+   * 
+   * @param token Token to be checked
+   *   
+   * @return
+   *   <li>An instance of {@link InfoUnaryOperator} containing information about the specific unary operator</li> 
+   *   <li><code>null</code> if the token is not an unary operator</li>
+   */
+  protected InfoUnaryOperator isUnaryOperator(final Token token) {
+    if ((token.getKind() == TokenKind.LITERAL) || (token.getKind() == TokenKind.SYMBOL)) {
+      InfoUnaryOperator operator = availableUnaryOperators.get(token.getUriLiteral());
+      return operator;
+    }
+    return null;
+  }
+
+  protected InfoMethod isMethod(final Token token, final Token lookToken) {
+    if ((lookToken != null) && (lookToken.getKind() == TokenKind.OPENPAREN)) {
+      return availableMethods.get(token.getUriLiteral());
+    }
+    return null;
+  }
+
+  protected void validateEdmProperty(final CommonExpression leftExpression, final PropertyExpressionImpl property, final Token propertyToken, final ActualBinaryOperator actBinOp) throws ExpressionParserException, ExpressionParserInternalError {
+
+    // Exist if no edm provided
+    if (resourceEntityType == null) {
+      return;
+    }
+
+    if (leftExpression == null) {
+      //e.g. "$filter=city eq 'Hong Kong'" --> "city" is checked against the resource entity type of the last URL segment 
+      validateEdmPropertyOfStructuredType(resourceEntityType, property, propertyToken);
+      return;
+    }
+    //e.g. "$filter='Hong Kong' eq address/city" --> city is "checked" against the type of the property "address".
+    //     "address" itself must be a (navigation)property of the resource entity type of the last URL segment AND
+    //     "address" must have a structural edm type
+    EdmType parentType = leftExpression.getEdmType(); //parentType point now to the type of property "address"
+
+    if ((actBinOp != null) && (actBinOp.operator.getOperator() != BinaryOperator.PROPERTY_ACCESS)) {
+      validateEdmPropertyOfStructuredType(resourceEntityType, property, propertyToken);
+      return;
+    } else {
+      if ((leftExpression.getKind() != ExpressionKind.PROPERTY) && (leftExpression.getKind() != ExpressionKind.MEMBER)) {
+        if (actBinOp != null) {
+          //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 6
+          throw FilterParserExceptionImpl.createLEFT_SIDE_NOT_A_PROPERTY(actBinOp.token, curExpression);
+        } else {
+          // not Tested, should not occur 
+          throw ExpressionParserInternalError.createCOMMON();
+        }
+
+      }
+    }
+
+    if (parentType instanceof EdmEntityType) {
+      //e.g. "$filter='Hong Kong' eq navigationProp/city" --> "navigationProp" is a navigation property with a entity type
+      validateEdmPropertyOfStructuredType((EdmStructuralType) parentType, property, propertyToken);
+    } else if (parentType instanceof EdmComplexType) {
+      //e.g. "$filter='Hong Kong' eq address/city" --> "address" is a property with a complex type 
+      validateEdmPropertyOfStructuredType((EdmStructuralType) parentType, property, propertyToken);
+    } else {
+      //e.g. "$filter='Hong Kong' eq name/city" --> "name is of type String"
+      //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 5
+      throw FilterParserExceptionImpl.createLEFT_SIDE_NOT_STRUCTURAL_TYPE(parentType, property, propertyToken, curExpression);
+    }
+
+    return;
+  }
+
+  protected void validateEdmPropertyOfStructuredType(final EdmStructuralType parentType, final PropertyExpressionImpl property, final Token propertyToken) throws ExpressionParserException, ExpressionParserInternalError {
+    try {
+      String propertyName = property.getUriLiteral();
+      EdmTyped edmProperty = parentType.getProperty(propertyName);
+
+      if (edmProperty != null) {
+        property.setEdmProperty(edmProperty);
+        property.setEdmType(edmProperty.getType());
+      } else {
+        //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 3
+        throw FilterParserExceptionImpl.createPROPERTY_NAME_NOT_FOUND_IN_TYPE(parentType, property, propertyToken, curExpression);
+      }
+
+    } catch (EdmException e) {
+      // not Tested, should not occur
+      throw ExpressionParserInternalError.createERROR_ACCESSING_EDM(e);
+    }
+  }
+
+  /*
+    protected void validateEdmPropertyOfComplexType1(EdmComplexType parentType, PropertyExpressionImpl property, Token propertyToken) throws FilterParserException, FilterParserInternalError
+    {
+      try {
+        String propertyName = property.getUriLiteral();
+        EdmTyped edmProperty = parentType.getProperty(propertyName);
+
+        if (edmProperty != null)
+        {
+          property.setEdmProperty(edmProperty);
+          property.setEdmType(edmProperty.getType());
+        }
+        else
+        {
+          //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 3
+          throw FilterParserExceptionImpl.createPROPERTY_NAME_NOT_FOUND_IN_TYPE(parentType, property, propertyToken, curExpression);
+        }
+
+      } catch (EdmException e) {
+        // not Tested, should not occur
+        throw FilterParserInternalError.createERROR_ACCESSING_EDM(e);
+      }
+    }
+
+    protected void validateEdmPropertyOfEntityType1(EdmEntityType parentType, PropertyExpressionImpl property, Token propertyToken) throws FilterParserException, FilterParserInternalError
+    {
+      try {
+        String propertyName = property.getUriLiteral();
+        EdmTyped edmProperty = parentType.getProperty(propertyName);
+
+        if (edmProperty != null)
+        {
+          property.setEdmProperty(edmProperty);
+          property.setEdmType(edmProperty.getType());
+        }
+        else
+        {
+          //Tested with TestParserExceptions.TestPMvalidateEdmProperty CASE 1
+          throw FilterParserExceptionImpl.createPROPERTY_NAME_NOT_FOUND_IN_TYPE(parentType, property, propertyToken, curExpression);
+        }
+
+      } catch (EdmException e) {
+        // not Tested, should not occur
+        throw FilterParserInternalError.createERROR_ACCESSING_EDM(e);
+      }
+    }*/
+
+  protected void validateUnaryOperatorTypes(final UnaryExpression unaryExpression) throws ExpressionParserInternalError {
+    InfoUnaryOperator unOpt = availableUnaryOperators.get(unaryExpression.getOperator().toUriLiteral());
+    EdmType operandType = unaryExpression.getOperand().getEdmType();
+
+    if ((operandType == null) && (resourceEntityType == null)) {
+      return;
+    }
+
+    List<EdmType> actualParameterTypes = new ArrayList<EdmType>();
+    actualParameterTypes.add(operandType);
+
+    ParameterSet parameterSet = unOpt.validateParameterSet(actualParameterTypes);
+    if (parameterSet != null) {
+      unaryExpression.setEdmType(parameterSet.getReturnType());
+    }
+  }
+
+  protected void validateBinaryOperatorTypes(final BinaryExpression binaryExpression) throws ExpressionParserException, ExpressionParserInternalError {
+    InfoBinaryOperator binOpt = availableBinaryOperators.get(binaryExpression.getOperator().toUriLiteral());
+
+    List<EdmType> actualParameterTypes = new ArrayList<EdmType>();
+    EdmType operand = binaryExpression.getLeftOperand().getEdmType();
+
+    if ((operand == null) && (resourceEntityType == null)) {
+      return;
+    }
+    actualParameterTypes.add(operand);
+
+    operand = binaryExpression.getRightOperand().getEdmType();
+
+    if ((operand == null) && (resourceEntityType == null)) {
+      return;
+    }
+    actualParameterTypes.add(operand);
+
+    ParameterSet parameterSet = binOpt.validateParameterSet(actualParameterTypes);
+    if (parameterSet == null) {
+      BinaryExpressionImpl binaryExpressionImpl = (BinaryExpressionImpl) binaryExpression;
+
+      // Tested with TestParserExceptions.TestPMvalidateBinaryOperator
+      throw FilterParserExceptionImpl.createINVALID_TYPES_FOR_BINARY_OPERATOR(binaryExpression.getOperator(), binaryExpression.getLeftOperand().getEdmType(), binaryExpression.getRightOperand().getEdmType(), binaryExpressionImpl.getToken(), curExpression);
+    }
+    binaryExpression.setEdmType(parameterSet.getReturnType());
+  }
+
+  protected void validateMethodTypes(final MethodExpression methodExpression, final Token methodToken) throws ExpressionParserException, ExpressionParserInternalError {
+    InfoMethod methOpt = availableMethods.get(methodExpression.getUriLiteral());
+
+    List<EdmType> actualParameterTypes = new ArrayList<EdmType>();
+
+    //If there are no parameter then don't perform a type check
+    if (methodExpression.getParameters().size() == 0) {
+      return;
+    }
+
+    for (CommonExpression parameter : methodExpression.getParameters()) {
+      //If there is not at parsing time its not possible to determine the type of eg myPropertyName.
+      //Since this should not cause validation errors null type node arguments are leading to bypass
+      //the validation
+      if ((parameter.getEdmType() == null) && (resourceEntityType == null)) {
+        return;
+      }
+      actualParameterTypes.add(parameter.getEdmType());
+    }
+
+    ParameterSet parameterSet = methOpt.validateParameterSet(actualParameterTypes);
+    //If there is not returntype then the input parameter 
+    if (parameterSet == null) {
+      // Tested with TestParserExceptions.testPMvalidateMethodTypes CASE 1
+      throw FilterParserExceptionImpl.createMETHOD_WRONG_INPUT_TYPE((MethodExpressionImpl) methodExpression, methodToken, curExpression);
+    }
+    methodExpression.setEdmType(parameterSet.getReturnType());
+  }
+
+  static void initAvailTables() {
+    Map<String, InfoBinaryOperator> lAvailableBinaryOperators = new HashMap<String, InfoBinaryOperator>();
+    Map<String, InfoMethod> lAvailableMethods = new HashMap<String, InfoMethod>();
+    Map<String, InfoUnaryOperator> lAvailableUnaryOperators = new HashMap<String, InfoUnaryOperator>();
+
+    //create type validators
+    //InputTypeValidator typeValidatorPromotion = new InputTypeValidator.TypePromotionValidator();
+    ParameterSetCombination combination = null;
+    //create type helpers
+    EdmSimpleType boolean_ = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Boolean);
+    EdmSimpleType sbyte = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.SByte);
+    EdmSimpleType byte_ = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Byte);
+    EdmSimpleType int16 = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Int16);
+    EdmSimpleType int32 = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Int32);
+    EdmSimpleType int64 = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Int64);
+    EdmSimpleType single = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Single);
+    EdmSimpleType double_ = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Double);
+    EdmSimpleType decimal = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Decimal);
+    EdmSimpleType string = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.String);
+    EdmSimpleType time = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Time);
+    EdmSimpleType datetime = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.DateTime);
+    EdmSimpleType datetimeoffset = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.DateTimeOffset);
+    EdmSimpleType guid = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Guid);
+    EdmSimpleType binary = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Binary);
+
+    //---Memeber member access---
+    lAvailableBinaryOperators.put("/", new InfoBinaryOperator(BinaryOperator.PROPERTY_ACCESS, "Primary", 100, new ParameterSetCombination.PSCReturnTypeEqLastParameter()));//todo fix this
+
+    //---Multiplicative---
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(sbyte, sbyte, sbyte));
+    combination.add(new ParameterSet(byte_, byte_, byte_));
+    combination.add(new ParameterSet(int16, int16, int16));
+    combination.add(new ParameterSet(int32, int32, int32));
+    combination.add(new ParameterSet(int64, int64, int64));
+    combination.add(new ParameterSet(single, single, single));
+    combination.add(new ParameterSet(double_, double_, double_));
+
+    combination.add(new ParameterSet(decimal, decimal, decimal));
+
+    lAvailableBinaryOperators.put(BinaryOperator.MUL.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.MUL, "Multiplicative", 60, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.DIV.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.DIV, "Multiplicative", 60, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.MODULO.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.MODULO, "Multiplicative", 60, combination));
+
+    //---Additive---
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(sbyte, sbyte, sbyte));
+    combination.add(new ParameterSet(byte_, byte_, byte_));
+    combination.add(new ParameterSet(int16, int16, int16));
+    combination.add(new ParameterSet(int32, int32, int32));
+    combination.add(new ParameterSet(int64, int64, int64));
+    combination.add(new ParameterSet(single, single, single));
+    combination.add(new ParameterSet(double_, double_, double_));
+    combination.add(new ParameterSet(decimal, decimal, decimal));
+
+    lAvailableBinaryOperators.put(BinaryOperator.ADD.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.ADD, "Additive", 50, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.SUB.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.SUB, "Additive", 50, combination));
+
+    //---Relational---
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, string, string));
+    combination.add(new ParameterSet(boolean_, time, time));
+    combination.add(new ParameterSet(boolean_, datetime, datetime));
+    combination.add(new ParameterSet(boolean_, datetimeoffset, datetimeoffset));
+    combination.add(new ParameterSet(boolean_, guid, guid));
+    combination.add(new ParameterSet(boolean_, sbyte, sbyte));
+    combination.add(new ParameterSet(boolean_, byte_, byte_));
+    combination.add(new ParameterSet(boolean_, int16, int16));
+    combination.add(new ParameterSet(boolean_, int32, int32));
+    combination.add(new ParameterSet(boolean_, int64, int64));
+    combination.add(new ParameterSet(boolean_, single, single));
+    combination.add(new ParameterSet(boolean_, double_, double_));
+    combination.add(new ParameterSet(boolean_, decimal, decimal));
+    combination.add(new ParameterSet(boolean_, binary, binary));
+
+    lAvailableBinaryOperators.put(BinaryOperator.LT.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.LT, "Relational", 40, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.GT.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.GT, "Relational", 40, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.GE.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.GE, "Relational", 40, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.LE.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.LE, "Relational", 40, combination));
+
+    //---Equality---
+    //combination = new ParameterSetCombination.PSCflex();
+    combination.addFirst(new ParameterSet(boolean_, boolean_, boolean_));
+    /*combination.add(new ParameterSet(boolean_, string, string));
+    combination.add(new ParameterSet(boolean_, time, time));
+    combination.add(new ParameterSet(boolean_, datetime, datetime));
+    combination.add(new ParameterSet(boolean_, datetimeoffset, datetimeoffset));
+    combination.add(new ParameterSet(boolean_, guid, guid));
+    combination.add(new ParameterSet(boolean_, sbyte, sbyte));
+    combination.add(new ParameterSet(boolean_, byte_, byte_));
+    combination.add(new ParameterSet(boolean_, int16, int16));
+    combination.add(new ParameterSet(boolean_, int32, int32));
+    combination.add(new ParameterSet(boolean_, int64, int64));
+    combination.add(new ParameterSet(boolean_, single, single));
+    combination.add(new ParameterSet(boolean_, double_, double_));
+    combination.add(new ParameterSet(boolean_, decimal, decimal));
+    combination.add(new ParameterSet(boolean_, binary, binary));*/
+
+    lAvailableBinaryOperators.put(BinaryOperator.EQ.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.EQ, "Equality", 30, combination));
+    lAvailableBinaryOperators.put(BinaryOperator.NE.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.NE, "Equality", 30, combination));
+
+    //"---Conditinal AND---
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, boolean_, boolean_));
+
+    lAvailableBinaryOperators.put(BinaryOperator.AND.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.AND, "Conditinal", 20, combination));
+
+    //---Conditinal OR---
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, boolean_, boolean_));
+
+    lAvailableBinaryOperators.put(BinaryOperator.OR.toUriLiteral(), new InfoBinaryOperator(BinaryOperator.OR, "Conditinal", 10, combination));
+
+    //endswith
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, string, string));
+    lAvailableMethods.put(MethodOperator.ENDSWITH.toUriLiteral(), new InfoMethod(MethodOperator.ENDSWITH, 2, 2, combination));
+
+    //indexof
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, string, string));
+    lAvailableMethods.put(MethodOperator.INDEXOF.toUriLiteral(), new InfoMethod(MethodOperator.INDEXOF, 2, 2, combination));
+
+    //startswith
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, string, string));
+    lAvailableMethods.put(MethodOperator.STARTSWITH.toUriLiteral(), new InfoMethod(MethodOperator.STARTSWITH, 2, 2, combination));
+
+    //tolower
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(string, string));
+    lAvailableMethods.put(MethodOperator.TOLOWER.toUriLiteral(), new InfoMethod(MethodOperator.TOLOWER, combination));
+
+    //toupper
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(string, string));
+    lAvailableMethods.put(MethodOperator.TOUPPER.toUriLiteral(), new InfoMethod(MethodOperator.TOUPPER, combination));
+
+    //trim
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(string, string));
+    lAvailableMethods.put(MethodOperator.TRIM.toUriLiteral(), new InfoMethod(MethodOperator.TRIM, combination));
+
+    //substring
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(string, string, int32));
+    combination.add(new ParameterSet(string, string, int32, int32));
+    lAvailableMethods.put(MethodOperator.SUBSTRING.toUriLiteral(), new InfoMethod(MethodOperator.SUBSTRING, 1, -1, combination));
+
+    //substringof
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, string, string));
+    lAvailableMethods.put(MethodOperator.SUBSTRINGOF.toUriLiteral(), new InfoMethod(MethodOperator.SUBSTRINGOF, 1, -1, combination));
+
+    //concat
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(string, string, string).setFurtherType(string));
+    lAvailableMethods.put(MethodOperator.CONCAT.toUriLiteral(), new InfoMethod(MethodOperator.CONCAT, 2, -1, combination));
+
+    //length
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, string));
+    lAvailableMethods.put(MethodOperator.LENGTH.toUriLiteral(), new InfoMethod(MethodOperator.LENGTH, combination));
+
+    //year
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, datetime));
+    lAvailableMethods.put(MethodOperator.YEAR.toUriLiteral(), new InfoMethod(MethodOperator.YEAR, combination));
+
+    //month
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, datetime));
+    lAvailableMethods.put(MethodOperator.MONTH.toUriLiteral(), new InfoMethod(MethodOperator.MONTH, combination));
+
+    //day
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, datetime));
+    lAvailableMethods.put(MethodOperator.DAY.toUriLiteral(), new InfoMethod(MethodOperator.DAY, combination));
+
+    //hour
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, datetime));
+    combination.add(new ParameterSet(int32, time));
+    combination.add(new ParameterSet(int32, datetimeoffset));
+    lAvailableMethods.put(MethodOperator.HOUR.toUriLiteral(), new InfoMethod(MethodOperator.HOUR, combination));
+
+    //minute
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, datetime));
+    combination.add(new ParameterSet(int32, time));
+    combination.add(new ParameterSet(int32, datetimeoffset));
+    lAvailableMethods.put(MethodOperator.MINUTE.toUriLiteral(), new InfoMethod(MethodOperator.MINUTE, combination));
+
+    //second
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(int32, datetime));
+    combination.add(new ParameterSet(int32, time));
+    combination.add(new ParameterSet(int32, datetimeoffset));
+    lAvailableMethods.put(MethodOperator.SECOND.toUriLiteral(), new InfoMethod(MethodOperator.SECOND, combination));
+
+    //round
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(decimal, decimal));
+    combination.add(new ParameterSet(double_, double_));
+    lAvailableMethods.put(MethodOperator.ROUND.toUriLiteral(), new InfoMethod(MethodOperator.ROUND, combination));
+
+    //ceiling
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(decimal, decimal));
+    combination.add(new ParameterSet(double_, double_));
+    lAvailableMethods.put(MethodOperator.CEILING.toUriLiteral(), new InfoMethod(MethodOperator.CEILING, combination));
+
+    //floor
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(decimal, decimal));
+    combination.add(new ParameterSet(double_, double_));
+    lAvailableMethods.put(MethodOperator.FLOOR.toUriLiteral(), new InfoMethod(MethodOperator.FLOOR, combination));
+
+    //---unary---
+
+    //minus
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(sbyte, sbyte));
+    combination.add(new ParameterSet(byte_, byte_));
+    combination.add(new ParameterSet(int16, int16));
+    combination.add(new ParameterSet(int32, int32));
+    combination.add(new ParameterSet(int64, int64));
+    combination.add(new ParameterSet(single, single));
+    combination.add(new ParameterSet(double_, double_));
+    combination.add(new ParameterSet(decimal, decimal));
+
+    //minus
+    lAvailableUnaryOperators.put(UnaryOperator.MINUS.toUriLiteral(), new InfoUnaryOperator(UnaryOperator.MINUS, "minus", combination));
+
+    //not
+    combination = new ParameterSetCombination.PSCflex();
+    combination.add(new ParameterSet(boolean_, boolean_));
+    lAvailableUnaryOperators.put(UnaryOperator.NOT.toUriLiteral(), new InfoUnaryOperator(UnaryOperator.NOT, "not", combination));
+
+    availableBinaryOperators = Collections.unmodifiableMap(lAvailableBinaryOperators);
+    availableMethods = Collections.unmodifiableMap(lAvailableMethods);
+    availableUnaryOperators = Collections.unmodifiableMap(lAvailableUnaryOperators);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoBinaryOperator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoBinaryOperator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoBinaryOperator.java
new file mode 100644
index 0000000..fdcf225
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoBinaryOperator.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+
+/**
+ * Describes a binary operator which is allowed in OData expressions
+ * @author SAP AG
+ */
+class InfoBinaryOperator {
+  private BinaryOperator operator;
+  private String category;
+  private String syntax;
+  private int priority;
+  ParameterSetCombination combination;
+
+  public InfoBinaryOperator(final BinaryOperator operator, final String category, final int priority, final ParameterSetCombination combination) {
+    this.operator = operator;
+    this.category = category;
+    syntax = operator.toUriLiteral();
+    this.priority = priority;
+    this.combination = combination;
+  }
+
+  public String getCategory() {
+    return category;
+  }
+
+  public String getSyntax() {
+    return syntax;
+  }
+
+  public BinaryOperator getOperator() {
+    return operator;
+  }
+
+  public int getPriority() {
+    return priority;
+  }
+
+  public ParameterSet validateParameterSet(final List<EdmType> actualParameterTypes) throws ExpressionParserInternalError {
+    return combination.validate(actualParameterTypes);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoMethod.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoMethod.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoMethod.java
new file mode 100644
index 0000000..38778f3
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoMethod.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
+
+/**
+ * Describes a method expression which is allowed in OData expressions
+ * @author SAP AG
+ */
+class InfoMethod {
+
+  public MethodOperator method;
+  public String syntax;
+  public int minParameter;
+  public int maxParameter;
+  ParameterSetCombination combination;
+
+  public InfoMethod(final MethodOperator method, final ParameterSetCombination combination) {
+    this.method = method;
+    syntax = method.toUriLiteral();
+    minParameter = 1;
+    maxParameter = 1;
+    this.combination = combination;
+  }
+
+  public InfoMethod(final MethodOperator method, final int minParameters, final int maxParameters, final ParameterSetCombination combination) {
+    this.method = method;
+    syntax = method.toUriLiteral();
+    minParameter = minParameters;
+    maxParameter = maxParameters;
+    this.combination = combination;
+  }
+
+  public InfoMethod(final MethodOperator method, final String string, final int minParameters, final int maxParameters, final ParameterSetCombination combination) {
+    this.method = method;
+    syntax = string;
+    minParameter = minParameters;
+    maxParameter = maxParameters;
+    this.combination = combination;
+  }
+
+  public MethodOperator getMethod() {
+    return method;
+  }
+
+  public String getSyntax() {
+    return syntax;
+  }
+
+  public int getMinParameter() {
+    return minParameter;
+  }
+
+  public int getMaxParameter() {
+    return maxParameter;
+  }
+
+  public ParameterSet validateParameterSet(final List<EdmType> actualParameterTypes) throws ExpressionParserInternalError {
+    return combination.validate(actualParameterTypes);
+  }
+
+  /**
+   * Returns the EdmType of the returned value of a Method
+   * If a method may have different return types (depending on the input type) null will be returned. 
+   */
+  public EdmType getReturnType() {
+    return combination.getReturnType();
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoUnaryOperator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoUnaryOperator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoUnaryOperator.java
new file mode 100644
index 0000000..16463d9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InfoUnaryOperator.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.expression.UnaryOperator;
+
+/**
+ * Describes a unary operator which is allowed in OData expressions
+ * @author SAP AG
+ */
+class InfoUnaryOperator {
+  UnaryOperator operator;
+  private String category;
+  private String syntax;
+  ParameterSetCombination combination;
+
+  public InfoUnaryOperator(final UnaryOperator operator, final String category, final ParameterSetCombination combination) {
+    this.operator = operator;
+    this.category = category;
+    syntax = operator.toUriLiteral();
+    this.combination = combination;
+  }
+
+  public String getCategory() {
+    return category;
+  }
+
+  public String getSyntax() {
+    return syntax;
+  }
+
+  public UnaryOperator getOperator() {
+    return operator;
+  }
+
+  public ParameterSet validateParameterSet(final List<EdmType> actualParameterTypes) throws ExpressionParserInternalError {
+    return combination.validate(actualParameterTypes);
+  }
+
+  /**
+   * Returns the EdmType of the returned value of a Method
+   * If a method may have different return types (depending on the input type) null will be returned. 
+   */
+  /*
+  public EdmType getReturnType()
+  {
+  int parameterCount = allowedParameterTypes.size();
+  if (parameterCount == 0)
+   return null;
+
+  if (parameterCount == 1)
+   return allowedParameterTypes.get(0).getReturnType();
+
+  //There are more than 1 possible return type, check if they are equal, if not return null.
+  EdmType returnType = allowedParameterTypes.get(0).getReturnType();
+  for (int i = 1; i < parameterCount; i++)
+   if (returnType != allowedParameterTypes.get(i))
+     return null;
+
+  return returnType;
+  }*/
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InputTypeValidator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InputTypeValidator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InputTypeValidator.java
new file mode 100644
index 0000000..246b769
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/InputTypeValidator.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+public interface InputTypeValidator {
+
+  public EdmType validateParameterSet(List<ParameterSet> allowedParameterTypes, List<EdmType> actualParameterTypes) throws ExpressionParserInternalError;
+
+  public static class TypePromotionValidator implements InputTypeValidator {
+
+    @Override
+    public EdmType validateParameterSet(final List<ParameterSet> allowedParameterTypes, final List<EdmType> actualParameterTypes) throws ExpressionParserInternalError {
+      //first check for exact parameter combination
+      for (ParameterSet parameterSet : allowedParameterTypes) {
+        boolean s = parameterSet.equals(actualParameterTypes, false);
+        if (s) {
+          return parameterSet.getReturnType();
+        }
+      }
+
+      //first check for parameter combination with promotion
+      for (ParameterSet parameterSet : allowedParameterTypes) {
+        boolean s = parameterSet.equals(actualParameterTypes, true);
+        if (s) {
+          return parameterSet.getReturnType();
+        }
+      }
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/JsonVisitor.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/JsonVisitor.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/JsonVisitor.java
new file mode 100644
index 0000000..48bb8fe
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/JsonVisitor.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
+import org.apache.olingo.odata2.api.uri.expression.MemberExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderExpression;
+import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
+import org.apache.olingo.odata2.api.uri.expression.SortOrder;
+import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.UnaryOperator;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class JsonVisitor implements ExpressionVisitor {
+
+  @Override
+  public Object visitFilterExpression(final FilterExpression filterExpression, final String expressionString, final Object expression) {
+    return expression;
+  }
+
+  @Override
+  public Object visitBinary(final BinaryExpression binaryExpression, final BinaryOperator operator, final Object leftSide, final Object rightSide) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", binaryExpression.getKind().toString()).separator()
+          .namedStringValue("operator", operator.toUriLiteral()).separator()
+          .namedStringValueRaw("type", getType(binaryExpression)).separator()
+          .name("left").unquotedValue(leftSide.toString()).separator()
+          .name("right").unquotedValue(rightSide.toString())
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitOrderByExpression(final OrderByExpression orderByExpression, final String expressionString, final List<Object> orders) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", "order collection").separator()
+          .name("orders")
+          .beginArray();
+      boolean first = true;
+      for (final Object order : orders) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        jsonStreamWriter.unquotedValue(order.toString());
+      }
+      jsonStreamWriter.endArray()
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitOrder(final OrderExpression orderExpression, final Object filterResult, final SortOrder sortOrder) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", orderExpression.getKind().toString()).separator()
+          .namedStringValueRaw("sortorder", sortOrder.toString()).separator()
+          .name("expression").unquotedValue(filterResult.toString())
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitLiteral(final LiteralExpression literal, final EdmLiteral edmLiteral) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", literal.getKind().toString()).separator()
+          .namedStringValueRaw("type", getType(literal)).separator()
+          .namedStringValue("value", edmLiteral.getLiteral())
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitMethod(final MethodExpression methodExpression, final MethodOperator method, final List<Object> parameters) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", methodExpression.getKind().toString()).separator()
+          .namedStringValueRaw("operator", method.toUriLiteral()).separator()
+          .namedStringValueRaw("type", getType(methodExpression)).separator()
+          .name("parameters")
+          .beginArray();
+      boolean first = true;
+      for (Object parameter : parameters) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        jsonStreamWriter.unquotedValue(parameter.toString());
+      }
+      jsonStreamWriter.endArray()
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitMember(final MemberExpression memberExpression, final Object path, final Object property) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", memberExpression.getKind().toString()).separator()
+          .namedStringValueRaw("type", getType(memberExpression)).separator()
+          .name("source").unquotedValue(path.toString()).separator()
+          .name("path").unquotedValue(property.toString())
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitProperty(final PropertyExpression propertyExpression, final String uriLiteral, final EdmTyped edmProperty) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", propertyExpression.getKind().toString()).separator()
+          .namedStringValue("name", uriLiteral).separator()
+          .namedStringValueRaw("type", getType(propertyExpression))
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  @Override
+  public Object visitUnary(final UnaryExpression unaryExpression, final UnaryOperator operator, final Object operand) {
+    try {
+      StringWriter writer = new StringWriter();
+      JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("nodeType", unaryExpression.getKind().toString()).separator()
+          .namedStringValueRaw("operator", operator.toUriLiteral()).separator()
+          .namedStringValueRaw("type", getType(unaryExpression)).separator()
+          .name("operand").unquotedValue(operand.toString())
+          .endObject();
+      writer.flush();
+      return writer.toString();
+    } catch (final IOException e) {
+      return null;
+    }
+  }
+
+  private static String getType(final CommonExpression expression) {
+    try {
+      final EdmType type = expression.getEdmType();
+      return type == null ? null : type.getNamespace() + Edm.DELIMITER + type.getName();
+    } catch (final EdmException e) {
+      return "EdmException occurred: " + e.getMessage();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/LiteralExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/LiteralExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/LiteralExpressionImpl.java
new file mode 100644
index 0000000..bc41e28
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/LiteralExpressionImpl.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
+
+public class LiteralExpressionImpl implements LiteralExpression {
+
+  private EdmType edmType;
+  private EdmLiteral edmLiteral;
+  private String uriLiteral;
+
+  public LiteralExpressionImpl(final String uriLiteral, final EdmLiteral javaLiteral) {
+    this.uriLiteral = uriLiteral;
+    edmLiteral = javaLiteral;
+    edmType = edmLiteral.getType();
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return edmType;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    this.edmType = edmType;
+    return this;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.LITERAL;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return uriLiteral;
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) {
+    Object ret = visitor.visitLiteral(this, edmLiteral);
+    return ret;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MemberExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MemberExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MemberExpressionImpl.java
new file mode 100644
index 0000000..b4d5ed8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MemberExpressionImpl.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.MemberExpression;
+
+/**
+ * @author SAP AG
+ */
+public class MemberExpressionImpl implements BinaryExpression, MemberExpression {
+  CommonExpression path;
+  CommonExpression property;
+  EdmType edmType;
+
+  public MemberExpressionImpl(final CommonExpression path, final CommonExpression property) {
+    this.path = path;
+    this.property = property;
+    edmType = property.getEdmType();
+  }
+
+  @Override
+  public CommonExpression getPath() {
+    return path;
+  }
+
+  @Override
+  public CommonExpression getProperty() {
+    return property;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return edmType;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    this.edmType = edmType;
+    return this;
+  }
+
+  @Override
+  public BinaryOperator getOperator() {
+    return BinaryOperator.PROPERTY_ACCESS;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.MEMBER;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return BinaryOperator.PROPERTY_ACCESS.toUriLiteral();
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    Object retSource = path.accept(visitor);
+    Object retPath = property.accept(visitor);
+
+    Object ret = visitor.visitMember(this, retSource, retPath);
+    return ret;
+  }
+
+  @Override
+  public CommonExpression getLeftOperand() {
+    return path;
+  }
+
+  @Override
+  public CommonExpression getRightOperand() {
+    return property;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MethodExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MethodExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MethodExpressionImpl.java
new file mode 100644
index 0000000..26a8ba4
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/MethodExpressionImpl.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
+
+/**
+ * @author SAP AG
+ */
+public class MethodExpressionImpl implements MethodExpression {
+
+  private InfoMethod infoMethod;
+  private EdmType returnType;
+  private List<CommonExpression> actualParameters;
+
+  public MethodExpressionImpl(final InfoMethod infoMethod) {
+    this.infoMethod = infoMethod;
+    returnType = infoMethod.getReturnType();
+    actualParameters = new ArrayList<CommonExpression>();
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return returnType;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    returnType = edmType;
+    return this;
+  }
+
+  @Override
+  public MethodOperator getMethod() {
+    return infoMethod.getMethod();
+  }
+
+  public InfoMethod getMethodInfo() {
+    return infoMethod;
+  }
+
+  @Override
+  public List<CommonExpression> getParameters() {
+    return actualParameters;
+  }
+
+  @Override
+  public int getParameterCount() {
+    return actualParameters.size();
+  }
+
+  /**
+   * @param expression
+   * @return A self reference for method chaining" 
+   */
+  public MethodExpressionImpl appendParameter(final CommonExpression expression) {
+    actualParameters.add(expression);
+    return this;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.METHOD;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return infoMethod.getSyntax();
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    ArrayList<Object> retParameters = new ArrayList<Object>();
+    for (CommonExpression parameter : actualParameters) {
+      Object retParameter = parameter.accept(visitor);
+      retParameters.add(retParameter);
+    }
+
+    Object ret = visitor.visitMethod(this, getMethod(), retParameters);
+    return ret;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByExpressionImpl.java
new file mode 100644
index 0000000..7e28dc2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByExpressionImpl.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderExpression;
+
+/**
+ * @author SAP AG
+ */
+public class OrderByExpressionImpl implements OrderByExpression {
+  private String orderbyString;
+
+  List<OrderExpression> orders;
+
+  public OrderByExpressionImpl(final String orderbyString) {
+    this.orderbyString = orderbyString;
+    orders = new ArrayList<OrderExpression>();
+  }
+
+  @Override
+  public String getExpressionString() {
+    return orderbyString;
+  }
+
+  @Override
+  public List<OrderExpression> getOrders() {
+    return orders;
+  }
+
+  @Override
+  public int getOrdersCount() {
+    return orders.size();
+  }
+
+  public void addOrder(final OrderExpression orderNode) {
+    orders.add(orderNode);
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.ORDERBY;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return null;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    return this;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return orderbyString;
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    ArrayList<Object> retParameters = new ArrayList<Object>();
+    for (OrderExpression order : orders) {
+      Object retParameter = order.accept(visitor);
+      retParameters.add(retParameter);
+    }
+
+    Object ret = visitor.visitOrderByExpression(this, orderbyString, retParameters);
+    return ret;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParser.java
new file mode 100644
index 0000000..c1ab197
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParser.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+
+/**
+ * Interface which defines a method for parsing a $orderby expression to allow different parser implementations
+ * <p>
+ * The current expression parser supports expressions as defined in the OData specification 2.0 with the following restrictions
+ *   - the methods "cast", "isof" and "replace" are not supported
+ *   
+ * The expression parser can be used with providing an Entity Data Model (EDM) an without providing it.
+ *  <p>When a EDM is provided the expression parser will be as strict as possible. That means:
+ *  <li>All properties used in the expression must be defined inside the EDM</li>
+ *  <li>The types of EDM properties will be checked against the lists of allowed type per method, binary- and unary operator</li>
+ *  </p>
+ *  <p>If no EDM is provided the expression parser performs a lax validation
+ *  <li>The properties used in the expression are not looked up inside the EDM and the type of the expression node representing the 
+ *      property will be "null"</li>
+ *  <li>Expression node with EDM-types which are "null" are not considered during the parameter type validation, to the return type of the parent expression node will
+ *  also become "null"</li>
+ *  
+ * @author SAP AG
+ */
+public interface OrderByParser {
+  /**
+   * Parses a $orderby expression string and creates an $orderby expression tree
+   * @param orderByExpression
+   *   The $orderby expression string ( for example "name asc" ) to be parsed
+   * @return
+   *    The $orderby expression tree
+   * @throws ExpressionParserException
+   *   Exception thrown due to errors while parsing the $orderby expression string 
+   * @throws ODataMessageException
+   *   Used for extensibility
+   */
+  abstract OrderByExpression parseOrderByString(String orderByExpression) throws ExpressionParserException, ODataMessageException;
+}


[44/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/exception/ODataJPAMessageServiceDefault.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/exception/ODataJPAMessageServiceDefault.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/exception/ODataJPAMessageServiceDefault.java
new file mode 100644
index 0000000..2039efc
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/exception/ODataJPAMessageServiceDefault.java
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.exception;
+
+import java.util.Arrays;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingFormatArgumentException;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAMessageService;
+import org.apache.olingo.odata2.processor.core.jpa.ODataJPAContextImpl;
+
+public class ODataJPAMessageServiceDefault implements ODataJPAMessageService {
+
+  private static final String BUNDLE_NAME = "jpaprocessor_msg"; //$NON-NLS-1$
+  private static final Map<Locale, ODataJPAMessageService> LOCALE_2_MESSAGE_SERVICE = new HashMap<Locale, ODataJPAMessageService>();
+  private static final ResourceBundle defaultResourceBundle = ResourceBundle.getBundle(BUNDLE_NAME);
+  private final ResourceBundle resourceBundle;
+  private final Locale lanLocale;
+
+  @Override
+  public String getLocalizedMessage(final MessageReference context, final Throwable exception) {
+
+    Object[] contentAsArray = context.getContent().toArray(new Object[0]);
+
+    if (contentAsArray.length == 0 && exception != null) {
+      contentAsArray = new Object[2];
+      contentAsArray[0] = exception.getStackTrace()[1].getClassName();
+      contentAsArray[1] = exception.getMessage();
+    }
+    String value = null;
+    String key = context.getKey();
+
+    try {
+      value = getMessage(key);
+      StringBuilder builder = new StringBuilder();
+      Formatter f = null;
+      if (lanLocale == null) {
+        f = new Formatter();
+      } else {
+        f = new Formatter(builder, lanLocale);
+      }
+      f.format(value, contentAsArray);
+      f.close();
+      return builder.toString();
+
+    } catch (MissingResourceException e) {
+      return "Missing message for key '" + key + "'!";
+    } catch (MissingFormatArgumentException e) {
+      return "Missing replacement for place holder in value '" + value
+          + "' for following arguments '"
+          + Arrays.toString(contentAsArray) + "'!";
+    }
+  }
+
+  private ODataJPAMessageServiceDefault(final ResourceBundle resourceBundle,
+      final Locale locale) {
+    this.resourceBundle = resourceBundle;
+    lanLocale = locale;
+  }
+
+  public static ODataJPAMessageService getInstance(final Locale locale) {
+
+    Locale acceptedLocale = Locale.ENGLISH;
+    if ((ODataJPAContextImpl.getContextInThreadLocal() != null) && (ODataJPAContextImpl.getContextInThreadLocal().getAcceptableLanguages() != null)) {
+
+      List<Locale> acceptedLanguages = ODataJPAContextImpl.getContextInThreadLocal().getAcceptableLanguages();
+
+      Iterator<Locale> itr = acceptedLanguages.iterator();
+
+      while (itr.hasNext()) {
+
+        Locale tempLocale = itr.next();
+        if (ResourceBundle.getBundle(BUNDLE_NAME, tempLocale).getLocale().equals(tempLocale)) {
+          acceptedLocale = tempLocale;
+          break;
+        }
+      }
+    }
+
+    ODataJPAMessageService messagesInstance = LOCALE_2_MESSAGE_SERVICE
+        .get(acceptedLocale);
+    if (messagesInstance == null) {
+      ResourceBundle resourceBundle = ResourceBundle.getBundle(BUNDLE_NAME, acceptedLocale);
+
+      if (resourceBundle != null) {
+        messagesInstance = new ODataJPAMessageServiceDefault(
+            resourceBundle, acceptedLocale);
+        LOCALE_2_MESSAGE_SERVICE.put(acceptedLocale, messagesInstance);
+      } else if (defaultResourceBundle != null) {
+        messagesInstance = new ODataJPAMessageServiceDefault(
+            defaultResourceBundle, null);
+      }
+
+    }
+    return messagesInstance;
+  }
+
+  private String getMessage(final String key) {
+    return resourceBundle.getString(key);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/factory/ODataJPAFactoryImpl.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/factory/ODataJPAFactoryImpl.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/factory/ODataJPAFactoryImpl.java
new file mode 100644
index 0000000..ca843a9
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/factory/ODataJPAFactoryImpl.java
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.factory;
+
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext.JPAMethodContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAMessageService;
+import org.apache.olingo.odata2.processor.api.jpa.factory.JPAAccessFactory;
+import org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAAccessFactory;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView;
+import org.apache.olingo.odata2.processor.core.jpa.ODataJPAContextImpl;
+import org.apache.olingo.odata2.processor.core.jpa.ODataJPAProcessorDefault;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAFunctionContext;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAProcessorImpl;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmMappingModelService;
+import org.apache.olingo.odata2.processor.core.jpa.edm.ODataJPAEdmProvider;
+import org.apache.olingo.odata2.processor.core.jpa.exception.ODataJPAMessageServiceDefault;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLJoinSelectContext;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLJoinSelectSingleContext;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLJoinSelectSingleStatementBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLJoinStatementBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectContext;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectSingleContext;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectSingleStatementBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectStatementBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmModel;
+
+public class ODataJPAFactoryImpl extends ODataJPAFactory {
+
+  @Override
+  public JPQLBuilderFactory getJPQLBuilderFactory() {
+    return JPQLBuilderFactoryImpl.create();
+  };
+
+  @Override
+  public JPAAccessFactory getJPAAccessFactory() {
+    return JPAAccessFactoryImpl.create();
+  };
+
+  @Override
+  public ODataJPAAccessFactory getODataJPAAccessFactory() {
+    return ODataJPAAccessFactoryImpl.create();
+  };
+
+  private static class JPQLBuilderFactoryImpl implements JPQLBuilderFactory {
+
+    private static JPQLBuilderFactoryImpl factory = null;
+
+    private JPQLBuilderFactoryImpl() {}
+
+    @Override
+    public JPQLStatementBuilder getStatementBuilder(final JPQLContextView context) {
+      JPQLStatementBuilder builder = null;
+      switch (context.getType()) {
+      case SELECT:
+      case SELECT_COUNT: // for $count, Same as select
+        builder = new JPQLSelectStatementBuilder(context);
+        break;
+      case SELECT_SINGLE:
+        builder = new JPQLSelectSingleStatementBuilder(context);
+        break;
+      case JOIN:
+      case JOIN_COUNT: // for $count, Same as join
+        builder = new JPQLJoinStatementBuilder(context);
+        break;
+      case JOIN_SINGLE:
+        builder = new JPQLJoinSelectSingleStatementBuilder(context);
+      default:
+        break;
+      }
+
+      return builder;
+    }
+
+    @Override
+    public JPQLContextBuilder getContextBuilder(final JPQLContextType contextType) {
+      JPQLContextBuilder contextBuilder = null;
+
+      switch (contextType) {
+      case SELECT:
+        JPQLSelectContext selectContext = new JPQLSelectContext(false);
+        contextBuilder = selectContext.new JPQLSelectContextBuilder();
+        break;
+      case SELECT_SINGLE:
+        JPQLSelectSingleContext singleSelectContext = new JPQLSelectSingleContext();
+        contextBuilder = singleSelectContext.new JPQLSelectSingleContextBuilder();
+        break;
+      case JOIN:
+        JPQLJoinSelectContext joinContext = new JPQLJoinSelectContext(
+            false);
+        contextBuilder = joinContext.new JPQLJoinContextBuilder();
+        break;
+      case JOIN_SINGLE:
+        JPQLJoinSelectSingleContext joinSingleContext = new JPQLJoinSelectSingleContext();
+        contextBuilder = joinSingleContext.new JPQLJoinSelectSingleContextBuilder();
+        break;
+      case SELECT_COUNT:
+        JPQLSelectContext selectCountContext = new JPQLSelectContext(
+            true);
+        contextBuilder = selectCountContext.new JPQLSelectContextBuilder();
+        break;
+      case JOIN_COUNT:
+        JPQLJoinSelectContext joinCountContext = new JPQLJoinSelectContext(
+            true);
+        contextBuilder = joinCountContext.new JPQLJoinContextBuilder();
+      default:
+        break;
+      }
+
+      return contextBuilder;
+    }
+
+    private static JPQLBuilderFactory create() {
+      if (factory == null) {
+        return new JPQLBuilderFactoryImpl();
+      } else {
+        return factory;
+      }
+    }
+
+    @Override
+    public JPAMethodContextBuilder getJPAMethodContextBuilder(
+        final JPQLContextType contextType) {
+
+      JPAMethodContextBuilder contextBuilder = null;
+      switch (contextType) {
+      case FUNCTION:
+        JPAFunctionContext methodConext = new JPAFunctionContext();
+        contextBuilder = methodConext.new JPAFunctionContextBuilder();
+
+        break;
+      default:
+        break;
+      }
+      return contextBuilder;
+    }
+
+  }
+
+  private static class ODataJPAAccessFactoryImpl implements
+      ODataJPAAccessFactory {
+
+    private static ODataJPAAccessFactoryImpl factory = null;
+
+    private ODataJPAAccessFactoryImpl() {}
+
+    @Override
+    public ODataSingleProcessor createODataProcessor(
+        final ODataJPAContext oDataJPAContext) {
+      return new ODataJPAProcessorDefault(oDataJPAContext);
+    }
+
+    @Override
+    public EdmProvider createJPAEdmProvider(final ODataJPAContext oDataJPAContext) {
+      return new ODataJPAEdmProvider(oDataJPAContext);
+    }
+
+    @Override
+    public ODataJPAContext createODataJPAContext() {
+      return new ODataJPAContextImpl();
+    }
+
+    private static ODataJPAAccessFactoryImpl create() {
+      if (factory == null) {
+        return new ODataJPAAccessFactoryImpl();
+      } else {
+        return factory;
+      }
+    }
+
+    @Override
+    public ODataJPAMessageService getODataJPAMessageService(final Locale locale) {
+      return ODataJPAMessageServiceDefault.getInstance(locale);
+    }
+
+  }
+
+  private static class JPAAccessFactoryImpl implements JPAAccessFactory {
+
+    private static JPAAccessFactoryImpl factory = null;
+
+    private JPAAccessFactoryImpl() {}
+
+    @Override
+    public JPAEdmModelView getJPAEdmModelView(
+        final ODataJPAContext oDataJPAContext) {
+      JPAEdmModelView view = null;
+
+      view = new JPAEdmModel(oDataJPAContext);
+      return view;
+    }
+
+    @Override
+    public JPAProcessor getJPAProcessor(final ODataJPAContext oDataJPAContext) {
+      JPAProcessor jpaProcessor = new JPAProcessorImpl(oDataJPAContext);
+
+      return jpaProcessor;
+    }
+
+    private static JPAAccessFactoryImpl create() {
+      if (factory == null) {
+        return new JPAAccessFactoryImpl();
+      } else {
+        return factory;
+      }
+    }
+
+    @Override
+    public JPAEdmMappingModelAccess getJPAEdmMappingModelAccess(
+        final ODataJPAContext oDataJPAContext) {
+      JPAEdmMappingModelAccess mappingModelAccess = new JPAEdmMappingModelService(
+          oDataJPAContext);
+
+      return mappingModelAccess;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectContext.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectContext.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectContext.java
new file mode 100644
index 0000000..c4768fe
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectContext.java
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLJoinContextView;
+import org.apache.olingo.odata2.processor.core.jpa.ODataExpressionParser;
+
+public class JPQLJoinSelectContext extends JPQLSelectContext implements
+    JPQLJoinContextView {
+
+  private List<JPAJoinClause> jpaJoinClauses = null;
+
+  protected void setJPAOuterJoinClause(final List<JPAJoinClause> jpaOuterJoinClauses) {
+    jpaJoinClauses = jpaOuterJoinClauses;
+  }
+
+  public JPQLJoinSelectContext(final boolean isCountOnly) {
+    super(isCountOnly);
+  }
+
+  public class JPQLJoinContextBuilder extends JPQLSelectContextBuilder {
+
+    protected int relationShipAliasCounter = 0;
+
+    @Override
+    public JPQLContext build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+      try {
+
+        if (JPQLJoinSelectContext.this.isCountOnly) {
+          setType(JPQLContextType.JOIN_COUNT);
+        } else {
+          setType(JPQLContextType.JOIN);
+        }
+
+        setJPAOuterJoinClause(generateJoinClauses());
+
+        if (!jpaJoinClauses.isEmpty()) {
+          JPAJoinClause joinClause = jpaJoinClauses
+              .get(jpaJoinClauses.size() - 1);
+          setJPAEntityName(joinClause
+              .getEntityName());
+          setJPAEntityAlias(joinClause
+              .getEntityRelationShipAlias());
+        }
+
+        setOrderByCollection(generateOrderByFileds());
+
+        setSelectExpression(generateSelectExpression());
+
+        setWhereExpression(generateWhereExpression());
+
+      } catch (ODataException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.INNER_EXCEPTION, e);
+      }
+
+      return JPQLJoinSelectContext.this;
+    }
+
+    protected List<JPAJoinClause> generateJoinClauses()
+        throws ODataJPARuntimeException, EdmException {
+
+      List<JPAJoinClause> jpaOuterJoinClauses = new ArrayList<JPAJoinClause>();
+      JPAJoinClause jpaOuterJoinClause = null;
+      String joinCondition = null;
+      String entityAlias = generateJPAEntityAlias();
+      joinCondition = ODataExpressionParser.parseKeyPredicates(
+          entitySetView.getKeyPredicates(),
+          entityAlias);
+
+      EdmEntityType entityType = entitySetView.getStartEntitySet()
+          .getEntityType();
+      Mapping mapping = (Mapping) entityType.getMapping();
+      String entityTypeName = null;
+      if (mapping != null) {
+        entityTypeName = mapping.getInternalName();
+      } else {
+        entityTypeName = entityType.getName();
+      }
+
+      jpaOuterJoinClause = new JPAJoinClause(
+          entityTypeName,
+          entityAlias,
+          null,
+          null, joinCondition,
+          JPAJoinClause.JOIN.INNER);
+
+      jpaOuterJoinClauses.add(jpaOuterJoinClause);
+
+      for (NavigationSegment navigationSegment : entitySetView
+          .getNavigationSegments()) {
+
+        EdmNavigationProperty navigationProperty = navigationSegment
+            .getNavigationProperty();
+
+        String relationShipAlias = generateRelationShipAlias();
+
+        joinCondition = ODataExpressionParser.parseKeyPredicates(
+            navigationSegment.getKeyPredicates(),
+            relationShipAlias);
+
+        jpaOuterJoinClause = new JPAJoinClause(
+            getFromEntityName(navigationProperty),
+            entityAlias,
+            getRelationShipName(navigationProperty),
+            relationShipAlias, joinCondition,
+            JPAJoinClause.JOIN.INNER);
+
+        jpaOuterJoinClauses.add(jpaOuterJoinClause);
+
+      }
+
+      return jpaOuterJoinClauses;
+    }
+
+    private String getFromEntityName(
+        final EdmNavigationProperty navigationProperty) throws EdmException {
+
+      String fromRole = navigationProperty.getFromRole();
+
+      EdmEntityType toEntityType = navigationProperty.getRelationship()
+          .getEnd(fromRole).getEntityType();
+
+      EdmMapping mapping = toEntityType.getMapping();
+
+      String entityName = null;
+      if (mapping != null) {
+        entityName = mapping.getInternalName();
+      } else {
+        entityName = toEntityType.getName();
+      }
+
+      return entityName;
+
+    }
+
+    private String getRelationShipName(
+        final EdmNavigationProperty navigationProperty) throws EdmException {
+
+      EdmMapping mapping = navigationProperty.getMapping();
+
+      String relationShipName = null;
+      if (mapping != null) {
+        relationShipName = mapping.getInternalName();
+      } else {
+        relationShipName = navigationProperty.getName();
+      }
+
+      return relationShipName;
+    }
+
+    private String generateRelationShipAlias() {
+      return new String("R" + ++relationShipAliasCounter);
+    }
+  }
+
+  @Override
+  public List<JPAJoinClause> getJPAJoinClauses() {
+    return jpaJoinClauses;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContext.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContext.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContext.java
new file mode 100644
index 0000000..3f504c1
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContext.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLJoinSelectSingleContextView;
+import org.apache.olingo.odata2.processor.core.jpa.ODataExpressionParser;
+
+public class JPQLJoinSelectSingleContext extends JPQLSelectSingleContext
+    implements JPQLJoinSelectSingleContextView {
+
+  private List<JPAJoinClause> jpaJoinClauses = null;
+
+  protected void setJPAJoinClause(final List<JPAJoinClause> jpaJoinClauses) {
+    this.jpaJoinClauses = jpaJoinClauses;
+  }
+
+  public class JPQLJoinSelectSingleContextBuilder extends
+      JPQLSelectSingleContextBuilder {
+
+    protected int relationShipAliasCounter = 0;
+
+    @Override
+    public JPQLContext build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+      try {
+        setType(JPQLContextType.JOIN_SINGLE);
+        setJPAJoinClause(generateJoinClauses());
+
+        if (!jpaJoinClauses.isEmpty()) {
+          JPAJoinClause joinClause = jpaJoinClauses
+              .get(jpaJoinClauses.size() - 1);
+          setJPAEntityName(joinClause.getEntityName());
+          setJPAEntityAlias(joinClause
+              .getEntityRelationShipAlias());
+        }
+
+        setKeyPredicates(entityView
+            .getKeyPredicates());
+
+        setSelectExpression(generateSelectExpression());
+
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL, e);
+      }
+
+      return JPQLJoinSelectSingleContext.this;
+    }
+
+    protected List<JPAJoinClause> generateJoinClauses()
+        throws ODataJPARuntimeException, EdmException {
+
+      List<JPAJoinClause> jpaOuterJoinClauses = new ArrayList<JPAJoinClause>();
+      JPAJoinClause jpaOuterJoinClause = null;
+      String joinCondition = null;
+      String entityAlias = generateJPAEntityAlias();
+      joinCondition = ODataExpressionParser.parseKeyPredicates(
+          entityView.getKeyPredicates(), entityAlias);
+
+      EdmEntityType entityType = entityView.getStartEntitySet()
+          .getEntityType();
+      Mapping mapping = (Mapping) entityType.getMapping();
+      String entityTypeName = null;
+      if (mapping != null) {
+        entityTypeName = mapping.getInternalName();
+      } else {
+        entityTypeName = entityType.getName();
+      }
+
+      jpaOuterJoinClause = new JPAJoinClause(entityTypeName, entityAlias,
+          null, null, joinCondition, JPAJoinClause.JOIN.INNER);
+
+      jpaOuterJoinClauses.add(jpaOuterJoinClause);
+
+      for (NavigationSegment navigationSegment : entityView
+          .getNavigationSegments()) {
+
+        EdmNavigationProperty navigationProperty = navigationSegment
+            .getNavigationProperty();
+
+        String relationShipAlias = generateRelationShipAlias();
+
+        joinCondition = ODataExpressionParser
+            .parseKeyPredicates(
+                navigationSegment.getKeyPredicates(),
+                relationShipAlias);
+
+        jpaOuterJoinClause = new JPAJoinClause(
+            getFromEntityName(navigationProperty), entityAlias,
+            getRelationShipName(navigationProperty),
+            relationShipAlias, joinCondition,
+            JPAJoinClause.JOIN.INNER);
+
+        jpaOuterJoinClauses.add(jpaOuterJoinClause);
+
+      }
+
+      return jpaOuterJoinClauses;
+    }
+
+    private String getFromEntityName(
+        final EdmNavigationProperty navigationProperty) throws EdmException {
+
+      String fromRole = navigationProperty.getFromRole();
+
+      EdmEntityType fromEntityType = navigationProperty.getRelationship()
+          .getEnd(fromRole).getEntityType();
+
+      EdmMapping mapping = fromEntityType.getMapping();
+
+      String entityName = null;
+      if (mapping != null) {
+        entityName = mapping.getInternalName();
+      } else {
+        entityName = fromEntityType.getName();
+      }
+
+      return entityName;
+
+    }
+
+    private String getRelationShipName(
+        final EdmNavigationProperty navigationProperty) throws EdmException {
+
+      EdmMapping mapping = navigationProperty.getMapping();
+
+      String relationShipName = null;
+      if (mapping != null) {
+        relationShipName = mapping.getInternalName();
+      } else {
+        relationShipName = navigationProperty.getName();
+      }
+
+      return relationShipName;
+    }
+
+    private String generateRelationShipAlias() {
+      return new String("R" + ++relationShipAliasCounter);
+    }
+  }
+
+  @Override
+  public List<JPAJoinClause> getJPAJoinClauses() {
+    return jpaJoinClauses;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilder.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilder.java
new file mode 100644
index 0000000..1e7d6f0
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilder.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLJoinSelectSingleContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+
+public class JPQLJoinSelectSingleStatementBuilder extends JPQLStatementBuilder {
+
+  JPQLStatement jpqlStatement;
+  private JPQLJoinSelectSingleContextView context;
+
+  public JPQLJoinSelectSingleStatementBuilder(final JPQLContextView context) {
+    this.context = (JPQLJoinSelectSingleContextView) context;
+  }
+
+  @Override
+  public JPQLStatement build() throws ODataJPARuntimeException {
+    jpqlStatement = createStatement(createJPQLQuery());
+    return jpqlStatement;
+
+  }
+
+  private String createJPQLQuery() throws ODataJPARuntimeException {
+
+    StringBuilder jpqlQuery = new StringBuilder();
+    StringBuilder joinWhereCondition = null;
+
+    jpqlQuery.append(JPQLStatement.KEYWORD.SELECT).append(
+        JPQLStatement.DELIMITER.SPACE);
+    jpqlQuery.append(context.getSelectExpression()).append(JPQLStatement.DELIMITER.SPACE);
+    jpqlQuery.append(JPQLStatement.KEYWORD.FROM).append(
+        JPQLStatement.DELIMITER.SPACE);
+
+    if (context.getJPAJoinClauses() != null
+        && context.getJPAJoinClauses().size() > 0) {
+      List<JPAJoinClause> joinClauseList = context.getJPAJoinClauses();
+      JPAJoinClause joinClause = joinClauseList.get(0);
+      String joinCondition = joinClause.getJoinCondition();
+      joinWhereCondition = new StringBuilder();
+      if (joinCondition != null) {
+        joinWhereCondition.append(joinCondition);
+      }
+      String relationShipAlias = null;
+      joinClause = joinClauseList.get(1);
+      jpqlQuery.append(joinClause.getEntityName()).append(
+          JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(joinClause.getEntityAlias());
+
+      int i = 1;
+      int limit = joinClauseList.size();
+      relationShipAlias = joinClause.getEntityAlias();
+      while (i < limit) {
+        jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
+        jpqlQuery.append(JPQLStatement.KEYWORD.JOIN).append(
+            JPQLStatement.DELIMITER.SPACE);
+
+        joinClause = joinClauseList.get(i);
+        jpqlQuery.append(relationShipAlias).append(
+            JPQLStatement.DELIMITER.PERIOD);
+        jpqlQuery.append(joinClause.getEntityRelationShip()).append(
+            JPQLStatement.DELIMITER.SPACE);
+        jpqlQuery.append(joinClause.getEntityRelationShipAlias());
+
+        relationShipAlias = joinClause.getEntityRelationShipAlias();
+        i++;
+
+        joinCondition = joinClause.getJoinCondition();
+        if (joinCondition != null) {
+          joinWhereCondition.append(JPQLStatement.DELIMITER.SPACE
+              + JPQLStatement.Operator.AND
+              + JPQLStatement.DELIMITER.SPACE);
+
+          joinWhereCondition.append(joinCondition);
+        }
+
+      }
+    } else {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.JOIN_CLAUSE_EXPECTED, null);
+    }
+
+    if (joinWhereCondition.length() > 0) {
+      jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.KEYWORD.WHERE).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(joinWhereCondition.toString());
+    }
+
+    return jpqlQuery.toString();
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilder.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilder.java
new file mode 100644
index 0000000..336dd9b
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilder.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLJoinContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+
+public class JPQLJoinStatementBuilder extends JPQLStatementBuilder {
+
+  JPQLStatement jpqlStatement;
+  private JPQLJoinContextView context;
+
+  public JPQLJoinStatementBuilder(final JPQLContextView context) {
+    this.context = (JPQLJoinContextView) context;
+  }
+
+  @Override
+  public JPQLStatement build() throws ODataJPARuntimeException {
+    jpqlStatement = createStatement(createJPQLQuery());
+    return jpqlStatement;
+
+  }
+
+  private String createJPQLQuery() throws ODataJPARuntimeException {
+
+    StringBuilder jpqlQuery = new StringBuilder();
+    StringBuilder joinWhereCondition = null;
+
+    jpqlQuery.append(JPQLStatement.KEYWORD.SELECT).append(JPQLStatement.DELIMITER.SPACE);
+    if (context.getType().equals(JPQLContextType.JOIN_COUNT)) {//$COUNT
+      jpqlQuery.append(JPQLStatement.KEYWORD.COUNT).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.DELIMITER.PARENTHESIS_LEFT).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(context.getSelectExpression()).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.DELIMITER.PARENTHESIS_RIGHT).append(JPQLStatement.DELIMITER.SPACE);
+    } else { //Normal
+      jpqlQuery.append(context.getSelectExpression()).append(JPQLStatement.DELIMITER.SPACE);
+    }
+
+    jpqlQuery.append(JPQLStatement.KEYWORD.FROM).append(
+        JPQLStatement.DELIMITER.SPACE);
+
+    if (context.getJPAJoinClauses() != null
+        && context.getJPAJoinClauses().size() > 0) {
+      List<JPAJoinClause> joinClauseList = context.getJPAJoinClauses();
+      JPAJoinClause joinClause = joinClauseList.get(0);
+      String joinCondition = joinClause.getJoinCondition();
+      joinWhereCondition = new StringBuilder();
+      if (joinCondition != null) {
+        joinWhereCondition.append(joinCondition);
+      }
+      String relationShipAlias = null;
+      joinClause = joinClauseList.get(1);
+      jpqlQuery.append(joinClause.getEntityName()).append(
+          JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(joinClause.getEntityAlias());
+
+      int i = 1;
+      int limit = joinClauseList.size();
+      relationShipAlias = joinClause.getEntityAlias();
+      while (i < limit) {
+        jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
+        jpqlQuery.append(JPQLStatement.KEYWORD.JOIN).append(
+            JPQLStatement.DELIMITER.SPACE);
+
+        joinClause = joinClauseList.get(i);
+        jpqlQuery.append(relationShipAlias).append(
+            JPQLStatement.DELIMITER.PERIOD);
+        jpqlQuery.append(joinClause.getEntityRelationShip()).append(
+            JPQLStatement.DELIMITER.SPACE);
+        jpqlQuery.append(joinClause.getEntityRelationShipAlias());
+
+        relationShipAlias = joinClause.getEntityRelationShipAlias();
+        i++;
+
+        joinCondition = joinClause.getJoinCondition();
+        if (joinCondition != null) {
+          joinWhereCondition.append(JPQLStatement.DELIMITER.SPACE
+              + JPQLStatement.Operator.AND
+              + JPQLStatement.DELIMITER.SPACE);
+
+          joinWhereCondition.append(joinCondition);
+        }
+      }
+    } else {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.JOIN_CLAUSE_EXPECTED, null);
+    }
+    String whereExpression = context.getWhereExpression();
+    if (whereExpression != null || joinWhereCondition.length() > 0) {
+      jpqlQuery.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.KEYWORD.WHERE).append(
+          JPQLStatement.DELIMITER.SPACE);
+      if (whereExpression != null) {
+        jpqlQuery.append(whereExpression);
+        if (joinWhereCondition != null) {
+          jpqlQuery.append(JPQLStatement.DELIMITER.SPACE
+              + JPQLStatement.Operator.AND
+              + JPQLStatement.DELIMITER.SPACE);
+        }
+      }
+      if (joinWhereCondition != null) {
+        jpqlQuery.append(joinWhereCondition.toString());
+      }
+
+    }
+
+    if (context.getOrderByCollection() != null
+        && context.getOrderByCollection().size() > 0) {
+
+      StringBuilder orderByBuilder = new StringBuilder();
+      Iterator<Entry<String, String>> orderItr = context
+          .getOrderByCollection().entrySet().iterator();
+
+      int i = 0;
+
+      while (orderItr.hasNext()) {
+        if (i != 0) {
+          orderByBuilder.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.DELIMITER.COMMA)
+              .append(JPQLStatement.DELIMITER.SPACE);
+        }
+        Entry<String, String> entry = orderItr.next();
+        orderByBuilder.append(entry.getKey())
+            .append(JPQLStatement.DELIMITER.SPACE);
+        orderByBuilder.append(entry.getValue());
+        i++;
+      }
+      jpqlQuery.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.KEYWORD.ORDERBY).append(
+          JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(orderByBuilder);
+    }
+
+    return jpqlQuery.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContext.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContext.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContext.java
new file mode 100644
index 0000000..61cd133
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContext.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.HashMap;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLSelectContextView;
+import org.apache.olingo.odata2.processor.core.jpa.ODataExpressionParser;
+
+public class JPQLSelectContext extends JPQLContext implements
+    JPQLSelectContextView {
+
+  protected String selectExpression;
+  protected HashMap<String, String> orderByCollection;
+  protected String whereCondition;
+
+  protected boolean isCountOnly = false;//Support for $count
+
+  public JPQLSelectContext(final boolean isCountOnly) {
+    this.isCountOnly = isCountOnly;
+  }
+
+  protected final void setOrderByCollection(
+      final HashMap<String, String> orderByCollection) {
+    this.orderByCollection = orderByCollection;
+  }
+
+  protected final void setWhereExpression(final String filterExpression) {
+    whereCondition = filterExpression;
+  }
+
+  protected final void setSelectExpression(final String selectExpression) {
+    this.selectExpression = selectExpression;
+  }
+
+  @Override
+  public String getSelectExpression() {
+    return selectExpression;
+  }
+
+  @Override
+  public HashMap<String, String> getOrderByCollection() {
+    return orderByCollection;
+  }
+
+  @Override
+  public String getWhereExpression() {
+    return whereCondition;
+  }
+
+  public class JPQLSelectContextBuilder
+      extends
+      org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder {
+
+    protected GetEntitySetUriInfo entitySetView;
+
+    @Override
+    public JPQLContext build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+      if (entitySetView != null) {
+
+        try {
+
+          if (isCountOnly) {
+            setType(JPQLContextType.SELECT_COUNT);
+          } else {
+            setType(JPQLContextType.SELECT);
+          }
+          EdmEntityType entityType = entitySetView
+              .getTargetEntitySet().getEntityType();
+          EdmMapping mapping = entityType.getMapping();
+          if (mapping != null) {
+            setJPAEntityName(mapping.getInternalName());
+          } else {
+            setJPAEntityName(entityType.getName());
+          }
+
+          setJPAEntityAlias(generateJPAEntityAlias());
+
+          setOrderByCollection(generateOrderByFileds());
+
+          setSelectExpression(generateSelectExpression());
+
+          setWhereExpression(generateWhereExpression());
+        } catch (ODataException e) {
+          throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+        }
+      }
+
+      return JPQLSelectContext.this;
+
+    }
+
+    @Override
+    protected void setResultsView(final Object resultsView) {
+      if (resultsView instanceof GetEntitySetUriInfo) {
+        entitySetView = (GetEntitySetUriInfo) resultsView;
+      }
+
+    }
+
+    /*
+     * Generate Select Clause 
+     */
+    protected String generateSelectExpression() throws EdmException {
+      return getJPAEntityAlias();
+    }
+
+    /*
+     * Generate Order By Clause Fields
+     */
+    protected HashMap<String, String> generateOrderByFileds()
+        throws ODataJPARuntimeException, EdmException {
+
+      if (entitySetView.getOrderBy() != null) {
+
+        return ODataExpressionParser
+            .parseToJPAOrderByExpression(entitySetView.getOrderBy(), getJPAEntityAlias());
+
+      } else if (entitySetView.getTop() != null
+          || entitySetView.getSkip() != null) {
+
+        return ODataExpressionParser
+            .parseKeyPropertiesToJPAOrderByExpression(entitySetView.getTargetEntitySet()
+                .getEntityType().getKeyProperties(), getJPAEntityAlias());
+      } else {
+        return null;
+      }
+
+    }
+
+    /*
+     * Generate Where Clause Expression
+     */
+    protected String generateWhereExpression() throws ODataException {
+      if (entitySetView.getFilter() != null) {
+        return ODataExpressionParser
+            .parseToJPAWhereExpression(entitySetView.getFilter(), getJPAEntityAlias());
+      }
+      return null;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContext.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContext.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContext.java
new file mode 100644
index 0000000..f2ddcef
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContext.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLSelectSingleContextView;
+
+public class JPQLSelectSingleContext extends JPQLContext implements JPQLSelectSingleContextView {
+
+  private String selectExpression;
+  private List<KeyPredicate> keyPredicates;
+
+  protected void setKeyPredicates(final List<KeyPredicate> keyPredicates) {
+    this.keyPredicates = keyPredicates;
+  }
+
+  @Override
+  public List<KeyPredicate> getKeyPredicates() {
+    return keyPredicates;
+  }
+
+  protected final void setSelectExpression(final String selectExpression) {
+    this.selectExpression = selectExpression;
+  }
+
+  @Override
+  public String getSelectExpression() {
+    return selectExpression;
+  }
+
+  public class JPQLSelectSingleContextBuilder
+      extends
+      org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder {
+
+    protected GetEntityUriInfo entityView;
+
+    @Override
+    public JPQLContext build() throws ODataJPAModelException, ODataJPARuntimeException {
+      if (entityView != null) {
+
+        try {
+
+          setType(JPQLContextType.SELECT_SINGLE);
+
+          EdmEntityType entityType = entityView
+              .getTargetEntitySet().getEntityType();
+          EdmMapping mapping = entityType.getMapping();
+          if (mapping != null) {
+            setJPAEntityName(mapping.getInternalName());
+          } else {
+            setJPAEntityName(entityType.getName());
+          }
+
+          setJPAEntityAlias(generateJPAEntityAlias());
+
+          setKeyPredicates(entityView.getKeyPredicates());
+
+          setSelectExpression(generateSelectExpression());
+
+        } catch (EdmException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        }
+
+      }
+
+      return JPQLSelectSingleContext.this;
+
+    }
+
+    @Override
+    protected void setResultsView(final Object resultsView) {
+      if (resultsView instanceof GetEntityUriInfo) {
+        entityView = (GetEntityUriInfo) resultsView;
+      }
+
+    }
+
+    /*
+     * Generate Select Clause 
+     */
+    protected String generateSelectExpression() throws EdmException {
+      return getJPAEntityAlias();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilder.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilder.java
new file mode 100644
index 0000000..7ffa49f
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilder.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLSelectSingleContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.ODataExpressionParser;
+
+public class JPQLSelectSingleStatementBuilder extends JPQLStatementBuilder {
+
+  JPQLStatement jpqlStatement;
+  private JPQLSelectSingleContextView context;
+
+  public JPQLSelectSingleStatementBuilder(final JPQLContextView context) {
+    this.context = (JPQLSelectSingleContextView) context;
+  }
+
+  @Override
+  public JPQLStatement build() throws ODataJPARuntimeException {
+    jpqlStatement = createStatement(createJPQLQuery());
+    return jpqlStatement;
+
+  }
+
+  private String createJPQLQuery() throws ODataJPARuntimeException {
+
+    StringBuilder jpqlQuery = new StringBuilder();
+    String tableAlias = context.getJPAEntityAlias();
+    String fromClause = context.getJPAEntityName()
+        + JPQLStatement.DELIMITER.SPACE + tableAlias;
+
+    jpqlQuery.append(JPQLStatement.KEYWORD.SELECT).append(
+        JPQLStatement.DELIMITER.SPACE);
+    jpqlQuery.append(context.getSelectExpression()).append(JPQLStatement.DELIMITER.SPACE);
+    jpqlQuery.append(JPQLStatement.KEYWORD.FROM).append(JPQLStatement.DELIMITER.SPACE);
+    jpqlQuery.append(fromClause);
+
+    if (context.getKeyPredicates() != null
+        && context.getKeyPredicates().size() > 0) {
+      jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.KEYWORD.WHERE).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(ODataExpressionParser.parseKeyPredicates(context.getKeyPredicates(),
+          context.getJPAEntityAlias()));
+    }
+
+    return jpqlQuery.toString();
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilder.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilder.java
new file mode 100644
index 0000000..8fc2792
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilder.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import java.util.Iterator;
+import java.util.Map.Entry;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLSelectContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+
+public class JPQLSelectStatementBuilder extends JPQLStatementBuilder {
+
+  JPQLStatement jpqlStatement;
+  private JPQLSelectContextView context;
+
+  public JPQLSelectStatementBuilder(final JPQLContextView context) {
+    this.context = (JPQLSelectContextView) context;
+  }
+
+  @Override
+  public JPQLStatement build() throws ODataJPARuntimeException {
+    jpqlStatement = createStatement(createJPQLQuery());
+    return jpqlStatement;
+
+  }
+
+  private String createJPQLQuery() throws ODataJPARuntimeException {
+
+    StringBuilder jpqlQuery = new StringBuilder();
+    String tableAlias = context.getJPAEntityAlias();
+    String fromClause = context.getJPAEntityName() + JPQLStatement.DELIMITER.SPACE + tableAlias;
+
+    jpqlQuery.append(JPQLStatement.KEYWORD.SELECT).append(JPQLStatement.DELIMITER.SPACE);
+    if (context.getType().equals(JPQLContextType.SELECT_COUNT)) { //$COUNT
+      jpqlQuery.append(JPQLStatement.KEYWORD.COUNT).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.DELIMITER.PARENTHESIS_LEFT).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(context.getSelectExpression()).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.DELIMITER.PARENTHESIS_RIGHT).append(JPQLStatement.DELIMITER.SPACE);
+    } else {//Normal
+      jpqlQuery.append(context.getSelectExpression()).append(JPQLStatement.DELIMITER.SPACE);
+    }
+
+    jpqlQuery.append(JPQLStatement.KEYWORD.FROM).append(JPQLStatement.DELIMITER.SPACE);
+    jpqlQuery.append(fromClause);
+
+    if (context.getWhereExpression() != null) {
+      jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.KEYWORD.WHERE).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(context.getWhereExpression());
+    }
+
+    if (context.getOrderByCollection() != null
+        && context.getOrderByCollection().size() > 0) {
+
+      StringBuilder orderByBuilder = new StringBuilder();
+      Iterator<Entry<String, String>> orderItr = context
+          .getOrderByCollection().entrySet().iterator();
+
+      int i = 0;
+
+      while (orderItr.hasNext()) {
+        if (i != 0) {
+          orderByBuilder.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.DELIMITER.COMMA).append(JPQLStatement.DELIMITER.SPACE);
+        }
+        Entry<String, String> entry = orderItr.next();
+        orderByBuilder.append(entry.getKey()).append(JPQLStatement.DELIMITER.SPACE);
+        orderByBuilder.append(entry.getValue());
+        i++;
+      }
+      jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(JPQLStatement.KEYWORD.ORDERBY).append(JPQLStatement.DELIMITER.SPACE);
+      jpqlQuery.append(orderByBuilder);
+    }
+
+    return jpqlQuery.toString();
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociation.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociation.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociation.java
new file mode 100644
index 0000000..0f6e1ec
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociation.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmAssociation extends JPAEdmBaseViewImpl implements
+    JPAEdmAssociationView {
+
+  private JPAEdmAssociationEndView associationEndView;
+
+  private Association currentAssociation;
+  private List<Association> consistentAssociatonList;
+  private HashMap<String, Association> associationMap;
+  private HashMap<String, JPAEdmAssociationEndView> associationEndMap;
+  private List<JPAEdmReferentialConstraintView> inconsistentRefConstraintViewList;
+  private int numberOfSimilarEndPoints;
+
+  public JPAEdmAssociation(final JPAEdmAssociationEndView associationEndview,
+      final JPAEdmEntityTypeView entityTypeView,
+      final JPAEdmPropertyView propertyView, final int value) {
+    super(associationEndview);
+    associationEndView = associationEndview;
+    numberOfSimilarEndPoints = value;
+    init();
+  }
+
+  public JPAEdmAssociation(final JPAEdmSchemaView view) {
+    super(view);
+    init();
+  }
+
+  private void init() {
+    isConsistent = false;
+    consistentAssociatonList = new ArrayList<Association>();
+    inconsistentRefConstraintViewList = new LinkedList<JPAEdmReferentialConstraintView>();
+    associationMap = new HashMap<String, Association>();
+    associationEndMap = new HashMap<String, JPAEdmAssociationEndView>();
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmAssociationBuilder();
+    }
+    return builder;
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    return currentAssociation;
+  }
+
+  @Override
+  public List<Association> getConsistentEdmAssociationList() {
+    return consistentAssociatonList;
+  }
+
+  @Override
+  public Association searchAssociation(final JPAEdmAssociationEndView view) {
+    if (view != null) {
+      for (String key : associationMap.keySet()) {
+        Association association = associationMap.get(key);
+        if (association != null) {
+          if (view.compare(association.getEnd1(),
+              association.getEnd2())) {
+            JPAEdmAssociationEndView associationEnd = associationEndMap
+                .get(association.getName());
+            if (associationEnd.getJoinColumnName() != null
+                && associationEnd
+                    .getJoinColumnReferenceColumnName() != null
+                && view.getJoinColumnName() != null
+                && view.getJoinColumnReferenceColumnName() != null) {
+              if (view.getJoinColumnName().equals(
+                  associationEnd.getJoinColumnName())
+                  && view.getJoinColumnReferenceColumnName()
+                      .equals(associationEnd
+                          .getJoinColumnReferenceColumnName())) {
+                currentAssociation = association;
+                return association;
+              }
+
+            }
+            if (associationEnd.getMappedByName() != null) {
+              if (associationEnd.getMappedByName().equals(
+                  view.getOwningPropertyName())) {
+                currentAssociation = association;
+                return association;
+              }
+            }
+            if (associationEnd.getOwningPropertyName() != null) {
+              if (associationEnd.getOwningPropertyName().equals(
+                  view.getMappedByName())) {
+                currentAssociation = association;
+                return association;
+              }
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void addJPAEdmAssociationView(final JPAEdmAssociationView associationView,
+      final JPAEdmAssociationEndView associationEndView) {
+    if (associationView != null) {
+      currentAssociation = associationView.getEdmAssociation();
+      associationMap
+          .put(currentAssociation.getName(), currentAssociation);
+      associationEndMap.put(currentAssociation.getName(),
+          associationEndView);
+      addJPAEdmRefConstraintView(associationView
+          .getJPAEdmReferentialConstraintView());
+    }
+  }
+
+  @Override
+  public void addJPAEdmRefConstraintView(
+      final JPAEdmReferentialConstraintView refView) {
+    if (refView != null && refView.isExists()) {
+      inconsistentRefConstraintViewList.add(refView);
+    }
+  }
+
+  @Override
+  public JPAEdmReferentialConstraintView getJPAEdmReferentialConstraintView() {
+    if (inconsistentRefConstraintViewList.isEmpty()) {
+      return null;
+    }
+    return inconsistentRefConstraintViewList.get(0);
+  }
+
+  private class JPAEdmAssociationBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+
+      if (associationEndView != null
+          && searchAssociation(associationEndView) == null) {
+        currentAssociation = new Association();
+        currentAssociation.setEnd1(associationEndView
+            .getEdmAssociationEnd1());
+        currentAssociation.setEnd2(associationEndView
+            .getEdmAssociationEnd2());
+
+        JPAEdmNameBuilder.build(JPAEdmAssociation.this,
+            numberOfSimilarEndPoints);
+
+        associationMap.put(currentAssociation.getName(),
+            currentAssociation);
+
+      } else if (!inconsistentRefConstraintViewList.isEmpty()) {
+        int inconsistentRefConstraintViewSize = inconsistentRefConstraintViewList
+            .size();
+        int index = 0;
+        for (int i = 0; i < inconsistentRefConstraintViewSize; i++) {
+          JPAEdmReferentialConstraintView view = inconsistentRefConstraintViewList
+              .get(index);
+
+          if (view.isExists() && !view.isConsistent()) {
+            view.getBuilder().build();
+          }
+          if (view.isConsistent()) {
+            Association newAssociation = new Association();
+            copyAssociation(newAssociation, associationMap.get(view
+                .getEdmRelationShipName()));
+            newAssociation.setReferentialConstraint(view
+                .getEdmReferentialConstraint());
+            consistentAssociatonList.add(newAssociation);
+            associationMap.put(view.getEdmRelationShipName(),
+                newAssociation);
+            inconsistentRefConstraintViewList.remove(index);
+          } else {
+            associationMap.remove(view.getEdmRelationShipName());
+            index++;
+          }
+        }
+      }
+
+      if (associationMap.size() == consistentAssociatonList.size()) {
+        isConsistent = true;
+      } else {
+        for (String key : associationMap.keySet()) {
+          Association association = associationMap.get(key);
+          if (!consistentAssociatonList.contains(association)) {
+            consistentAssociatonList.add(association);
+          }
+        }
+        isConsistent = true;
+      }
+
+    }
+
+    private void copyAssociation(final Association copyToAssociation,
+        final Association copyFromAssociation) {
+      copyToAssociation.setEnd1(copyFromAssociation.getEnd1());
+      copyToAssociation.setEnd2(copyFromAssociation.getEnd2());
+      copyToAssociation.setName(copyFromAssociation.getName());
+      copyToAssociation.setAnnotationAttributes(copyFromAssociation
+          .getAnnotationAttributes());
+      copyToAssociation.setAnnotationElements(copyFromAssociation
+          .getAnnotationElements());
+      copyToAssociation.setDocumentation(copyFromAssociation
+          .getDocumentation());
+
+    }
+  }
+
+  @Override
+  public int getNumberOfAssociationsWithSimilarEndPoints(
+      final JPAEdmAssociationEndView view) {
+    int count = 0;
+    AssociationEnd currentAssociationEnd1 = view.getEdmAssociationEnd1();
+    AssociationEnd currentAssociationEnd2 = view.getEdmAssociationEnd2();
+    AssociationEnd end1 = null;
+    AssociationEnd end2 = null;
+    for (String key : associationMap.keySet()) {
+      Association association = associationMap.get(key);
+      if (association != null) {
+        end1 = association.getEnd1();
+        end2 = association.getEnd2();
+        if ((end1.getType().equals(currentAssociationEnd1.getType()) && end2
+            .getType().equals(currentAssociationEnd2.getType()))
+            || (end1.getType().equals(
+                currentAssociationEnd2.getType()) && end2
+                .getType().equals(
+                    currentAssociationEnd1.getType()))) {
+          count++;
+        }
+      }
+    }
+    return count;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEnd.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEnd.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEnd.java
new file mode 100644
index 0000000..91176ad
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationEnd.java
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.lang.reflect.AnnotatedElement;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.metamodel.Attribute.PersistentAttributeType;
+
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmAssociationEnd extends JPAEdmBaseViewImpl implements
+    JPAEdmAssociationEndView {
+
+  private JPAEdmEntityTypeView entityTypeView = null;
+  private JPAEdmPropertyView propertyView = null;
+  private AssociationEnd currentAssociationEnd1 = null;
+  private AssociationEnd currentAssociationEnd2 = null;
+  private String columnName;
+  private String referencedColumnName;
+  private String mappedBy;
+  private String ownerPropertyName;
+
+  public JPAEdmAssociationEnd(final JPAEdmEntityTypeView entityTypeView,
+      final JPAEdmPropertyView propertyView) {
+    super(entityTypeView);
+    this.entityTypeView = entityTypeView;
+    this.propertyView = propertyView;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmAssociationEndBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public AssociationEnd getEdmAssociationEnd1() {
+    return currentAssociationEnd1;
+  }
+
+  @Override
+  public AssociationEnd getEdmAssociationEnd2() {
+    return currentAssociationEnd2;
+  }
+
+  private class JPAEdmAssociationEndBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException {
+
+      JoinColumn joinColumn = null;
+
+      currentAssociationEnd1 = new AssociationEnd();
+      currentAssociationEnd2 = new AssociationEnd();
+
+      JPAEdmNameBuilder.build(JPAEdmAssociationEnd.this, entityTypeView,
+          propertyView);
+
+      currentAssociationEnd1.setRole(currentAssociationEnd1.getType()
+          .getName());
+      currentAssociationEnd2.setRole(currentAssociationEnd2.getType()
+          .getName());
+
+      setEdmMultiplicity(propertyView.getJPAAttribute()
+          .getPersistentAttributeType());
+
+      AnnotatedElement annotatedElement = (AnnotatedElement) propertyView.getJPAAttribute()
+          .getJavaMember();
+      if (annotatedElement != null) {
+        joinColumn = annotatedElement.getAnnotation(JoinColumn.class);
+        if (joinColumn != null) {
+          columnName = joinColumn.name();
+          referencedColumnName = joinColumn.referencedColumnName();
+        }
+
+      }
+      ownerPropertyName = propertyView.getJPAAttribute().getName();
+
+    }
+
+    private void setEdmMultiplicity(final PersistentAttributeType type) {
+      AnnotatedElement annotatedElement = (AnnotatedElement) propertyView.getJPAAttribute()
+          .getJavaMember();
+      switch (type) {
+      case ONE_TO_MANY:
+        currentAssociationEnd1.setMultiplicity(EdmMultiplicity.ONE);
+        currentAssociationEnd2.setMultiplicity(EdmMultiplicity.MANY);
+        if (annotatedElement != null) {
+          OneToMany reln = annotatedElement.getAnnotation(OneToMany.class);
+          if (reln != null) {
+            mappedBy = reln.mappedBy();
+          }
+        }
+        break;
+      case MANY_TO_MANY:
+        currentAssociationEnd1.setMultiplicity(EdmMultiplicity.MANY);
+        currentAssociationEnd2.setMultiplicity(EdmMultiplicity.MANY);
+        if (annotatedElement != null) {
+          ManyToMany reln = annotatedElement.getAnnotation(ManyToMany.class);
+          if (reln != null) {
+            mappedBy = reln.mappedBy();
+          }
+        }
+        break;
+      case MANY_TO_ONE:
+        currentAssociationEnd1.setMultiplicity(EdmMultiplicity.MANY);
+        currentAssociationEnd2.setMultiplicity(EdmMultiplicity.ONE);
+        break;
+      case ONE_TO_ONE:
+        currentAssociationEnd1.setMultiplicity(EdmMultiplicity.ONE);
+        currentAssociationEnd2.setMultiplicity(EdmMultiplicity.ONE);
+        if (annotatedElement != null) {
+          OneToOne reln = annotatedElement.getAnnotation(OneToOne.class);
+          if (reln != null) {
+            mappedBy = reln.mappedBy();
+          }
+        }
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+  @Override
+  public boolean compare(final AssociationEnd end1, final AssociationEnd end2) {
+    if ((end1.getType().equals(currentAssociationEnd1.getType())
+        && end2.getType().equals(currentAssociationEnd2.getType())
+        && end1.getMultiplicity().equals(
+            currentAssociationEnd1.getMultiplicity()) && end2
+        .getMultiplicity().equals(
+            currentAssociationEnd2.getMultiplicity()))
+        || (end1.getType().equals(currentAssociationEnd2.getType())
+            && end2.getType().equals(
+                currentAssociationEnd1.getType())
+            && end1.getMultiplicity().equals(
+                currentAssociationEnd2.getMultiplicity()) && end2
+            .getMultiplicity().equals(
+                currentAssociationEnd1.getMultiplicity()))) {
+      return true;
+    }
+
+    return false;
+  }
+
+  @Override
+  public String getJoinColumnName() {
+    return columnName;
+  }
+
+  @Override
+  public String getJoinColumnReferenceColumnName() {
+    return referencedColumnName;
+  }
+
+  @Override
+  public String getMappedByName() {
+    return mappedBy;
+  }
+
+  @Override
+  public String getOwningPropertyName() {
+    return ownerPropertyName;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSet.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSet.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSet.java
new file mode 100644
index 0000000..d6ce8ac
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmAssociationSet.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmAssociationSet extends JPAEdmBaseViewImpl implements
+    JPAEdmAssociationSetView {
+
+  private JPAEdmSchemaView schemaView;
+  private AssociationSet currentAssociationSet;
+  private List<AssociationSet> associationSetList;
+  private Association currentAssociation;
+
+  public JPAEdmAssociationSet(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmAssociationSetBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public List<AssociationSet> getConsistentEdmAssociationSetList() {
+    return associationSetList;
+  }
+
+  @Override
+  public AssociationSet getEdmAssociationSet() {
+    return currentAssociationSet;
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    return currentAssociation;
+  }
+
+  private class JPAEdmAssociationSetBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException {
+
+      if (associationSetList == null) {
+        associationSetList = new ArrayList<AssociationSet>();
+      }
+
+      JPAEdmAssociationView associationView = schemaView
+          .getJPAEdmAssociationView();
+      JPAEdmEntitySetView entitySetView = schemaView
+          .getJPAEdmEntityContainerView().getJPAEdmEntitySetView();
+
+      List<EntitySet> entitySetList = entitySetView
+          .getConsistentEdmEntitySetList();
+      if (associationView.isConsistent()) {
+        for (Association association : associationView
+            .getConsistentEdmAssociationList()) {
+
+          currentAssociation = association;
+
+          FullQualifiedName fQname = new FullQualifiedName(schemaView
+              .getEdmSchema().getNamespace(),
+              association.getName());
+          currentAssociationSet = new AssociationSet();
+          currentAssociationSet.setAssociation(fQname);
+
+          int endCount = 0;
+          short endFlag = 0;
+          for (EntitySet entitySet : entitySetList) {
+            fQname = entitySet.getEntityType();
+            endFlag = 0;
+            if (fQname.equals(association.getEnd1().getType())
+                || ++endFlag > 1
+                || fQname.equals(association.getEnd2()
+                    .getType())) {
+
+              AssociationSetEnd end = new AssociationSetEnd();
+              end.setEntitySet(entitySet.getName());
+              if (endFlag == 0) {
+                currentAssociationSet.setEnd1(end);
+                end.setRole(association.getEnd1().getRole());
+                endCount++;
+              } else {
+                endCount++;
+                currentAssociationSet.setEnd2(end);
+                end.setRole(association.getEnd2().getRole());
+              }
+
+              if (endCount == 2) {
+                break;
+              }
+            }
+          }
+          if (endCount == 2) {
+            JPAEdmNameBuilder.build(JPAEdmAssociationSet.this);
+            associationSetList.add(currentAssociationSet);
+          }
+
+        }
+
+      }
+    }
+  }
+}


[05/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeTest.java
new file mode 100644
index 0000000..6f75f39
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeTest.java
@@ -0,0 +1,1383 @@
+/*******************************************************************************
+ * 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.edm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmSimpleTypeTest extends BaseTest {
+
+  @Test
+  public void testNameSpace() throws Exception {
+    assertEquals(EdmSimpleType.SYSTEM_NAMESPACE, Bit.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.SYSTEM_NAMESPACE, Uint7.getInstance().getNamespace());
+
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmNull.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmBinary.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmBoolean.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmDateTime.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmDateTimeOffset.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmDecimal.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmDouble.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmGuid.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmInt16.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmInt32.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmInt64.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmSByte.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmSingle.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmString.getInstance().getNamespace());
+    assertEquals(EdmSimpleType.EDM_NAMESPACE, EdmTime.getInstance().getNamespace());
+  }
+
+  @Test
+  public void testNames() throws Exception {
+    assertEquals("Bit", Bit.getInstance().getName());
+    assertEquals("Uint7", Uint7.getInstance().getName());
+    assertEquals("Null", EdmNull.getInstance().getName());
+
+    assertEquals("Binary", EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance().getName());
+    assertEquals("Boolean", EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().getName());
+    assertEquals("Byte", EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance().getName());
+    assertEquals("DateTime", EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().getName());
+    assertEquals("DateTimeOffset", EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().getName());
+    assertEquals("Decimal", EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance().getName());
+    assertEquals("Double", EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance().getName());
+    assertEquals("Guid", EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance().getName());
+    assertEquals("Int16", EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance().getName());
+    assertEquals("Int32", EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance().getName());
+    assertEquals("Int64", EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance().getName());
+    assertEquals("SByte", EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance().getName());
+    assertEquals("Single", EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance().getName());
+    assertEquals("String", EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().getName());
+    assertEquals("Time", EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance().getName());
+  }
+
+  @Test
+  public void testKind() throws Exception {
+    for (EdmSimpleTypeKind kind : EdmSimpleTypeKind.values()) {
+      assertEquals(EdmTypeKind.SIMPLE, kind.getEdmSimpleTypeInstance().getKind());
+    }
+  }
+
+  private void testCompatibility(final EdmSimpleType type, final EdmSimpleType... edmSimpleTypes) {
+    for (EdmSimpleType compatible : edmSimpleTypes) {
+      assertTrue(type.isCompatible(compatible));
+    }
+  }
+
+  @Test
+  public void testUint7Compatibility() {
+    testCompatibility(Uint7.getInstance(), Uint7.getInstance(), Bit.getInstance());
+    assertFalse(Uint7.getInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testBinaryCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testBooleanCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance(),
+        Bit.getInstance());
+    assertFalse(EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testByteCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance());
+    assertFalse(EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testDateTimeCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testDateTimeOffsetCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testDecimalCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testDoubleCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testGuidCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testInt16Compatibility() {
+    testCompatibility(EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testInt32Compatibility() {
+    testCompatibility(EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testInt64Compatibility() {
+    testCompatibility(EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testSByteCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testSingleCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance(),
+        Bit.getInstance(),
+        Uint7.getInstance(),
+        EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testStringCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void testTimeCompatibility() {
+    testCompatibility(EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance(),
+        EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance());
+    assertFalse(EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance().isCompatible(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()));
+  }
+
+  @Test
+  public void toUriLiteralBinary() throws Exception {
+    assertEquals("binary'FA12AAA1'", EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance().toUriLiteral("+hKqoQ=="));
+  }
+
+  @Test
+  public void toUriLiteralBoolean() throws Exception {
+    assertEquals("true", EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().toUriLiteral("true"));
+    assertEquals("false", EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().toUriLiteral("false"));
+    assertEquals("0", EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().toUriLiteral("0"));
+    assertEquals("1", EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().toUriLiteral("1"));
+  }
+
+  @Test
+  public void toUriLiteralByte() throws Exception {
+    assertEquals("127", EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance().toUriLiteral("127"));
+  }
+
+  @Test
+  public void toUriLiteralDateTime() throws Exception {
+    assertEquals("datetime'2009-12-26T21:23:38'", EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().toUriLiteral("2009-12-26T21:23:38"));
+    assertEquals("datetime'2009-12-26T21:23:38Z'", EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().toUriLiteral("2009-12-26T21:23:38Z"));
+  }
+
+  @Test
+  public void toUriLiteralDateTimeOffset() throws Exception {
+    assertEquals("datetimeoffset'2009-12-26T21:23:38Z'", EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().toUriLiteral("2009-12-26T21:23:38Z"));
+    assertEquals("datetimeoffset'2002-10-10T12:00:00-05:00'", EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().toUriLiteral("2002-10-10T12:00:00-05:00"));
+  }
+
+  @Test
+  public void toUriLiteralInt16() throws Exception {
+    assertEquals("127", EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance().toUriLiteral("127"));
+  }
+
+  @Test
+  public void toUriLiteralInt32() throws Exception {
+    assertEquals("127", EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance().toUriLiteral("127"));
+  }
+
+  @Test
+  public void toUriLiteralInt64() throws Exception {
+    assertEquals("127L", EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance().toUriLiteral("127"));
+  }
+
+  @Test
+  public void toUriLiteralSByte() throws Exception {
+    assertEquals("127", EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance().toUriLiteral("127"));
+  }
+
+  @Test
+  public void toUriLiteralSingle() throws Exception {
+    assertEquals("127F", EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance().toUriLiteral("127"));
+  }
+
+  @Test
+  public void toUriLiteralString() throws Exception {
+    assertEquals("'StringValue'", EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().toUriLiteral("StringValue"));
+    assertEquals("'String''Value'", EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().toUriLiteral("String'Value"));
+    assertEquals("'String''''''Value'", EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().toUriLiteral("String'''Value"));
+  }
+
+  @Test
+  public void toUriLiteralTime() throws Exception {
+    assertEquals("time'P120D'", EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance().toUriLiteral("P120D"));
+  }
+
+  @Test
+  public void toStringAll() throws Exception {
+    assertEquals("System.Bit", Bit.getInstance().toString());
+    assertEquals("System.Uint7", Uint7.getInstance().toString());
+
+    assertEquals("Edm.Null", EdmNull.getInstance().toString());
+    assertEquals("Edm.Binary", EdmBinary.getInstance().toString());
+    assertEquals("Edm.Boolean", EdmBoolean.getInstance().toString());
+    assertEquals("Edm.DateTime", EdmDateTime.getInstance().toString());
+    assertEquals("Edm.DateTimeOffset", EdmDateTimeOffset.getInstance().toString());
+    assertEquals("Edm.Decimal", EdmDecimal.getInstance().toString());
+    assertEquals("Edm.Double", EdmDouble.getInstance().toString());
+    assertEquals("Edm.Guid", EdmGuid.getInstance().toString());
+    assertEquals("Edm.Int16", EdmInt16.getInstance().toString());
+    assertEquals("Edm.Int32", EdmInt32.getInstance().toString());
+    assertEquals("Edm.Int64", EdmInt64.getInstance().toString());
+    assertEquals("Edm.SByte", EdmSByte.getInstance().toString());
+    assertEquals("Edm.Single", EdmSingle.getInstance().toString());
+    assertEquals("Edm.String", EdmString.getInstance().toString());
+    assertEquals("Edm.Time", EdmTime.getInstance().toString());
+  }
+
+  private EdmFacets getMaxLengthFacets(final Integer maxLength) {
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getMaxLength()).thenReturn(maxLength);
+    return facets;
+  }
+
+  private EdmFacets getNullableFacets(final Boolean nullable) {
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(nullable);
+    return facets;
+  }
+
+  private EdmFacets getPrecisionScaleFacets(final Integer precision, final Integer scale) {
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.getPrecision()).thenReturn(precision);
+    when(facets.getScale()).thenReturn(scale);
+    return facets;
+  }
+
+  private EdmFacets getUnicodeFacets(final Boolean unicode) {
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isUnicode()).thenReturn(unicode);
+    when(facets.getMaxLength()).thenReturn(null);
+    return facets;
+  }
+
+  private void expectErrorInValueToString(final EdmSimpleType instance, final Object value, final EdmLiteralKind literalKind, final EdmFacets facets, final MessageReference messageReference) {
+    try {
+      instance.valueToString(value, literalKind, facets);
+      fail("Expected exception not thrown");
+    } catch (EdmSimpleTypeException e) {
+      assertNotNull(e.getMessageReference());
+      assertEquals(messageReference.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  @Test
+  public void checkNull() throws Exception {
+    for (EdmSimpleTypeKind kind : EdmSimpleTypeKind.values()) {
+      if (kind == EdmSimpleTypeKind.Null) {
+        continue;
+      }
+      final EdmSimpleType instance = kind.getEdmSimpleTypeInstance();
+      assertNull(instance.valueToString(null, EdmLiteralKind.DEFAULT, null));
+      assertNull(instance.valueToString(null, EdmLiteralKind.DEFAULT, getNullableFacets(true)));
+      assertNull(instance.valueToString(null, EdmLiteralKind.DEFAULT, getNullableFacets(null)));
+
+      expectErrorInValueToString(instance, null, EdmLiteralKind.DEFAULT, getNullableFacets(false), EdmSimpleTypeException.VALUE_NULL_NOT_ALLOWED);
+    }
+  }
+
+  @Test
+  public void defaultType() throws Exception {
+    assertEquals(Byte.class, Bit.getInstance().getDefaultType());
+    assertEquals(Byte.class, Uint7.getInstance().getDefaultType());
+    assertNull(EdmNull.getInstance().getDefaultType());
+
+    assertEquals(byte[].class, EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Boolean.class, EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Short.class, EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Calendar.class, EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Calendar.class, EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(BigDecimal.class, EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Double.class, EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(UUID.class, EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Short.class, EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Integer.class, EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Long.class, EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Byte.class, EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Float.class, EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(String.class, EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().getDefaultType());
+    assertEquals(Calendar.class, EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance().getDefaultType());
+  }
+
+  @Test
+  public void valueToStringBinary() throws Exception {
+    final byte[] binary = new byte[] { (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+    final EdmSimpleType instance = EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance();
+
+    assertEquals("qrvM3e7/", instance.valueToString(binary, EdmLiteralKind.DEFAULT, null));
+    assertEquals("qrvM3e7/", instance.valueToString(binary, EdmLiteralKind.JSON, null));
+    assertEquals("binary'AABBCCDDEEFF'", instance.valueToString(binary, EdmLiteralKind.URI, null));
+
+    assertEquals("qrvM3e7/", instance.valueToString(binary, EdmLiteralKind.DEFAULT, getMaxLengthFacets(6)));
+    assertEquals("qrvM3e7/", instance.valueToString(binary, EdmLiteralKind.JSON, getMaxLengthFacets(6)));
+    assertEquals("binary'AABBCCDDEEFF'", instance.valueToString(binary, EdmLiteralKind.URI, getMaxLengthFacets(6)));
+    assertEquals("qrvM3e7/", instance.valueToString(binary, EdmLiteralKind.DEFAULT, getMaxLengthFacets(Integer.MAX_VALUE)));
+    assertEquals("binary'AABBCCDDEEFF'", instance.valueToString(binary, EdmLiteralKind.URI, getMaxLengthFacets(Integer.MAX_VALUE)));
+    assertEquals("qrvM3e7/", instance.valueToString(binary, EdmLiteralKind.DEFAULT, getMaxLengthFacets(null)));
+
+    assertEquals("qg==", instance.valueToString(new Byte[] { new Byte((byte) 170) }, EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, binary, EdmLiteralKind.DEFAULT, getMaxLengthFacets(3), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, binary, EdmLiteralKind.JSON, getMaxLengthFacets(3), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, binary, EdmLiteralKind.URI, getMaxLengthFacets(3), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+
+    expectErrorInValueToString(instance, 0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, binary, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringBoolean() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance();
+
+    assertEquals("true", instance.valueToString(true, EdmLiteralKind.DEFAULT, null));
+    assertEquals("true", instance.valueToString(true, EdmLiteralKind.JSON, null));
+    assertEquals("true", instance.valueToString(true, EdmLiteralKind.URI, null));
+    assertEquals("false", instance.valueToString(Boolean.FALSE, EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, 0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, false, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringByte() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, -1, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, 256, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, 'A', EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringDateTime() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance();
+    Calendar dateTime = Calendar.getInstance();
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:30"));
+    dateTime.set(2012, 2, 1, 11, 2, 3);
+    assertEquals("2012-02-29T23:32:03", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(1330558323000)/", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("datetime'2012-02-29T23:32:03'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    dateTime.add(Calendar.MILLISECOND, 1);
+    assertEquals("2012-02-29T23:32:03.001", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(1330558323001)/", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("datetime'2012-02-29T23:32:03.001'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    final Long millis = 1330558323007L;
+    assertEquals("2012-02-29T23:32:03.007", instance.valueToString(millis, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(" + millis + ")/", instance.valueToString(millis, EdmLiteralKind.JSON, null));
+    assertEquals("datetime'2012-02-29T23:32:03.007'", instance.valueToString(millis, EdmLiteralKind.URI, null));
+
+    assertEquals("2012-02-29T23:32:03.007", instance.valueToString(new Date(millis), EdmLiteralKind.DEFAULT, null));
+
+    dateTime.add(Calendar.MILLISECOND, 9);
+    assertEquals("2012-02-29T23:32:03.01", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null)));
+    dateTime.add(Calendar.MILLISECOND, -10);
+    assertEquals("2012-02-29T23:32:03", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null)));
+    dateTime.add(Calendar.MILLISECOND, -13);
+    assertEquals("2012-02-29T23:32:02.987", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, null)));
+    assertEquals("2012-02-29T23:32:02.98700", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null)));
+    dateTime.add(Calendar.MILLISECOND, 3);
+    assertEquals("2012-02-29T23:32:02.99", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null)));
+    dateTime.add(Calendar.MILLISECOND, -90);
+    assertEquals("2012-02-29T23:32:02.9", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(1, null)));
+    dateTime.add(Calendar.MILLISECOND, 100);
+    assertEquals("2012-02-29T23:32:03.0000000", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(7, null)));
+
+    Calendar dateTime2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-11:30"));
+    dateTime2.clear();
+    dateTime2.set(1969, 11, 31, 12, 29, 58);
+    assertEquals("/Date(-2000)/", instance.valueToString(dateTime2, EdmLiteralKind.JSON, null));
+
+    dateTime.add(Calendar.MILLISECOND, -100);
+    expectErrorInValueToString(instance, dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+
+    expectErrorInValueToString(instance, 0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, dateTime, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringDateTimeOffset() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance();
+    Calendar dateTime = Calendar.getInstance();
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
+    dateTime.set(2012, 1, 29, 1, 2, 3);
+    assertEquals("2012-02-29T01:02:03Z", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(1330477323000)/", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("datetimeoffset'2012-02-29T01:02:03Z'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT-1:30"));
+    assertEquals("2012-02-29T01:02:03-01:30", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(1330477323000-0090)/", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("datetimeoffset'2012-02-29T01:02:03-01:30'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:00"));
+    assertEquals("2012-02-29T01:02:03+11:00", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(1330477323000+0660)/", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("datetimeoffset'2012-02-29T01:02:03+11:00'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    dateTime.set(1969, 11, 30, 11, 59, 58);
+    assertEquals("/Date(-129602000+0660)/", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+
+    final Long millis = 1330558323007L;
+    assertEquals("2012-02-29T23:32:03.007Z", instance.valueToString(millis, EdmLiteralKind.DEFAULT, null));
+    assertEquals("/Date(" + millis + ")/", instance.valueToString(millis, EdmLiteralKind.JSON, null));
+    assertEquals("datetimeoffset'2012-02-29T23:32:03.007Z'", instance.valueToString(millis, EdmLiteralKind.URI, null));
+
+    final Date date = new Date(millis);
+    final String time = date.toString().substring(11, 19);
+    assertTrue(instance.valueToString(date, EdmLiteralKind.DEFAULT, null).contains(time));
+
+    expectErrorInValueToString(instance, 0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, dateTime, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringDecimal() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0M", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+    assertEquals("12345678901234567890123456789", instance.valueToString(new BigInteger("12345678901234567890123456789"), EdmLiteralKind.DEFAULT, null));
+    assertEquals("0.00390625", instance.valueToString(1.0 / 256, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-0.125", instance.valueToString(-0.125f, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-1234567890.1234567890", instance.valueToString(new BigDecimal("-1234567890.1234567890"), EdmLiteralKind.DEFAULT, null));
+
+    assertEquals("-32768", instance.valueToString(-32768, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, null)));
+    assertEquals("0.5", instance.valueToString(0.5, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, null)));
+
+    assertEquals("-32768", instance.valueToString(-32768, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(42, null)));
+    assertEquals("-32768", instance.valueToString(-32768, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null)));
+    assertEquals("32768", instance.valueToString(32768, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null)));
+    assertEquals("0.5", instance.valueToString(0.5, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(1, null)));
+    assertEquals("0.5", instance.valueToString(0.5, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, 1)));
+    assertEquals("100", instance.valueToString(new BigDecimal(BigInteger.ONE, -2), EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(3, null)));
+
+    expectErrorInValueToString(instance, new BigInteger("123456789012345678901234567890"), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, new BigDecimal(BigInteger.TEN, -28), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, new BigDecimal(BigInteger.ONE, 30), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, -1234, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, 1234, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(3, null), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, 0.00390625, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, 0.00390625, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, 7), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+
+    expectErrorInValueToString(instance, 'A', EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, Double.NaN, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringDouble() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0D", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0.00390625", instance.valueToString(1.0 / 256, EdmLiteralKind.DEFAULT, null));
+    assertEquals("4.2E-41", instance.valueToString(42e-42, EdmLiteralKind.DEFAULT, null));
+    assertEquals("INF", instance.valueToString(Double.POSITIVE_INFINITY, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-0.125", instance.valueToString(-0.125f, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-INF", instance.valueToString(Float.NEGATIVE_INFINITY, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-1234567890.12345", instance.valueToString(new BigDecimal("-1234567890.12345"), EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, 1234567890123456L, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, new BigDecimal("1234567890123456"), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, new BigDecimal(BigInteger.TEN, 400), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+
+    expectErrorInValueToString(instance, 'A', EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringGuid() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance();
+    final UUID uuid = UUID.randomUUID();
+
+    assertEquals(uuid.toString(), instance.valueToString(uuid, EdmLiteralKind.DEFAULT, null));
+    assertEquals(uuid.toString(), instance.valueToString(uuid, EdmLiteralKind.JSON, null));
+    assertEquals("guid'" + uuid.toString() + "'", instance.valueToString(uuid, EdmLiteralKind.URI, null));
+
+    expectErrorInValueToString(instance, 'A', EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringInt16() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, 123456, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, -32769, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+
+    expectErrorInValueToString(instance, 1.0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringInt32() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, 12345678901L, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, -2147483649L, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+
+    expectErrorInValueToString(instance, 1.0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringInt64() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0L", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+    assertEquals("12345678901L", instance.valueToString(12345678901L, EdmLiteralKind.URI, null));
+    assertEquals("1234567890123456789", instance.valueToString(new BigInteger("1234567890123456789"), EdmLiteralKind.DEFAULT, null));
+    assertEquals("-1234567890123456789L", instance.valueToString(new BigInteger("-1234567890123456789"), EdmLiteralKind.URI, null));
+
+    expectErrorInValueToString(instance, new BigInteger("123456789012345678901"), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+
+    expectErrorInValueToString(instance, 1.0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringSByte() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("64", instance.valueToString(64L, EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, -129, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, 128, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, 'A', EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringSingle() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance();
+
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0", instance.valueToString(0, EdmLiteralKind.JSON, null));
+    assertEquals("0F", instance.valueToString(0, EdmLiteralKind.URI, null));
+    assertEquals("8", instance.valueToString((byte) 8, EdmLiteralKind.DEFAULT, null));
+    assertEquals("16", instance.valueToString((short) 16, EdmLiteralKind.DEFAULT, null));
+    assertEquals("32", instance.valueToString(Integer.valueOf(32), EdmLiteralKind.DEFAULT, null));
+    assertEquals("255", instance.valueToString(255L, EdmLiteralKind.DEFAULT, null));
+    assertEquals("0.00390625", instance.valueToString(1.0 / 256, EdmLiteralKind.DEFAULT, null));
+    assertEquals("4.2E-8", instance.valueToString(42e-9, EdmLiteralKind.DEFAULT, null));
+    assertEquals("INF", instance.valueToString(Double.POSITIVE_INFINITY, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-0.125", instance.valueToString(-0.125f, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-INF", instance.valueToString(Float.NEGATIVE_INFINITY, EdmLiteralKind.DEFAULT, null));
+    assertEquals("-12345.67", instance.valueToString(new BigDecimal("-12345.67"), EdmLiteralKind.DEFAULT, null));
+
+    expectErrorInValueToString(instance, 12345678L, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, new BigDecimal("12345678"), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, new BigDecimal(BigInteger.TEN, 39), EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+    expectErrorInValueToString(instance, 42e38, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT);
+
+    expectErrorInValueToString(instance, 'A', EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, 1, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringString() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.String.getEdmSimpleTypeInstance();
+
+    assertEquals("text", instance.valueToString("text", EdmLiteralKind.DEFAULT, null));
+    assertEquals("a\nb", instance.valueToString("a\nb", EdmLiteralKind.JSON, null));
+    assertEquals("'true'", instance.valueToString(true, EdmLiteralKind.URI, null));
+    assertEquals("'a''b'", instance.valueToString("a'b", EdmLiteralKind.URI, null));
+
+    assertEquals("text", instance.valueToString("text", EdmLiteralKind.DEFAULT, getUnicodeFacets(true)));
+    assertEquals("text", instance.valueToString("text", EdmLiteralKind.DEFAULT, getUnicodeFacets(null)));
+    assertEquals("text", instance.valueToString("text", EdmLiteralKind.DEFAULT, getMaxLengthFacets(4)));
+    assertEquals("text", instance.valueToString("text", EdmLiteralKind.DEFAULT, getMaxLengthFacets(Integer.MAX_VALUE)));
+    assertEquals("text", instance.valueToString("text", EdmLiteralKind.DEFAULT, getMaxLengthFacets(null)));
+
+    expectErrorInValueToString(instance, "schräg", EdmLiteralKind.DEFAULT, getUnicodeFacets(false), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, "text", EdmLiteralKind.DEFAULT, getMaxLengthFacets(3), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+
+    expectErrorInValueToString(instance, "text", null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  @Test
+  public void valueToStringTime() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance();
+    Calendar dateTime = Calendar.getInstance();
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT-11:30"));
+    dateTime.set(Calendar.HOUR_OF_DAY, 23);
+    dateTime.set(Calendar.MINUTE, 32);
+    dateTime.set(Calendar.SECOND, 3);
+    assertEquals("PT23H32M3S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("PT23H32M3S", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("time'PT23H32M3S'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    dateTime.add(Calendar.MILLISECOND, 1);
+    assertEquals("PT23H32M3.001S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, null));
+    assertEquals("PT23H32M3.001S", instance.valueToString(dateTime, EdmLiteralKind.JSON, null));
+    assertEquals("time'PT23H32M3.001S'", instance.valueToString(dateTime, EdmLiteralKind.URI, null));
+
+    final Long millis = 84723007L;
+    assertEquals("PT23H32M3.007S", instance.valueToString(millis, EdmLiteralKind.DEFAULT, null));
+    assertEquals("PT23H32M3.007S", instance.valueToString(millis, EdmLiteralKind.JSON, null));
+    assertEquals("time'PT23H32M3.007S'", instance.valueToString(millis, EdmLiteralKind.URI, null));
+
+    assertTrue(instance.valueToString(new Date(millis), EdmLiteralKind.DEFAULT, null).contains("M3.007S"));
+
+    dateTime.add(Calendar.MILLISECOND, -1);
+    assertEquals("PT23H32M3S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null)));
+    assertEquals("PT23H32M3.0S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(1, null)));
+    dateTime.add(Calendar.MILLISECOND, 10);
+    assertEquals("PT23H32M3.01S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null)));
+    dateTime.add(Calendar.MILLISECOND, -23);
+    assertEquals("PT23H32M2.987S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, null)));
+    assertEquals("PT23H32M2.98700S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null)));
+    dateTime.add(Calendar.MILLISECOND, -87);
+    assertEquals("PT23H32M2.9S", instance.valueToString(dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(1, null)));
+
+    expectErrorInValueToString(instance, dateTime, EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null), EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED);
+    expectErrorInValueToString(instance, 0, EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED);
+    expectErrorInValueToString(instance, dateTime, null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+  }
+
+  private void expectErrorInValueOfString(final EdmSimpleType instance, final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final MessageReference messageReference) {
+    try {
+      instance.valueOfString(value, literalKind, facets, instance.getDefaultType());
+      fail("Expected exception not thrown");
+    } catch (EdmSimpleTypeException e) {
+      assertNotNull(e.getMessageReference());
+      assertEquals(messageReference.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  private void expectTypeErrorInValueOfString(final EdmSimpleType instance, final String value, final EdmLiteralKind literalKind) {
+    try {
+      instance.valueOfString(value, literalKind, null, Class.class);
+      fail("Expected exception not thrown");
+    } catch (EdmSimpleTypeException e) {
+      assertNotNull(e.getMessageReference());
+      assertEquals(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  private void expectUnconvertibleErrorInValueOfString(final EdmSimpleType instance, final String value, final Class<?> type) {
+    try {
+      instance.valueOfString(value, EdmLiteralKind.DEFAULT, null, type);
+      fail("Expected exception not thrown");
+    } catch (EdmSimpleTypeException e) {
+      assertNotNull(e.getMessageReference());
+      assertEquals(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  @Test
+  public void checkValueOfNull() throws Exception {
+    for (EdmSimpleTypeKind kind : EdmSimpleTypeKind.values()) {
+      if (kind == EdmSimpleTypeKind.Null) {
+        continue;
+      }
+      final EdmSimpleType instance = kind.getEdmSimpleTypeInstance();
+      assertNull(instance.valueOfString(null, EdmLiteralKind.DEFAULT, null, instance.getDefaultType()));
+      assertNull(instance.valueOfString(null, EdmLiteralKind.DEFAULT, getNullableFacets(true), instance.getDefaultType()));
+      assertNull(instance.valueOfString(null, EdmLiteralKind.DEFAULT, getNullableFacets(null), instance.getDefaultType()));
+
+      expectErrorInValueOfString(instance, null, EdmLiteralKind.DEFAULT, getNullableFacets(false), EdmSimpleTypeException.LITERAL_NULL_NOT_ALLOWED);
+      expectErrorInValueOfString(instance, "", null, null, EdmSimpleTypeException.LITERAL_KIND_MISSING);
+    }
+  }
+
+  @Test
+  public void valueOfStringBinary() throws Exception {
+    final byte[] binary = new byte[] { (byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD, (byte) 0xEE, (byte) 0xFF };
+    final EdmSimpleType instance = EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance();
+
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM3e7/", EdmLiteralKind.DEFAULT, null, byte[].class)));
+    assertTrue(Arrays.equals(new Byte[] { binary[0], binary[1], binary[2] }, instance.valueOfString("qrvM", EdmLiteralKind.JSON, null, Byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("binary'AABBCCDDEEFF'", EdmLiteralKind.URI, null, byte[].class)));
+
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM3e7/", EdmLiteralKind.DEFAULT, getMaxLengthFacets(6), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM3e7/", EdmLiteralKind.JSON, getMaxLengthFacets(6), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("binary'AABBCCDDEEFF'", EdmLiteralKind.URI, getMaxLengthFacets(6), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("X'AABBCCDDEEFF'", EdmLiteralKind.URI, getMaxLengthFacets(6), byte[].class)));
+    assertTrue(Arrays.equals(new byte[] { 42 }, instance.valueOfString("Kg==", EdmLiteralKind.DEFAULT, getMaxLengthFacets(1), byte[].class)));
+    assertTrue(Arrays.equals(new byte[] { 1, 2 }, instance.valueOfString("AQI=", EdmLiteralKind.JSON, getMaxLengthFacets(2), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM\r\n3e7/\r\n", EdmLiteralKind.DEFAULT, getMaxLengthFacets(6), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM3e7/", EdmLiteralKind.DEFAULT, getMaxLengthFacets(Integer.MAX_VALUE), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("X'AABBCCDDEEFF'", EdmLiteralKind.URI, getMaxLengthFacets(Integer.MAX_VALUE), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM3e7/", EdmLiteralKind.DEFAULT, getMaxLengthFacets(null), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("qrvM3e7/", EdmLiteralKind.JSON, getMaxLengthFacets(null), byte[].class)));
+    assertTrue(Arrays.equals(binary, instance.valueOfString("X'AABBCCDDEEFF'", EdmLiteralKind.URI, getMaxLengthFacets(null), byte[].class)));
+
+    expectErrorInValueOfString(instance, "qrvM3e7/", EdmLiteralKind.DEFAULT, getMaxLengthFacets(3), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "qrvM3e7/", EdmLiteralKind.JSON, getMaxLengthFacets(3), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "binary'AABBCCDDEEFF'", EdmLiteralKind.URI, getMaxLengthFacets(3), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+
+    expectErrorInValueOfString(instance, "@", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "@", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "binary'ZZ'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "Y'AA'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "qrvM3e7/", EdmLiteralKind.DEFAULT);
+  }
+
+  @Test
+  public void valueOfStringBoolean() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance();
+
+    assertEquals(true, instance.valueOfString("true", EdmLiteralKind.DEFAULT, null, Boolean.class));
+    assertEquals(false, instance.valueOfString("false", EdmLiteralKind.JSON, null, Boolean.class));
+    assertEquals(true, instance.valueOfString("1", EdmLiteralKind.URI, null, Boolean.class));
+    assertEquals(false, instance.valueOfString("0", EdmLiteralKind.URI, null, Boolean.class));
+
+    expectErrorInValueOfString(instance, "True", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "-1", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "FALSE", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+  }
+
+  @Test
+  public void valueOfStringByte() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance();
+
+    assertEquals(Short.valueOf((short) 1), instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, Short.class));
+    assertEquals(Integer.valueOf(2), instance.valueOfString("2", EdmLiteralKind.JSON, null, Integer.class));
+    assertEquals(Byte.valueOf((byte) 127), instance.valueOfString("127", EdmLiteralKind.URI, null, Byte.class));
+    assertEquals(Short.valueOf((short) 255), instance.valueOfString("255", EdmLiteralKind.URI, null, Short.class));
+    assertEquals(Long.valueOf(0), instance.valueOfString("0", EdmLiteralKind.DEFAULT, null, Long.class));
+
+    expectErrorInValueOfString(instance, "0x42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "abc", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "256", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "-1", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+  }
+
+  @Test
+  public void valueOfStringDateTime() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance();
+    Calendar dateTime = Calendar.getInstance();
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
+    dateTime.set(2012, 1, 29, 23, 32, 3);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:03", EdmLiteralKind.DEFAULT, null, Calendar.class));
+    assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29T23:32:03", EdmLiteralKind.JSON, null, Long.class));
+    assertEquals(dateTime, instance.valueOfString("/Date(1330558323000)/", EdmLiteralKind.JSON, null, Calendar.class));
+    assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("/Date(1330558323000)/", EdmLiteralKind.JSON, null, Long.class));
+    assertEquals(dateTime.getTime(), instance.valueOfString("/Date(1330558323000)/", EdmLiteralKind.JSON, null, Date.class));
+    assertEquals(dateTime.getTime(), instance.valueOfString("datetime'2012-02-29T23:32:03'", EdmLiteralKind.URI, null, Date.class));
+
+    dateTime.add(Calendar.MILLISECOND, 1);
+    assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29T23:32:03.001", EdmLiteralKind.DEFAULT, null, Long.class));
+    assertEquals(dateTime.getTime(), instance.valueOfString("/Date(1330558323001)/", EdmLiteralKind.JSON, null, Date.class));
+    assertEquals(dateTime, instance.valueOfString("datetime'2012-02-29T23:32:03.001'", EdmLiteralKind.URI, null, Calendar.class));
+
+    dateTime.add(Calendar.MILLISECOND, 9);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:03.01", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null), Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:03.0100000", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null), Calendar.class));
+    dateTime.add(Calendar.MILLISECOND, -10);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:03.000", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null), Calendar.class));
+    dateTime.add(Calendar.MILLISECOND, -13);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:02.987", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, null), Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:02.98700", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null), Calendar.class));
+    dateTime.add(Calendar.MILLISECOND, 3);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:02.99", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null), Calendar.class));
+    dateTime.add(Calendar.MILLISECOND, -90);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32:02.9", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(1, null), Calendar.class));
+    dateTime.add(Calendar.MILLISECOND, -2900);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T23:32", EdmLiteralKind.DEFAULT, null, Calendar.class));
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
+    dateTime.set(1969, 11, 31, 23, 59, 18);
+    assertEquals(dateTime, instance.valueOfString("/Date(-42000)/", EdmLiteralKind.JSON, null, Calendar.class));
+
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02.9", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02.98700", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02.9876", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02.", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02.00000000", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "20120229T233202", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1900-02-29T00:00:00", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "2012-02-29T24:00:01", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "\\/Date(1)\\/", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "/Date(12345678901234567890)/", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "/Date(1330558323000+0060)/", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "datetime'2012-02-29T23:32:02+01:00'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "date'2012-02-29T23:32:02'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "datetime'2012-02-29T23:32:02", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "datetime'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "2012-02-29T23:32", EdmLiteralKind.DEFAULT);
+    expectTypeErrorInValueOfString(instance, "/Date(1)/", EdmLiteralKind.JSON);
+  }
+
+  @Test
+  public void valueOfStringDateTimeOffset() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance();
+    Calendar dateTime = Calendar.getInstance();
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT"));
+    dateTime.set(2012, 1, 29, 1, 2, 3);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03Z", EdmLiteralKind.DEFAULT, null, Calendar.class));
+    assertEquals(Long.valueOf(dateTime.getTimeInMillis()), instance.valueOfString("2012-02-29T01:02:03+00:00", EdmLiteralKind.DEFAULT, null, Long.class));
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03", EdmLiteralKind.DEFAULT, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("/Date(1330477323000)/", EdmLiteralKind.JSON, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("/Date(1330477323000-0000)/", EdmLiteralKind.JSON, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("datetimeoffset'2012-02-29T01:02:03Z'", EdmLiteralKind.URI, null, Calendar.class));
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT-01:30"));
+    dateTime.set(2012, 1, 29, 1, 2, 3);
+    assertEquals(dateTime.getTime(), instance.valueOfString("2012-02-29T01:02:03-01:30", EdmLiteralKind.DEFAULT, null, Date.class));
+    assertEquals(dateTime, instance.valueOfString("/Date(1330477323000-0090)/", EdmLiteralKind.JSON, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("datetimeoffset'2012-02-29T01:02:03-01:30'", EdmLiteralKind.URI, null, Calendar.class));
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:00"));
+    dateTime.set(2012, 1, 29, 1, 2, 3);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03+11:00", EdmLiteralKind.DEFAULT, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("/Date(1330477323000+0660)/", EdmLiteralKind.JSON, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("datetimeoffset'2012-02-29T01:02:03+11:00'", EdmLiteralKind.URI, null, Calendar.class));
+
+    dateTime.add(Calendar.MILLISECOND, 7);
+    assertEquals(dateTime, instance.valueOfString("2012-02-29T01:02:03.007+11:00", EdmLiteralKind.DEFAULT, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("/Date(1330477323007+0660)/", EdmLiteralKind.JSON, null, Calendar.class));
+    assertEquals(dateTime, instance.valueOfString("datetimeoffset'2012-02-29T01:02:03.007+11:00'", EdmLiteralKind.URI, null, Calendar.class));
+
+    dateTime.clear();
+    dateTime.setTimeZone(TimeZone.getTimeZone("GMT+11:00"));
+    dateTime.set(1969, 11, 31, 23, 59, 18);
+    assertEquals(dateTime, instance.valueOfString("/Date(-42000+0660)/", EdmLiteralKind.JSON, null, Calendar.class));
+
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02.9Z", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(0, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "datetime'2012-02-29T23:32:02'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02X", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "2012-02-29T23:32:02+24:00", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "/Date(12345678901234567890)/", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "/Date(1234567890-1440)/", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "/Date(1234567890Z)/", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "datetimeoffset'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "datetimeoffset''Z", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "2012-02-29T01:02:03Z", EdmLiteralKind.DEFAULT);
+  }
+
+  @Test
+  public void valueOfStringDecimal() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance();
+
+    assertEquals(BigDecimal.ONE, instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, BigDecimal.class));
+    assertEquals(Byte.valueOf((byte) -2), instance.valueOfString("-2", EdmLiteralKind.JSON, null, Byte.class));
+    assertEquals(new BigDecimal("-12345678901234567890"), instance.valueOfString("-12345678901234567890M", EdmLiteralKind.URI, null, BigDecimal.class));
+    assertEquals(Short.valueOf((short) 0), instance.valueOfString("0M", EdmLiteralKind.URI, null, Short.class));
+
+    assertEquals(Integer.valueOf(-32768), instance.valueOfString("-32768", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(42, null), Integer.class));
+    assertEquals(Long.valueOf(-32768), instance.valueOfString("-32768", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null), Long.class));
+    assertEquals(BigInteger.valueOf(32768), instance.valueOfString("32768", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null), BigInteger.class));
+    assertEquals(Double.valueOf(0.5), instance.valueOfString("0.5", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(1, null), Double.class));
+    assertEquals(Float.valueOf(0.5F), instance.valueOfString("0.5", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, 1), Float.class));
+    assertEquals(new BigDecimal("12.3"), instance.valueOfString("12.3", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(3, 1), BigDecimal.class));
+
+    expectErrorInValueOfString(instance, "-1234", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(2, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "1234", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(3, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "12.34", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(3, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "12.34", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(3, 2), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "12.34", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(4, 1), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "0.00390625", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(5, null), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+    expectErrorInValueOfString(instance, "0.00390625", EdmLiteralKind.DEFAULT, getPrecisionScaleFacets(null, 7), EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED);
+
+    expectErrorInValueOfString(instance, "-1E2", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, ".1", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0.1", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1M", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0D", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0F", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0x42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "123456789012345678901234567890", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-32769", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "32768", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-2147483649", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "2147483648", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-9223372036854775809", Long.class);
+    expectUnconvertibleErrorInValueOfString(instance, "9223372036854775808", Long.class);
+    expectUnconvertibleErrorInValueOfString(instance, "12345678901234.0625", Double.class);
+    expectUnconvertibleErrorInValueOfString(instance, "1234567.0625", Float.class);
+  }
+
+  @Test
+  public void valueOfStringDouble() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance();
+
+    assertEquals(Double.valueOf(1.42), instance.valueOfString("1.42", EdmLiteralKind.DEFAULT, null, Double.class));
+    assertEquals(Float.valueOf(-42.25F), instance.valueOfString("-42.25", EdmLiteralKind.JSON, null, Float.class));
+    assertEquals(Double.valueOf(42.0), instance.valueOfString("42D", EdmLiteralKind.URI, null, Double.class));
+    assertEquals(Double.valueOf(42E42), instance.valueOfString("42E42d", EdmLiteralKind.URI, null, Double.class));
+    assertEquals(BigDecimal.TEN, instance.valueOfString("10D", EdmLiteralKind.URI, null, BigDecimal.class));
+    assertEquals(Byte.valueOf((byte) 0), instance.valueOfString("0", EdmLiteralKind.JSON, null, Byte.class));
+    assertEquals(Short.valueOf((short) 1), instance.valueOfString("1.00", EdmLiteralKind.DEFAULT, null, Short.class));
+    assertEquals(Integer.valueOf(42), instance.valueOfString("4.2E1", EdmLiteralKind.DEFAULT, null, Integer.class));
+    assertEquals(Long.valueOf(1234567890), instance.valueOfString("1234567890E-00", EdmLiteralKind.DEFAULT, null, Long.class));
+
+    assertEquals(Double.valueOf(Double.NaN), instance.valueOfString("NaN", EdmLiteralKind.DEFAULT, null, Double.class));
+    assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), instance.valueOfString("-INF", EdmLiteralKind.JSON, null, Double.class));
+    assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), instance.valueOfString("INF", EdmLiteralKind.URI, null, Double.class));
+
+    expectErrorInValueOfString(instance, "42E400", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42.42.42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42.42.42D", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42F", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0x42P42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1.42", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "INF", BigDecimal.class);
+    expectUnconvertibleErrorInValueOfString(instance, "NaN", BigDecimal.class);
+    expectUnconvertibleErrorInValueOfString(instance, "1234567.0625", Float.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-INF", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "NaN", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Long.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-32769", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "32768", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-2147483649", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "2147483648", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-922337203685477.75E4", Long.class);
+    expectUnconvertibleErrorInValueOfString(instance, "922337203685477.75E4", Long.class);
+  }
+
+  @Test
+  public void valueOfStringGuid() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance();
+    final UUID uuid = UUID.fromString("aabbccdd-aabb-ccdd-eeff-aabbccddeeff");
+
+    assertEquals(uuid, instance.valueOfString("aabbccdd-aabb-ccdd-eeff-aabbccddeeff", EdmLiteralKind.DEFAULT, null, UUID.class));
+    assertEquals(uuid, instance.valueOfString("AABBCCDD-AABB-CCDD-EEFF-AABBCCDDEEFF", EdmLiteralKind.JSON, null, UUID.class));
+    assertEquals(uuid, instance.valueOfString("guid'AABBCCDD-aabb-ccdd-eeff-AABBCCDDEEFF'", EdmLiteralKind.URI, null, UUID.class));
+
+    expectErrorInValueOfString(instance, "AABBCCDDAABBCCDDEEFFAABBCCDDEEFF", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "uid'AABBCCDD-aabb-ccdd-eeff-AABBCCDDEEFF'", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, uuid.toString(), EdmLiteralKind.DEFAULT);
+  }
+
+  @Test
+  public void valueOfStringInt16() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance();
+
+    assertEquals(Byte.valueOf((byte) 1), instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, Byte.class));
+    assertEquals(Short.valueOf((short) 2), instance.valueOfString("2", EdmLiteralKind.JSON, null, Short.class));
+    assertEquals(Short.valueOf((short) -32768), instance.valueOfString("-32768", EdmLiteralKind.URI, null, Short.class));
+    assertEquals(Short.valueOf((short) 32767), instance.valueOfString("32767", EdmLiteralKind.URI, null, Short.class));
+    assertEquals(Integer.valueOf(0), instance.valueOfString("0", EdmLiteralKind.DEFAULT, null, Integer.class));
+    assertEquals(Long.valueOf(-1), instance.valueOfString("-1", EdmLiteralKind.DEFAULT, null, Long.class));
+
+    expectErrorInValueOfString(instance, "32768", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+  }
+
+  @Test
+  public void valueOfStringInt32() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance();
+
+    assertEquals(Byte.valueOf((byte) 1), instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, Byte.class));
+    assertEquals(Short.valueOf((short) 2), instance.valueOfString("2", EdmLiteralKind.JSON, null, Short.class));
+    assertEquals(Integer.valueOf(-10000000), instance.valueOfString("-10000000", EdmLiteralKind.URI, null, Integer.class));
+    assertEquals(Long.valueOf(10000000), instance.valueOfString("10000000", EdmLiteralKind.URI, null, Long.class));
+
+    expectErrorInValueOfString(instance, "-2147483649", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-32769", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "32768", Short.class);
+  }
+
+  @Test
+  public void valueOfStringInt64() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance();
+
+    assertEquals(Short.valueOf((short) 1), instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, Short.class));
+    assertEquals(Integer.valueOf(2), instance.valueOfString("2", EdmLiteralKind.JSON, null, Integer.class));
+    assertEquals(Long.valueOf(-1234567890123456789L), instance.valueOfString("-1234567890123456789L", EdmLiteralKind.URI, null, Long.class));
+    assertEquals(BigInteger.ONE, instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, BigInteger.class));
+    assertEquals(Long.valueOf(0), instance.valueOfString("0l", EdmLiteralKind.URI, null, Long.class));
+    assertEquals(Byte.valueOf((byte) 0), instance.valueOfString("0L", EdmLiteralKind.URI, null, Byte.class));
+
+    expectErrorInValueOfString(instance, "-12345678901234567890", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0L", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0M", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0x42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-32769", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "32768", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-2147483649", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "2147483648", Integer.class);
+  }
+
+  @Test
+  public void valueOfStringSByte() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.SByte.getEdmSimpleTypeInstance();
+
+    assertEquals(Byte.valueOf((byte) 1), instance.valueOfString("1", EdmLiteralKind.DEFAULT, null, Byte.class));
+    assertEquals(Short.valueOf((short) -2), instance.valueOfString("-2", EdmLiteralKind.JSON, null, Short.class));
+    assertEquals(Byte.valueOf((byte) 127), instance.valueOfString("127", EdmLiteralKind.URI, null, Byte.class));
+    assertEquals(Byte.valueOf((byte) -128), instance.valueOfString("-128", EdmLiteralKind.URI, null, Byte.class));
+    assertEquals(Integer.valueOf(0), instance.valueOfString("0", EdmLiteralKind.DEFAULT, null, Integer.class));
+    assertEquals(Long.valueOf(0), instance.valueOfString("0", EdmLiteralKind.DEFAULT, null, Long.class));
+
+    expectErrorInValueOfString(instance, "128", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "-129", EdmLiteralKind.JSON, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "1.0", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1", EdmLiteralKind.DEFAULT);
+  }
+
+  @Test
+  public void valueOfStringSingle() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance();
+
+    assertEquals(Float.valueOf(1.42F), instance.valueOfString("1.42", EdmLiteralKind.DEFAULT, null, Float.class));
+    assertEquals(Double.valueOf(-42.42), instance.valueOfString("-42.42", EdmLiteralKind.JSON, null, Double.class));
+    assertEquals(Float.valueOf(42.0F), instance.valueOfString("42F", EdmLiteralKind.URI, null, Float.class));
+    assertEquals(Float.valueOf(2.2E38F), instance.valueOfString("22E37f", EdmLiteralKind.URI, null, Float.class));
+    assertEquals(BigDecimal.TEN, instance.valueOfString("10F", EdmLiteralKind.URI, null, BigDecimal.class));
+    assertEquals(Byte.valueOf((byte) 0), instance.valueOfString("0", EdmLiteralKind.JSON, null, Byte.class));
+    assertEquals(Short.valueOf((short) 1), instance.valueOfString("1.00", EdmLiteralKind.DEFAULT, null, Short.class));
+    assertEquals(Integer.valueOf(42), instance.valueOfString("4.2E1", EdmLiteralKind.DEFAULT, null, Integer.class));
+    assertEquals(Long.valueOf(12345678), instance.valueOfString("12345.678E+03", EdmLiteralKind.DEFAULT, null, Long.class));
+
+    assertEquals(Float.valueOf(Float.NaN), instance.valueOfString("NaN", EdmLiteralKind.DEFAULT, null, Float.class));
+    assertEquals(Float.valueOf(Float.NEGATIVE_INFINITY), instance.valueOfString("-INF", EdmLiteralKind.JSON, null, Float.class));
+    assertEquals(Float.valueOf(Float.POSITIVE_INFINITY), instance.valueOfString("INF", EdmLiteralKind.URI, null, Float.class));
+    assertEquals(Double.valueOf(Float.NaN), instance.valueOfString("NaN", EdmLiteralKind.DEFAULT, null, Double.class));
+    assertEquals(Double.valueOf(Float.NEGATIVE_INFINITY), instance.valueOfString("-INF", EdmLiteralKind.JSON, null, Double.class));
+
+    expectErrorInValueOfString(instance, "42E42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42.42.42", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42.42.42F", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42D", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "42", EdmLiteralKind.URI, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+    expectErrorInValueOfString(instance, "0x42P4", EdmLiteralKind.DEFAULT, null, EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT);
+
+    expectTypeErrorInValueOfString(instance, "1.42", EdmLiteralKind.DEFAULT);
+    expectUnconvertibleErrorInValueOfString(instance, "INF", BigDecimal.class);
+    expectUnconvertibleErrorInValueOfString(instance, "NaN", BigDecimal.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-INF", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "NaN", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "5E-1", Long.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-129", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "128", Byte.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-32769", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "32768", Short.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-2147483.875E3", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "2147483.875E3", Integer.class);
+    expectUnconvertibleErrorInValueOfString(instance, "-1E19", Long.class);
+    expectUnconvertibleErrorInValueOfString(instance, "1E19", Long.class);
+  }
+
+  @Test
+  public void valueOfStringString() throws Exception {
+    final EdmSimpleType instance = EdmSimpleTypeKind.String.getEdmSimpleTypeInstance();
+
+    assertEquals("text", instance.valueOfString("text", EdmLiteralKind.DEFAULT, null, String.class));
+    assertEquals("a\nb", instance.valueOfString("a\nb", EdmLiteralKind.JSON, null, String.class));
+    assertEquals("true", instance.valueOfString("'true'", EdmLiteralKind.URI, null, String.class));
+    assertEquals("a'b", instance.valueOfString("'a''b'", EdmLiteralKind.URI, null, String.class));
+
+    assertEquals("text", instance.valueOfString("text", EdmLiteralKind.DEFAULT, getUnicodeFacets(true), String.class));
+    assertEquals("text", instance.valueOfString("text", EdmLiteralKind.DEFAULT, getUnicodeFacets(null), String.class));
+    assertEquals("text", instance.valueOfString("text", EdmLiteralKind.DEFAULT, getMaxLengthFacets(4), String.class));
+    assertEquals("text", instance.valueOfString("text", EdmLiteralKind.DEFAULT, getMaxLengthFacets(Integer.MAX_VALUE)

<TRUNCATED>

[19/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProv.java
new file mode 100644
index 0000000..72f294f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProv.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+
+public class EdmComplexTypeImplProv extends EdmStructuralTypeImplProv implements EdmComplexType {
+
+  public EdmComplexTypeImplProv(final EdmImplProv edm, final ComplexType complexType, final String namespace) throws EdmException {
+    super(edm, complexType, EdmTypeKind.COMPLEX, namespace);
+  }
+
+  @Override
+  public EdmComplexType getBaseType() throws EdmException {
+    return (EdmComplexType) edmBaseType;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(structuralType.getAnnotationAttributes(), structuralType.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmElementImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmElementImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmElementImplProv.java
new file mode 100644
index 0000000..599abde
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmElementImplProv.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmElement;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * @author SAP AG
+ */
+public abstract class EdmElementImplProv extends EdmTypedImplProv implements EdmElement {
+
+  private EdmFacets edmFacets;
+  private EdmMapping edmMapping;
+
+  public EdmElementImplProv(final EdmImplProv edm, final String name, final FullQualifiedName typeName, final EdmFacets edmFacets, final EdmMapping edmMapping) throws EdmException {
+    super(edm, name, typeName, (edmFacets == null || edmFacets.isNullable() == null) || edmFacets.isNullable() ? EdmMultiplicity.ZERO_TO_ONE : EdmMultiplicity.ONE);
+    this.edmFacets = edmFacets;
+    this.edmMapping = edmMapping;
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return edmMapping;
+  }
+
+  @Override
+  public EdmFacets getFacets() throws EdmException {
+    return edmFacets;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProv.java
new file mode 100644
index 0000000..016f1d8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProv.java
@@ -0,0 +1,184 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+/**
+ * @author SAP AG
+ */
+public class EdmEntityContainerImplProv implements EdmEntityContainer, EdmAnnotatable {
+
+  private EdmImplProv edm;
+  private EntityContainerInfo entityContainer;
+  private Map<String, EdmEntitySet> edmEntitySets;
+  private Map<String, EdmAssociationSet> edmAssociationSets;
+  private Map<String, EdmFunctionImport> edmFunctionImports;
+  private EdmEntityContainer edmExtendedEntityContainer;
+  private boolean isDefaultContainer;
+
+  public EdmEntityContainerImplProv(final EdmImplProv edm, final EntityContainerInfo entityContainer) throws EdmException {
+    this.edm = edm;
+    this.entityContainer = entityContainer;
+    edmEntitySets = new HashMap<String, EdmEntitySet>();
+    edmAssociationSets = new HashMap<String, EdmAssociationSet>();
+    edmFunctionImports = new HashMap<String, EdmFunctionImport>();
+    isDefaultContainer = entityContainer.isDefaultEntityContainer();
+
+    if (entityContainer.getExtendz() != null) {
+      edmExtendedEntityContainer = edm.getEntityContainer(entityContainer.getExtendz());
+      if (edmExtendedEntityContainer == null) {
+        throw new EdmException(EdmException.COMMON);
+      }
+    }
+  }
+
+  @Override
+  public String getName() throws EdmException {
+    return entityContainer.getName();
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet(final String name) throws EdmException {
+    EdmEntitySet edmEntitySet = edmEntitySets.get(name);
+    if (edmEntitySet != null) {
+      return edmEntitySet;
+    }
+
+    EntitySet entitySet;
+    try {
+      entitySet = edm.edmProvider.getEntitySet(entityContainer.getName(), name);
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.PROVIDERPROBLEM, e);
+    }
+
+    if (entitySet != null) {
+      edmEntitySet = createEntitySet(entitySet);
+      edmEntitySets.put(name, edmEntitySet);
+    } else if (edmExtendedEntityContainer != null) {
+      edmEntitySet = edmExtendedEntityContainer.getEntitySet(name);
+      if (edmEntitySet != null) {
+        edmEntitySets.put(name, edmEntitySet);
+      }
+    }
+
+    return edmEntitySet;
+  }
+
+  @Override
+  public EdmFunctionImport getFunctionImport(final String name) throws EdmException {
+    EdmFunctionImport edmFunctionImport = edmFunctionImports.get(name);
+    if (edmFunctionImport != null) {
+      return edmFunctionImport;
+    }
+
+    FunctionImport functionImport;
+    try {
+      functionImport = edm.edmProvider.getFunctionImport(entityContainer.getName(), name);
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.PROVIDERPROBLEM, e);
+    }
+
+    if (functionImport != null) {
+      edmFunctionImport = createFunctionImport(functionImport);
+      edmFunctionImports.put(name, edmFunctionImport);
+    } else if (edmExtendedEntityContainer != null) {
+      edmFunctionImport = edmExtendedEntityContainer.getFunctionImport(name);
+      if (edmFunctionImport != null) {
+        edmFunctionImports.put(name, edmFunctionImport);
+      }
+    }
+
+    return edmFunctionImport;
+  }
+
+  @Override
+  public EdmAssociationSet getAssociationSet(final EdmEntitySet sourceEntitySet, final EdmNavigationProperty navigationProperty) throws EdmException {
+    EdmAssociation edmAssociation = navigationProperty.getRelationship();
+    String association = edmAssociation.getNamespace() + "." + edmAssociation.getName();
+    String entitySetName = sourceEntitySet.getName();
+    String entitySetFromRole = navigationProperty.getFromRole();
+
+    String key = entitySetName + ">>" + association + ">>" + entitySetFromRole;
+
+    EdmAssociationSet edmAssociationSet = edmAssociationSets.get(key);
+    if (edmAssociationSet != null) {
+      return edmAssociationSet;
+    }
+
+    AssociationSet associationSet;
+    FullQualifiedName associationFQName = new FullQualifiedName(edmAssociation.getNamespace(), edmAssociation.getName());
+    try {
+      associationSet = edm.edmProvider.getAssociationSet(entityContainer.getName(), associationFQName, entitySetName, entitySetFromRole);
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.PROVIDERPROBLEM, e);
+    }
+
+    if (associationSet != null) {
+      edmAssociationSet = createAssociationSet(associationSet);
+      edmAssociationSets.put(key, edmAssociationSet);
+      return edmAssociationSet;
+    } else if (edmExtendedEntityContainer != null) {
+      edmAssociationSet = edmExtendedEntityContainer.getAssociationSet(sourceEntitySet, navigationProperty);
+      edmAssociationSets.put(key, edmAssociationSet);
+      return edmAssociationSet;
+    } else {
+      throw new EdmException(EdmException.COMMON);
+    }
+  }
+
+  private EdmEntitySet createEntitySet(final EntitySet entitySet) throws EdmException {
+    return new EdmEntitySetImplProv(edm, entitySet, this);
+  }
+
+  private EdmFunctionImport createFunctionImport(final FunctionImport functionImport) throws EdmException {
+    return new EdmFunctionImportImplProv(edm, functionImport, this);
+  }
+
+  private EdmAssociationSet createAssociationSet(final AssociationSet associationSet) throws EdmException {
+    return new EdmAssociationSetImplProv(edm, associationSet, this);
+  }
+
+  @Override
+  public boolean isDefaultEntityContainer() {
+    return isDefaultContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(entityContainer.getAnnotationAttributes(), entityContainer.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetImplProv.java
new file mode 100644
index 0000000..d864b5c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetImplProv.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+
+public class EdmEntitySetImplProv extends EdmNamedImplProv implements EdmEntitySet, EdmAnnotatable {
+
+  private EntitySet entitySet;
+  private EdmEntityContainer edmEntityContainer;
+  private EdmEntityType edmEntityType;
+
+  public EdmEntitySetImplProv(final EdmImplProv edm, final EntitySet entitySet, final EdmEntityContainer edmEntityContainer) throws EdmException {
+    super(edm, entitySet.getName());
+    this.entitySet = entitySet;
+    this.edmEntityContainer = edmEntityContainer;
+  }
+
+  @Override
+  public EdmEntityType getEntityType() throws EdmException {
+    if (edmEntityType == null) {
+      FullQualifiedName fqName = entitySet.getEntityType();
+      edmEntityType = edm.getEntityType(fqName.getNamespace(), fqName.getName());
+      if (edmEntityType == null) {
+        throw new EdmException(EdmException.COMMON);
+      }
+    }
+    return edmEntityType;
+  }
+
+  @Override
+  public EdmEntitySet getRelatedEntitySet(final EdmNavigationProperty navigationProperty) throws EdmException {
+    EdmAssociationSet associationSet = edmEntityContainer.getAssociationSet(edmEntityContainer.getEntitySet(entitySet.getName()), navigationProperty);
+    EdmAssociationSetEnd toEnd = associationSet.getEnd(navigationProperty.getToRole());
+    if (toEnd == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+    EdmEntitySet targetEntitySet = toEnd.getEntitySet();
+    if (targetEntitySet == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+    return targetEntitySet;
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(entitySet.getAnnotationAttributes(), entitySet.getAnnotationElements());
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return entitySet.getMapping();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProv.java
new file mode 100644
index 0000000..85a6177
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProv.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+
+public class EdmEntitySetInfoImplProv implements EdmEntitySetInfo {
+
+  private final String entitySetName;
+  private final URI entitySetUri;
+  private final String entityContainerName;
+  private final boolean isDefaultEntityContainer;
+
+  public EdmEntitySetInfoImplProv(final EntitySet entitySet, final EntityContainerInfo entityContainerInfo) throws EdmException {
+    entityContainerName = entityContainerInfo.getName();
+    isDefaultEntityContainer = entityContainerInfo.isDefaultEntityContainer();
+
+    entitySetName = entitySet.getName();
+
+    try {
+      if (isDefaultEntityContainer) {
+        entitySetUri = new URI(entitySetName);
+      } else {
+        entitySetUri = new URI(entityContainerName + "." + entitySetName);
+      }
+    } catch (URISyntaxException e) {
+      throw new EdmException(EdmException.COMMON, e);
+    }
+
+  }
+
+  @Override
+  public String getEntityContainerName() {
+    return entityContainerName;
+
+  }
+
+  @Override
+  public String getEntitySetName() {
+    return entitySetName;
+
+  }
+
+  @Override
+  public boolean isDefaultEntityContainer() {
+    return isDefaultEntityContainer;
+
+  }
+
+  @Override
+  public URI getEntitySetUri() {
+    return entitySetUri;
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProv.java
new file mode 100644
index 0000000..de82bb0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProv.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+
+public class EdmEntityTypeImplProv extends EdmStructuralTypeImplProv implements EdmEntityType {
+
+  private EntityType entityType;
+
+  private Map<String, EdmProperty> keyProperties;
+  private List<EdmProperty> edmKeyProperties;
+  private List<String> edmKeyPropertyNames;
+
+  private Map<String, NavigationProperty> navigationProperties;
+  private List<String> edmNavigationPropertyNames;
+
+  public EdmEntityTypeImplProv(final EdmImplProv edm, final EntityType entityType, final String namespace) throws EdmException {
+    super(edm, entityType, EdmTypeKind.ENTITY, namespace);
+    this.entityType = entityType;
+
+    buildNavigationPropertiesInternal();
+  }
+
+  private void buildNavigationPropertiesInternal() throws EdmException {
+    navigationProperties = new HashMap<String, NavigationProperty>();
+
+    if (entityType.getNavigationProperties() != null) {
+      for (final NavigationProperty navigationProperty : entityType.getNavigationProperties()) {
+        navigationProperties.put(navigationProperty.getName(), navigationProperty);
+      }
+    }
+  }
+
+  @Override
+  public List<String> getKeyPropertyNames() throws EdmException {
+    if (edmKeyPropertyNames == null) {
+      if (edmBaseType != null) {
+        return ((EdmEntityType) edmBaseType).getKeyPropertyNames();
+      }
+
+      edmKeyPropertyNames = new ArrayList<String>();
+
+      if (entityType.getKey() != null) {
+        for (final PropertyRef keyProperty : entityType.getKey().getKeys()) {
+          edmKeyPropertyNames.add(keyProperty.getName());
+        }
+      } else {
+        //Entity Type does not define a key
+        throw new EdmException(EdmException.COMMON);
+      }
+    }
+
+    return edmKeyPropertyNames;
+  }
+
+  @Override
+  public List<EdmProperty> getKeyProperties() throws EdmException {
+    if (edmKeyProperties == null) {
+      if (edmBaseType != null) {
+        return ((EdmEntityType) edmBaseType).getKeyProperties();
+      }
+
+      if (keyProperties == null) {
+        keyProperties = new HashMap<String, EdmProperty>();
+        edmKeyProperties = new ArrayList<EdmProperty>();
+
+        for (String keyPropertyName : getKeyPropertyNames()) {
+          final EdmTyped edmProperty = getProperty(keyPropertyName);
+          if (edmProperty != null && edmProperty instanceof EdmProperty) {
+            keyProperties.put(keyPropertyName, (EdmProperty) edmProperty);
+            edmKeyProperties.add((EdmProperty) edmProperty);
+          } else {
+            throw new EdmException(EdmException.COMMON);
+          }
+        }
+      }
+    }
+
+    return edmKeyProperties;
+  }
+
+  @Override
+  public boolean hasStream() throws EdmException {
+    return entityType.isHasStream();
+  }
+
+  @Override
+  public EdmCustomizableFeedMappings getCustomizableFeedMappings() throws EdmException {
+    return entityType.getCustomizableFeedMappings();
+  }
+
+  @Override
+  public List<String> getNavigationPropertyNames() throws EdmException {
+    if (edmNavigationPropertyNames == null) {
+      edmNavigationPropertyNames = new ArrayList<String>();
+      if (edmBaseType != null) {
+        edmNavigationPropertyNames.addAll(((EdmEntityType) edmBaseType).getNavigationPropertyNames());
+      }
+      if (entityType.getNavigationProperties() != null) {
+        for (final NavigationProperty navigationProperty : entityType.getNavigationProperties()) {
+          edmNavigationPropertyNames.add(navigationProperty.getName());
+        }
+      }
+    }
+    return edmNavigationPropertyNames;
+  }
+
+  @Override
+  public EdmEntityType getBaseType() throws EdmException {
+    return (EdmEntityType) edmBaseType;
+  }
+
+  @Override
+  protected EdmTyped getPropertyInternal(final String name) throws EdmException {
+    EdmTyped edmProperty = super.getPropertyInternal(name);
+
+    if (edmProperty != null) {
+      return edmProperty;
+    }
+
+    if (navigationProperties.containsKey(name)) {
+      edmProperty = createNavigationProperty(navigationProperties.get(name));
+      edmProperties.put(name, edmProperty);
+    } else if (edmBaseType != null) {
+      edmProperty = edmBaseType.getProperty(name);
+      if (edmProperty != null) {
+        edmProperties.put(name, edmProperty);
+      }
+    }
+
+    return edmProperty;
+  }
+
+  protected EdmTyped createNavigationProperty(final NavigationProperty property) throws EdmException {
+    return new EdmNavigationPropertyImplProv(edm, property);
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(entityType.getAnnotationAttributes(), entityType.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProv.java
new file mode 100644
index 0000000..9e0e555
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProv.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.ReturnType;
+
+/**
+ * @author SAP AG
+ */
+public class EdmFunctionImportImplProv extends EdmNamedImplProv implements EdmFunctionImport, EdmAnnotatable {
+
+  private FunctionImport functionImport;
+  private EdmEntityContainer edmEntityContainer;
+  private Map<String, EdmParameter> edmParameters;
+  private Map<String, FunctionImportParameter> parameters;
+  private List<String> parametersList;
+
+  public EdmFunctionImportImplProv(final EdmImplProv edm, final FunctionImport functionImport, final EdmEntityContainer edmEntityContainer) throws EdmException {
+    super(edm, functionImport.getName());
+    this.functionImport = functionImport;
+    this.edmEntityContainer = edmEntityContainer;
+
+    buildFunctionImportParametersInternal();
+
+    edmParameters = new HashMap<String, EdmParameter>();
+  }
+
+  private void buildFunctionImportParametersInternal() {
+    parameters = new HashMap<String, FunctionImportParameter>();
+
+    List<FunctionImportParameter> parameters = functionImport.getParameters();
+    if (parameters != null) {
+      FunctionImportParameter functionImportParameter;
+      for (Iterator<FunctionImportParameter> iterator = parameters.iterator(); iterator.hasNext();) {
+        functionImportParameter = iterator.next();
+        this.parameters.put(functionImportParameter.getName(), functionImportParameter);
+      }
+    }
+  }
+
+  @Override
+  public EdmParameter getParameter(final String name) throws EdmException {
+    EdmParameter parameter = null;
+    if (edmParameters.containsKey(name)) {
+      parameter = edmParameters.get(name);
+    } else {
+      parameter = createParameter(name);
+    }
+
+    return parameter;
+  }
+
+  private EdmParameter createParameter(final String name) throws EdmException {
+    EdmParameter edmParameter = null;
+    if (parameters.containsKey(name)) {
+      FunctionImportParameter parameter = parameters.get(name);
+      edmParameter = new EdmParameterImplProv(edm, parameter);
+      edmParameters.put(name, edmParameter);
+    }
+    return edmParameter;
+  }
+
+  @Override
+  public List<String> getParameterNames() throws EdmException {
+    if (parametersList == null) {
+      parametersList = new ArrayList<String>();
+
+      Set<String> keySet = parameters.keySet();
+      Iterator<String> iterator = keySet.iterator();
+      while (iterator.hasNext()) {
+        parametersList.add(iterator.next());
+      }
+    }
+
+    return parametersList;
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet() throws EdmException {
+    return edmEntityContainer.getEntitySet(functionImport.getEntitySet());
+  }
+
+  @Override
+  public String getHttpMethod() throws EdmException {
+    return functionImport.getHttpMethod();
+  }
+
+  @Override
+  public EdmTyped getReturnType() throws EdmException {
+    final ReturnType returnType = functionImport.getReturnType();
+    return new EdmTypedImplProv(edm, functionImport.getName(), returnType.getTypeName(), returnType.getMultiplicity());
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(functionImport.getAnnotationAttributes(), functionImport.getAnnotationElements());
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return functionImport.getMapping();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProv.java
new file mode 100644
index 0000000..126c08c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProv.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EdmProviderAccessor;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.edm.EdmImpl;
+
+public class EdmImplProv extends EdmImpl implements EdmProviderAccessor {
+
+  protected EdmProvider edmProvider;
+
+  public EdmImplProv(final EdmProvider edmProvider) {
+    super(new EdmServiceMetadataImplProv(edmProvider));
+    this.edmProvider = edmProvider;
+  }
+
+  @Override
+  protected EdmEntityContainer createEntityContainer(final String name) throws ODataException {
+    EntityContainerInfo enitityContainerInfo = edmProvider.getEntityContainerInfo(name);
+    if (enitityContainerInfo == null) {
+      return null;
+    }
+    return new EdmEntityContainerImplProv(this, enitityContainerInfo);
+  }
+
+  @Override
+  protected EdmEntityType createEntityType(final FullQualifiedName fqName) throws ODataException {
+    EntityType entityType = edmProvider.getEntityType(fqName);
+    if (entityType == null) {
+      return null;
+    }
+
+    return new EdmEntityTypeImplProv(this, entityType, fqName.getNamespace());
+  }
+
+  @Override
+  protected EdmComplexType createComplexType(final FullQualifiedName fqName) throws ODataException {
+    ComplexType complexType = edmProvider.getComplexType(fqName);
+    if (complexType == null) {
+      return null;
+    }
+    return new EdmComplexTypeImplProv(this, complexType, fqName.getNamespace());
+  }
+
+  @Override
+  protected EdmAssociation createAssociation(final FullQualifiedName fqName) throws ODataException {
+    Association association = edmProvider.getAssociation(fqName);
+    if (association == null) {
+      return null;
+    }
+    return new EdmAssociationImplProv(this, association, fqName.getNamespace());
+  }
+
+  @Override
+  public EdmProvider getEdmProvider() {
+    return edmProvider;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProv.java
new file mode 100644
index 0000000..0d29c1b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProv.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNamed;
+
+public abstract class EdmNamedImplProv implements EdmNamed {
+
+  private static final Pattern PATTERN_VALID_NAME = Pattern
+      .compile("^[:A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02ff\\u0370-\\u037d"
+          + "\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f\\u2c00-\\u2fef\\u3001-\\ud7ff"
+          + "\\uf900-\\ufdcf\\ufdf0-\\ufffd\\x10000-\\xEFFFF]"
+          + "[:A-Z_a-z\\u00C0\\u00D6\\u00D8-\\u00F6"
+          + "\\u00F8-\\u02ff\\u0370-\\u037d\\u037f-\\u1fff\\u200c\\u200d\\u2070-\\u218f"
+          + "\\u2c00-\\u2fef\\u3001-\\udfff\\uf900-\\ufdcf\\ufdf0-\\ufffd\\-\\.0-9"
+          + "\\u00b7\\u0300-\\u036f\\u203f-\\u2040]*\\Z");
+  protected EdmImplProv edm;
+  private String name;
+
+  public EdmNamedImplProv(final EdmImplProv edm, final String name) throws EdmException {
+    this.edm = edm;
+    this.name = getValidatedName(name);
+  }
+
+  @Override
+  public String getName() throws EdmException {
+    return name;
+  }
+
+  private String getValidatedName(final String name) throws EdmException {
+    Matcher matcher = PATTERN_VALID_NAME.matcher(name);
+    if (matcher.matches()) {
+      return name;
+    }
+    throw new EdmException(EdmException.COMMON);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProv.java
new file mode 100644
index 0000000..7d603e7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProv.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+
+public class EdmNavigationPropertyImplProv extends EdmTypedImplProv implements EdmNavigationProperty, EdmAnnotatable {
+
+  private NavigationProperty navigationProperty;
+
+  public EdmNavigationPropertyImplProv(final EdmImplProv edm, final NavigationProperty property) throws EdmException {
+    super(edm, property.getName(), null, null);
+    navigationProperty = property;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    return getRelationship().getEnd(navigationProperty.getToRole()).getEntityType();
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() throws EdmException {
+    return ((EdmAssociationImplProv) getRelationship()).getEndMultiplicity(navigationProperty.getToRole());
+  }
+
+  @Override
+  public EdmAssociation getRelationship() throws EdmException {
+    final FullQualifiedName relationship = navigationProperty.getRelationship();
+    return edm.getAssociation(relationship.getNamespace(), relationship.getName());
+  }
+
+  @Override
+  public String getFromRole() throws EdmException {
+    return navigationProperty.getFromRole();
+  }
+
+  @Override
+  public String getToRole() throws EdmException {
+    return navigationProperty.getToRole();
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(navigationProperty.getAnnotationAttributes(), navigationProperty.getAnnotationElements());
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return navigationProperty.getMapping();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmParameterImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmParameterImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmParameterImplProv.java
new file mode 100644
index 0000000..79a6423
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmParameterImplProv.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class EdmParameterImplProv extends EdmElementImplProv implements EdmParameter, EdmAnnotatable {
+
+  FunctionImportParameter parameter;
+
+  public EdmParameterImplProv(final EdmImplProv edm, final FunctionImportParameter parameter) throws EdmException {
+    super(edm, parameter.getName(), parameter.getType().getFullQualifiedName(), parameter.getFacets(), parameter.getMapping());
+    this.parameter = parameter;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = EdmSimpleTypeFacadeImpl.getEdmSimpleType(parameter.getType());
+      if (edmType == null) {
+        throw new EdmException(EdmException.COMMON);
+      }
+    }
+    return edmType;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(parameter.getAnnotationAttributes(), parameter.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProv.java
new file mode 100644
index 0000000..b2545be
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProv.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+
+public abstract class EdmPropertyImplProv extends EdmElementImplProv implements EdmProperty, EdmAnnotatable {
+
+  private Property property;
+
+  public EdmPropertyImplProv(final EdmImplProv edm, final FullQualifiedName propertyName, final Property property) throws EdmException {
+    super(edm, property.getName(), propertyName, property.getFacets(), property.getMapping());
+    this.property = property;
+  }
+
+  @Override
+  public EdmCustomizableFeedMappings getCustomizableFeedMappings() throws EdmException {
+    return property.getCustomizableFeedMappings();
+  }
+
+  @Override
+  public String getMimeType() throws EdmException {
+    return property.getMimeType();
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(property.getAnnotationAttributes(), property.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
new file mode 100644
index 0000000..259422a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProv.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * 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.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 javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+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.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.ep.producer.XmlMetadataProducer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+
+/**
+ * @author SAP AG
+ */
+public class EdmServiceMetadataImplProv implements EdmServiceMetadata {
+
+  private EdmProvider edmProvider;
+  private String dataServiceVersion;
+  private List<Schema> schemas;
+  private List<EdmEntitySetInfo> entitySetInfos;
+
+  public EdmServiceMetadataImplProv(final EdmProvider edmProvider) {
+    this.edmProvider = edmProvider;
+  }
+
+  @Override
+  public InputStream getMetadata() throws ODataException {
+    if (schemas == null) {
+      schemas = edmProvider.getSchemas();
+    }
+
+    OutputStreamWriter writer = null;
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+    EntityProviderException cachedException = null;
+    DataServices metadata = new DataServices().setSchemas(schemas).setDataServiceVersion(getDataServiceVersion());
+
+    try {
+      writer = new OutputStreamWriter(csb.getOutputStream(), "UTF-8");
+      XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+      XmlMetadataProducer.writeMetadata(metadata, xmlStreamWriter, null);
+      return csb.getInputStream();
+    } catch (XMLStreamException e) {
+      cachedException = new EntityProviderException(EntityProviderException.COMMON, e);
+      throw cachedException;
+    } catch (UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.COMMON, e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (writer != null) {
+        try {
+          writer.close();
+        } catch (IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.COMMON, e);
+          }
+        }
+      }
+    }
+  }
+
+  @Override
+  public String getDataServiceVersion() throws ODataException {
+    if (schemas == null) {
+      schemas = edmProvider.getSchemas();
+    }
+
+    if (dataServiceVersion == null) {
+      dataServiceVersion = ODataServiceVersion.V10;
+
+      if (schemas != null) {
+        for (Schema schema : schemas) {
+          List<EntityType> entityTypes = schema.getEntityTypes();
+          if (entityTypes != null) {
+            for (EntityType entityType : entityTypes) {
+              List<Property> properties = entityType.getProperties();
+              if (properties != null) {
+                for (Property property : properties) {
+                  if (property.getCustomizableFeedMappings() != null) {
+                    if (property.getCustomizableFeedMappings().getFcKeepInContent() != null) {
+                      if (!property.getCustomizableFeedMappings().getFcKeepInContent()) {
+                        dataServiceVersion = ODataServiceVersion.V20;
+                        return dataServiceVersion;
+                      }
+                    }
+                  }
+                }
+                if (entityType.getCustomizableFeedMappings() != null) {
+                  if (entityType.getCustomizableFeedMappings().getFcKeepInContent() != null) {
+                    if (entityType.getCustomizableFeedMappings().getFcKeepInContent()) {
+                      dataServiceVersion = ODataServiceVersion.V20;
+                      return dataServiceVersion;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    return dataServiceVersion;
+  }
+
+  @Override
+  public List<EdmEntitySetInfo> getEntitySetInfos() throws ODataException {
+    if (entitySetInfos == null) {
+      entitySetInfos = new ArrayList<EdmEntitySetInfo>();
+
+      if (schemas == null) {
+        schemas = edmProvider.getSchemas();
+      }
+
+      for (Schema schema : schemas) {
+        for (EntityContainer entityContainer : schema.getEntityContainers()) {
+          for (EntitySet entitySet : entityContainer.getEntitySets()) {
+            EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, entityContainer);
+            entitySetInfos.add(entitySetInfo);
+          }
+        }
+      }
+
+    }
+
+    return entitySetInfos;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmSimplePropertyImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmSimplePropertyImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmSimplePropertyImplProv.java
new file mode 100644
index 0000000..47d4841
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmSimplePropertyImplProv.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+public class EdmSimplePropertyImplProv extends EdmPropertyImplProv {
+
+  private SimpleProperty property;
+
+  public EdmSimplePropertyImplProv(final EdmImplProv edm, final SimpleProperty property) throws EdmException {
+    super(edm, property.getType().getFullQualifiedName(), property);
+    this.property = property;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = EdmSimpleTypeFacadeImpl.getEdmSimpleType(property.getType());
+      if (edmType == null) {
+        throw new EdmException(EdmException.COMMON);
+      }
+    }
+    return edmType;
+  }
+
+  @Override
+  public boolean isSimple() {
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmStructuralTypeImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmStructuralTypeImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmStructuralTypeImplProv.java
new file mode 100644
index 0000000..38619a2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmStructuralTypeImplProv.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+
+/**
+ * @author SAP AG
+ */
+public abstract class EdmStructuralTypeImplProv extends EdmNamedImplProv implements EdmStructuralType, EdmAnnotatable {
+
+  protected EdmStructuralType edmBaseType;
+  protected ComplexType structuralType;
+  private EdmTypeKind edmTypeKind;
+  protected String namespace;
+  protected Map<String, EdmTyped> edmProperties;
+  private Map<String, Property> properties;
+  private List<String> edmPropertyNames;
+
+  public EdmStructuralTypeImplProv(final EdmImplProv edm, final ComplexType structuralType, final EdmTypeKind edmTypeKind, final String namespace) throws EdmException {
+    super(edm, structuralType.getName());
+    this.structuralType = structuralType;
+    this.namespace = namespace;
+    this.edmTypeKind = edmTypeKind;
+
+    resolveBaseType();
+
+    buildPropertiesInternal();
+
+    edmProperties = new HashMap<String, EdmTyped>();
+  }
+
+  private void resolveBaseType() throws EdmException {
+    FullQualifiedName fqName = structuralType.getBaseType();
+    if (fqName != null) {
+      if (EdmTypeKind.COMPLEX.equals(edmTypeKind)) {
+        edmBaseType = edm.getComplexType(fqName.getNamespace(), fqName.getName());
+      } else if (EdmTypeKind.ENTITY.equals(edmTypeKind)) {
+        edmBaseType = edm.getEntityType(fqName.getNamespace(), fqName.getName());
+      }
+      if (edmBaseType == null) {
+        throw new EdmException(EdmException.COMMON);
+      }
+    }
+  }
+
+  private void buildPropertiesInternal() throws EdmException {
+    properties = new HashMap<String, Property>();
+
+    if (structuralType.getProperties() != null) {
+      for (final Property property : structuralType.getProperties()) {
+        properties.put(property.getName(), property);
+      }
+    }
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return namespace;
+  }
+
+  @Override
+  public EdmTyped getProperty(final String name) throws EdmException {
+    EdmTyped property = edmProperties.get(name);
+    if (property == null) {
+      property = getPropertyInternal(name);
+      if (property == null && edmBaseType != null) {
+        property = edmBaseType.getProperty(name);
+      }
+    }
+    return property;
+  }
+
+  @Override
+  public List<String> getPropertyNames() throws EdmException {
+    if (edmPropertyNames == null) {
+      edmPropertyNames = new ArrayList<String>();
+      if (edmBaseType != null) {
+        edmPropertyNames.addAll(edmBaseType.getPropertyNames());
+      }
+      if (structuralType.getProperties() != null) {
+        for (final Property property : structuralType.getProperties()) {
+          edmPropertyNames.add(property.getName());
+        }
+      }
+    }
+
+    return edmPropertyNames;
+  }
+
+  @Override
+  public EdmStructuralType getBaseType() throws EdmException {
+    return edmBaseType;
+  }
+
+  @Override
+  public EdmTypeKind getKind() {
+    return edmTypeKind;
+  }
+
+  @Override
+  public EdmMapping getMapping() throws EdmException {
+    return structuralType.getMapping();
+  }
+
+  protected EdmTyped getPropertyInternal(final String name) throws EdmException {
+    EdmTyped edmProperty = null;
+
+    if (properties.containsKey(name)) {
+      edmProperty = createProperty(properties.get(name));
+      edmProperties.put(name, edmProperty);
+    } else if (edmBaseType != null) {
+      edmProperty = edmBaseType.getProperty(name);
+      if (edmProperty != null) {
+        edmProperties.put(name, edmProperty);
+      }
+    }
+
+    return edmProperty;
+  }
+
+  protected EdmTyped createProperty(final Property property) throws EdmException {
+    if (property instanceof SimpleProperty) {
+      return new EdmSimplePropertyImplProv(edm, (SimpleProperty) property);
+    } else if (property instanceof ComplexProperty) {
+      return new EdmComplexPropertyImplProv(edm, (ComplexProperty) property);
+    } else {
+      throw new EdmException(EdmException.COMMON);
+    }
+  }
+
+  @Override
+  public String toString() {
+    try {
+      return namespace + Edm.DELIMITER + getName();
+    } catch (final EdmException e) {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmTypedImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmTypedImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmTypedImplProv.java
new file mode 100644
index 0000000..d763b0b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmTypedImplProv.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class EdmTypedImplProv extends EdmNamedImplProv implements EdmTyped {
+
+  protected EdmType edmType;
+  private FullQualifiedName typeName;
+  private EdmMultiplicity multiplicity;
+
+  public EdmTypedImplProv(final EdmImplProv edm, final String name, final FullQualifiedName typeName, final EdmMultiplicity multiplicity) throws EdmException {
+    super(edm, name);
+    this.typeName = typeName;
+    this.multiplicity = multiplicity;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      final String namespace = typeName.getNamespace();
+      if (EdmSimpleType.EDM_NAMESPACE.equals(typeName.getNamespace())) {
+        edmType = EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.valueOf(typeName.getName()));
+      } else {
+        edmType = edm.getComplexType(namespace, typeName.getName());
+      }
+      if (edmType == null) {
+        edmType = edm.getEntityType(namespace, typeName.getName());
+      }
+
+      if (edmType == null) {
+        throw new EdmException(EdmException.COMMON);
+      }
+
+    }
+    return edmType;
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() throws EdmException {
+    return multiplicity;
+  }
+}


[38/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContextTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContextTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContextTest.java
new file mode 100644
index 0000000..eae1716
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleContextTest.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLJoinSelectSingleContext.JPQLJoinSelectSingleContextBuilder;
+
+public class JPQLJoinSelectSingleContextTest {
+
+  GetEntityUriInfo entityUriInfo;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {}
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {}
+
+  public void setUp(final boolean toThrowException) throws Exception {
+    entityUriInfo = EasyMock.createMock(GetEntityUriInfo.class);
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    List<NavigationSegment> navigationSegments = new ArrayList<NavigationSegment>();
+    final EdmNavigationProperty navigationProperty = createNavigationProperty("a");
+    final EdmNavigationProperty navigationProperty1 = createNavigationProperty("b");
+    final List<KeyPredicate> keyPredicates = createKeyPredicates(toThrowException);
+    NavigationSegment navigationSegment = new NavigationSegment() {
+
+      @Override
+      public EdmNavigationProperty getNavigationProperty() {
+        return navigationProperty;
+      }
+
+      @Override
+      public List<KeyPredicate> getKeyPredicates() {
+        return keyPredicates;
+      }
+
+      @Override
+      public EdmEntitySet getEntitySet() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+    NavigationSegment navigationSegment1 = new NavigationSegment() {
+
+      @Override
+      public EdmNavigationProperty getNavigationProperty() {
+        return navigationProperty1;
+      }
+
+      @Override
+      public List<KeyPredicate> getKeyPredicates() {
+        return keyPredicates;
+      }
+
+      @Override
+      public EdmEntitySet getEntitySet() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+    navigationSegments.add(navigationSegment);
+    navigationSegments.add(navigationSegment1);
+    EasyMock.expect(entityUriInfo.getNavigationSegments()).andStubReturn(navigationSegments);
+    EasyMock.expect(entityUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(entityUriInfo.getFilter()).andStubReturn(null);
+    EasyMock.expect(entityUriInfo.getKeyPredicates()).andStubReturn(createKeyPredicates(toThrowException));
+    EasyMock.expect(entityUriInfo
+        .getTargetEntitySet()).andStubReturn(edmEntitySet);
+    EdmEntitySet startEdmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType startEdmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(startEdmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(startEdmEntityType.getName()).andStubReturn("SOHeader");
+    EasyMock.expect(startEdmEntitySet.getEntityType()).andStubReturn(startEdmEntityType);
+    EasyMock.expect(entityUriInfo.getStartEntitySet()).andStubReturn(
+        startEdmEntitySet);
+    EasyMock.replay(startEdmEntityType, startEdmEntitySet);
+    EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(edmEntityType);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("SOHeader");
+    EasyMock.replay(edmEntityType, edmEntitySet, entityUriInfo);
+
+  }
+
+  @After
+  public void tearDown() throws Exception {}
+
+  @Test
+  public void testGetJPAOuterJoinClauses() throws Exception {
+    setUp(false);
+
+    JPQLJoinSelectSingleContext joinContext = new JPQLJoinSelectSingleContext();
+    JPQLJoinSelectSingleContextBuilder joinContextBuilder = joinContext.new JPQLJoinSelectSingleContextBuilder();
+    try {
+      joinContextBuilder.entityView = entityUriInfo;
+      joinContextBuilder.build();
+    } catch (ODataJPAModelException e) {
+      fail("Should not come here");
+    } catch (ODataJPARuntimeException e) {
+      fail("Should not come here");
+    }
+    List<JPAJoinClause> joinClauses = joinContext.getJPAJoinClauses();
+    assertNotNull(joinClauses);
+    assertTrue(joinClauses.size() > 0);
+    assertEquals("E1", joinClauses.get(0).getEntityAlias());
+    assertEquals("SOHeader", joinClauses.get(0).getEntityName());
+    assertEquals("s_Itema", joinClauses.get(1).getEntityRelationShip());
+    assertEquals("R1", joinClauses.get(1).getEntityRelationShipAlias());
+  }
+
+  @Test
+  public void testExceptionThrown() throws Exception {
+    setUp(true);
+    JPQLJoinSelectSingleContext joinContext = new JPQLJoinSelectSingleContext();
+    JPQLJoinSelectSingleContextBuilder joinContextBuilder = joinContext.new JPQLJoinSelectSingleContextBuilder();
+    try {
+      joinContextBuilder.entityView = entityUriInfo;
+      joinContextBuilder.build();
+      fail("Should not come here");
+    } catch (ODataJPAModelException e) {
+      fail("Should not come here");
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+  private EdmNavigationProperty createNavigationProperty(final String z) throws EdmException {
+    EdmNavigationProperty navigationProperty = EasyMock.createMock(EdmNavigationProperty.class);
+    EdmAssociation association = EasyMock.createMock(EdmAssociation.class);
+    EdmAssociationEnd associationEnd = EasyMock.createMock(EdmAssociationEnd.class);
+    EasyMock.expect(navigationProperty.getFromRole()).andStubReturn("roleA" + z);
+    EasyMock.expect(navigationProperty.getToRole()).andStubReturn("roleB" + z);
+    EasyMock.expect(navigationProperty.getName()).andStubReturn("navP" + z);
+    EasyMock.expect(navigationProperty.getName()).andStubReturn("navP" + z);
+    EasyMock.expect(navigationProperty.getMultiplicity()).andStubReturn(EdmMultiplicity.ONE);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("sItem" + z);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(edmMapping);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("soItem" + z);
+    EasyMock.expect(associationEnd.getEntityType()).andStubReturn(edmEntityType);
+    EasyMock.expect(association.getEnd("roleA" + z)).andStubReturn(associationEnd);
+    EasyMock.expect(navigationProperty.getRelationship()).andStubReturn(association);
+    EdmMapping edmMapping1 = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping1.getInternalName()).andStubReturn("s_Item" + z);
+    EasyMock.expect(navigationProperty.getMapping()).andStubReturn(edmMapping1);
+    EasyMock.replay(edmMapping, edmMapping1, edmEntityType, associationEnd, association, navigationProperty);
+    return navigationProperty;
+  }
+
+  private List<KeyPredicate> createKeyPredicates(final boolean toThrowException) throws EdmException {
+    KeyPredicate keyPredicate = EasyMock.createMock(KeyPredicate.class);
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("soid");
+    EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+    EasyMock.expect(edmProperty.getName()).andStubReturn("soid");
+    EdmSimpleType edmType = EasyMock.createMock(EdmSimpleType.class);
+    if (toThrowException) {
+      EasyMock.expect(edmProperty.getType()).andStubThrow(new EdmException(null));
+    } else {
+      EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+    }
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(edmProperty);
+
+    EasyMock.replay(edmType, edmMapping, edmProperty, keyPredicate);
+    List<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    keyPredicates.add(keyPredicate);
+    return keyPredicates;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilderTest.java
new file mode 100644
index 0000000..91faa5d
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinSelectSingleStatementBuilderTest.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLJoinSelectSingleContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+
+public class JPQLJoinSelectSingleStatementBuilderTest {
+  JPQLJoinSelectSingleContextView context = null;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {}
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {}
+
+  public void setUp(final List<JPAJoinClause> joinClauseList) throws Exception {
+    context = EasyMock.createMock(JPQLJoinSelectSingleContextView.class);
+    EasyMock.expect(context.getJPAEntityAlias()).andStubReturn("gt1");
+    EasyMock.expect(context.getJPAEntityName()).andStubReturn("SOHeader");
+    EasyMock.expect(context.getType()).andStubReturn(JPQLContextType.SELECT);
+    EasyMock.expect(context.getKeyPredicates()).andStubReturn(createKeyPredicates());
+    EasyMock.expect(context.getSelectExpression()).andStubReturn("gt1");
+    EasyMock.expect(context.getJPAJoinClauses()).andStubReturn(joinClauseList);
+    EasyMock.replay(context);
+  }
+
+  private List<JPAJoinClause> getJoinClauseList() {
+    List<JPAJoinClause> joinClauseList = new ArrayList<JPAJoinClause>();
+    JPAJoinClause jpaOuterJoinClause = new JPAJoinClause("SOHeader", "soh", null, null, "soh.soId = 1", JPAJoinClause.JOIN.LEFT);
+    joinClauseList.add(jpaOuterJoinClause);
+    jpaOuterJoinClause = new JPAJoinClause("SOHeader", "soh", "soItem", "soi", "soi.shId = soh.soId", JPAJoinClause.JOIN.LEFT);
+    joinClauseList.add(jpaOuterJoinClause);
+    jpaOuterJoinClause = new JPAJoinClause("SOItem", "si", "material", "mat", "mat.id = 'abc'", JPAJoinClause.JOIN.LEFT);
+    joinClauseList.add(jpaOuterJoinClause);
+    return joinClauseList;
+  }
+
+  @After
+  public void tearDown() throws Exception {}
+
+  @Test
+  public void testBuild() throws Exception {
+    setUp(getJoinClauseList());
+    JPQLJoinSelectSingleStatementBuilder jpqlJoinSelectsingleStatementBuilder = new JPQLJoinSelectSingleStatementBuilder(context);
+    try {
+      JPQLStatement jpqlStatement = jpqlJoinSelectsingleStatementBuilder.build();
+      assertEquals("SELECT gt1 FROM SOHeader soh JOIN soh.soItem soi JOIN soi.material mat WHERE soh.soId = 1 AND soi.shId = soh.soId AND mat.id = 'abc'", jpqlStatement.toString());
+    } catch (ODataJPARuntimeException e) {
+      fail("Should not have come here");
+    }
+
+  }
+
+  private List<KeyPredicate> createKeyPredicates() throws EdmException {
+    KeyPredicate keyPredicate = EasyMock.createMock(KeyPredicate.class);
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("soid");
+    EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+    EdmSimpleType edmType = EasyMock.createMock(EdmSimpleType.class);
+    EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(edmProperty);
+
+    EasyMock.replay(edmType, edmMapping, edmProperty, keyPredicate);
+    List<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    keyPredicates.add(keyPredicate);
+    return keyPredicates;
+  }
+
+  @Test
+  public void testJoinClauseAsNull() throws Exception {
+    setUp(null);
+    JPQLJoinSelectSingleStatementBuilder jpqlJoinSelectsingleStatementBuilder = new JPQLJoinSelectSingleStatementBuilder(context);
+    try {
+      jpqlJoinSelectsingleStatementBuilder.build();
+      fail("Should not have come here");
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testJoinClauseListAsEmpty() throws Exception {
+    List<JPAJoinClause> joinClauseList = new ArrayList<JPAJoinClause>();
+    setUp(joinClauseList);
+    JPQLJoinSelectSingleStatementBuilder jpqlJoinSelectsingleStatementBuilder = new JPQLJoinSelectSingleStatementBuilder(context);
+    try {
+      jpqlJoinSelectsingleStatementBuilder.build();
+      fail("Should not have come here");
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilderTest.java
new file mode 100644
index 0000000..542800e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinStatementBuilderTest.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLJoinContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+
+public class JPQLJoinStatementBuilderTest {
+  JPQLJoinContextView context = null;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {}
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {}
+
+  public void setUp(final List<JPAJoinClause> joinClauseList) throws Exception {
+    context = EasyMock.createMock(JPQLJoinContextView.class);
+    EasyMock.expect(context.getJPAEntityAlias()).andStubReturn("mat");
+    EasyMock.expect(context.getJPAEntityName()).andStubReturn("SOHeader");
+    EasyMock.expect(context.getType()).andStubReturn(JPQLContextType.SELECT);
+    EasyMock.expect(context.getSelectExpression()).andStubReturn("mat");
+    EasyMock.expect(context.getWhereExpression()).andStubReturn("soh.buyerId = 2");
+    HashMap<String, String> orderByMap = new HashMap<String, String>();
+    orderByMap.put("mat.buyerId", "asc");
+    orderByMap.put("mat.city", "desc");
+    EasyMock.expect(context.getOrderByCollection()).andStubReturn(orderByMap);
+    EasyMock.expect(context.getJPAJoinClauses()).andStubReturn(joinClauseList);
+    EasyMock.replay(context);
+  }
+
+  private List<JPAJoinClause> getJoinClauseList() {
+    List<JPAJoinClause> joinClauseList = new ArrayList<JPAJoinClause>();
+    JPAJoinClause jpaOuterJoinClause = new JPAJoinClause("SOHeader", "soh", null, null, "soh.createdBy = 'Peter'", JPAJoinClause.JOIN.LEFT);
+    joinClauseList.add(jpaOuterJoinClause);
+    jpaOuterJoinClause = new JPAJoinClause("SOHeader", "soh", "soItem", "soi", "soi.shId = soh.soId", JPAJoinClause.JOIN.LEFT);
+    joinClauseList.add(jpaOuterJoinClause);
+    jpaOuterJoinClause = new JPAJoinClause("SOItem", "si", "material", "mat", "mat.id = 'abc'", JPAJoinClause.JOIN.LEFT);
+    joinClauseList.add(jpaOuterJoinClause);
+    return joinClauseList;
+  }
+
+  @After
+  public void tearDown() throws Exception {}
+
+  @Test
+  public void testBuild() throws Exception {
+    setUp(getJoinClauseList());
+    JPQLJoinStatementBuilder jpqlJoinStatementBuilder = new JPQLJoinStatementBuilder(context);
+    try {
+      JPQLStatement jpqlStatement = jpqlJoinStatementBuilder.build();
+      assertEquals("SELECT mat FROM SOHeader soh JOIN soh.soItem soi JOIN soi.material mat WHERE soh.buyerId = 2 AND soh.createdBy = 'Peter' AND soi.shId = soh.soId AND mat.id = 'abc' ORDER BY mat.buyerId asc , mat.city desc", jpqlStatement.toString());
+    } catch (ODataJPARuntimeException e) {
+      fail("Should not have come here");
+    }
+
+  }
+
+  @Test
+  public void testJoinClauseAsNull() throws Exception {
+    setUp(null);
+    JPQLJoinStatementBuilder jpqlJoinStatementBuilder = new JPQLJoinStatementBuilder(context);
+    try {
+      jpqlJoinStatementBuilder.build();
+      fail("Should not have come here");
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testJoinClauseListAsEmpty() throws Exception {
+    setUp(new ArrayList<JPAJoinClause>());
+    JPQLJoinStatementBuilder jpqlJoinStatementBuilder = new JPQLJoinStatementBuilder(context);
+    try {
+      jpqlJoinStatementBuilder.build();
+      fail("Should not have come here");
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContextImplTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContextImplTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContextImplTest.java
new file mode 100644
index 0000000..09f533d
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectContextImplTest.java
@@ -0,0 +1,454 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderExpression;
+import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
+import org.apache.olingo.odata2.api.uri.expression.SortOrder;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectContext.JPQLSelectContextBuilder;
+
+public class JPQLSelectContextImplTest {
+
+  private static String entityTypeName = "MockEntity";
+  private static String[] fields = { "Field1", "Field2" };
+  private static List<KeyPredicate> keyPredicates;
+  private static SortOrder[] orderType = { SortOrder.asc, SortOrder.desc };
+
+  private static JPQLSelectContextBuilder builder;
+  private static JPQLSelectContext selectContext;
+
+  @BeforeClass
+  public static void setup() {
+
+  }
+
+  private void buildSelectContext(final boolean orderByIsNull,
+      final boolean selectFieldsIsNull, final boolean filterIsNull,
+      final boolean isTopNull, final boolean isSkipNull) {
+    builder = null;
+    selectContext = null;
+    keyPredicates = new ArrayList<KeyPredicate>();
+    GetEntitySetUriInfo resultsView = EasyMock
+        .createMock(GetEntitySetUriInfo.class);
+
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+    KeyPredicate keyPredicate = EasyMock.createMock(KeyPredicate.class);
+    EdmProperty kpProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType1 = EasyMock.createMock(EdmType.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    try {
+      EasyMock.expect(mapping.getInternalName()).andStubReturn("Field1");
+      EasyMock.expect(kpProperty.getMapping()).andStubReturn(mapping);
+      EasyMock.expect(kpProperty.getType()).andStubReturn(edmType1);
+
+    } catch (EdmException e2) {
+      fail("this should not happen");
+    }
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(kpProperty);
+    EasyMock.replay(mapping, edmType1, kpProperty, keyPredicate);
+    keyPredicates.add(keyPredicate);
+    int i = 0;
+    List<OrderExpression> orderList = new ArrayList<OrderExpression>(2);
+    do {
+
+      EdmType edmType = EasyMock.createMock(EdmType.class);
+      try {
+        EasyMock.expect(edmType.getName()).andStubReturn(fields[i]);
+        EasyMock.replay(edmType);
+      } catch (EdmException e2) {
+        fail("Exception not Expected");
+      }
+
+      PropertyExpression commonExpression = EasyMock
+          .createMock(PropertyExpression.class);
+      EasyMock.expect(commonExpression.getEdmType()).andStubReturn(
+          edmType);
+
+      EdmProperty edmTyped = EasyMock.createMock(EdmProperty.class);
+      EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+      EasyMock.expect(edmMapping.getInternalName()).andStubReturn(
+          fields[i]);
+      try {
+        EasyMock.expect(edmTyped.getMapping())
+            .andStubReturn(edmMapping);
+      } catch (EdmException e) {
+        // TODO Auto-generated catch block
+        e.printStackTrace();
+      }
+      EasyMock.expect(commonExpression.getEdmProperty()).andStubReturn(
+          edmTyped);
+      OrderExpression order = EasyMock.createMock(OrderExpression.class);
+      EasyMock.expect(order.getExpression()).andStubReturn(
+          commonExpression);
+      EasyMock.expect(order.getSortOrder()).andStubReturn(orderType[i]);
+      EasyMock.replay(edmMapping, edmTyped, commonExpression);
+      EasyMock.replay(order);
+
+      orderList.add(order);
+
+    } while (++i < 2);
+
+    OrderByExpression orderBy = EasyMock
+        .createMock(OrderByExpression.class);
+    EasyMock.expect(orderBy.getOrders()).andStubReturn(orderList);
+    EasyMock.replay(orderBy);
+
+    try {
+      i = 0;
+      List<SelectItem> selectItemList = new ArrayList<SelectItem>(2);
+      do {
+        EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+        EasyMock.expect(edmMapping.getInternalName()).andStubReturn(
+            fields[i]);
+        EdmProperty edmProperty = EasyMock
+            .createMock(EdmProperty.class);
+        EasyMock.expect(edmProperty.getMapping()).andStubReturn(
+            edmMapping);
+        EasyMock.replay(edmMapping, edmProperty);
+
+        SelectItem selectItem = EasyMock.createMock(SelectItem.class);
+        EasyMock.expect(selectItem.getProperty()).andStubReturn(
+            edmProperty);
+        EasyMock.replay(selectItem);
+
+        selectItemList.add(selectItem);
+
+      } while (++i < 2);
+      EasyMock.expect(entityType.getMapping()).andStubReturn(null);
+      EasyMock.expect(entityType.getName()).andStubReturn(entityTypeName);
+      EasyMock.expect(entityType.getKeyProperties()).andStubReturn(getLocalKeyProperties());
+
+      EasyMock.replay(entityType);
+      EasyMock.expect(entitySet.getEntityType())
+          .andStubReturn(entityType);
+      EasyMock.replay(entitySet);
+
+      EasyMock.expect(resultsView.getTargetEntitySet()).andStubReturn(
+          entitySet);
+      if (orderByIsNull) {
+        EasyMock.expect(resultsView.getOrderBy()).andStubReturn(null);
+      } else {
+        EasyMock.expect(resultsView.getOrderBy())
+            .andStubReturn(orderBy);
+      }
+      if (selectFieldsIsNull) {
+        EasyMock.expect(resultsView.getSelect()).andStubReturn(null);
+      } else {
+        EasyMock.expect(resultsView.getSelect()).andStubReturn(
+            selectItemList);
+      }
+      // FilterExpression filterExpression =
+      // EasyMock.createMock(FilterExpression.class);
+      // EasyMock.expect(filterExpression.g)
+      if (filterIsNull) {
+        EasyMock.expect(resultsView.getFilter()).andStubReturn(null);
+      } else {
+        EasyMock.expect(resultsView.getFilter()).andStubReturn(
+            getFilterExpressionMockedObj(ExpressionKind.PROPERTY,
+                "SalesOrder"));
+      }
+      if (isTopNull) {
+        EasyMock.expect(resultsView.getTop()).andStubReturn(null);
+      } else {
+        EasyMock.expect(resultsView.getTop()).andStubReturn(10);
+      }
+      if (isSkipNull) {
+        EasyMock.expect(resultsView.getSkip()).andStubReturn(null);
+      } else {
+        EasyMock.expect(resultsView.getSkip()).andStubReturn(0);
+      }
+      EasyMock.expect(resultsView.getKeyPredicates()).andStubReturn(
+          keyPredicates);
+      EasyMock.replay(resultsView);
+
+    } catch (EdmException e1) {
+      fail("Exception not Expected");
+    }
+    try {
+      builder = (JPQLSelectContextBuilder) JPQLContext.createBuilder(
+          JPQLContextType.SELECT, resultsView);
+
+      selectContext = (JPQLSelectContext) builder.build();
+    } catch (ODataJPAModelException e) {
+      fail("Exception not Expected");
+    } catch (ODataJPARuntimeException e) {
+      fail("Runtime Exception thrown");
+    }
+  }
+
+  private List<EdmProperty> getLocalKeyProperties() {
+    List<EdmProperty> propertyList = new ArrayList<EdmProperty>();
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("Field1");
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(null);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    propertyList.add(edmProperty);
+    return propertyList;
+  }
+
+  @Test
+  public void testEntityNameThrowingException() {
+    // buildSelectContext(false, false, false);
+    GetEntitySetUriInfo resultsView = EasyMock
+        .createMock(GetEntitySetUriInfo.class);
+
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+
+    try {
+      EasyMock.expect(entityType.getName()).andStubThrow(
+          new EdmException(null));
+      EasyMock.expect(entitySet.getEntityType()).andStubThrow(
+          new EdmException(null));
+    } catch (EdmException e1) {
+      // throw new ODataException();
+    }
+
+    EasyMock.replay(entityType);
+    EasyMock.replay(entitySet);
+
+    EasyMock.expect(resultsView.getTargetEntitySet()).andStubReturn(
+        entitySet);
+    EasyMock.expect(resultsView.getOrderBy()).andStubReturn(null);
+    EasyMock.expect(resultsView.getSelect()).andStubReturn(null);
+    EasyMock.expect(resultsView.getFilter()).andStubReturn(null);
+    EasyMock.replay(resultsView);
+    try {
+      JPQLSelectContextBuilder builder1 = (JPQLSelectContextBuilder) JPQLContext
+          .createBuilder(JPQLContextType.SELECT, resultsView);
+
+      builder1.build();
+      fail("Should not come here");
+    } catch (ODataJPAModelException e) {
+      fail();
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testSelectFieldsAsNull() {
+    buildSelectContext(false, true, true, true, true);
+
+    try {
+      selectContext = (JPQLSelectContext) builder.build();
+      assertEquals("E2", selectContext.getSelectExpression());
+    } catch (ODataJPAModelException e) {
+      fail();
+    } catch (ODataJPARuntimeException e) {
+      fail();
+    }
+  }
+
+  @Test
+  public void testGetOrderByCollection() {
+    buildSelectContext(false, false, true, true, true);
+    assertEquals(
+        true,
+        selectContext.getOrderByCollection().containsKey(
+            "E1." + JPQLSelectContextImplTest.fields[0]));
+    assertEquals(
+        "",
+        selectContext.getOrderByCollection().get(
+            "E1." + JPQLSelectContextImplTest.fields[0]));
+
+    assertEquals(
+        true,
+        selectContext.getOrderByCollection().containsKey(
+            "E1." + JPQLSelectContextImplTest.fields[1]));
+    assertEquals(
+        "DESC",
+        selectContext.getOrderByCollection().get(
+            "E1." + JPQLSelectContextImplTest.fields[1]));
+  }
+
+  @Test
+  public void testGetWhereExpression() {
+    buildSelectContext(false, false, true, true, true);
+    // fail("Not yet implemented");
+  }
+
+  @Test
+  public void testGetJPAEntityName() {
+    buildSelectContext(false, false, true, true, true);
+    assertEquals(JPQLSelectContextImplTest.entityTypeName,
+        selectContext.getJPAEntityName());
+  }
+
+  @Test
+  public void testGetType() {
+    buildSelectContext(false, false, true, true, true);
+    assertEquals(JPQLContextType.SELECT, selectContext.getType());
+  }
+
+  @Test
+  public void testCreateBuilder() {
+    buildSelectContext(false, false, true, true, true);
+    assertEquals(JPQLSelectContextBuilder.class.toString(), builder
+        .getClass().toString());
+  }
+
+  @Test
+  public void testEntitySetAsNull() {
+    buildSelectContext(false, false, true, true, true);
+    try {
+      JPQLSelectContextBuilder builder = (JPQLSelectContextBuilder) JPQLContext
+          .createBuilder(JPQLContextType.SELECT, null);
+
+      JPQLSelectContext selectContext1 = (JPQLSelectContext) builder
+          .build();
+      assertNull(selectContext1.getJPAEntityAlias());
+      assertNull(selectContext1.getJPAEntityName());
+      assertNull(selectContext1.getOrderByCollection());
+      assertNull(selectContext1.getSelectExpression());
+      assertNull(selectContext1.getType());
+      assertNull(selectContext1.getWhereExpression());
+    } catch (ODataJPAModelException e) {
+      fail("Exception not Expected");
+    } catch (ODataJPARuntimeException e) {
+      fail("Runtime Exception thrown");
+    }
+  }
+
+  @Test
+  public void testOrderingWithSkip() {
+    buildSelectContext(true, false, true, true, false);
+    assertEquals(
+        true,
+        selectContext.getOrderByCollection().containsKey(
+            "E1." + JPQLSelectContextImplTest.fields[0]));
+    assertEquals(
+        "",
+        selectContext.getOrderByCollection().get(
+            "E1." + JPQLSelectContextImplTest.fields[0]));
+
+    assertEquals(
+        false,
+        selectContext.getOrderByCollection().containsKey(
+            "E1." + JPQLSelectContextImplTest.fields[1]));
+
+  }
+
+  @Test
+  public void testOrderingWithTop() {
+    buildSelectContext(true, false, true, false, true);
+    assertEquals(
+        true,
+        selectContext.getOrderByCollection().containsKey(
+            "E1." + JPQLSelectContextImplTest.fields[0]));
+    assertEquals(
+        "",
+        selectContext.getOrderByCollection().get(
+            "E1." + JPQLSelectContextImplTest.fields[0]));
+
+    assertEquals(
+        false,
+        selectContext.getOrderByCollection().containsKey(
+            "E1." + JPQLSelectContextImplTest.fields[1]));
+
+  }
+
+  @Test
+  public void testOrderByTopSkipAsNull() {
+    buildSelectContext(true, true, true, true, true);
+    assertNull(selectContext.getOrderByCollection());
+  }
+
+  @Test
+  public void testFilter() {
+    buildSelectContext(true, false, false, false, false);
+    assertEquals("E1.field", selectContext.whereCondition);
+
+  }
+
+  private FilterExpression getFilterExpressionMockedObj(
+      final ExpressionKind leftOperandExpKind, final String propertyName)
+      throws EdmException {
+    FilterExpression filterExpression = EasyMock
+        .createMock(FilterExpression.class);
+    EasyMock.expect(filterExpression.getKind())
+        .andStubReturn(ExpressionKind.FILTER);
+    EasyMock.expect(filterExpression.getExpression())
+        .andStubReturn(
+            getPropertyExpressionMockedObj(leftOperandExpKind,
+                propertyName));
+    EasyMock.replay(filterExpression);
+    return filterExpression;
+  }
+
+  private PropertyExpression getPropertyExpressionMockedObj(
+      final ExpressionKind expKind, final String propertyName) {
+    PropertyExpression leftOperandPropertyExpresion = EasyMock
+        .createMock(PropertyExpression.class);
+    EasyMock.expect(leftOperandPropertyExpresion.getKind()).andReturn(
+        ExpressionKind.PROPERTY);
+    EasyMock.expect(leftOperandPropertyExpresion.getPropertyName())
+        .andReturn(propertyName);
+    EdmProperty edmtTyped = EasyMock.createMock(EdmProperty.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn("field");
+    try {
+      EasyMock.expect(edmtTyped.getMapping()).andStubReturn(mapping);
+    } catch (EdmException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    EasyMock.expect(leftOperandPropertyExpresion.getEdmProperty())
+        .andReturn(edmtTyped);
+    EasyMock.replay(mapping, edmtTyped, leftOperandPropertyExpresion);
+    return leftOperandPropertyExpresion;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContextImplTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContextImplTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContextImplTest.java
new file mode 100644
index 0000000..7baa021
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleContextImplTest.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectSingleContext.JPQLSelectSingleContextBuilder;
+
+public class JPQLSelectSingleContextImplTest {
+
+  private static String entityTypeName = "MockEntity";
+  private static String[] fields = { "Field1", "Field2" };
+  private static List<KeyPredicate> keyPredicates;
+
+  private static JPQLSelectSingleContextBuilder builder;
+  private static JPQLSelectSingleContext selectContext;
+
+  private void buildContextBuilder(final boolean isSelectNull) {
+    builder = null;
+    selectContext = null;
+    keyPredicates = new ArrayList<KeyPredicate>();
+    GetEntityUriInfo resultsView = EasyMock
+        .createMock(GetEntityUriInfo.class);
+
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+
+    KeyPredicate keyPredicate = EasyMock.createMock(KeyPredicate.class);
+    EdmProperty kpProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType = EasyMock.createMock(EdmType.class);
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    try {
+      EasyMock.expect(kpProperty.getName()).andStubReturn("Field1");
+      EasyMock.expect(kpProperty.getType()).andStubReturn(edmType);
+
+    } catch (EdmException e2) {
+      fail("this should not happen");
+    }
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(kpProperty);
+    EasyMock.replay(edmType, kpProperty, keyPredicate);
+    keyPredicates.add(keyPredicate);
+    int i = 0;
+    try {
+
+      List<SelectItem> selectItemList = new ArrayList<SelectItem>(2);
+      do {
+        EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+        EasyMock.expect(edmMapping.getInternalName()).andStubReturn(
+            fields[i]);
+        EdmProperty edmProperty = EasyMock
+            .createMock(EdmProperty.class);
+        EasyMock.expect(edmProperty.getMapping()).andStubReturn(
+            edmMapping);
+        EasyMock.replay(edmMapping, edmProperty);
+
+        SelectItem selectItem = EasyMock.createMock(SelectItem.class);
+        EasyMock.expect(selectItem.getProperty()).andStubReturn(
+            edmProperty);
+        EasyMock.replay(selectItem);
+
+        selectItemList.add(selectItem);
+
+      } while (++i < 2);
+
+      EasyMock.expect(entityType.getMapping()).andStubReturn(null);
+      EasyMock.expect(entityType.getName()).andStubReturn(entityTypeName);
+      EasyMock.replay(entityType);
+      EasyMock.expect(entitySet.getEntityType())
+          .andStubReturn(entityType);
+      EasyMock.replay(entitySet);
+
+      EasyMock.expect(resultsView.getTargetEntitySet()).andStubReturn(
+          entitySet);
+      if (isSelectNull) {
+        selectItemList = null;
+      }
+      EasyMock.expect(resultsView.getSelect()).andStubReturn(
+          selectItemList);
+      ArrayList<KeyPredicate> arrayList = new ArrayList<KeyPredicate>();
+      arrayList.add(keyPredicate);
+      EasyMock.expect(resultsView.getKeyPredicates()).andStubReturn(
+          arrayList);
+      EasyMock.replay(resultsView);
+
+    } catch (EdmException e1) {
+      fail("Exception not Expected");
+    }
+    try {
+      builder = (JPQLSelectSingleContextBuilder) JPQLContext
+          .createBuilder(JPQLContextType.SELECT_SINGLE, resultsView);
+
+      selectContext = (JPQLSelectSingleContext) builder.build();
+    } catch (ODataJPAModelException e) {
+      fail("Exception not Expected");
+    } catch (ODataJPARuntimeException e) {
+      fail("Runtime Exception thrown");
+    }
+  }
+
+  @Test
+  public void testEntityNameThrowingException() {
+    // buildSelectContext(false, false, false);
+    GetEntityUriInfo resultsView = EasyMock
+        .createMock(GetEntityUriInfo.class);
+
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+
+    try {
+      EasyMock.expect(entityType.getName()).andStubThrow(
+          new EdmException(null));
+      EasyMock.expect(entitySet.getEntityType()).andStubThrow(
+          new EdmException(null));
+    } catch (EdmException e1) {
+      // throw new ODataException();
+    }
+
+    EasyMock.replay(entityType);
+    EasyMock.replay(entitySet);
+
+    EasyMock.expect(resultsView.getTargetEntitySet()).andStubReturn(
+        entitySet);
+    EasyMock.expect(resultsView.getSelect()).andStubReturn(null);
+    EasyMock.expect(resultsView.getFilter()).andStubReturn(null);
+    EasyMock.replay(resultsView);
+    try {
+      JPQLSelectSingleContextBuilder builder1 = (JPQLSelectSingleContextBuilder) JPQLContext
+          .createBuilder(JPQLContextType.SELECT_SINGLE, resultsView);
+      builder1.build();
+      fail("Should not come here");
+    } catch (ODataJPAModelException e) {
+      fail();
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testSlectedFieldsAsNull() {
+    buildContextBuilder(true);
+    try {
+      selectContext = (JPQLSelectSingleContext) builder.build();
+      assertEquals("E2", selectContext.getSelectExpression());
+    } catch (ODataJPAModelException e) {
+      fail();
+    } catch (ODataJPARuntimeException e) {
+      fail();
+    }
+  }
+
+  @Test
+  public void getKeyPredicates() {
+    buildContextBuilder(false);
+    assertEquals(keyPredicates.size(), selectContext.getKeyPredicates()
+        .size());
+    assertEquals(keyPredicates, selectContext.getKeyPredicates());
+  }
+
+  @Test
+  public void testGetJPAEntityName() {
+    buildContextBuilder(false);
+    assertEquals(JPQLSelectSingleContextImplTest.entityTypeName,
+        selectContext.getJPAEntityName());
+  }
+
+  @Test
+  public void testGetType() {
+    buildContextBuilder(false);
+    assertEquals(JPQLContextType.SELECT_SINGLE, selectContext.getType());
+  }
+
+  @Test
+  public void testCreateBuilder() {
+    buildContextBuilder(false);
+    assertEquals(JPQLSelectSingleContextBuilder.class.toString(), builder
+        .getClass().toString());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilderTest.java
new file mode 100644
index 0000000..a22dc63
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectSingleStatementBuilderTest.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+
+public class JPQLSelectSingleStatementBuilderTest {
+
+  /**
+   * @throws java.lang.Exception
+   */
+  private JPQLSelectSingleStatementBuilder JPQLSelectSingleStatementBuilder;
+
+  @Before
+  public void setUp() throws Exception {
+
+  }
+
+  private JPQLSelectSingleContext createSelectContext() throws ODataJPARuntimeException, EdmException {
+    //Object Instantiation
+
+    JPQLSelectSingleContext JPQLSelectSingleContextImpl = null;// new JPQLSelectSingleContextImpl();
+    GetEntityUriInfo getEntityView = EasyMock.createMock(GetEntityUriInfo.class);
+
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    List<SelectItem> selectItemList = null;
+
+    //Setting up the expected value
+    KeyPredicate keyPredicate = EasyMock
+        .createMock(KeyPredicate.class);
+    EdmProperty kpProperty = EasyMock
+        .createMock(EdmProperty.class);
+    EdmSimpleType edmType = EasyMock
+        .createMock(EdmSimpleType.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("Field1");
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    try {
+      EasyMock.expect(kpProperty.getName()).andStubReturn("Field1");
+      EasyMock.expect(kpProperty.getType()).andStubReturn(edmType);
+
+      EasyMock.expect(kpProperty.getMapping()).andStubReturn(edmMapping);
+
+    } catch (EdmException e2) {
+      fail("this should not happen");
+    }
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(kpProperty);
+    EasyMock.replay(edmMapping, edmType, kpProperty, keyPredicate);
+    EasyMock.expect(getEntityView.getTargetEntitySet()).andStubReturn(edmEntitySet);
+    EasyMock.expect(getEntityView.getSelect()).andStubReturn(selectItemList);
+
+    EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(edmEntityType);
+    EasyMock.replay(edmEntitySet);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("SalesOrderHeader");
+    EasyMock.replay(edmEntityType);
+    ArrayList<KeyPredicate> arrayList = new ArrayList<KeyPredicate>();
+    arrayList.add(keyPredicate);
+    EasyMock.expect(getEntityView.getKeyPredicates()).andStubReturn(
+        arrayList);
+    EasyMock.replay(getEntityView);
+
+    JPQLContextBuilder contextBuilder1 = JPQLContext.createBuilder(JPQLContextType.SELECT_SINGLE, getEntityView);
+    try {
+      JPQLSelectSingleContextImpl = (JPQLSelectSingleContext) contextBuilder1.build();
+    } catch (ODataJPAModelException e) {
+      fail("Model Exception thrown");
+    }
+
+    return JPQLSelectSingleContextImpl;
+  }
+
+  /**
+  * Test method for {@link org.apache.olingo.odata2.processor.jpa.jpql.JPQLSelectSingleStatementBuilder#build)}.
+  * @throws EdmException 
+   * @throws ODataJPARuntimeException 
+  */
+
+  @Test
+  public void testBuildSimpleQuery() throws EdmException, ODataJPARuntimeException {
+    JPQLSelectSingleContext JPQLSelectSingleContextImpl = createSelectContext();
+    JPQLSelectSingleStatementBuilder = new JPQLSelectSingleStatementBuilder(JPQLSelectSingleContextImpl);
+
+    assertEquals("SELECT E1 FROM SalesOrderHeader E1 WHERE E1.Field1 = 1", JPQLSelectSingleStatementBuilder.build().toString());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilderTest.java
new file mode 100644
index 0000000..e7af4bd
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLSelectStatementBuilderTest.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+
+public class JPQLSelectStatementBuilderTest {
+
+  /**
+   * @throws java.lang.Exception
+   */
+  private JPQLSelectStatementBuilder jpqlSelectStatementBuilder;
+
+  @Before
+  public void setUp() throws Exception {
+
+  }
+
+  private JPQLSelectContext createSelectContext(final OrderByExpression orderByExpression, final FilterExpression filterExpression) throws ODataJPARuntimeException, EdmException {
+    //Object Instantiation
+
+    JPQLSelectContext jpqlSelectContextImpl = null;
+    GetEntitySetUriInfo getEntitySetView = EasyMock.createMock(GetEntitySetUriInfo.class);
+
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    List<SelectItem> selectItemList = null;
+
+    //Setting up the expected value
+
+    EasyMock.expect(getEntitySetView.getTargetEntitySet()).andStubReturn(edmEntitySet);
+    EasyMock.expect(getEntitySetView.getOrderBy()).andStubReturn(orderByExpression);
+    EasyMock.expect(getEntitySetView.getSelect()).andStubReturn(selectItemList);
+    EasyMock.expect(getEntitySetView.getFilter()).andStubReturn(filterExpression);
+    EasyMock.replay(getEntitySetView);
+    EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(edmEntityType);
+    EasyMock.replay(edmEntitySet);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("SalesOrderHeader");
+    EasyMock.replay(edmEntityType);
+
+    JPQLContextBuilder contextBuilder1 = JPQLContext.createBuilder(JPQLContextType.SELECT, getEntitySetView);
+    try {
+      jpqlSelectContextImpl = (JPQLSelectContext) contextBuilder1.build();
+    } catch (ODataJPAModelException e) {
+      fail("Model Exception thrown");
+    }
+
+    return jpqlSelectContextImpl;
+  }
+
+  /**
+   * Test method for {@link org.apache.olingo.odata2.processor.jpa.jpql.JPQLSelectStatementBuilder#build)}.
+   * @throws EdmException 
+   * @throws ODataJPARuntimeException 
+   */
+
+  @Test
+  public void testBuildSimpleQuery() throws EdmException, ODataJPARuntimeException {
+    OrderByExpression orderByExpression = EasyMock.createMock(OrderByExpression.class);
+    JPQLSelectContext jpqlSelectContextImpl = createSelectContext(orderByExpression, null);
+    jpqlSelectStatementBuilder = new JPQLSelectStatementBuilder(jpqlSelectContextImpl);
+
+    assertEquals("SELECT E1 FROM SalesOrderHeader E1", jpqlSelectStatementBuilder.build().toString());
+  }
+
+  @Test
+  public void testBuildQueryWithOrderBy() throws EdmException, ODataJPARuntimeException {
+    OrderByExpression orderByExpression = EasyMock.createMock(OrderByExpression.class);
+
+    JPQLSelectContext jpqlSelectContextImpl = createSelectContext(orderByExpression, null);
+    HashMap<String, String> orderByCollection = new HashMap<String, String>();
+    orderByCollection.put("E1.soID", "ASC");
+    orderByCollection.put("E1.buyerId", "DESC");
+    jpqlSelectContextImpl.setOrderByCollection(orderByCollection);
+    jpqlSelectStatementBuilder = new JPQLSelectStatementBuilder(jpqlSelectContextImpl);
+
+    assertEquals("SELECT E1 FROM SalesOrderHeader E1 ORDER BY E1.soID ASC , E1.buyerId DESC", jpqlSelectStatementBuilder.build().toString());
+  }
+
+  @Test
+  public void testBuildQueryWithFilter() throws EdmException, ODataJPARuntimeException {
+    OrderByExpression orderByExpression = EasyMock.createMock(OrderByExpression.class);
+    FilterExpression filterExpression = null;//getFilterExpressionMockedObj();
+    JPQLSelectContext jpqlSelectContextImpl = createSelectContext(orderByExpression, filterExpression);
+    jpqlSelectContextImpl.setWhereExpression("E1.soID >= 1234");
+
+    jpqlSelectStatementBuilder = new JPQLSelectStatementBuilder(jpqlSelectContextImpl);
+
+    assertEquals("SELECT E1 FROM SalesOrderHeader E1 WHERE E1.soID >= 1234", jpqlSelectStatementBuilder.build().toString());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/ODataJPAContextMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/ODataJPAContextMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/ODataJPAContextMock.java
new file mode 100644
index 0000000..da6d075
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/ODataJPAContextMock.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock;
+
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.metamodel.Metamodel;
+
+import org.easymock.EasyMock;
+
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+
+public abstract class ODataJPAContextMock {
+
+  public static final String NAMESPACE = "salesorderprocessing";
+  public static final String MAPPING_MODEL = "SalesOrderProcessingMappingModel";
+  public static final String PERSISTENCE_UNIT_NAME = "salesorderprocessing";
+
+  public static ODataJPAContext mockODataJPAContext()
+  {
+    ODataJPAContext odataJPAContext = EasyMock.createMock(ODataJPAContext.class);
+    EasyMock.expect(odataJPAContext.getPersistenceUnitName()).andStubReturn(NAMESPACE);
+    EasyMock.expect(odataJPAContext.getEntityManagerFactory()).andReturn(mockEntityManagerFactory());
+    EasyMock.expect(odataJPAContext.getJPAEdmMappingModel()).andReturn(MAPPING_MODEL);
+    EasyMock.expect(odataJPAContext.getJPAEdmExtension()).andReturn(null);
+    EasyMock.replay(odataJPAContext);
+    return odataJPAContext;
+  }
+
+  private static EntityManagerFactory mockEntityManagerFactory() {
+    EntityManagerFactory emf = EasyMock.createMock(EntityManagerFactory.class);
+    EasyMock.expect(emf.getMetamodel()).andReturn(mockMetaModel());
+    EasyMock.replay(emf);
+    return emf;
+  }
+
+  private static Metamodel mockMetaModel() {
+    Metamodel metaModel = EasyMock.createMock(Metamodel.class);
+    EasyMock.replay(metaModel);
+    return metaModel;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/EdmSchemaMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/EdmSchemaMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/EdmSchemaMock.java
new file mode 100644
index 0000000..ad3fe5a
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/EdmSchemaMock.java
@@ -0,0 +1,216 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+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.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmMappingImpl;
+
+public class EdmSchemaMock {
+
+  private static final String ASSOCIATION_ROLE_NAME_ONE = "SalesOrderHeader";
+  private static final String ASSOCIATION_NAME = "SalesOrderHeader_SalesOrderItem";
+  private static final String ASSOCIATION_SET_NAME = "SalesOrderHeader_SalesOrderItemSet";
+  private static final String ASSOCIATION_ROLE_NAME_TWO = "SalesOrderItem";
+  private static final String NAMESPACE = "salesorderprocessing";
+  private static final String ENTITY_CONTAINER_NAME = "salesorderprocessingContainer";
+  private static final String ENTITY_NAME_ONE = "SalesOrderHeader";
+  private static final String ENTITY_NAME_TWO = "SalesOrderItem";
+  private static final String ENTITY_SET_NAME_ONE = "SalesOrderHeaders";
+  private static final String FUNCTION_IMPORT_NAME_ONE = "SalesOrder_FunctionImport1";
+  private static final String FUNCTION_IMPORT_NAME_TWO = "SalesOrder_FunctionImport2";
+  private static final String ENTITY_SET_NAME_TWO = "SalesOrderItems";
+  private static final String COMPLEX_TYPE_NAME_ONE = "Address";
+  private static final String COMPLEX_TYPE_NAME_TWO = "SalesOrderItemKey";
+
+  public static Schema createMockEdmSchema()
+  {
+    Schema schema = new Schema();
+    schema.setNamespace(NAMESPACE);
+    schema.setComplexTypes(createComplexTypes());
+    schema.setEntityContainers(createEntityContainer());
+    schema.setEntityTypes(createEntityTypes());
+    schema.setAssociations(createAssociations());
+    return schema;
+  }
+
+  private static List<EntityContainer> createEntityContainer() {
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    EntityContainer entityContainer = new EntityContainer();
+    entityContainer.setDefaultEntityContainer(true);
+    entityContainer.setName(ENTITY_CONTAINER_NAME);
+    entityContainer.setEntitySets(createEntitySets());
+    entityContainer.setAssociationSets(createAssociationSets());
+    entityContainer.setFunctionImports(createFunctionImports());
+    entityContainers.add(entityContainer);
+    return entityContainers;
+  }
+
+  private static List<AssociationSet> createAssociationSets() {
+    List<AssociationSet> associationSets = new ArrayList<AssociationSet>();
+    AssociationSet associationSet = new AssociationSet();
+    associationSet.setName(ASSOCIATION_SET_NAME);
+    associationSet.setAssociation(new FullQualifiedName(NAMESPACE, ASSOCIATION_NAME));
+    associationSet.setEnd1(new AssociationSetEnd().setEntitySet(ENTITY_SET_NAME_ONE)
+        .setRole(ASSOCIATION_ROLE_NAME_ONE));
+    associationSet.setEnd2(new AssociationSetEnd().setEntitySet(ENTITY_SET_NAME_TWO)
+        .setRole(ASSOCIATION_ROLE_NAME_TWO));
+    associationSets.add(associationSet);
+    return associationSets;
+  }
+
+  private static List<EntitySet> createEntitySets() {
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    EntitySet entitySet = new EntitySet();
+    entitySet.setName(ENTITY_SET_NAME_ONE);
+    entitySet.setEntityType(new FullQualifiedName(NAMESPACE, ENTITY_NAME_ONE));
+    entitySets.add(entitySet);
+    entitySet = new EntitySet();
+    entitySet.setName(ENTITY_SET_NAME_TWO);
+    entitySet.setEntityType(new FullQualifiedName(NAMESPACE, ENTITY_NAME_TWO));
+    entitySets.add(entitySet);
+    return entitySets;
+  }
+
+  private static List<FunctionImport> createFunctionImports() {
+    List<FunctionImport> functionImports = new ArrayList<FunctionImport>();
+    FunctionImport functionImport = new FunctionImport();
+    functionImport.setName(FUNCTION_IMPORT_NAME_ONE);
+    functionImports.add(functionImport);
+    functionImport = new FunctionImport();
+    functionImport.setName(FUNCTION_IMPORT_NAME_TWO);
+    functionImports.add(functionImport);
+    return functionImports;
+  }
+
+  private static List<Association> createAssociations() {
+    List<Association> associations = new ArrayList<Association>();
+    Association association = new Association();
+    association.setName(ASSOCIATION_NAME);
+    association.setEnd1(new AssociationEnd().setMultiplicity(EdmMultiplicity.ONE)
+        .setRole(ASSOCIATION_ROLE_NAME_ONE)
+        .setType(new FullQualifiedName(NAMESPACE, ENTITY_NAME_ONE)));
+    association.setEnd2(new AssociationEnd().setMultiplicity(EdmMultiplicity.MANY)
+        .setRole(ASSOCIATION_ROLE_NAME_TWO)
+        .setType(new FullQualifiedName(NAMESPACE, ENTITY_NAME_TWO)));
+    associations.add(association);
+    return associations;
+  }
+
+  private static List<EntityType> createEntityTypes() {
+    List<EntityType> entityTypes = new ArrayList<EntityType>();
+    EntityType entityType = new EntityType();
+    entityType.setName(ENTITY_NAME_ONE);
+    String[] keyNamesOne = { "SoId" };
+    entityType.setKey(createKey(keyNamesOne));
+    entityTypes.add(entityType);
+
+    entityType = new EntityType();
+    entityType.setName(ENTITY_NAME_TWO);
+    String[] keyNamesTwo = { "SoId", "LiId" };
+    entityType.setKey(createKey(keyNamesTwo));
+    entityTypes.add(entityType);
+    return entityTypes;
+
+  }
+
+  private static Key createKey(final String[] keyNames) {
+    Key key = new Key();
+    List<PropertyRef> keys = new ArrayList<PropertyRef>();
+    for (String keyName : keyNames) {
+      keys.add(new PropertyRef().setName(keyName));
+    }
+    key.setKeys(keys);
+    return null;
+  }
+
+  private static List<ComplexType> createComplexTypes() {
+    List<ComplexType> complexTypes = new ArrayList<ComplexType>();
+    ComplexType complexTypeOne = new ComplexType();
+    complexTypeOne.setName(COMPLEX_TYPE_NAME_ONE);
+    complexTypeOne.setProperties(createComplexTypePropertiesOne());
+    complexTypes.add(complexTypeOne);
+    ComplexType complexTypeTwo = new ComplexType();
+    complexTypeTwo.setName(COMPLEX_TYPE_NAME_TWO);
+    complexTypeTwo.setProperties(createComplexTypePropertiesTwo());
+    complexTypes.add(complexTypeTwo);
+    return complexTypes;
+  }
+
+  private static List<Property> createComplexTypePropertiesTwo() {
+    List<Property> properties = new ArrayList<Property>();
+    SimpleProperty property = new SimpleProperty();
+    property.setName("SoId");
+    property.setType(EdmSimpleTypeKind.Int64);
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    mapping.setJPAColumnName("Sales_Order_Id");
+    ((Mapping) mapping).setInternalName("SalesOrderItemKey.SoId");
+    property.setMapping((Mapping) mapping);
+    properties.add(property);
+    property = new SimpleProperty();
+    property.setName("LiId");
+    property.setType(EdmSimpleTypeKind.Int64);
+    mapping = new JPAEdmMappingImpl();
+    mapping.setJPAColumnName("Sales_Order_Item_Id");
+    property.setMapping((Mapping) mapping);
+    properties.add(property);
+    return properties;
+
+  }
+
+  private static List<Property> createComplexTypePropertiesOne() {
+    List<Property> properties = new ArrayList<Property>();
+    SimpleProperty property = new SimpleProperty();
+    property.setName("StreetName");
+    property.setType(EdmSimpleTypeKind.String);
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    mapping.setJPAColumnName("STREET_NAME");
+    property.setMapping((Mapping) mapping);
+    properties.add(property);
+    property = new SimpleProperty();
+    property.setName("City");
+    property.setType(EdmSimpleTypeKind.String);
+    mapping = new JPAEdmMappingImpl();
+    mapping.setJPAColumnName("CITY");
+    property.setMapping((Mapping) mapping);
+    properties.add(property);
+    return properties;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAAttributeMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAAttributeMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAAttributeMock.java
new file mode 100644
index 0000000..0ec7610
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPAAttributeMock.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.lang.reflect.Member;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
+
+public abstract class JPAAttributeMock<X, Y> implements Attribute<X, Y> {
+
+  @Override
+  public ManagedType<X> getDeclaringType() {
+    return null;
+  }
+
+  @Override
+  public Member getJavaMember() {
+    return null;
+  }
+
+  @Override
+  public Class<Y> getJavaType() {
+    return null;
+  }
+
+  @Override
+  public String getName() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.Attribute.PersistentAttributeType getPersistentAttributeType() {
+    return null;
+  }
+
+  @Override
+  public boolean isAssociation() {
+    return false;
+  }
+
+  @Override
+  public boolean isCollection() {
+    return false;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorMock.java
new file mode 100644
index 0000000..eb99b4a
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorMock.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.annotation.edm.Facets;
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport;
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport.Multiplicity;
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport.ReturnType;
+import org.apache.olingo.odata2.api.annotation.edm.Parameter;
+import org.apache.olingo.odata2.api.annotation.edm.Parameter.Mode;
+
+public class JPACustomProcessorMock {
+
+  public static final String className = "JPACustomProcessorMock";
+  public static final String edmName = "JPACustomProcessor";
+
+  @FunctionImport(name = "Method1", entitySet = "MockSet", returnType = ReturnType.ENTITY_TYPE, multiplicity = Multiplicity.MANY)
+  public List<JPACustomProcessorMock> method1(
+      @Parameter(name = "Param1", facets = @Facets(nullable = true, maxLength = 2), mode = Mode.IN) final String param1,
+      final int param2,
+      @Parameter(name = "Param3", facets = @Facets(precision = 10, scale = 2), mode = Mode.IN) final double param3) {
+    return new ArrayList<JPACustomProcessorMock>();
+  }
+
+  @FunctionImport(name = "Method2", entitySet = "MockSet", returnType = ReturnType.ENTITY_TYPE, multiplicity = Multiplicity.MANY)
+  public List<JPACustomProcessorMock> method2(
+      @Parameter(facets = @Facets(maxLength = 2), name = "Param2") final String param2) {
+    return new ArrayList<JPACustomProcessorMock>();
+  }
+
+  @FunctionImport(returnType = ReturnType.SCALAR)
+  public int method3(@Parameter(name = "Param3") final String param3) {
+    return 0;
+  }
+
+  @FunctionImport(returnType = ReturnType.NONE)
+  public void method4() {
+    return;
+  }
+
+  @FunctionImport(returnType = ReturnType.ENTITY_TYPE, entitySet = "MockSet", multiplicity = Multiplicity.ONE)
+  public JPACustomProcessorMock method7() {
+    return null;
+  }
+
+  @FunctionImport(returnType = ReturnType.COMPLEX_TYPE, multiplicity = Multiplicity.ONE)
+  public JPACustomProcessorMock method9() {
+    return null;
+  }
+
+  @FunctionImport(returnType = ReturnType.COMPLEX_TYPE, multiplicity = Multiplicity.MANY)
+  public List<JPACustomProcessorMock> method10() {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorNegativeMock.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorNegativeMock.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorNegativeMock.java
new file mode 100644
index 0000000..b5e560a
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/mock/model/JPACustomProcessorNegativeMock.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.mock.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport;
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport.Multiplicity;
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport.ReturnType;
+import org.apache.olingo.odata2.api.annotation.edm.Parameter;
+
+public class JPACustomProcessorNegativeMock {
+
+  @FunctionImport(returnType = ReturnType.ENTITY_TYPE, multiplicity = Multiplicity.MANY)
+  public List<JPACustomProcessorNegativeMock> method5() {
+    return null;
+  }
+
+  @FunctionImport(returnType = ReturnType.ENTITY_TYPE, entitySet = "MockSet", multiplicity = Multiplicity.MANY)
+  public void method6() {
+    return;
+  }
+
+  @FunctionImport(returnType = ReturnType.ENTITY_TYPE, entitySet = "MockSet", multiplicity = Multiplicity.MANY)
+  public JPACustomProcessorNegativeMock method8() {
+    return null;
+  }
+
+  @FunctionImport(returnType = ReturnType.COMPLEX_TYPE, multiplicity = Multiplicity.ONE)
+  public JPACustomProcessorNegativeMock method11() {
+    return null;
+  }
+
+  @FunctionImport(returnType = ReturnType.SCALAR, multiplicity = Multiplicity.ONE)
+  public JPACustomProcessorMock method12() {
+    return null;
+  }
+
+  @FunctionImport(returnType = ReturnType.SCALAR, multiplicity = Multiplicity.ONE)
+  public int method13(@Parameter(name = "") final int y) {
+    return 0;
+  }
+
+  @FunctionImport(returnType = ReturnType.SCALAR, multiplicity = Multiplicity.ONE)
+  public void method16(@Parameter(name = "") final int y) {
+    return;
+  }
+
+  @FunctionImport(returnType = ReturnType.COMPLEX_TYPE, multiplicity = Multiplicity.ONE)
+  public void method17(@Parameter(name = "") final int y) {
+    return;
+  }
+}


[31/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Schema.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Schema.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Schema.java
new file mode 100644
index 0000000..9a62330
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Schema.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent a schema
+ * @author SAP AG
+ */
+public class Schema {
+
+  private String namespace;
+  private String alias;
+  private List<Using> usings;
+  private List<EntityType> entityTypes;
+  private List<ComplexType> complexTypes;
+  private List<Association> associations;
+  private List<EntityContainer> entityContainers;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * Sets the namespace for this {@link Schema}
+   * @param namespace
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the alias for this {@link Schema}
+   * @param alias
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setAlias(final String alias) {
+    this.alias = alias;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Using} for this {@link Schema}
+   * @param usings
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setUsings(final List<Using> usings) {
+    this.usings = usings;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EntityType}s for this {@link Schema}
+   * @param entityTypes
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setEntityTypes(final List<EntityType> entityTypes) {
+    this.entityTypes = entityTypes;
+    return this;
+  }
+
+  /**
+   * Sets the {@link ComplexType}s for this {@link Schema}
+   * @param complexTypes
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setComplexTypes(final List<ComplexType> complexTypes) {
+    this.complexTypes = complexTypes;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Association}s for this {@link Schema}
+   * @param associations
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setAssociations(final List<Association> associations) {
+    this.associations = associations;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EntityContainer}s for this {@link Schema}
+   * @param entityContainers
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setEntityContainers(final List<EntityContainer> entityContainers) {
+    this.entityContainers = entityContainers;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link Schema}
+   * @param annotationAttributes
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link Schema}
+   * @param annotationElements
+   * @return {@link Schema} for method chaining
+   */
+  public Schema setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+
+  /**
+   * @return <b>String</b> namespace of this {@link Schema}
+   */
+  public String getNamespace() {
+    return namespace;
+  }
+
+  /**
+   * @return <b>String</b> alias of this {@link Schema}
+   */
+  public String getAlias() {
+    return alias;
+  }
+
+  /**
+   * @return List<{@link Using}> of this {@link Schema}
+   */
+  public List<Using> getUsings() {
+    return usings;
+  }
+
+  /**
+   * @return List<{@link EntityType}> of this {@link Schema}
+   */
+  public List<EntityType> getEntityTypes() {
+    return entityTypes;
+  }
+
+  /**
+   * @return List<{@link ComplexType}> of this {@link Schema}
+   */
+  public List<ComplexType> getComplexTypes() {
+    return complexTypes;
+  }
+
+  /**
+   * @return List<{@link Association}> of this {@link Schema}
+   */
+  public List<Association> getAssociations() {
+    return associations;
+  }
+
+  /**
+   * @return List<{@link EntityContainer}> of this {@link Schema}
+   */
+  public List<EntityContainer> getEntityContainers() {
+    return entityContainers;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/SimpleProperty.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/SimpleProperty.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/SimpleProperty.java
new file mode 100644
index 0000000..0cfb01f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/SimpleProperty.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+
+/**
+ * Objects of this class represent a simple property.
+ * @author SAP AG
+ */
+public class SimpleProperty extends Property {
+
+  private EdmSimpleTypeKind type;
+
+  /**
+   * @return {@link EdmSimpleTypeKind} of this property
+   */
+  public EdmSimpleTypeKind getType() {
+    return type;
+  }
+
+  /**
+   * Sets the {@link EdmSimpleTypeKind} for this {@link Property}.
+   * @param type
+   * @return {@link Property} for method chaining
+   */
+  public SimpleProperty setType(final EdmSimpleTypeKind type) {
+    this.type = type;
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setName(final String name) {
+    super.setName(name);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setFacets(final EdmFacets facets) {
+    super.setFacets(facets);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setCustomizableFeedMappings(final CustomizableFeedMappings customizableFeedMappings) {
+    super.setCustomizableFeedMappings(customizableFeedMappings);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setMimeType(final String mimeType) {
+    super.setMimeType(mimeType);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setMapping(final Mapping mapping) {
+    super.setMapping(mapping);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setDocumentation(final Documentation documentation) {
+    super.setDocumentation(documentation);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    super.setAnnotationAttributes(annotationAttributes);
+    return this;
+  }
+
+  @Override
+  public SimpleProperty setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    super.setAnnotationElements(annotationElements);
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Using.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Using.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Using.java
new file mode 100644
index 0000000..fbf908f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Using.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author SAP AG
+ */
+public class Using {
+
+  private String namespace;
+  private String alias;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * Sets the namespace for this {@link Using}
+   * @param namespace
+   * @return {@link Using} for method chaining
+   */
+  public Using setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the alias for this {@link Using}
+   * @param alias
+   * @return {@link Using} for method chaining
+   */
+  public Using setAlias(final String alias) {
+    this.alias = alias;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link Using}
+   * @param documentation
+   * @return {@link Using} for method chaining
+   */
+  public Using setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link Using}
+   * @param annotationAttributes
+   * @return {@link Using} for method chaining
+   */
+  public Using setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link Using}
+   * @param annotationElements
+   * @return {@link Using} for method chaining
+   */
+  public Using setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+
+  /**
+   * @return <b>String</b> namespace
+   */
+  public String getNamespace() {
+    return namespace;
+  }
+
+  /**
+   * @return <b>String</b> alias
+   */
+  public String getAlias() {
+    return alias;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public Collection<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public Collection<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/package-info.java
new file mode 100644
index 0000000..3e4324c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/package-info.java
@@ -0,0 +1,287 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Entity Data Model Provider API
+ * <p>Classes in this package are used to provide an EDM to the library as well as to the application. To do this the class {@link org.apache.olingo.odata2.api.edm.provider.EdmProvider} has to be implemented.</p>
+ * <p>Inside the OData library we are using a lazy loading concept which means the EdmProvider is only called for an element if it is needed. See some sample coding for an EdmProvider below</p>
+ * <p>public class Provider extends EdmProvider {
+  <p>public static final String NAMESPACE_1 = "RefScenario";
+  <br/>public static final String NAMESPACE_2 = "RefScenario2";
+  <br/>private static final FullQualifiedName ENTITY_TYPE_1_1 = new FullQualifiedName(NAMESPACE_1, "Employee");
+  <br/>private static final FullQualifiedName ENTITY_TYPE_1_BASE = new FullQualifiedName(NAMESPACE_1, "Base");
+  <br/>private static final FullQualifiedName ENTITY_TYPE_1_4 = new FullQualifiedName(NAMESPACE_1, "Manager");
+  <br/>private static final FullQualifiedName ENTITY_TYPE_2_1 = new FullQualifiedName(NAMESPACE_2, "Photo");
+  <br/>private static final FullQualifiedName COMPLEX_TYPE_1 = new FullQualifiedName(NAMESPACE_1, "c_Location");
+  <br/>private static final FullQualifiedName COMPLEX_TYPE_2 = new FullQualifiedName(NAMESPACE_1, "c_City");
+  <br/>private static final FullQualifiedName ASSOCIATION_1_1 = new FullQualifiedName(NAMESPACE_1, "ManagerEmployees");
+  <br/>private static final String ROLE_1_1 = "r_Employees";
+  <br/>private static final String ROLE_1_4 = "r_Manager";
+  <br/>private static final String ENTITY_CONTAINER_1 = "Container1";
+  <br/>private static final String ENTITY_CONTAINER_2 = "Container2";
+  <br/>private static final String ENTITY_SET_1_1 = "Employees";
+  <br/>private static final String ENTITY_SET_1_4 = "Managers";
+  <br/>private static final String ENTITY_SET_2_1 = "Photos";
+  <br/>private static final String FUNCTION_IMPORT_1 = "EmployeeSearch";
+  <br/>private static final String FUNCTION_IMPORT_2 = "AllLocations";
+  </p>
+  <p>public List<Schema> getSchemas() throws ODataException {
+    <p>List<Schema> schemas = new ArrayList<Schema>();
+    <br/>Schema schema = new Schema();
+    <br/>schema.setNamespace(NAMESPACE_1);
+
+    <br/>List<EntityType> entityTypes = new ArrayList<EntityType>();
+    <br/>entityTypes.add(getEntityType(ENTITY_TYPE_1_1));
+    <br/>entityTypes.add(getEntityType(ENTITY_TYPE_1_4));
+    <br/>entityTypes.add(getEntityType(ENTITY_TYPE_1_BASE));
+    <br/>schema.setEntityTypes(entityTypes);
+
+    <br/>List<ComplexType> complexTypes = new ArrayList<ComplexType>();
+    <br/>complexTypes.add(getComplexType(COMPLEX_TYPE_1));
+    <br/>complexTypes.add(getComplexType(COMPLEX_TYPE_2));
+    <br/>schema.setComplexTypes(complexTypes);
+
+    <br/>List<Association> associations = new ArrayList<Association>();
+    <br/>associations.add(getAssociation(ASSOCIATION_1_1));
+    <br/>schema.setAssociations(associations);
+
+    <br/>EntityContainer entityContainer = new EntityContainer();
+    <br/>entityContainer.setName(ENTITY_CONTAINER_1).setDefaultEntityContainer(true);
+
+    <br/>List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    <br/>entitySets.add(getEntitySet(ENTITY_CONTAINER_1, ENTITY_SET_1_1));
+    <br/>entitySets.add(getEntitySet(ENTITY_CONTAINER_1, ENTITY_SET_1_4));
+    <br/>entityContainer.setEntitySets(entitySets);
+
+    <br/>List<AssociationSet> associationSets = new ArrayList<AssociationSet>();
+    <br/>associationSets.add(getAssociationSet(ENTITY_CONTAINER_1, ASSOCIATION_1_1, ENTITY_SET_1_4, ROLE_1_4));
+    <br/>entityContainer.setAssociationSets(associationSets);
+
+    <br/>List<FunctionImport> functionImports = new ArrayList<FunctionImport>();
+    <br/>functionImports.add(getFunctionImport(ENTITY_CONTAINER_1, FUNCTION_IMPORT_1));
+    <br/>functionImports.add(getFunctionImport(ENTITY_CONTAINER_1, FUNCTION_IMPORT_2));
+    <br/>entityContainer.setFunctionImports(functionImports);
+
+    <br/>schema.setEntityContainers(Arrays.asList(entityContainer));
+
+    <br/>schemas.add(schema);
+    </p>
+    <p>schema = new Schema();
+    <br/>schema.setNamespace(NAMESPACE_2);
+
+    <br/>schema.setEntityTypes(Arrays.asList(getEntityType(ENTITY_TYPE_2_1)));
+
+    <br/>entityContainer = new EntityContainer();
+    <br/>entityContainer.setName(ENTITY_CONTAINER_2);
+    <br/>entityContainer.setEntitySets(Arrays.asList(getEntitySet(ENTITY_CONTAINER_2, ENTITY_SET_2_1)));
+    <br/>schema.setEntityContainers(Arrays.asList(entityContainer));
+
+    <br/>schemas.add(schema);
+</p>
+    <p>return schemas;</p>
+  }
+
+  <p>public EntityType getEntityType(FullQualifiedName edmFQName) throws ODataException {
+    <p>if (NAMESPACE_1.equals(edmFQName.getNamespace())) {
+      <br/>if (ENTITY_TYPE_1_1.getName().equals(edmFQName.getName())) {
+        <br/>List<Property> properties = new ArrayList<Property>();
+        <br/>properties.add(new SimpleProperty().setName("EmployeeId").setType(EdmSimpleTypeKind.String)
+            .setFacets(new Facets().setNullable(false))
+            .setMapping(new Mapping().setInternalName("getId")));
+        <br/>properties.add(new SimpleProperty().setName("EmployeeName").setType(EdmSimpleTypeKind.String)
+            .setCustomizableFeedMappings(new CustomizableFeedMappings()
+                .setFcTargetPath(EdmTargetPath.SYNDICATION_TITLE)));
+        <br/>properties.add(new SimpleProperty().setName("ManagerId").setType(EdmSimpleTypeKind.String)
+            .setMapping(new Mapping().setInternalName("getManager.getId")));
+        <br/>properties.add(new SimpleProperty().setName("RoomId").setType(EdmSimpleTypeKind.String)
+            .setMapping(new Mapping().setInternalName("getRoom.getId")));
+        <br/>properties.add(new SimpleProperty().setName("TeamId").setType(EdmSimpleTypeKind.String)
+            .setFacets(new Facets().setMaxLength(2))
+            .setMapping(new Mapping().setInternalName("getTeam.getId")));
+        <br/>properties.add(new ComplexProperty().setName("Location").setType(COMPLEX_TYPE_1)
+            .setFacets(new Facets().setNullable(false)));
+        <br/>properties.add(new SimpleProperty().setName("Age").setType(EdmSimpleTypeKind.Int16));
+        <br/>properties.add(new SimpleProperty().setName("EntryDate").setType(EdmSimpleTypeKind.DateTime)
+            .setFacets(new Facets().setNullable(true))
+            .setCustomizableFeedMappings(new CustomizableFeedMappings()
+                .setFcTargetPath(EdmTargetPath.SYNDICATION_UPDATED)));
+        <br/>properties.add(new SimpleProperty().setName("ImageUrl").setType(EdmSimpleTypeKind.String)
+            .setMapping(new Mapping().setInternalName("getImageUri")));
+        <br/>List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
+        <br/>navigationProperties.add(new NavigationProperty().setName("ne_Manager")
+            .setRelationship(ASSOCIATION_1_1).setFromRole(ROLE_1_1).setToRole(ROLE_1_4));
+
+        <br/>return new EntityType().setName(ENTITY_TYPE_1_1.getName())
+            .setProperties(properties)
+            .setHasStream(true)
+            .setKey(getKey("EmployeeId"))
+            .setNavigationProperties(navigationProperties)
+            .setMapping(new Mapping().setMimeType("getImageType"));
+
+      <p>} else if (ENTITY_TYPE_1_BASE.getName().equals(edmFQName.getName())) {
+        <br/>List<Property> properties = new ArrayList<Property>();
+        <br/>properties.add(new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.String)
+            .setFacets(new Facets().setNullable(false).setDefaultValue("1")));
+        <br/>properties.add(new SimpleProperty().setName("Name").setType(EdmSimpleTypeKind.String)
+            .setCustomizableFeedMappings(new CustomizableFeedMappings()
+                .setFcTargetPath(EdmTargetPath.SYNDICATION_TITLE)));
+
+        <br/>return new EntityType().setName(ENTITY_TYPE_1_BASE.getName())
+            .setAbstract(true)
+            .setProperties(properties)
+            .setKey(getKey("Id"));
+
+      <p>} else if (ENTITY_TYPE_1_4.getName().equals(edmFQName.getName())) {
+        <br/>List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
+        <br/>navigationProperties.add(new NavigationProperty().setName("nm_Employees")
+            .setRelationship(ASSOCIATION_1_1).setFromRole(ROLE_1_4).setToRole(ROLE_1_1));
+
+        <br/>return new EntityType().setName(ENTITY_TYPE_1_4.getName())
+            .setBaseType(ENTITY_TYPE_1_1)
+            .setHasStream(true)
+            .setNavigationProperties(navigationProperties)
+            .setMapping(new Mapping().setMimeType("getImageType"));
+
+      <p>} else if (NAMESPACE_2.equals(edmFQName.getNamespace())) {
+        <br/>if (ENTITY_TYPE_2_1.getName().equals(edmFQName.getName())) {
+          <br/>List<Property> properties = new ArrayList<Property>();
+          <br/>properties.add(new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.Int32)
+              .setFacets(new Facets().setNullable(false).setConcurrencyMode(EdmConcurrencyMode.Fixed)));
+          <br/>properties.add(new SimpleProperty().setName("Name").setType(EdmSimpleTypeKind.String)
+              .setCustomizableFeedMappings(new CustomizableFeedMappings()
+                  .setFcTargetPath(EdmTargetPath.SYNDICATION_TITLE)));
+          <br/>properties.add(new SimpleProperty().setName("Type").setType(EdmSimpleTypeKind.String)
+              .setFacets(new Facets().setNullable(false)));
+          <br/>properties.add(new SimpleProperty().setName("ImageUrl").setType(EdmSimpleTypeKind.String)
+              .setCustomizableFeedMappings(new CustomizableFeedMappings()
+                  .setFcTargetPath(EdmTargetPath.SYNDICATION_AUTHORURI))
+              .setMapping(new Mapping().setInternalName("getImageUri")));
+          <br/>properties.add(new SimpleProperty().setName("Image").setType(EdmSimpleTypeKind.Binary)
+              .setMapping(new Mapping().setMimeType("getImageType")));
+          <br/>properties.add(new SimpleProperty().setName("BinaryData").setType(EdmSimpleTypeKind.Binary)
+              .setFacets(new Facets().setNullable(true))
+              .setMimeType("image/jpeg"));
+          <br/>properties.add(new SimpleProperty().setName("Содержание").setType(EdmSimpleTypeKind.String)
+              .setFacets(new Facets().setNullable(true))
+              .setCustomizableFeedMappings(new CustomizableFeedMappings()
+                  .setFcKeepInContent(false)
+                  .setFcNsPrefix("ру") // CYRILLIC SMALL LETTER ER + CYRILLIC SMALL LETTER U
+                  .setFcNsUri("http://localhost")
+                  .setFcTargetPath("Содержание"))
+              .setMapping(new Mapping().setInternalName("getContent")));
+
+          <br/>return new EntityType().setName(ENTITY_TYPE_2_1.getName())
+              .setProperties(properties)
+              .setHasStream(true)
+              .setKey(getKey("Id", "Type"))
+              .setMapping(new Mapping().setMimeType("getType"));
+        }
+      }
+    }
+    <p>return null;
+  }
+
+  <p>public ComplexType getComplexType(FullQualifiedName edmFQName) throws ODataException {
+    <br/>if (NAMESPACE_1.equals(edmFQName.getNamespace()))
+      <br/>if (COMPLEX_TYPE_1.getName().equals(edmFQName.getName())) {
+        <br/>List<Property> properties = new ArrayList<Property>();
+        <br/>properties.add(new ComplexProperty().setName("City").setType(COMPLEX_TYPE_2));
+        <br/>properties.add(new SimpleProperty().setName("Country").setType(EdmSimpleTypeKind.String));
+        <br/>return new ComplexType().setName(COMPLEX_TYPE_1.getName()).setProperties(properties);
+
+      } <br/>else if (COMPLEX_TYPE_2.getName().equals(edmFQName.getName())) {
+        <br/>List<Property> properties = new ArrayList<Property>();
+        <br/>properties.add(new SimpleProperty().setName("PostalCode").setType(EdmSimpleTypeKind.String));
+        <br/>properties.add(new SimpleProperty().setName("CityName").setType(EdmSimpleTypeKind.String));
+        <br/>return new ComplexType().setName(COMPLEX_TYPE_2.getName()).setProperties(properties);
+      }
+
+    <br/>return null;
+  }
+
+  <p>public Association getAssociation(FullQualifiedName edmFQName) throws ODataException {
+    <br/>if (NAMESPACE_1.equals(edmFQName.getNamespace())) {
+      <br/>if (ASSOCIATION_1_1.getName().equals(edmFQName.getName())) {
+        <br/>return new Association().setName(ASSOCIATION_1_1.getName())
+            .setEnd1(new AssociationEnd().setType(ENTITY_TYPE_1_1).setRole(ROLE_1_1).setMultiplicity(EdmMultiplicity.MANY))
+            .setEnd2(new AssociationEnd().setType(ENTITY_TYPE_1_4).setRole(ROLE_1_4).setMultiplicity(EdmMultiplicity.ONE));
+      }
+    }
+    <br/>return null;
+  }
+
+  <p>public EntityContainerInfo getEntityContainerInfo(String name) throws ODataException {
+    <br/>if (name == null || ENTITY_CONTAINER_1.equals(name)) {
+      <br/>return new EntityContainerInfo().setName(ENTITY_CONTAINER_1).setDefaultEntityContainer(true);
+    } <br/>else if (ENTITY_CONTAINER_2.equals(name)) {
+      <br/>return new EntityContainerInfo().setName(name).setDefaultEntityContainer(false);
+    }
+    <br/>return null;
+  }
+
+  <p>public EntitySet getEntitySet(String entityContainer, String name) throws ODataException {
+    <br/>if (ENTITY_CONTAINER_1.equals(entityContainer)) {
+      <br/>if (ENTITY_SET_1_1.equals(name)) {
+        <br/>return new EntitySet().setName(name).setEntityType(ENTITY_TYPE_1_1);
+      }
+    } <br/>else if (ENTITY_CONTAINER_2.equals(entityContainer)) {
+      <br/>if (ENTITY_SET_2_1.equals(name)) {
+        <br/>return new EntitySet().setName(name).setEntityType(ENTITY_TYPE_2_1);
+      }
+    }
+    <br/>return null;
+  }
+
+  <p>public FunctionImport getFunctionImport(String entityContainer, String name) throws ODataException {
+    <br/>if (ENTITY_CONTAINER_1.equals(entityContainer)) {
+      <br/>if (FUNCTION_IMPORT_1.equals(name)) {
+        <br/>List<FunctionImportParameter> parameters = new ArrayList<FunctionImportParameter>();
+        <br/>parameters.add(new FunctionImportParameter().setName("q").setType(EdmSimpleTypeKind.String)
+            .setFacets(new Facets().setNullable(true)));
+        <br/>return new FunctionImport().setName(name)
+            .setReturnType(new ReturnType().setTypeName(ENTITY_TYPE_1_1).setMultiplicity(EdmMultiplicity.MANY))
+            .setEntitySet(ENTITY_SET_1_1)
+            .setHttpMethod("GET")
+            .setParameters(parameters);
+
+      } <br/>else if (FUNCTION_IMPORT_2.equals(name)) {
+        <br/>return new FunctionImport().setName(name)
+            .setReturnType(new ReturnType().setTypeName(COMPLEX_TYPE_1).setMultiplicity(EdmMultiplicity.MANY))
+            .setHttpMethod("GET");
+
+      }
+    }
+
+    <br/>return null;
+  }
+
+  <p>public AssociationSet getAssociationSet(String entityContainer, FullQualifiedName association, String sourceEntitySetName, String sourceEntitySetRole) throws ODataException {
+    <br/>if (ENTITY_CONTAINER_1.equals(entityContainer))
+      <br/>if (ASSOCIATION_1_1.equals(association))
+        <br/>return new AssociationSet().setName(ASSOCIATION_1_1.getName())
+            .setAssociation(ASSOCIATION_1_1)
+            .setEnd1(new AssociationSetEnd().setRole(ROLE_1_4).setEntitySet(ENTITY_SET_1_4))
+            .setEnd2(new AssociationSetEnd().setRole(ROLE_1_1).setEntitySet(ENTITY_SET_1_1));
+
+    <br/>return null;
+  }
+}
+</p>
+ */
+package org.apache.olingo.odata2.api.edm.provider;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
new file mode 100644
index 0000000..724c967
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProvider.java
@@ -0,0 +1,698 @@
+/*******************************************************************************
+ * 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.api.ep;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+
+/**
+ * <p>Entity Provider</p> 
+ * <p>An {@link EntityProvider} provides all necessary <b>read</b> and <b>write</b>
+ * methods for accessing the entities defined in an <code>Entity Data Model</code>.
+ * Therefore this library provides (in its <code>core</code> packages) as convenience
+ * basic entity providers for accessing entities in the <b>XML</b> and <b>JSON</b>
+ * formats.</p>
+ * @author SAP AG
+ */
+public final class EntityProvider {
+
+  /**
+   * (Internal) interface for all {@link EntityProvider} necessary <b>read</b> and <b>write</b> methods for accessing 
+   * entities defined in an <code>Entity Data Model</code>.
+   * <p>
+   * This interface is declared as inner interface (class) because the {@link EntityProvider} provides a convenience
+   * access (and basic implementation for <b>XML</b> and <b>JSON</b> format) to all interface methods.
+   * <br/>
+   * Hence, it is <b>not recommended</b> to implement this interface (it is possible to implement it and to provide an 
+   * own {@link EntityProvider} for support of additional formats but it is recommended to
+   * handle additional formats directly within an <code>ODataProcessor</code>).
+   */
+  public interface EntityProviderInterface {
+
+    /**
+     * Write metadata document in XML format for the given schemas and the provided predefined 
+     * namespaces at the EDMX element. PredefinedNamespaces is of type 
+     * Map{@literal <}prefix,namespace{@literal >} and may be null or an empty Map.
+     * 
+     * @param schemas all XML schemas which will be written
+     * @param predefinedNamespaces type of Map{@literal <}prefix,namespace{@literal >} and may be null or an empty Map
+     * @return resulting {@link ODataResponse} with written metadata content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeMetadata(List<Schema> schemas, Map<String, String> predefinedNamespaces) throws EntityProviderException;
+
+    /**
+     * Write service document based on given {@link Edm} and <code>service root</code> as
+     * given content type.
+     * 
+     * @param contentType format in which service document should be written
+     * @param edm entity data model to be written
+     * @param serviceRoot service root for the written service document
+     * @return resulting {@link ODataResponse} with written service document content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeServiceDocument(String contentType, Edm edm, String serviceRoot) throws EntityProviderException;
+
+    /**
+     * Write property as content type <code>application/octet-stream</code> or <code>text/plain</code>.
+     * 
+     * @param edmProperty entity data model for to be written property
+     * @param value property which will be written
+     * @return resulting {@link ODataResponse} with written property value content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writePropertyValue(EdmProperty edmProperty, Object value) throws EntityProviderException;
+
+    /**
+     * Write text value as content type <code>text/plain</code>.
+     * 
+     * @param value text value which will be written
+     * @return resulting {@link ODataResponse} with written text/plain content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeText(String value) throws EntityProviderException;
+
+    /**
+     * Write binary content with content type header set to given <code>mime type</code> parameter.
+     * 
+     * @param mimeType mime type which is written and used as content type header information.
+     * @param data which is written to {@link ODataResponse}.
+     * @return response object resulting {@link ODataResponse} with written binary content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeBinary(String mimeType, byte[] data) throws EntityProviderException;
+
+    /**
+     * Write given <code>data</code> (which is given in form of a {@link List} with a {@link Map} for each entity. Such a {@link Map}
+     * contains all properties [as <code>property name</code> to <code>property value</code> mapping] for the entry) in the specified
+     * format (given as <code>contentType</code>) based on given <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+     * and <code>properties</code> for this entity provider (given as {@link EntityProviderWriteProperties}).
+     * 
+     * @param contentType format in which the feed should be written
+     * @param entitySet entity data model for given entity data set
+     * @param data set of entries in form of a {@link List} with a {@link Map} for each entity (such a {@link Map}
+     *              contains all properties [as <code>property name</code> to <code>property value</code> mapping).
+     * @param properties additional properties necessary for writing of data 
+     * @return resulting {@link ODataResponse} with written feed content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeFeed(String contentType, EdmEntitySet entitySet, List<Map<String, Object>> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+    /**
+     * Write given <code>data</code> (which is given in form of a {@link Map} for which contains all properties 
+     * as <code>property name</code> to <code>property value</code> mapping) for the entry in the specified
+     * format (given as <code>contentType</code>) based on <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+     * and <code>properties</code> for this entity provider (given as {@link EntityProviderWriteProperties}).
+     * 
+     * @param contentType format in which the entry should be written
+     * @param entitySet entity data model for given entity data set
+     * @param data which contains all properties as <code>property name</code> to <code>property value</code> mapping for the entry
+     * @param properties additional properties necessary for writing of data 
+     * @return resulting {@link ODataResponse} with written entry content
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeEntry(String contentType, EdmEntitySet entitySet, Map<String, Object> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+    /**
+     * Write given <code>value</code> (which is given in form of an {@link Object}) for the property in the specified
+     * format (given as <code>contentType</code>) based on given <code>entity data model for an entity property</code> 
+     * (given as {@link EdmProperty}).
+     * 
+     * @param contentType format in which the property should be written
+     * @param edmProperty entity data model for given property
+     * @param value data which is written
+     * @return resulting {@link ODataResponse} with written property content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeProperty(String contentType, EdmProperty edmProperty, Object value) throws EntityProviderException;
+
+    /**
+     * Write <b>link</b> for key property based on <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+     * in the specified format (given as <code>contentType</code>).
+     * The necessary key property values must be provided within the <code>data</code> (in the form of <code>property name</code>
+     * to <code>property value</code> mapping) and <code>properties</code> for this entity provider must be set
+     * (given as {@link EntityProviderWriteProperties}).
+     * 
+     * @param contentType format in which the entry should be written
+     * @param entitySet entity data model for given entity data set
+     * @param data which contains all key properties as <code>property name</code> to <code>property value</code> mapping for the entry
+     * @param properties additional properties necessary for writing of data 
+     * @return resulting {@link ODataResponse} with written link content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeLink(String contentType, EdmEntitySet entitySet, Map<String, Object> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+    /**
+     * Write all <b>links</b> for key property based on <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+     * in the specified format (given as <code>contentType</code>) for a set of entries.
+     * The necessary key property values must be provided within the <code>data</code> (in form of a {@link List} with a {@link Map} 
+     * for each entry. Such a {@link Map} contains all key properties [as <code>property name</code> to 
+     * <code>property value</code> mapping] for the entry) and <code>properties</code> for this entity provider must be set
+     * (given as {@link EntityProviderWriteProperties}).
+     * 
+     * @param contentType format in which the entry should be written
+     * @param entitySet entity data model for given entity data set
+     * @param data set of entries in form of a {@link List} with a {@link Map} for each entry (such a {@link Map}
+     *              contains all key properties [as <code>property name</code> to <code>property value</code> mapping).
+     * @param properties additional properties necessary for writing of data 
+     * @return resulting {@link ODataResponse} with written links content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeLinks(String contentType, EdmEntitySet entitySet, List<Map<String, Object>> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+    /**
+     * Write <code>data</code> result (given as {@link Object}) of function import based on <code>return type</code> 
+     * of {@link EdmFunctionImport} in specified format (given as <code>contentType</code>). Additional <code>properties</code> 
+     * for this entity provider must be set (given as {@link EntityProviderWriteProperties}).
+     * 
+     * @param contentType format in which the entry should be written
+     * @param functionImport entity data model for executed function import
+     * @param data result of function import
+     * @param properties additional properties necessary for writing of data 
+     * @return resulting {@link ODataResponse} with written function import result content.
+     * @throws EntityProviderException if writing of data (serialization) fails
+     */
+    ODataResponse writeFunctionImport(String contentType, EdmFunctionImport functionImport, Object data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) a data feed from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+     * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide this data as {@link ODataEntry}.
+     * 
+     * @param contentType format of content in the given input stream.
+     * @param entitySet entity data model for entity set to be read
+     * @param content feed data in form of an {@link InputStream} which contains the data in specified format
+     * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}.
+     * @return an {@link ODataFeed} object
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    ODataFeed readFeed(String contentType, EdmEntitySet entitySet, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) data from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+     * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide this data as {@link ODataEntry}.
+     * 
+     * @param contentType format of content in the given input stream.
+     * @param entitySet entity data model for entity set to be read
+     * @param content data in form of an {@link InputStream} which contains the data in specified format
+     * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}.
+     * @return entry as {@link ODataEntry}
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    ODataEntry readEntry(String contentType, EdmEntitySet entitySet, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) properties from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+     * based on <code>entity data model</code> (given as {@link EdmProperty}) and provide this data as {@link Map} which contains
+     * the read data in form of <code>property name</code> to <code>property value</code> mapping.
+     * 
+     * @param contentType format of content in the given input stream.
+     * @param edmProperty entity data model for entity property to be read
+     * @param content data in form of an {@link InputStream} which contains the data in specified format
+     * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}.
+     * @return property as name and value in a map
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    Map<String, Object> readProperty(String contentType, EdmProperty edmProperty, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) a property value from <code>content</code> (as {@link InputStream}) in format <code>text/plain</code>
+     * based on <code>entity data model</code> (given as {@link EdmProperty}) and provide this data as {@link Object}.
+     * 
+     * @param edmProperty entity data model for entity property to be read
+     * @param content data in form of an {@link InputStream} which contains the data in format <code>text/plain</code>
+     * @param typeMapping defines the mapping for this <code>edm property</code> to a <code>java class</code> which should be used
+     *                  during read of the content. If according <code>edm property</code> can not be read
+     *                  into given <code>java class</code> an {@link EntityProviderException} is thrown.
+     *                  Supported mappings are documented in {@link org.apache.olingo.odata2.api.edm.EdmSimpleType}.
+     * @return property value as object
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    Object readPropertyValue(EdmProperty edmProperty, InputStream content, Class<?> typeMapping) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) a link from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+     * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide the link as {@link String}.
+     * 
+     * @param contentType format of content in the given input stream.
+     * @param entitySet entity data model for entity property to be read
+     * @param content data in form of an {@link InputStream} which contains the data in specified format
+     * @return link as string
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    String readLink(String contentType, EdmEntitySet entitySet, InputStream content) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) all links from <code>content</code> (as {@link InputStream})
+     * in specified format (given as <code>contentType</code>) based on <code>entity data model</code>
+     * (given as {@link EdmEntitySet}) and provide the link as List of Strings.
+     *
+     * @param contentType format of content in the given input stream.
+     * @param entitySet entity data model for entity property to be read
+     * @param content data in form of an {@link InputStream} which contains the data in specified format
+     * @return links as List of Strings
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    List<String> readLinks(String contentType, EdmEntitySet entitySet, InputStream content) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) data from metadata <code>inputStream</code> (as {@link InputStream}) and provide Edm as {@link Edm}
+     * 
+     * @param inputStream the given input stream
+     * @param validate has to be true if metadata should be validated 
+     * @return Edm as {@link Edm}
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    Edm readMetadata(InputStream inputStream, boolean validate) throws EntityProviderException;
+
+    /**
+     * Read (de-serialize) binary data from <code>content</code> (as {@link InputStream}) and provide it as <code>byte[]</code>.
+     * 
+     * @param content data in form of an {@link InputStream} which contains the binary data
+     * @return binary data as bytes
+     * @throws EntityProviderException if reading of data (de-serialization) fails
+     */
+    byte[] readBinary(InputStream content) throws EntityProviderException;
+
+    /**
+     * <p>Serializes an error message according to the OData standard.</p>
+     * @param context     contains error details see {@link ODataErrorContext}
+     * @return            an {@link ODataResponse} containing the serialized error message
+     */
+    ODataResponse writeErrorDocument(ODataErrorContext context);
+
+    /**
+     * Read (de-serialize) data from service document <code>inputStream</code> (as {@link InputStream}) and provide ServiceDocument as {@link ServiceDocument}
+     * 
+     * @param serviceDocument the given input stream
+     * @param contentType format of content in the given input stream
+     * @return ServiceDocument as {@link ServiceDocument}
+     * @throws EntityProviderException  if reading of data (de-serialization) fails
+     */
+    ServiceDocument readServiceDocument(InputStream serviceDocument, String contentType) throws EntityProviderException;
+
+    /**
+     * Parse Batch Request body <code>inputStream</code> (as {@link InputStream}) and provide a list of Batch Parts as {@link BatchPart}
+     * 
+     * @param contentType format of content in the given input stream
+     * @param content request body
+     * @param properties additional properties necessary for parsing. Must not be null.
+     * @return list of {@link BatchPart}
+     * @throws BatchException  if parsing fails
+     */
+    List<BatchPart> parseBatchRequest(String contentType, InputStream content, EntityProviderBatchProperties properties) throws BatchException;
+
+    /**
+     * Write responses of Batch Response Parts in Batch Response as {@link ODataResponse}.
+     * Batch Response body matches one-to-one with the corresponding Batch Request body
+     * 
+     * @param batchResponseParts a list of {@link BatchResponsePart}
+     * @return Batch Response as {@link ODataResponse}
+     * @throws BatchException 
+     */
+    ODataResponse writeBatchResponse(List<BatchResponsePart> batchResponseParts) throws BatchException;
+  }
+
+  /**
+   * Create an instance for the {@link EntityProviderInterface} over the {@link RuntimeDelegate}.
+   * 
+   * @return instance of {@link EntityProviderInterface}
+   */
+  private static EntityProviderInterface createEntityProvider() {
+    return RuntimeDelegate.createEntityProvider();
+  }
+
+  /**
+   * <p>Serializes an error message according to the OData standard.</p>
+   * An exception is not thrown because this method is used in exception handling.</p>
+   * @param context     contains error details see {@link ODataErrorContext}
+   * @return            an {@link ODataResponse} containing the serialized error message
+   */
+  public static ODataResponse writeErrorDocument(final ODataErrorContext context) {
+    return createEntityProvider().writeErrorDocument(context);
+  }
+
+  /**
+   * Write metadata document in XML format for the given schemas and the provided predefined 
+   * namespaces at the EDMX element. PredefinedNamespaces is of type 
+   * Map{@literal <}prefix,namespace{@literal >} and may be null or an empty Map.
+   * 
+   * @param schemas all XML schemas which will be written
+   * @param predefinedNamespaces type of Map{@literal <}prefix,namespace{@literal >} and may be null or an empty Map
+   * @return resulting {@link ODataResponse} with written metadata content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeMetadata(final List<Schema> schemas, final Map<String, String> predefinedNamespaces) throws EntityProviderException {
+    return createEntityProvider().writeMetadata(schemas, predefinedNamespaces);
+  }
+
+  /**
+   * Write service document based on given {@link Edm} and <code>service root</code> as
+   * given content type.
+   * 
+   * @param contentType format in which service document should be written
+   * @param edm entity data model to be written
+   * @param serviceRoot service root for the written service document
+   * @return resulting {@link ODataResponse} with written service document content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeServiceDocument(final String contentType, final Edm edm, final String serviceRoot) throws EntityProviderException {
+    return createEntityProvider().writeServiceDocument(contentType, edm, serviceRoot);
+  }
+
+  /**
+   * Write property as content type <code>application/octet-stream</code> or <code>text/plain</code>.
+   * 
+   * @param edmProperty entity data model for to be written property
+   * @param value property which will be written
+   * @return resulting {@link ODataResponse} with written property value content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writePropertyValue(final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    return createEntityProvider().writePropertyValue(edmProperty, value);
+  }
+
+  /**
+   * Write text value as content type <code>text/plain</code>.
+   * 
+   * @param value text value which will be written
+   * @return resulting {@link ODataResponse} with written text/plain content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeText(final String value) throws EntityProviderException {
+    return createEntityProvider().writeText(value);
+  }
+
+  /**
+   * Write binary content with content type header set to given <code>mime type</code> parameter.
+   * 
+   * @param mimeType mime type which is written and used as content type header information.
+   * @param data which is written to {@link ODataResponse}.
+   * @return response object resulting {@link ODataResponse} with written binary content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeBinary(final String mimeType, final byte[] data) throws EntityProviderException {
+    return createEntityProvider().writeBinary(mimeType, data);
+  }
+
+  /**
+   * Write given <code>data</code> (which is given in form of a {@link List} with a {@link Map} for each entity. Such a {@link Map}
+   * contains all properties [as <code>property name</code> to <code>property value</code> mapping] for the entry) in the specified
+   * format (given as <code>contentType</code>) based on given <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+   * and <code>properties</code> for this entity provider (given as {@link EntityProviderWriteProperties}).
+   * 
+   * @param contentType format in which the feed should be written
+   * @param entitySet entity data model for given entity data set
+   * @param data set of entries in form of a {@link List} with a {@link Map} for each entity (such a {@link Map}
+   *              contains all properties [as <code>property name</code> to <code>property value</code> mapping).
+   * @param properties additional properties necessary for writing of data 
+   * @return resulting {@link ODataResponse} with written feed content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeFeed(final String contentType, final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return createEntityProvider().writeFeed(contentType, entitySet, data, properties);
+  }
+
+  /**
+   * Write given <code>data</code> (which is given in form of a {@link Map} for which contains all properties 
+   * as <code>property name</code> to <code>property value</code> mapping) for the entry in the specified
+   * format (given as <code>contentType</code>) based on <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+   * and <code>properties</code> for this entity provider (given as {@link EntityProviderWriteProperties}).
+   * 
+   * @param contentType format in which the entry should be written
+   * @param entitySet entity data model for given entity data set
+   * @param data which contains all properties as <code>property name</code> to <code>property value</code> mapping for the entry
+   * @param properties additional properties necessary for writing of data 
+   * @return resulting {@link ODataResponse} with written entry content
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeEntry(final String contentType, final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return createEntityProvider().writeEntry(contentType, entitySet, data, properties);
+  }
+
+  /**
+   * Write given <code>value</code> (which is given in form of an {@link Object}) for the property in the specified
+   * format (given as <code>contentType</code>) based on given <code>entity data model for an entity property</code> 
+   * (given as {@link EdmProperty}).
+   * 
+   * @param contentType format in which the property should be written
+   * @param edmProperty entity data model for given property
+   * @param value data which is written
+   * @return resulting {@link ODataResponse} with written property content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeProperty(final String contentType, final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    return createEntityProvider().writeProperty(contentType, edmProperty, value);
+  }
+
+  /**
+   * Write <b>link</b> for key property based on <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+   * in the specified format (given as <code>contentType</code>).
+   * The necessary key property values must be provided within the <code>data</code> (in the form of <code>property name</code>
+   * to <code>property value</code> mapping) and <code>properties</code> for this entity provider must be set
+   * (given as {@link EntityProviderWriteProperties}).
+   * 
+   * @param contentType format in which the entry should be written
+   * @param entitySet entity data model for given entity data set
+   * @param data which contains all key properties as <code>property name</code> to <code>property value</code> mapping for the entry
+   * @param properties additional properties necessary for writing of data 
+   * @return resulting {@link ODataResponse} with written link content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeLink(final String contentType, final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return createEntityProvider().writeLink(contentType, entitySet, data, properties);
+  }
+
+  /**
+   * Write all <b>links</b> for key property based on <code>entity data model for an entity set</code> (given as {@link EdmEntitySet})
+   * in the specified format (given as <code>contentType</code>) for a set of entries.
+   * The necessary key property values must be provided within the <code>data</code> (in form of a {@link List} with a {@link Map} 
+   * for each entry. Such a {@link Map} contains all key properties [as <code>property name</code> to 
+   * <code>property value</code> mapping] for the entry) and <code>properties</code> for this entity provider must be set
+   * (given as {@link EntityProviderWriteProperties}).
+   * 
+   * @param contentType format in which the entry should be written
+   * @param entitySet entity data model for given entity data set
+   * @param data set of entries in form of a {@link List} with a {@link Map} for each entry (such a {@link Map}
+   *              contains all key properties [as <code>property name</code> to <code>property value</code> mapping).
+   * @param properties additional properties necessary for writing of data 
+   * @return resulting {@link ODataResponse} with written links content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeLinks(final String contentType, final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return createEntityProvider().writeLinks(contentType, entitySet, data, properties);
+  }
+
+  /**
+   * Write <code>data</code> result (given as {@link Object}) of function import based on <code>return type</code> 
+   * of {@link EdmFunctionImport} in specified format (given as <code>contentType</code>). Additional <code>properties</code> 
+   * for this entity provider must be set (given as {@link EntityProviderWriteProperties}).
+   * 
+   * @param contentType format in which the entry should be written
+   * @param functionImport entity data model for executed function import
+   * @param data result of function import
+   * @param properties additional properties necessary for writing of data 
+   * @return resulting {@link ODataResponse} with written function import result content.
+   * @throws EntityProviderException if writing of data (serialization) fails
+   */
+  public static ODataResponse writeFunctionImport(final String contentType, final EdmFunctionImport functionImport, final Object data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return createEntityProvider().writeFunctionImport(contentType, functionImport, data, properties);
+  }
+
+  /**
+   * Read (de-serialize) a data feed from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+   * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide this data as {@link ODataEntry}.
+   * 
+   * @param contentType format of content in the given input stream.
+   * @param entitySet entity data model for entity set to be read
+   * @param content feed data in form of an {@link InputStream} which contains the data in specified format
+   * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}. Must not be null.
+   * @return an {@link ODataFeed} object
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static ODataFeed readFeed(final String contentType, final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return createEntityProvider().readFeed(contentType, entitySet, content, properties);
+  }
+
+  /**
+   * Read (de-serialize) data from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+   * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide this data as {@link ODataEntry}.
+   * 
+   * @param contentType format of content in the given input stream.
+   * @param entitySet entity data model for entity set to be read
+   * @param content data in form of an {@link InputStream} which contains the data in specified format
+   * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}. Must not be null.
+   * @return entry as {@link ODataEntry}
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static ODataEntry readEntry(final String contentType, final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return createEntityProvider().readEntry(contentType, entitySet, content, properties);
+  }
+
+  /**
+   * Read (de-serialize) properties from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+   * based on <code>entity data model</code> (given as {@link EdmProperty}) and provide this data as {@link Map} which contains
+   * the read data in form of <code>property name</code> to <code>property value</code> mapping.
+   * 
+   * @param contentType format of content in the given input stream.
+   * @param edmProperty entity data model for entity property to be read
+   * @param content data in form of an {@link InputStream} which contains the data in specified format
+   * @param properties additional properties necessary for reading content from {@link InputStream} into {@link Map}. Must not be null.
+   * @return property as name and value in a map
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static Map<String, Object> readProperty(final String contentType, final EdmProperty edmProperty, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return createEntityProvider().readProperty(contentType, edmProperty, content, properties);
+  }
+
+  /**
+   * Read (de-serialize) a property value from <code>content</code> (as {@link InputStream}) in format <code>text/plain</code>
+   * based on <code>entity data model</code> (given as {@link EdmProperty}) and provide this data as {@link Object}.
+   * 
+   * @param edmProperty entity data model for entity property to be read
+   * @param content data in form of an {@link InputStream} which contains the data in format <code>text/plain</code>
+   * @return property value as object
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static Object readPropertyValue(final EdmProperty edmProperty, final InputStream content) throws EntityProviderException {
+    return createEntityProvider().readPropertyValue(edmProperty, content, null);
+  }
+
+  /**
+   * Read (de-serialize) a property value from <code>content</code> (as {@link InputStream}) in format <code>text/plain</code>
+   * based on <code>entity data model</code> (given as {@link EdmProperty}) and provide this data as {@link Object}.
+   * 
+   * @param edmProperty entity data model for entity property to be read
+   * @param content data in form of an {@link InputStream} which contains the data in format <code>text/plain</code>
+   * @param typeMapping defines the mapping for this <code>edm property</code> to a <code>java class</code> which should be used
+   *                  during read of the content. If according <code>edm property</code> can not be read
+   *                  into given <code>java class</code> an {@link EntityProviderException} is thrown.
+   *                  Supported mappings are documented in {@link org.apache.olingo.odata2.api.edm.EdmSimpleType}.
+   * @return property value as object
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static Object readPropertyValue(final EdmProperty edmProperty, final InputStream content, final Class<?> typeMapping) throws EntityProviderException {
+    return createEntityProvider().readPropertyValue(edmProperty, content, typeMapping);
+  }
+
+  /**
+   * Read (de-serialize) a link from <code>content</code> (as {@link InputStream}) in specified format (given as <code>contentType</code>)
+   * based on <code>entity data model</code> (given as {@link EdmEntitySet}) and provide the link as {@link String}.
+   * 
+   * @param contentType format of content in the given input stream.
+   * @param entitySet entity data model for entity property to be read
+   * @param content data in form of an {@link InputStream} which contains the data in specified format
+   * @return link as string
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static String readLink(final String contentType, final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    return createEntityProvider().readLink(contentType, entitySet, content);
+  }
+
+  /**
+   * Read (de-serialize) a link collection from <code>content</code> (as {@link InputStream})
+   * in specified format (given as <code>contentType</code>) based on <code>entity data model</code>
+   * (given as {@link EdmEntitySet}) and provide the links as List of Strings.
+   *
+   * @param contentType format of content in the given input stream.
+   * @param entitySet entity data model for entity property to be read
+   * @param content data in form of an {@link InputStream} which contains the data in specified format
+   * @return links as List of Strings
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static List<String> readLinks(final String contentType, final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    return createEntityProvider().readLinks(contentType, entitySet, content);
+  }
+
+  /**
+   * Read (de-serialize) binary data from <code>content</code> (as {@link InputStream}) and provide it as <code>byte[]</code>.
+   * 
+   * @param content data in form of an {@link InputStream} which contains the binary data
+   * @return binary data as bytes
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static byte[] readBinary(final InputStream content) throws EntityProviderException {
+    return createEntityProvider().readBinary(content);
+  }
+
+  /**
+   * Read (de-serialize) data from metadata <code>inputStream</code> (as {@link InputStream}) and provide Edm as {@link Edm}
+   * 
+   * @param metadataXml a metadata xml input stream (means the metadata document)
+   * @param validate has to be true if metadata should be validated 
+   * @return Edm as {@link Edm}
+   * @throws EntityProviderException if reading of data (de-serialization) fails
+   */
+  public static Edm readMetadata(final InputStream metadataXml, final boolean validate) throws EntityProviderException {
+    return createEntityProvider().readMetadata(metadataXml, validate);
+  }
+
+  /**
+   * Read (de-serialize) data from service document <code>inputStream</code> (as {@link InputStream}) and provide ServiceDocument as {@link ServiceDocument}
+   * 
+   * @param serviceDocument the given input stream
+   * @param contentType format of content in the given input stream
+   * @return ServiceDocument as {@link ServiceDocument}
+   * @throws EntityProviderException  if reading of data (de-serialization) fails
+   */
+  public static ServiceDocument readServiceDocument(final InputStream serviceDocument, final String contentType) throws EntityProviderException {
+    return createEntityProvider().readServiceDocument(serviceDocument, contentType);
+  }
+
+  /**
+   * Parse Batch Request body <code>inputStream</code> (as {@link InputStream}) and provide a list of Batch Parts as {@link BatchPart}
+   * 
+   * @param contentType format of content in the given input stream
+   * @param content request body
+   * @param properties additional properties necessary for parsing. Must not be null.
+   * @return list of {@link BatchPart}
+   * @throws BatchException if parsing fails
+   */
+  public static List<BatchPart> parseBatchRequest(final String contentType, final InputStream content, final EntityProviderBatchProperties properties) throws BatchException {
+    return createEntityProvider().parseBatchRequest(contentType, content, properties);
+  }
+
+  /**
+   * Write responses of Batch Response Parts in Batch Response as {@link ODataResponse}.
+   * Batch Response body matches one-to-one with the corresponding Batch Request body
+   * 
+   * @param batchResponseParts a list of {@link BatchResponsePart}
+   * @return Batch Response as {@link ODataResponse}
+   * @throws BatchException 
+   */
+  public static ODataResponse writeBatchResponse(final List<BatchResponsePart> batchResponseParts) throws BatchException {
+    return createEntityProvider().writeBatchResponse(batchResponseParts);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderBatchProperties.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderBatchProperties.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderBatchProperties.java
new file mode 100644
index 0000000..ad60c86
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderBatchProperties.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.api.ep;
+
+import org.apache.olingo.odata2.api.uri.PathInfo;
+
+/**
+ * The {@link EntityProviderBatchProperties} contains necessary informations to parse a Batch Request body.
+ * 
+ * @author SAP AG
+ */
+public class EntityProviderBatchProperties {
+  /**
+   * PathInfo contains service root and preceding segments which should be used for URI parsing of a single request
+   */
+  private PathInfo pathInfo;
+
+  public static EntityProviderBatchPropertiesBuilder init() {
+    return new EntityProviderBatchPropertiesBuilder();
+  }
+
+  public PathInfo getPathInfo() {
+    return pathInfo;
+  }
+
+  public static class EntityProviderBatchPropertiesBuilder {
+    private final EntityProviderBatchProperties properties = new EntityProviderBatchProperties();
+
+    public EntityProviderBatchPropertiesBuilder() {}
+
+    public EntityProviderBatchPropertiesBuilder(final EntityProviderBatchProperties propertiesFrom) {
+      properties.pathInfo = propertiesFrom.pathInfo;
+    }
+
+    public EntityProviderBatchPropertiesBuilder pathInfo(final PathInfo pathInfo) {
+      properties.pathInfo = pathInfo;
+      return this;
+    }
+
+    public EntityProviderBatchProperties build() {
+      return properties;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
new file mode 100644
index 0000000..00970da
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ep/EntityProviderException.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.api.ep;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+
+/**
+ * An {@link EntityProviderException} is the base exception for all <code>EntityProvider</code> related exceptions.
+ * It extends the {@link ODataMessageException} and provides several {@link MessageReference} for specification of 
+ * the thrown exception.
+ */
+public class EntityProviderException extends ODataMessageException {
+
+  private static final long serialVersionUID = 1L;
+
+  /** INVALID_STATE requires no content value */
+  public static final MessageReference COMMON = createMessageReference(EntityProviderException.class, "COMMON");
+  /** EXCEPTION_OCCURRED requires 1 content value ('exception name') */
+  public static final MessageReference EXCEPTION_OCCURRED = createMessageReference(EntityProviderException.class, "EXCEPTION_OCCURRED");
+  /** INVALIDMAPPING requires 1 content value ('propertyName') */
+  public static final MessageReference INVALID_MAPPING = createMessageReference(EntityProviderException.class, "INVALID_MAPPING");
+  /** INVALID_ENTITYTYPE requires 2 content values ('supplied entity type' and 'content entity type') */
+  public static final MessageReference INVALID_ENTITYTYPE = createMessageReference(EntityProviderException.class, "INVALID_ENTITYTYPE");
+  /** INVALID_COMPLEX_TYPE requires 2 content values ('supplied complex type' and 'content complex type') */
+  public static final MessageReference INVALID_COMPLEX_TYPE = createMessageReference(EntityProviderException.class, "INVALID_COMPLEX_TYPE");
+  /** INVALID_CONTENT requires 2 content values ('invalid tag' and 'parent tag') */
+  public static final MessageReference INVALID_CONTENT = createMessageReference(EntityProviderException.class, "INVALID_CONTENT");
+  /** INVALID_PROPERTY_VALUE requires 1 content value ('invalid value') */
+  public static final MessageReference INVALID_PROPERTY_VALUE = createMessageReference(EntityProviderException.class, "INVALID_PROPERTY_VALUE");
+  /** MISSING_PROPERTY requires 1 content value ('invalid value') */
+  public static final MessageReference MISSING_PROPERTY = createMessageReference(EntityProviderException.class, "MISSING_PROPERTY");
+  /** INVALID_PARENT_TAG requires 2 content values ('missing attribute name' and 'tag name') */
+  public static final MessageReference MISSING_ATTRIBUTE = createMessageReference(EntityProviderException.class, "MISSING_ATTRIBUTE");
+  public static final MessageReference UNSUPPORTED_PROPERTY_TYPE = createMessageReference(EntityProviderException.class, "UNSUPPORTED_PROPERTY_TYPE");
+  public static final MessageReference INLINECOUNT_INVALID = createMessageReference(EntityProviderException.class, "INLINECOUNT_INVALID");
+  /** INVALID_STATE requires 1 content value ('message') */
+  public static final MessageReference INVALID_STATE = createMessageReference(EntityProviderException.class, "INVALID_STATE");
+  /** INVALID_INLINE_CONTENT requires 1 content value ('invalid inline message') */
+  public static final MessageReference INVALID_INLINE_CONTENT = createMessageReference(EntityProviderException.class, "INVALID_INLINE_CONTENT");
+  /** INVALID_PROPERTY requires 1 content value ('invalid property name') */
+  public static final MessageReference INVALID_PROPERTY = createMessageReference(EntityProviderException.class, "INVALID_PROPERTY");
+  /** ILLEGAL_ARGUMENT requires 1 content value ('message') */
+  public static final MessageReference ILLEGAL_ARGUMENT = createMessageReference(EntityProviderException.class, "ILLEGAL_ARGUMENT");
+  /** INVALID_NAMESPACE requires 1 content value ('invalid tag/namespace') */
+  public static final MessageReference INVALID_NAMESPACE = createMessageReference(EntityProviderException.class, "INVALID_NAMESPACE");
+  /** INVALID_PARENT_TAG requires 2 content values ('expected parent tag' and 'found parent tag') */
+  public static final MessageReference INVALID_PARENT_TAG = createMessageReference(EntityProviderException.class, "INVALID_PARENT_TAG");
+  public static final MessageReference EXPANDNOTSUPPORTED = createMessageReference(EntityProviderException.class, "EXPANDNOTSUPPORTED");
+  /** DOUBLE_PROPERTY requires 1 content value ('double tag/property') */
+  public static final MessageReference DOUBLE_PROPERTY = createMessageReference(EntityProviderException.class, "DOUBLE_PROPERTY");
+  /** NOT_SET_CHARACTER_ENCODING requires no content value */
+  public static final MessageReference NOT_SET_CHARACTER_ENCODING = createMessageReference(EntityProviderException.class, "NOT_SET_CHARACTER_ENCODING");
+  /** UNSUPPORTED_CHARACTER_ENCODING requires 1 content value ('found but unsupported character encoding') */
+  public static final MessageReference UNSUPPORTED_CHARACTER_ENCODING = createMessageReference(EntityProviderException.class, "UNSUPPORTED_CHARACTER_ENCODING");
+  /** MEDIA_DATA_NOT_INITIAL requires no content value */
+  public static final MessageReference MEDIA_DATA_NOT_INITIAL = createMessageReference(EntityProviderException.class, "MEDIA_DATA_NOT_INITIAL");
+  /** END_DOCUMENT_EXPECTED requires 1 content value ('actual token') */
+  public static final MessageReference END_DOCUMENT_EXPECTED = createMessageReference(EntityProviderException.class, "END_DOCUMENT_EXPECTED");
+  /** MISSING_RESULTS_ARRAY requires no content value */
+  public static final MessageReference MISSING_RESULTS_ARRAY = createMessageReference(EntityProviderException.class, "MISSING_RESULTS_ARRAY");
+
+  public EntityProviderException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public EntityProviderException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public EntityProviderException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, errorCode);
+  }
+
+  public EntityProviderException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+}


[33/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmServiceMetadata.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmServiceMetadata.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmServiceMetadata.java
new file mode 100644
index 0000000..3a14fc6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmServiceMetadata.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * This interface gives access to the metadata of a service, the calculated Data Service Version and an info list of all entity sets inside this EntityDataModel.
+ * @author SAP AG
+ *
+ */
+public interface EdmServiceMetadata {
+
+  /**
+   * @return {@link InputStream} containing the metadata document
+   * @throws ODataException
+   */
+  InputStream getMetadata() throws ODataException;
+
+  /**
+   * @return <b>String</b> data service version of this service
+   * @throws ODataException
+   */
+  String getDataServiceVersion() throws ODataException;
+
+  /**
+   * @return a list of {@link EdmEntitySetInfo} objects of all entity sets in this data model
+   * @throws ODataException
+   */
+  List<EdmEntitySetInfo> getEntitySetInfos() throws ODataException;;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleType.java
new file mode 100644
index 0000000..2b2f26a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleType.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * <p>EdmSimpleType is a primitive type as defined in the Entity Data Model (EDM).</p>
+ * <p>There are methods to convert EDM simple types from and to Java objects, respectively.
+ * The following Java types are supported:
+ * <table frame="hsides" rules="groups">
+ * <thead>
+ * <tr><th>EDM simple type</th><th>Java types</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><td>Binary</td><td>byte[], {@link Byte}[]</td></tr>
+ * <tr><td>Boolean</td><td>{@link Boolean}</td></tr>
+ * <tr><td>Byte</td><td>{@link Short}, {@link Byte}, {@link Integer}, {@link Long}</td></tr>
+ * <tr><td>DateTime</td><td>{@link java.util.Calendar}, {@link java.util.Date}, {@link Long}</td></tr>
+ * <tr><td>DateTimeOffset</td><td>{@link java.util.Calendar}, {@link java.util.Date}, {@link Long}</td></tr>
+ * <tr><td>Decimal</td><td>{@link java.math.BigDecimal}, {@link java.math.BigInteger}, {@link Double}, {@link Float}, {@link Byte}, {@link Short}, {@link Integer}, {@link Long}</td></tr>
+ * <tr><td>Double</td><td>{@link Double}, {@link Float}, {@link java.math.BigDecimal}, {@link Byte}, {@link Short}, {@link Integer}, {@link Long}</td></tr>
+ * <tr><td>Guid</td><td>{@link java.util.UUID}</td></tr>
+ * <tr><td>Int16</td><td>{@link Short}, {@link Byte}, {@link Integer}, {@link Long}</td></tr>
+ * <tr><td>Int32</td><td>{@link Integer}, {@link Byte}, {@link Short}, {@link Long}</td></tr>
+ * <tr><td>Int64</td><td>{@link Long}, {@link Byte}, {@link Short}, {@link Integer}, {@link java.math.BigInteger}</td></tr>
+ * <tr><td>SByte</td><td>{@link Byte}, {@link Short}, {@link Integer}, {@link Long}</td></tr>
+ * <tr><td>Single</td><td>{@link Float}, {@link Double}, {@link java.math.BigDecimal}, {@link Byte}, {@link Short}, {@link Integer}, {@link Long}</td></tr>
+ * <tr><td>String</td><td>{@link String}</td></tr>
+ * <tr><td>Time</td><td>{@link java.util.Calendar}, {@link java.util.Date}, {@link Long}</td></tr>
+ * </tbody>
+ * </table></p>
+ * <p>The first Java type is the default type for the respective EDM simple type.</p>
+ * <p>For all EDM simple types, the {@link EdmFacets facet} <code>Nullable</code> is
+ * taken into account.
+ * For <code>Binary</code>, <code>MaxLength</code> is also applicable.
+ * For <code>String</code>, the facets <code>MaxLength</code> and <code>Unicode</code>
+ * are also considered.
+ * The EDM simple types <code>DateTime</code>, <code>DateTimeOffset</code>, and
+ * <code>Time</code> can have a <code>Precision</code> facet.
+ * <code>Decimal</code> can have the facets <code>Precision</code> and <code>Scale</code>.</p> 
+ * <p>
+ * <table frame="box" rules="all">
+ * <thead>
+ * <tr><th>EDM simple type</th><th>Parsing details</th></tr>
+ * </thead>
+ * <tbody>
+ * <tr><td><b>DateTimeOffset</b></td>
+ * <td>
+ * When an time string is parsed to an according <code>EdmDateTimeOffset</code> object it is assumed that this time string represents the local time with a timezone set.
+ * <br/>
+ * As an example, when the following time string <code>"2012-02-29T15:33:00-04:00"</code> is parsed it is assumed that we have the local time ("15:33:00") which is in a timezone with an offset from UTC of "-04:00".
+ * Hence the result is a calendar object within the local time (which is "15:33:00") and the according timezone offset ("-04:00") which then results in the UTC time of "19:33:00+00:00" ("15:33:00" - "-04:00" -> "19:33:00 UTC").
+ * <br/>
+ * As further explanation about our date time handling I reference to the following ISO specification: ISO 8601 - http://en.wikipedia.org/wiki/ISO_8601 and the copied section:
+ * Time_offsets_from_UTC - http://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
+ * <blockquote>>
+ * The following times all refer to the same moment: "18:30Z", "22:30+04:00", and "15:00-03:30". Nautical time zone letters are not used with the exception of Z. 
+ * To calculate UTC time one has to subtract the offset from the local time, e.g. for "15:00-03:30" do 15:00 - (-03:30) to get 18:30 UTC.
+ * </blockquote>
+ * <em>The behavior of our ABAP OData Library and Microsoft examples is the same as described above.</em> 
+ * </td>
+ * </tr>
+ * </tbody>
+ * </table></p>
+ * </p>
+ * @author SAP AG
+ * @org.apache.olingo.odata2.DoNotImplement
+ */
+public interface EdmSimpleType extends EdmType {
+
+  public static final String EDM_NAMESPACE = "Edm";
+  public static final String SYSTEM_NAMESPACE = "System";
+
+  /**
+   * Checks type compatibility.
+   *
+   * @param simpleType  the {@link EdmSimpleType} to be tested for compatibility
+   * @return <code>true</code> if the provided type is compatible to this type
+   */
+  public boolean isCompatible(EdmSimpleType simpleType);
+
+  /**
+   * Returns the default Java type for this EDM simple type as described in
+   * the documentation of {@link EdmSimpleType}.
+   * @return the default Java type
+   */
+  public Class<?> getDefaultType();
+
+  /**
+   * Validates literal value.
+   *
+   * @param value        the literal value
+   * @param literalKind  the kind of literal representation of value
+   * @param facets       additional constraints for parsing (optional)
+   * @return <code>true</code> if the validation is successful
+   * @see EdmLiteralKind
+   * @see EdmFacets
+   */
+  public boolean validate(String value, EdmLiteralKind literalKind, EdmFacets facets);
+
+  /**
+   * Converts literal representation of value to system data type.
+   *
+   * @param value        the literal representation of value
+   * @param literalKind  the kind of literal representation of value
+   * @param facets       additional constraints for parsing (optional)
+   * @param returnType   the class of the returned value; it must be one of the
+   *                     list in the documentation of {@link EdmSimpleType}
+   * @return the value as an instance of the class the parameter <code>returnType</code> indicates
+   * @see EdmLiteralKind
+   * @see EdmFacets
+   */
+  public <T> T valueOfString(String value, EdmLiteralKind literalKind, EdmFacets facets, Class<T> returnType) throws EdmSimpleTypeException;
+
+  /**
+   * <p>Converts system data type to literal representation of value.</p>
+   * <p>Returns <code>null</code> if value is <code>null</code>
+   * and the facets allow the <code>null</code> value.</p>
+   *
+   * @param value  the Java value as Object; its type must be one of the list
+   *               in the documentation of {@link EdmSimpleType}
+   * @param literalKind  the requested kind of literal representation
+   * @param facets       additional constraints for formatting (optional)
+   * @return literal representation as String
+   * @see EdmLiteralKind
+   * @see EdmFacets
+   */
+  public String valueToString(Object value, EdmLiteralKind literalKind, EdmFacets facets) throws EdmSimpleTypeException;
+
+  /**
+   * Converts default literal representation to URI literal representation.
+   *
+   * @param literal  the literal in default representation
+   * @return URI literal representation as String
+   */
+  public String toUriLiteral(String literal) throws EdmSimpleTypeException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeException.java
new file mode 100644
index 0000000..2813616
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeException.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * Exception for parsing errors with {@link EdmSimpleType}s
+ * @author SAP AG
+ */
+public class EdmSimpleTypeException extends EdmException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(EdmSimpleTypeException.class, "COMMON");
+
+  public static final MessageReference LITERAL_KIND_MISSING = createMessageReference(EdmSimpleTypeException.class, "LITERAL_KIND_MISSING");
+  public static final MessageReference LITERAL_KIND_NOT_SUPPORTED = createMessageReference(EdmSimpleTypeException.class, "LITERAL_KIND_NOT_SUPPORTED");
+
+  public static final MessageReference LITERAL_NULL_NOT_ALLOWED = createMessageReference(EdmSimpleTypeException.class, "LITERAL_NULL_NOT_ALLOWED");
+  public static final MessageReference LITERAL_ILLEGAL_CONTENT = createMessageReference(EdmSimpleTypeException.class, "LITERAL_ILLEGAL_CONTENT");
+  public static final MessageReference LITERAL_FACETS_NOT_MATCHED = createMessageReference(EdmSimpleTypeException.class, "LITERAL_FACETS_NOT_MATCHED");
+  public static final MessageReference LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE = createMessageReference(EdmSimpleTypeException.class, "LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE");
+
+  public static final MessageReference VALUE_TYPE_NOT_SUPPORTED = createMessageReference(EdmSimpleTypeException.class, "VALUE_TYPE_NOT_SUPPORTED");
+  public static final MessageReference VALUE_NULL_NOT_ALLOWED = createMessageReference(EdmSimpleTypeException.class, "VALUE_NULL_NOT_ALLOWED");
+  public static final MessageReference VALUE_ILLEGAL_CONTENT = createMessageReference(EdmSimpleTypeException.class, "VALUE_ILLEGAL_CONTENT");
+  public static final MessageReference VALUE_FACETS_NOT_MATCHED = createMessageReference(EdmSimpleTypeException.class, "VALUE_FACETS_NOT_MATCHED");
+
+  public EdmSimpleTypeException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public EdmSimpleTypeException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public EdmSimpleTypeException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, errorCode);
+  }
+
+  public EdmSimpleTypeException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeFacade.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeFacade.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeFacade.java
new file mode 100644
index 0000000..ee67fc8
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeFacade.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * This facade is used as a hook into the core implementation.
+ * @author SAP AG
+ */
+public interface EdmSimpleTypeFacade {
+
+  /**
+   * IMPORTANT: Use {@link EdmSimpleTypeKind} parseUriLiteral for the implementation.
+   * <p>This method definition is used only inside the core of this library.
+   * @param uriLiteral
+   * @return the parsed literal
+   * @throws EdmLiteralException
+   */
+  public EdmLiteral parseUriLiteral(final String uriLiteral) throws EdmLiteralException;
+
+  /**
+   * IMPORTANT: Use {@link EdmSimpleTypeKind#getEdmSimpleTypeInstance()} for the application development.
+   * 
+   * <p>This method definition is used only inside the core of this library.</p>
+   * 
+   * @param typeKind for which an instance is requested
+   * @return an instance of the corresponding {@link EdmSimpleType} to given {@link EdmSimpleTypeKind}
+   */
+  public EdmSimpleType getEdmSimpleTypeInstance(final EdmSimpleTypeKind typeKind);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeKind.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeKind.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeKind.java
new file mode 100644
index 0000000..07936f1
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmSimpleTypeKind.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmSimpleTypeKind holds all EdmSimpleTypes defined as primitive type in the Entity Data Model (EDM).
+ * @author SAP AG
+ */
+public enum EdmSimpleTypeKind {
+
+  Binary, Boolean, Byte, DateTime, DateTimeOffset, Decimal, Double, Guid, Int16, Int32, Int64, SByte, Single, String, Time, Null;
+
+  /**
+   * Returns the {@link FullQualifiedName} for this SimpleTypeKind.
+   * @return {@link FullQualifiedName}
+   */
+  public FullQualifiedName getFullQualifiedName() {
+    return new FullQualifiedName(EdmSimpleType.EDM_NAMESPACE, toString());
+  }
+
+  /**
+   * Returns an instance for this {@link EdmSimpleTypeKind} in the form of {@link EdmSimpleType}.
+   * @return {@link EdmSimpleType} instance
+   */
+  public EdmSimpleType getEdmSimpleTypeInstance() {
+    return SimpleTypeFacadeHolder.instance.getEdmSimpleTypeInstance(this);
+  }
+
+  /**
+   * <p>Parses a URI literal and determines its EDM simple type on the way.</p>
+   * <p>If the literal is <code>null</code> or consists of the literal string
+   * "null", the EDM simple type <code>Null</code> is returned.</p>
+   * <p>The URI literal syntax of EDM simple types allows two ways of determining
+   * the type:
+   * <ul>
+   * <li>The literal has an explicit type indicator (prefix or suffix).</li>
+   * <li>The value is of a type compatible to all other possible types, e.g., "256"
+   * could be of type <code>Int16</code> or <code>Int32</code> but all possible
+   * values of <code>Int16</code> are also legal values of <code>Int32</code>
+   * so callers could promote it to <code>Int32</code> in all cases where they
+   * deem it necessary.<br/>
+   * For a given literal, always the narrowest possible type is chosen.</li>
+   * </ul></p>
+   * <p>There are two cases where it is not possible to choose unambiguously
+   * a compatible type:
+   * <ul>
+   * <li><code>0</code> or <code>1</code> could be a number but also a boolean value;
+   * therefore, the internal (system) type <code>Bit</code> is used for these values.</li>
+   * <li>Integer values between <code>0</code> and <code>127</code> (inclusive) could
+   * be of type <code>SByte</code> or <code>Byte</code> both of which are not compatible
+   * to the other; therefore, the internal (system) type <code>Uint7</code> is used
+   * for these values.</li>
+   * </ul></p>
+   * @param uriLiteral the literal
+   * @return an instance of {@link EdmLiteral}, containing the literal
+   *         in default String representation and the EDM simple type
+   * @throws EdmLiteralException if the literal is malformed
+   */
+  public static EdmLiteral parseUriLiteral(final String uriLiteral) throws EdmLiteralException {
+    return SimpleTypeFacadeHolder.instance.parseUriLiteral(uriLiteral);
+  }
+
+  /**
+   * Cached access to {@link EdmSimpleTypeFacade} which is used i.a. for {@link EdmSimpleType} instance creation 
+   * or parsing of {@link EdmLiteral}s.
+   */
+  private static class SimpleTypeFacadeHolder {
+    static final EdmSimpleTypeFacade instance = RuntimeDelegate.getSimpleTypeFacade();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmStructuralType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmStructuralType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmStructuralType.java
new file mode 100644
index 0000000..8859a20
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmStructuralType.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.util.List;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmStructuralType is the base for a complex type or an entity type.
+ * <p>Complex types and entity types are described in the Conceptual Schema Definition of the OData protocol.
+ * @author SAP AG
+ */
+public interface EdmStructuralType extends EdmMappable, EdmType {
+
+  /**
+   * Get property by name
+   * @param name
+   * @return simple or complex property as {@link EdmTyped}
+   * @throws EdmException
+   */
+  EdmTyped getProperty(String name) throws EdmException;
+
+  /**
+   * Get all property names
+   * 
+   * @return property names as type List<String>
+   * @throws EdmException
+   */
+  List<String> getPropertyNames() throws EdmException;
+
+  /**
+   * Base types are described in the OData protocol specification.
+   * 
+   * @return {@link EdmStructuralType}
+   * @throws EdmException
+   */
+  EdmStructuralType getBaseType() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTargetPath.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTargetPath.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTargetPath.java
new file mode 100644
index 0000000..037f4ef
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTargetPath.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmTargetPath specifies the possible default targets for an EDM property which is mapped to an atom element.
+ * @author SAP AG
+ */
+public class EdmTargetPath {
+
+  public static final String SYNDICATION_AUTHORNAME = "SyndicationAuthorName";
+  public static final String SYNDICATION_AUTHOREMAIL = "SyndicationAuthorEmail";
+  public static final String SYNDICATION_AUTHORURI = "SyndicationAuthorUri";
+  public static final String SYNDICATION_PUBLISHED = "SyndicationPublished";
+  public static final String SYNDICATION_RIGHTS = "SyndicationRights";
+  public static final String SYNDICATION_TITLE = "SyndicationTitle";
+  public static final String SYNDICATION_UPDATED = "SyndicationUpdated";
+  public static final String SYNDICATION_CONTRIBUTORNAME = "SyndicationContributorName";
+  public static final String SYNDICATION_CONTRIBUTOREMAIL = "SyndicationContributorEmail";
+  public static final String SYNDICATION_CONTRIBUTORURI = "SyndicationContributorUri";
+  public static final String SYNDICATION_SOURCE = "SyndicationSource";
+  public static final String SYNDICATION_SUMMARY = "SyndicationSummary";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmType.java
new file mode 100644
index 0000000..6292c32
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmType.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmType holds the namespace of a given type and its type as {@link EdmTypeKind}.
+ * @author SAP AG
+ */
+public interface EdmType extends EdmNamed {
+
+  /**
+   * Namespace of this {@link EdmType}
+   * @return namespace as String
+   * @throws EdmException
+   */
+  String getNamespace() throws EdmException;
+
+  /**
+   * @return {@link EdmTypeKind} of this {@link EdmType}
+   */
+  EdmTypeKind getKind();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTypeKind.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTypeKind.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTypeKind.java
new file mode 100644
index 0000000..d9dadd9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTypeKind.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmTypeKind specifies the type of an EDM element.
+ * @author SAP AG
+ */
+public enum EdmTypeKind {
+
+  UNDEFINED, SIMPLE, COMPLEX, ENTITY, NAVIGATION, ASSOCIATION, SYSTEM;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTyped.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTyped.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTyped.java
new file mode 100644
index 0000000..f238814
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmTyped.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmTyped indicates if an EDM element is of a special type and holds the multiplicity of that type.
+ * @author SAP AG
+ */
+public interface EdmTyped extends EdmNamed {
+
+  /**
+   * See {@link EdmType} for more information about possible types.
+   * 
+   * @return {@link EdmType}
+   * @throws EdmException
+   */
+  EdmType getType() throws EdmException;
+
+  /**
+   * See {@link EdmMultiplicity} for more information about possible multiplicities.
+   * 
+   * @return {@link EdmMultiplicity}
+   * @throws EdmException
+   */
+  EdmMultiplicity getMultiplicity() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/FullQualifiedName.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/FullQualifiedName.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/FullQualifiedName.java
new file mode 100644
index 0000000..4da0008
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/FullQualifiedName.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A full qualified name of any element in the EDM consists of a name and a namespace.
+ * @author SAP AG
+ */
+public class FullQualifiedName {
+
+  private final String namespace;
+  private final String name;
+
+  /**
+   * @param namespace
+   * @param name
+   */
+  public FullQualifiedName(final String namespace, final String name) {
+    this.namespace = namespace;
+    this.name = name;
+  }
+
+  /**
+   * @return namespace
+   */
+  public String getNamespace() {
+    return namespace;
+  }
+
+  /**
+   * @return name
+   */
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public int hashCode() {
+    return toString().hashCode();
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if ((obj == null) || !(obj instanceof FullQualifiedName)) {
+      return false;
+    }
+    final FullQualifiedName other = (FullQualifiedName) obj;
+    return namespace.equals(other.getNamespace()) && name.equals(other.getName());
+  }
+
+  @Override
+  public String toString() {
+    return namespace + Edm.DELIMITER + name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/package-info.java
new file mode 100644
index 0000000..de1be11
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h1>Entity Data Model API</h1>
+ * <p>The Entity Data Model is described in the OData protocol specification
+ * as well as in the Conceptual Schema Definition for the OData Protocol.
+ * Both can be found at <a href="http://www.odata.org/">http://www.odata.org/</a>.</p>
+ * <p>Many classes and interfaces contain the pragma:" @org.apache.olingo.odata2.DoNotImplement "
+ * to indicate these classes should only be used and not implemented.</p>
+ */
+package org.apache.olingo.odata2.api.edm;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationAttribute.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationAttribute.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationAttribute.java
new file mode 100644
index 0000000..cafce69
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationAttribute.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+
+/**
+ * Objects of this class represent an annotation attribute
+ * @author SAP AG
+ */
+public class AnnotationAttribute implements EdmAnnotationAttribute {
+
+  private String namespace;
+  private String prefix;
+  private String name;
+  private String text;
+
+  @Override
+  public String getNamespace() {
+    return namespace;
+  }
+
+  @Override
+  public String getPrefix() {
+    return prefix;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  /**
+   * Sets the namespace for this {@link AnnotationAttribute}.
+   * @param namespace
+   * @return {@link AnnotationAttribute} for method chaining
+   */
+  public AnnotationAttribute setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the prefix for this {@link AnnotationAttribute}.
+   * @param prefix
+   * @return {@link AnnotationAttribute} for method chaining
+   */
+  public AnnotationAttribute setPrefix(final String prefix) {
+    this.prefix = prefix;
+    return this;
+  }
+
+  /**
+   * Sets the name for this {@link AnnotationAttribute}.
+   * @param name
+   * @return {@link AnnotationAttribute} for method chaining
+   */
+  public AnnotationAttribute setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the text for this {@link AnnotationAttribute}.
+   * @param text
+   * @return {@link AnnotationAttribute} for method chaining
+   */
+  public AnnotationAttribute setText(final String text) {
+    this.text = text;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationElement.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationElement.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationElement.java
new file mode 100644
index 0000000..203ffca
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AnnotationElement.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+
+/**
+ * Objects of this class represent an annotation element.
+ * @author SAP AG
+ */
+public class AnnotationElement implements EdmAnnotationElement {
+
+  private String namespace;
+  private String prefix;
+  private String name;
+  private String text;
+  private List<AnnotationElement> childElements;
+  private List<AnnotationAttribute> attributes;
+
+  @Override
+  public String getNamespace() {
+    return namespace;
+  }
+
+  @Override
+  public String getPrefix() {
+    return prefix;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public String getText() {
+    return text;
+  }
+
+  @Override
+  public List<AnnotationElement> getChildElements() {
+    return childElements;
+  }
+
+  @Override
+  public List<AnnotationAttribute> getAttributes() {
+    return attributes;
+  }
+
+  /**
+   * Sets the attributes for this {@link AnnotationElement}.
+   * @param attributes
+   * @return {@link AnnotationElement} for method chaining
+   */
+  public AnnotationElement setAttributes(final List<AnnotationAttribute> attributes) {
+    this.attributes = attributes;
+    return this;
+  }
+
+  /**
+   * Sets the child elements for this {@link AnnotationElement}.
+   * Does not set child elements and characterData for one element.
+   * @param childElements
+   * @return {@link AnnotationElement} for method chaining
+   */
+  public AnnotationElement setChildElements(final List<AnnotationElement> childElements) {
+    this.childElements = childElements;
+    return this;
+  }
+
+  /**
+   * Sets the namespace for this {@link AnnotationElement}.
+   * @param namespace
+   * @return {@link AnnotationElement} for method chaining
+   */
+  public AnnotationElement setNamespace(final String namespace) {
+    this.namespace = namespace;
+    return this;
+  }
+
+  /**
+   * Sets the prefix for this {@link AnnotationElement}.
+   * @param prefix
+   * @return {@link AnnotationElement} for method chaining
+   */
+  public AnnotationElement setPrefix(final String prefix) {
+    this.prefix = prefix;
+    return this;
+  }
+
+  /**
+   * Sets the name for this {@link AnnotationElement}.
+   * @param name
+   * @return {@link AnnotationElement} for method chaining
+   */
+  public AnnotationElement setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the text for this {@link AnnotationElement} which will be displayed inside the tags.
+   * Must NOT be set if child elements are set!
+   * @param text
+   * @return {@link AnnotationElement} for method chaining
+   */
+  public AnnotationElement setText(final String text) {
+    this.text = text;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Association.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Association.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Association.java
new file mode 100644
index 0000000..1781d73
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Association.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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent an association
+ * @author SAP AG
+ */
+public class Association {
+
+  private String name;
+  private AssociationEnd end1;
+  private AssociationEnd end2;
+  private ReferentialConstraint referentialConstraint;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link AssociationEnd} end2
+   */
+  public AssociationEnd getEnd1() {
+    return end1;
+  }
+
+  /**
+   * @return {@link AssociationEnd} end2
+   */
+  public AssociationEnd getEnd2() {
+    return end2;
+  }
+
+  /**
+   * @return {@link ReferentialConstraint} referentialConstraint
+   */
+  public ReferentialConstraint getReferentialConstraint() {
+    return referentialConstraint;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name for this {@link Association}
+   * @param name
+   * @return {@link Association} for method chaining
+   */
+  public Association setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the first {@link AssociationEnd} for this {@link Association}
+   * @param end1
+   * @return {@link Association} for method chaining
+   */
+  public Association setEnd1(final AssociationEnd end1) {
+    this.end1 = end1;
+    return this;
+  }
+
+  /**
+   * Sets the second {@link AssociationEnd} for this {@link Association}
+   * @param end2
+   * @return {@link Association} for method chaining
+   */
+  public Association setEnd2(final AssociationEnd end2) {
+    this.end2 = end2;
+    return this;
+  }
+
+  /**
+   * Sets the {@link ReferentialConstraint} for this {@link Association}
+   * @param referentialConstraint
+   * @return {@link Association} for method chaining
+   */
+  public Association setReferentialConstraint(final ReferentialConstraint referentialConstraint) {
+    this.referentialConstraint = referentialConstraint;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link Association}
+   * @param documentation
+   * @return {@link Association} for method chaining
+   */
+  public Association setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link Association}
+   * @param annotationAttributes
+   * @return {@link Association} for method chaining
+   */
+  public Association setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link Association}
+   * @param annotationElements
+   * @return {@link Association} for method chaining
+   */
+  public Association setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationEnd.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationEnd.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationEnd.java
new file mode 100644
index 0000000..5ebccc1
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationEnd.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent an association end
+ * @author SAP AG
+ */
+public class AssociationEnd {
+
+  private FullQualifiedName type;
+  private String role;
+  private EdmMultiplicity multiplicity;
+  private OnDelete onDelete;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return {@link FullQualifiedName} full qualified name  (namespace and name)
+   */
+  public FullQualifiedName getType() {
+    return type;
+  }
+
+  /**
+   * @return <b>String</b> role
+   */
+  public String getRole() {
+    return role;
+  }
+
+  /**
+   * @return {@link EdmMultiplicity} multiplicity of this end
+   */
+  public EdmMultiplicity getMultiplicity() {
+    return multiplicity;
+  }
+
+  /**
+   * @return {@link OnDelete} on delete
+   */
+  public OnDelete getOnDelete() {
+    return onDelete;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the {@link FullQualifiedName} for this {@link AssociationEnd}
+   * @param type
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setType(final FullQualifiedName type) {
+    this.type = type;
+    return this;
+  }
+
+  /**
+   * Sets the role for this {@link AssociationEnd}
+   * @param role
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setRole(final String role) {
+    this.role = role;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmMultiplicity} for this {@link AssociationEnd}
+   * @param multiplicity
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setMultiplicity(final EdmMultiplicity multiplicity) {
+    this.multiplicity = multiplicity;
+    return this;
+  }
+
+  /**
+   * Sets {@link OnDelete} for this {@link AssociationEnd}
+   * @param onDelete
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setOnDelete(final OnDelete onDelete) {
+    this.onDelete = onDelete;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link AssociationEnd}
+   * @param documentation
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link AssociationEnd}
+   * @param annotationAttributes
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link AssociationEnd}
+   * @param annotationElements
+   * @return {@link AssociationEnd} for method chaining
+   */
+  public AssociationEnd setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSet.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSet.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSet.java
new file mode 100644
index 0000000..f093afa
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSet.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent an association set
+ * @author SAP AG
+ */
+public class AssociationSet {
+
+  private String name;
+  private FullQualifiedName association;
+  private AssociationSetEnd end1;
+  private AssociationSetEnd end2;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link FullQualifiedName} Association of this {@link AssociationSet} (namespace and name)
+   */
+  public FullQualifiedName getAssociation() {
+    return association;
+  }
+
+  /**
+   * @return {@link AssociationEnd} end1
+   */
+  public AssociationSetEnd getEnd1() {
+    return end1;
+  }
+
+  /**
+   * @return {@link AssociationEnd} end2
+   */
+  public AssociationSetEnd getEnd2() {
+    return end2;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name for this {@link AssociationSet}
+   * @param name
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the {@link FullQualifiedName} association for this {@link AssociationSet}
+   * @param association
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setAssociation(final FullQualifiedName association) {
+    this.association = association;
+    return this;
+  }
+
+  /**
+   * Sets the first {@link AssociationSetEnd} for this {@link AssociationSet}
+   * @param end1
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setEnd1(final AssociationSetEnd end1) {
+    this.end1 = end1;
+    return this;
+  }
+
+  /**
+   * Sets the second {@link AssociationSetEnd} for this {@link AssociationSet}
+   * @param end2
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setEnd2(final AssociationSetEnd end2) {
+    this.end2 = end2;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link AssociationSet}
+   * @param documentation
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link AssociationSet}
+   * @param annotationAttributes
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link AssociationSet}
+   * @param annotationElements
+   * @return {@link AssociationSet} for method chaining
+   */
+  public AssociationSet setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSetEnd.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSetEnd.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSetEnd.java
new file mode 100644
index 0000000..0f6ac55
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/AssociationSetEnd.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent an association set end
+ * @author SAP AG
+ */
+public class AssociationSetEnd {
+
+  private String role;
+  private String entitySet;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> role
+   */
+  public String getRole() {
+    return role;
+  }
+
+  /**
+   * @return <b>String</b> name of the target entity set
+   */
+  public String getEntitySet() {
+    return entitySet;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the role of this {@link AssociationSetEnd}
+   * @param role
+   * @return {@link AssociationSetEnd} for method chaining
+   */
+  public AssociationSetEnd setRole(final String role) {
+    this.role = role;
+    return this;
+  }
+
+  /**
+   * Sets the target entity set of this {@link AssociationSetEnd}
+   * @param entitySet
+   * @return {@link AssociationSetEnd} for method chaining
+   */
+  public AssociationSetEnd setEntitySet(final String entitySet) {
+    this.entitySet = entitySet;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} of this {@link AssociationSetEnd}
+   * @param documentation
+   * @return {@link AssociationSetEnd} for method chaining
+   */
+  public AssociationSetEnd setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link AssociationSetEnd}
+   * @param annotationAttributes
+   * @return {@link AssociationSetEnd} for method chaining
+   */
+  public AssociationSetEnd setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link AssociationSetEnd}
+   * @param annotationElements
+   * @return {@link AssociationSetEnd} for method chaining
+   */
+  public AssociationSetEnd setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexProperty.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexProperty.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexProperty.java
new file mode 100644
index 0000000..53f0b19
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexProperty.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent a complex property.
+ * @author SAP AG
+ */
+public class ComplexProperty extends Property {
+
+  private FullQualifiedName type;
+
+  /**
+   * @return {@link FullQualifiedName} of this property
+   */
+  public FullQualifiedName getType() {
+    return type;
+  }
+
+  /**
+   * Sets the {@link FullQualifiedName} for this {@link Property}
+   * @param type
+   * @return {@link Property} for method chaining
+   */
+  public ComplexProperty setType(final FullQualifiedName type) {
+    this.type = type;
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setName(final String name) {
+    super.setName(name);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setFacets(final EdmFacets facets) {
+    super.setFacets(facets);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setCustomizableFeedMappings(final CustomizableFeedMappings customizableFeedMappings) {
+    super.setCustomizableFeedMappings(customizableFeedMappings);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setMimeType(final String mimeType) {
+    super.setMimeType(mimeType);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setMapping(final Mapping mapping) {
+    super.setMapping(mapping);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setDocumentation(final Documentation documentation) {
+    super.setDocumentation(documentation);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    super.setAnnotationAttributes(annotationAttributes);
+    return this;
+  }
+
+  @Override
+  public ComplexProperty setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    super.setAnnotationElements(annotationElements);
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexType.java
new file mode 100644
index 0000000..6de4162
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ComplexType.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent a complex type
+ * @author SAP AG
+ */
+public class ComplexType {
+
+  private String name;
+  private FullQualifiedName baseType;
+  private boolean isAbstract;
+  private List<Property> properties;
+  private Mapping mapping;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link FullQualifiedName} of the base type of this type (namespace and name) 
+   */
+  public FullQualifiedName getBaseType() {
+    return baseType;
+  }
+
+  /**
+   * @return <b>boolean</b> if this type is abstract
+   */
+  public boolean isAbstract() {
+    return isAbstract;
+  }
+
+  /**
+   * @return List<{@link Property}> of all properties for this type
+   */
+  public List<Property> getProperties() {
+    return properties;
+  }
+
+  /**
+   * @return {@link Mapping} for this type
+   */
+  public Mapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name
+   * @param name
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the {@link FullQualifiedName} of the base type
+   * @param baseType
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setBaseType(final FullQualifiedName baseType) {
+    this.baseType = baseType;
+    return this;
+  }
+
+  /**
+   * Sets if it is abstract
+   * @param isAbstract
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setAbstract(final boolean isAbstract) {
+    this.isAbstract = isAbstract;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Property}s
+   * @param properties
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setProperties(final List<Property> properties) {
+    this.properties = properties;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Mapping}
+   * @param mapping
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setMapping(final Mapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation}
+   * @param documentation
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link ComplexType}
+   * @param annotationAttributes
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link ComplexType}
+   * @param annotationElements
+   * @return {@link ComplexType} for method chaining
+   */
+  public ComplexType setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/CustomizableFeedMappings.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/CustomizableFeedMappings.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/CustomizableFeedMappings.java
new file mode 100644
index 0000000..8f6d04e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/CustomizableFeedMappings.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+
+/**
+ * Objects of this class represent customizable feed mappings.
+ * @author SAP AG
+ */
+public class CustomizableFeedMappings implements EdmCustomizableFeedMappings {
+
+  private Boolean fcKeepInContent;
+  private EdmContentKind fcContentKind;
+  private String fcNsPrefix;
+  private String fcNsUri;
+  private String fcSourcePath;
+  private String fcTargetPath;
+
+  @Override
+  public Boolean isFcKeepInContent() {
+    return fcKeepInContent;
+  }
+
+  @Override
+  public EdmContentKind getFcContentKind() {
+    return fcContentKind;
+  }
+
+  @Override
+  public String getFcNsPrefix() {
+    return fcNsPrefix;
+  }
+
+  @Override
+  public String getFcNsUri() {
+    return fcNsUri;
+  }
+
+  @Override
+  public String getFcSourcePath() {
+    return fcSourcePath;
+  }
+
+  @Override
+  public String getFcTargetPath() {
+    return fcTargetPath;
+  }
+
+  /**
+   * @return <b>boolean</b>
+   */
+  public Boolean getFcKeepInContent() {
+    return fcKeepInContent;
+  }
+
+  /**
+   * Sets if this is kept in content.
+   * @param fcKeepInContent
+   * @return {@link CustomizableFeedMappings} for method chaining
+   */
+  public CustomizableFeedMappings setFcKeepInContent(final Boolean fcKeepInContent) {
+    this.fcKeepInContent = fcKeepInContent;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmContentKind}.
+   * @param fcContentKind
+   * @return {@link CustomizableFeedMappings} for method chaining
+   */
+  public CustomizableFeedMappings setFcContentKind(final EdmContentKind fcContentKind) {
+    this.fcContentKind = fcContentKind;
+    return this;
+  }
+
+  /**
+   * Sets the prefix.
+   * @param fcNsPrefix
+   * @return {@link CustomizableFeedMappings} for method chaining
+   */
+  public CustomizableFeedMappings setFcNsPrefix(final String fcNsPrefix) {
+    this.fcNsPrefix = fcNsPrefix;
+    return this;
+  }
+
+  /**
+   * Sets the Uri.
+   * @param fcNsUri
+   * @return {@link CustomizableFeedMappings} for method chaining
+   */
+  public CustomizableFeedMappings setFcNsUri(final String fcNsUri) {
+    this.fcNsUri = fcNsUri;
+    return this;
+  }
+
+  /**
+   * Sets the source path.
+   * @param fcSourcePath
+   * @return {@link CustomizableFeedMappings} for method chaining
+   */
+  public CustomizableFeedMappings setFcSourcePath(final String fcSourcePath) {
+    this.fcSourcePath = fcSourcePath;
+    return this;
+  }
+
+  /**
+   * <p>Sets the target path.</p>
+   * <p>For standard Atom elements, constants are available in
+   * {@link org.apache.olingo.odata2.api.edm.EdmTargetPath EdmTargetPath}.</p>
+   * @param fcTargetPath
+   * @return {@link CustomizableFeedMappings} for method chaining
+   */
+  public CustomizableFeedMappings setFcTargetPath(final String fcTargetPath) {
+    this.fcTargetPath = fcTargetPath;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/DataServices.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/DataServices.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/DataServices.java
new file mode 100644
index 0000000..908dac6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/DataServices.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent the data service. They contain all schemas of the EDM as well as the dataServiceVersion
+ * @author SAP AG
+ */
+public class DataServices {
+
+  private List<Schema> schemas;
+  private String dataServiceVersion;
+
+  /**
+   * Sets the schemas for this {@link DataServices}
+   * @param schemas
+   * @return {@link DataServices} for method chaining
+   */
+  public DataServices setSchemas(final List<Schema> schemas) {
+    this.schemas = schemas;
+    return this;
+  }
+
+  /**
+   * Sets the data service version for this {@link DataServices}
+   * @param dataServiceVersion
+   * @return {@link DataServices} for method chaining
+   */
+  public DataServices setDataServiceVersion(final String dataServiceVersion) {
+    this.dataServiceVersion = dataServiceVersion;
+    return this;
+  }
+
+  /**
+   * @return List<{@link Schema}>
+   */
+  public List<Schema> getSchemas() {
+    return schemas;
+  }
+
+  /**
+   * @return <b>String</b> data service version
+   */
+  public String getDataServiceVersion() {
+    return dataServiceVersion;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Documentation.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Documentation.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Documentation.java
new file mode 100644
index 0000000..36da190
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Documentation.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent documentation
+ * @author SAP AG
+ */
+public class Documentation {
+
+  private String summary;
+  private String longDescription;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> summary
+   */
+  public String getSummary() {
+    return summary;
+  }
+
+  /**
+   * @return <b>String</b> the long description
+   */
+  public String getLongDescription() {
+    return longDescription;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the summary for this {@link Documentation}
+   * @param summary
+   * @return {@link Documentation} for method chaining
+   */
+  public Documentation setSummary(final String summary) {
+    this.summary = summary;
+    return this;
+  }
+
+  /**
+   * Sets the long description for this {@link Documentation}
+   * @param longDescription
+   * @return {@link Documentation} for method chaining
+   */
+  public Documentation setLongDescription(final String longDescription) {
+    this.longDescription = longDescription;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link Documentation}
+   * @param annotationAttributes
+   * @return {@link Documentation} for method chaining
+   */
+  public Documentation setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link Documentation}
+   * @param annotationElements
+   * @return {@link Documentation} for method chaining
+   */
+  public Documentation setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}


[43/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImpl.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImpl.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImpl.java
new file mode 100644
index 0000000..4070032
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmBaseViewImpl.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import javax.persistence.metamodel.Metamodel;
+
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmBaseView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmExtension;
+
+public abstract class JPAEdmBaseViewImpl implements JPAEdmBaseView {
+
+  protected String pUnitName = null;
+  protected Metamodel metaModel = null;
+  protected boolean isConsistent = true;
+  protected JPAEdmBuilder builder = null;
+  protected JPAEdmExtension jpaEdmExtension = null;
+  private JPAEdmMappingModelAccess jpaEdmMappingModelAccess = null;
+
+  public JPAEdmBaseViewImpl(final JPAEdmBaseView view) {
+    pUnitName = view.getpUnitName();
+    metaModel = view.getJPAMetaModel();
+    jpaEdmMappingModelAccess = view.getJPAEdmMappingModelAccess();
+    jpaEdmExtension = view.getJPAEdmExtension();
+  }
+
+  public JPAEdmBaseViewImpl(final ODataJPAContext context) {
+    pUnitName = context.getPersistenceUnitName();
+    metaModel = context.getEntityManagerFactory().getMetamodel();
+    jpaEdmMappingModelAccess = ODataJPAFactory.createFactory()
+        .getJPAAccessFactory().getJPAEdmMappingModelAccess(context);
+    jpaEdmExtension = context.getJPAEdmExtension();
+    jpaEdmMappingModelAccess.loadMappingModel();
+  }
+
+  public JPAEdmBaseViewImpl(final Metamodel metaModel, final String pUnitName) {
+    this.metaModel = metaModel;
+    this.pUnitName = pUnitName;
+  }
+
+  @Override
+  public String getpUnitName() {
+    return pUnitName;
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return metaModel;
+  }
+
+  @Override
+  public boolean isConsistent() {
+    return isConsistent;
+  }
+
+  @Override
+  public void clean() {
+    pUnitName = null;
+    metaModel = null;
+    isConsistent = false;
+  }
+
+  @Override
+  public JPAEdmMappingModelAccess getJPAEdmMappingModelAccess() {
+    return jpaEdmMappingModelAccess;
+
+  }
+
+  @Override
+  public JPAEdmExtension getJPAEdmExtension() {
+    return jpaEdmExtension;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexType.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexType.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexType.java
new file mode 100644
index 0000000..a68dbc6
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmComplexType.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmComplexType extends JPAEdmBaseViewImpl implements
+    JPAEdmComplexTypeView {
+
+  private JPAEdmSchemaView schemaView;
+  private ComplexType currentComplexType = null;
+  private EmbeddableType<?> currentEmbeddableType = null;
+  private HashMap<String, ComplexType> searchMap = null;
+  private List<ComplexType> consistentComplextTypes = null;
+  private boolean directBuild;
+  private EmbeddableType<?> nestedComplexType = null;
+
+  public JPAEdmComplexType(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+    directBuild = true;
+  }
+
+  public JPAEdmComplexType(final JPAEdmSchemaView view, final Attribute<?, ?> complexAttribute) {
+    super(view);
+    schemaView = view;
+    for (EmbeddableType<?> jpaEmbeddable : schemaView.getJPAMetaModel().getEmbeddables())
+    {
+      if (jpaEmbeddable.getJavaType().getName().equals(complexAttribute.getJavaType().getName()))
+      {
+        nestedComplexType = jpaEmbeddable;
+        break;
+      }
+    }
+    directBuild = false;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmComplexTypeBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public ComplexType getEdmComplexType() {
+    return currentComplexType;
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final String embeddableTypeName) {
+    return searchMap.get(embeddableTypeName);
+  }
+
+  @Override
+  public EmbeddableType<?> getJPAEmbeddableType() {
+    return currentEmbeddableType;
+  }
+
+  @Override
+  public List<ComplexType> getConsistentEdmComplexTypes() {
+    return consistentComplextTypes;
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final FullQualifiedName type) {
+    String name = type.getName();
+    return searchComplexTypeByName(name);
+
+  }
+
+  private ComplexType searchComplexTypeByName(final String name) {
+    for (ComplexType complexType : consistentComplextTypes) {
+      if (null != complexType && null != complexType.getName() && complexType.getName().equals(name)) {
+        return complexType;
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public void addJPAEdmCompleTypeView(final JPAEdmComplexTypeView view) {
+    String searchKey = view.getJPAEmbeddableType().getJavaType().getName();
+
+    if (!searchMap.containsKey(searchKey)) {
+      consistentComplextTypes.add(view.getEdmComplexType());
+      searchMap.put(searchKey, view.getEdmComplexType());
+    }
+  }
+
+  @Override
+  public void expandEdmComplexType(final ComplexType complexType, List<Property> expandedList, final String embeddablePropertyName) {
+
+    if (expandedList == null) {
+      expandedList = new ArrayList<Property>();
+    }
+    for (Property property : complexType.getProperties())
+    {
+      try {
+        SimpleProperty newSimpleProperty = new SimpleProperty();
+        SimpleProperty oldSimpleProperty = (SimpleProperty) property;
+        newSimpleProperty.setAnnotationAttributes(oldSimpleProperty.getAnnotationAttributes());
+        newSimpleProperty.setAnnotationElements(oldSimpleProperty.getAnnotationElements());
+        newSimpleProperty.setCustomizableFeedMappings(oldSimpleProperty.getCustomizableFeedMappings());
+        newSimpleProperty.setDocumentation(oldSimpleProperty.getDocumentation());
+        newSimpleProperty.setFacets(oldSimpleProperty.getFacets());
+        newSimpleProperty.setMimeType(oldSimpleProperty.getMimeType());
+        newSimpleProperty.setName(oldSimpleProperty.getName());
+        newSimpleProperty.setType(oldSimpleProperty.getType());
+        JPAEdmMappingImpl newMapping = new JPAEdmMappingImpl();
+        Mapping mapping = oldSimpleProperty.getMapping();
+        JPAEdmMapping oldMapping = (JPAEdmMapping) mapping;
+        newMapping.setJPAColumnName(oldMapping.getJPAColumnName());
+        newMapping.setInternalName(embeddablePropertyName + "." + mapping.getInternalName());
+        newMapping.setMimeType(mapping.getMimeType());
+        newMapping.setObject(mapping.getObject());
+        newSimpleProperty.setMapping(newMapping);
+        expandedList.add(newSimpleProperty);
+      } catch (ClassCastException e) {
+        ComplexProperty complexProperty = (ComplexProperty) property;
+        String name = complexProperty.getMapping().getInternalName();
+        expandEdmComplexType(searchComplexTypeByName(complexProperty.getName()), expandedList, name);
+      }
+    }
+
+  }
+
+  private class JPAEdmComplexTypeBuilder implements JPAEdmBuilder {
+    /*
+     * 
+     * Each call to build method creates a new Complex Type.
+     * The Complex Type is created only if it is not created
+     * earlier. A local buffer is maintained to track the list
+     * of complex types created.
+     *  
+     * ************************************************************
+     * 				Build EDM Complex Type - STEPS
+     * ************************************************************
+     * 1) Fetch list of embeddable types from JPA Model
+     * 2) Search local buffer if there exists already a Complex 
+     * type for the embeddable type. 
+     * 3) If the complex type was already been built continue with
+     * the next embeddable type, else create new EDM Complex Type.
+     * 4) Create a Property view with Complex Type
+     * 5) Get Property Builder and build the Property with Complex
+     * type.
+     * 6) Set EDM complex type with list of properties built by
+     * the property view
+     * 7) Provide name for EDM complex type.
+     * 
+     * ************************************************************
+     * 				Build EDM Complex Type - STEPS
+     * ************************************************************
+     *
+     */
+    @Override
+    public void build() throws ODataJPAModelException, ODataJPARuntimeException {
+      Set<EmbeddableType<?>> embeddables = new HashSet<EmbeddableType<?>>();
+
+      if (consistentComplextTypes == null) {
+        consistentComplextTypes = new ArrayList<ComplexType>();
+      }
+
+      if (searchMap == null) {
+        searchMap = new HashMap<String, ComplexType>();
+      }
+
+      if (directBuild) {
+        embeddables = schemaView.getJPAMetaModel().getEmbeddables();
+      } else {
+        embeddables.add(nestedComplexType);
+      }
+
+      for (EmbeddableType<?> embeddableType : embeddables) {
+
+        currentEmbeddableType = embeddableType;
+        String searchKey = embeddableType.getJavaType().getName();
+
+        if (searchMap.containsKey(searchKey)) {
+          continue;
+        }
+
+        // Check for need to Exclude
+        if (isExcluded(JPAEdmComplexType.this)) {
+          continue;
+        }
+
+        JPAEdmPropertyView propertyView = new JPAEdmProperty(
+            schemaView, JPAEdmComplexType.this);
+        propertyView.getBuilder().build();
+
+        currentComplexType = new ComplexType();
+        currentComplexType
+            .setProperties(propertyView.getEdmPropertyList());
+        JPAEdmNameBuilder.build(JPAEdmComplexType.this);
+
+        searchMap.put(searchKey, currentComplexType);
+        consistentComplextTypes.add(currentComplexType);
+
+      }
+
+    }
+
+    private boolean isExcluded(final JPAEdmComplexType jpaEdmComplexType) {
+
+      JPAEdmMappingModelAccess mappingModelAccess = jpaEdmComplexType
+          .getJPAEdmMappingModelAccess();
+      if (mappingModelAccess != null
+          && mappingModelAccess.isMappingModelExists()
+          && mappingModelAccess.checkExclusionOfJPAEmbeddableType(jpaEdmComplexType.getJPAEmbeddableType()
+              .getJavaType().getSimpleName())) {
+        return true;
+      }
+      return false;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainer.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainer.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainer.java
new file mode 100644
index 0000000..587c2ef
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainer.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmFunctionImportView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmEntityContainer extends JPAEdmBaseViewImpl implements
+    JPAEdmEntityContainerView {
+
+  private JPAEdmEntitySetView entitySetView;
+  private JPAEdmSchemaView schemaView;
+  private JPAEdmAssociationSetView associationSetView;
+
+  private EntityContainer currentEntityContainer;
+  private List<EntityContainer> consistentEntityContainerList;
+
+  public JPAEdmEntityContainer(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmEntityContainerBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public EntityContainer getEdmEntityContainer() {
+    return currentEntityContainer;
+  }
+
+  @Override
+  public List<EntityContainer> getConsistentEdmEntityContainerList() {
+    return consistentEntityContainerList;
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return entitySetView;
+  }
+
+  @Override
+  public JPAEdmAssociationSetView getEdmAssociationSetView() {
+    return associationSetView;
+  }
+
+  @Override
+  public void clean() {
+    super.clean();
+    entitySetView = null;
+    associationSetView = null;
+    currentEntityContainer = null;
+    consistentEntityContainerList = null;
+  }
+
+  private class JPAEdmEntityContainerBuilder implements JPAEdmBuilder {
+    /*
+     * 
+     * Each call to build method creates a new Entity Container and builds
+     * the entity container with Association Sets and Entity Sets. The newly
+     * created and built entity container is added to the exiting Entity
+     * Container List.
+     * 
+     * ************************************************************ Build
+     * EDM Entity Container - STEPS
+     * ************************************************************ 1)
+     * Instantiate New EDM Entity Container 2) Build Name for EDM Entity
+     * Container 2) Create Entity Container List (if does not exists) 3)
+     * Build EDM Entity Set 4) Add EDM Entity Set to EDM Entity Container 6)
+     * Build EDM Association Set 7) Add EDM Association Set to EDM Entity
+     * Container 8) Add EDM Entity Container to the Container List
+     * ************************************************************ Build
+     * EDM Entity Container - STEPS
+     * ************************************************************
+     */
+    @Override
+    public void build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+
+      currentEntityContainer = new EntityContainer();
+
+      if (consistentEntityContainerList == null) {
+        currentEntityContainer.setDefaultEntityContainer(true);
+        consistentEntityContainerList = new ArrayList<EntityContainer>();
+      }
+
+      entitySetView = new JPAEdmEntitySet(schemaView);
+      entitySetView.getBuilder().build();
+      if (entitySetView.isConsistent()) {
+        currentEntityContainer.setEntitySets(entitySetView
+            .getConsistentEdmEntitySetList());
+      } else {
+        isConsistent = false;
+        return;
+      }
+
+      if (!schemaView.getJPAEdmAssociationView().isConsistent()) {
+        schemaView.getJPAEdmAssociationView().getBuilder().build();
+      }
+
+      associationSetView = new JPAEdmAssociationSet(schemaView);
+      associationSetView.getBuilder().build();
+      if (associationSetView.isConsistent()) {
+        currentEntityContainer.setAssociationSets(associationSetView
+            .getConsistentEdmAssociationSetList());
+      } else {
+        isConsistent = false;
+        return;
+      }
+
+      JPAEdmNameBuilder.build(JPAEdmEntityContainer.this);
+      if (schemaView.getJPAEdmExtension() != null) {
+        JPAEdmFunctionImportView functionImportView = new JPAEdmFunctionImport(
+            schemaView);
+        functionImportView.getBuilder().build();
+        if (functionImportView.getConsistentFunctionImportList() != null) {
+          currentEntityContainer
+              .setFunctionImports(functionImportView
+                  .getConsistentFunctionImportList());
+        }
+      }
+
+      consistentEntityContainerList.add(currentEntityContainer);
+      isConsistent = true;
+
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySet.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySet.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySet.java
new file mode 100644
index 0000000..d79ac2d
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySet.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmEntitySet extends JPAEdmBaseViewImpl implements
+    JPAEdmEntitySetView {
+
+  private EntitySet currentEntitySet = null;
+  private List<EntitySet> consistentEntitySetList = null;
+  private JPAEdmEntityTypeView entityTypeView = null;
+  private JPAEdmSchemaView schemaView;
+
+  public JPAEdmEntitySet(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmEntitySetBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public EntitySet getEdmEntitySet() {
+    return currentEntitySet;
+  }
+
+  @Override
+  public List<EntitySet> getConsistentEdmEntitySetList() {
+    return consistentEntitySetList;
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return entityTypeView;
+  }
+
+  @Override
+  public void clean() {
+    currentEntitySet = null;
+    consistentEntitySetList = null;
+    entityTypeView = null;
+    isConsistent = false;
+  }
+
+  private class JPAEdmEntitySetBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException, ODataJPARuntimeException {
+
+      if (consistentEntitySetList == null) {
+        consistentEntitySetList = new ArrayList<EntitySet>();
+      }
+
+      entityTypeView = new JPAEdmEntityType(schemaView);
+      entityTypeView.getBuilder().build();
+
+      if (entityTypeView.isConsistent() && entityTypeView.getConsistentEdmEntityTypes() != null) {
+
+        String nameSpace = schemaView.getEdmSchema().getNamespace();
+        for (EntityType entityType : entityTypeView
+            .getConsistentEdmEntityTypes()) {
+
+          currentEntitySet = new EntitySet();
+          currentEntitySet.setEntityType(new FullQualifiedName(
+              nameSpace, entityType.getName()));
+          JPAEdmNameBuilder.build(JPAEdmEntitySet.this, entityTypeView);
+          consistentEntitySetList.add(currentEntitySet);
+
+        }
+        isConsistent = true;
+      } else {
+        isConsistent = false;
+        return;
+      }
+
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityType.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityType.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityType.java
new file mode 100644
index 0000000..7bb5a5c
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityType.java
@@ -0,0 +1,242 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmEntityType extends JPAEdmBaseViewImpl implements
+    JPAEdmEntityTypeView {
+
+  private JPAEdmSchemaView schemaView = null;
+  private EntityType currentEdmEntityType = null;
+  private javax.persistence.metamodel.EntityType<?> currentJPAEntityType = null;
+  private EntityTypeList<EntityType> consistentEntityTypes = null;
+
+  private HashMap<String, EntityType> consistentEntityTypeMap;
+
+  public JPAEdmEntityType(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+    consistentEntityTypeMap = new HashMap<String, EntityType>();
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmEntityTypeBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public EntityType getEdmEntityType() {
+    return currentEdmEntityType;
+  }
+
+  @Override
+  public javax.persistence.metamodel.EntityType<?> getJPAEntityType() {
+    return currentJPAEntityType;
+  }
+
+  @Override
+  public List<EntityType> getConsistentEdmEntityTypes() {
+    return consistentEntityTypes;
+  }
+
+  @Override
+  public EntityType searchEdmEntityType(final String jpaEntityTypeName) {
+    return consistentEntityTypeMap.get(jpaEntityTypeName);
+  }
+
+  private class JPAEdmEntityTypeBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+
+      Set<javax.persistence.metamodel.EntityType<?>> jpaEntityTypes = metaModel
+          .getEntities();
+
+      if (jpaEntityTypes == null || jpaEntityTypes.isEmpty() == true) {
+        return;
+      } else if (consistentEntityTypes == null) {
+        consistentEntityTypes = new EntityTypeList<EntityType>();
+
+      }
+
+      for (javax.persistence.metamodel.EntityType<?> jpaEntityType : jpaEntityTypes) {
+        currentEdmEntityType = new EntityType();
+        currentJPAEntityType = jpaEntityType;
+
+        // Check for need to Exclude
+        if (isExcluded(JPAEdmEntityType.this)) {
+          continue;
+        }
+
+        JPAEdmNameBuilder.build(JPAEdmEntityType.this);
+
+        JPAEdmPropertyView propertyView = new JPAEdmProperty(schemaView);
+        propertyView.getBuilder().build();
+
+        currentEdmEntityType.setProperties(propertyView
+            .getEdmPropertyList());
+        if (propertyView.getJPAEdmNavigationPropertyView() != null) {
+          JPAEdmNavigationPropertyView navPropView = propertyView
+              .getJPAEdmNavigationPropertyView();
+          if (navPropView.getConsistentEdmNavigationProperties() != null
+              && !navPropView
+                  .getConsistentEdmNavigationProperties()
+                  .isEmpty()) {
+            currentEdmEntityType
+                .setNavigationProperties(navPropView
+                    .getConsistentEdmNavigationProperties());
+          }
+        }
+        JPAEdmKeyView keyView = propertyView.getJPAEdmKeyView();
+        currentEdmEntityType.setKey(keyView.getEdmKey());
+
+        consistentEntityTypes.add(currentEdmEntityType);
+        consistentEntityTypeMap.put(currentJPAEntityType.getName(),
+            currentEdmEntityType);
+      }
+
+    }
+
+    private boolean isExcluded(final JPAEdmEntityType jpaEdmEntityType) {
+      JPAEdmMappingModelAccess mappingModelAccess = jpaEdmEntityType
+          .getJPAEdmMappingModelAccess();
+      if (mappingModelAccess != null
+          && mappingModelAccess.isMappingModelExists()
+          && mappingModelAccess.checkExclusionOfJPAEntityType(jpaEdmEntityType.getJPAEntityType().getName())) {
+        return true;
+      }
+      return false;
+    }
+
+  }
+
+  private class EntityTypeList<X> extends ArrayList<EntityType> {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 719079109608251592L;
+
+    @Override
+    public Iterator<EntityType> iterator() {
+      return new EntityTypeListIterator<X>(size());
+    }
+
+  }
+
+  private class EntityTypeListIterator<E> implements ListIterator<EntityType> {
+
+    private int size = 0;
+    private int pos = 0;
+
+    public EntityTypeListIterator(final int listSize) {
+      this.size = listSize;
+    }
+
+    @Override
+    public void add(final EntityType e) {
+      consistentEntityTypes.add(e);
+      size++;
+    }
+
+    @Override
+    public boolean hasNext() {
+      if (pos < size) {
+        return true;
+      }
+
+      return false;
+    }
+
+    @Override
+    public boolean hasPrevious() {
+      if (pos > 0) {
+        return true;
+      }
+      return false;
+    }
+
+    @Override
+    public EntityType next() {
+      if (pos < size) {
+        currentEdmEntityType = consistentEntityTypes.get(pos++);
+        return currentEdmEntityType;
+      }
+
+      return null;
+    }
+
+    @Override
+    public int nextIndex() {
+      return pos;
+    }
+
+    @Override
+    public EntityType previous() {
+      if (pos > 0 && pos < size) {
+        currentEdmEntityType = consistentEntityTypes.get(--pos);
+        return currentEdmEntityType;
+      }
+      return null;
+    }
+
+    @Override
+    public int previousIndex() {
+      if (pos > 0) {
+        return pos - 1;
+      }
+
+      return 0;
+    }
+
+    @Override
+    public void remove() {
+      consistentEntityTypes.remove(pos);
+    }
+
+    @Override
+    public void set(final EntityType e) {
+      consistentEntityTypes.set(pos, e);
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImport.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImport.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImport.java
new file mode 100644
index 0000000..ad12196
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImport.java
@@ -0,0 +1,357 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport.Multiplicity;
+import org.apache.olingo.odata2.api.annotation.edm.FunctionImport.ReturnType;
+import org.apache.olingo.odata2.api.annotation.edm.Parameter;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmFunctionImportView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPATypeConvertor;
+
+public class JPAEdmFunctionImport extends JPAEdmBaseViewImpl implements
+    JPAEdmFunctionImportView {
+
+  private List<FunctionImport> consistentFunctionImportList = new ArrayList<FunctionImport>();
+  private JPAEdmBuilder builder = null;
+  private JPAEdmSchemaView schemaView;
+
+  public JPAEdmFunctionImport(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmFunctionImportBuilder();
+    }
+    return builder;
+  }
+
+  @Override
+  public List<FunctionImport> getConsistentFunctionImportList() {
+    return consistentFunctionImportList;
+  }
+
+  protected class JPAEdmFunctionImportBuilder implements JPAEdmBuilder {
+
+    private JPAEdmEntityTypeView jpaEdmEntityTypeView = null;
+    private JPAEdmComplexTypeView jpaEdmComplexTypeView = null;
+
+    @Override
+    public void build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+
+      HashMap<Class<?>, String[]> customOperations = schemaView
+          .getRegisteredOperations();
+
+      jpaEdmEntityTypeView = schemaView.getJPAEdmEntityContainerView()
+          .getJPAEdmEntitySetView().getJPAEdmEntityTypeView();
+      jpaEdmComplexTypeView = schemaView.getJPAEdmComplexTypeView();
+
+      if (customOperations != null) {
+
+        for (Class<?> clazz : customOperations.keySet()) {
+
+          String[] operationNames = customOperations.get(clazz);
+          Method[] methods = clazz.getMethods();
+          Method method = null;
+
+          int length = 0;
+          if (operationNames != null) {
+            length = operationNames.length;
+          } else {
+            length = methods.length;
+          }
+
+          boolean found = false;
+          for (int i = 0; i < length; i++) {
+
+            try {
+              if (operationNames != null) {
+                for (Method method2 : methods) {
+                  if (method2.getName().equals(
+                      operationNames[i])) {
+                    found = true;
+                    method = method2;
+                    break;
+                  }
+                }
+                if (found == true) {
+                  found = false;
+                } else {
+                  continue;
+                }
+              } else {
+                method = methods[i];
+              }
+
+              FunctionImport functionImport = buildFunctionImport(method);
+              if (functionImport != null) {
+                consistentFunctionImportList
+                    .add(functionImport);
+              }
+
+            } catch (SecurityException e) {
+              throw ODataJPAModelException.throwException(
+                  ODataJPAModelException.GENERAL, e);
+            }
+          }
+        }
+      }
+    }
+
+    private FunctionImport buildFunctionImport(final Method method)
+        throws ODataJPAModelException {
+
+      org.apache.olingo.odata2.api.annotation.edm.FunctionImport annotation = method
+          .getAnnotation(org.apache.olingo.odata2.api.annotation.edm.FunctionImport.class);
+      if (annotation != null && annotation.returnType() != ReturnType.NONE) {
+        FunctionImport functionImport = new FunctionImport();
+
+        if (annotation.name().equals("")) {
+          functionImport.setName(method.getName());
+        } else {
+          functionImport.setName(annotation.name());
+        }
+
+        JPAEdmMapping mapping = new JPAEdmMappingImpl();
+        ((Mapping) mapping).setInternalName(method.getName());
+        mapping.setJPAType(method.getDeclaringClass());
+        functionImport.setMapping((Mapping) mapping);
+
+        functionImport.setHttpMethod(annotation.httpMethod().name().toString());
+
+        buildReturnType(functionImport, method, annotation);
+        buildParameter(functionImport, method);
+
+        return functionImport;
+      }
+      return null;
+    }
+
+    private void buildParameter(final FunctionImport functionImport, final Method method)
+        throws ODataJPAModelException {
+
+      Annotation[][] annotations = method.getParameterAnnotations();
+      Class<?>[] parameterTypes = method.getParameterTypes();
+      List<FunctionImportParameter> funcImpList = new ArrayList<FunctionImportParameter>();
+      JPAEdmMapping mapping = null;
+      int j = 0;
+      for (Annotation[] annotationArr : annotations) {
+        Class<?> parameterType = parameterTypes[j++];
+
+        for (Annotation element : annotationArr) {
+          if (element instanceof Parameter) {
+            Parameter annotation = (Parameter) element;
+            FunctionImportParameter functionImportParameter = new FunctionImportParameter();
+            if (annotation.name().equals("")) {
+              throw ODataJPAModelException.throwException(
+                  ODataJPAModelException.FUNC_PARAM_NAME_EXP
+                      .addContent(method
+                          .getDeclaringClass()
+                          .getName(), method
+                          .getName()), null);
+            } else {
+              functionImportParameter.setName(annotation.name());
+            }
+
+            functionImportParameter.setType(JPATypeConvertor
+                .convertToEdmSimpleType(parameterType, null));
+            functionImportParameter.setMode(annotation.mode()
+                .toString());
+
+            Facets facets = new Facets();
+            if (annotation.facets().maxLength() > 0) {
+              facets.setMaxLength(annotation.facets().maxLength());
+            }
+            if (annotation.facets().nullable() == false) {
+              facets.setNullable(false);
+            } else {
+              facets.setNullable(true);
+            }
+
+            if (annotation.facets().precision() > 0) {
+              facets.setPrecision(annotation.facets().precision());
+            }
+            if (annotation.facets().scale() >= 0) {
+              facets.setScale(annotation.facets().scale());
+            }
+
+            functionImportParameter.setFacets(facets);
+            mapping = new JPAEdmMappingImpl();
+            mapping.setJPAType(parameterType);
+            functionImportParameter.setMapping((Mapping) mapping);
+            funcImpList.add(functionImportParameter);
+          }
+        }
+      }
+      if (!funcImpList.isEmpty()) {
+        functionImport.setParameters(funcImpList);
+      }
+    }
+
+    private void buildReturnType(final FunctionImport functionImport,
+        final Method method,
+        final org.apache.olingo.odata2.api.annotation.edm.FunctionImport annotation)
+        throws ODataJPAModelException {
+      ReturnType returnType = annotation.returnType();
+      Multiplicity multiplicity = null;
+
+      if (returnType != ReturnType.NONE) {
+        org.apache.olingo.odata2.api.edm.provider.ReturnType functionReturnType = new org.apache.olingo.odata2.api.edm.provider.ReturnType();
+        multiplicity = annotation.multiplicity();
+
+        if (multiplicity == Multiplicity.MANY) {
+          functionReturnType.setMultiplicity(EdmMultiplicity.MANY);
+        } else {
+          functionReturnType.setMultiplicity(EdmMultiplicity.ONE);
+        }
+
+        if (returnType == ReturnType.ENTITY_TYPE) {
+          String entitySet = annotation.entitySet();
+          if (entitySet.equals("")) {
+            throw ODataJPAModelException
+                .throwException(
+                    ODataJPAModelException.FUNC_ENTITYSET_EXP,
+                    null);
+          }
+          functionImport.setEntitySet(entitySet);
+        }
+
+        Class<?> methodReturnType = method.getReturnType();
+        if (methodReturnType == null
+            || methodReturnType.getName().equals("void")) {
+          throw ODataJPAModelException.throwException(
+              ODataJPAModelException.FUNC_RETURN_TYPE_EXP
+                  .addContent(method.getDeclaringClass(),
+                      method.getName()), null);
+        }
+        switch (returnType) {
+        case ENTITY_TYPE:
+          EntityType edmEntityType = null;
+          if (multiplicity == Multiplicity.ONE) {
+            edmEntityType = jpaEdmEntityTypeView
+                .searchEdmEntityType(methodReturnType
+                    .getSimpleName());
+          } else if (multiplicity == Multiplicity.MANY) {
+            edmEntityType = jpaEdmEntityTypeView
+                .searchEdmEntityType(getReturnTypeSimpleName(method));
+          }
+
+          if (edmEntityType == null) {
+            throw ODataJPAModelException
+                .throwException(
+                    ODataJPAModelException.FUNC_RETURN_TYPE_ENTITY_NOT_FOUND
+                        .addContent(
+                            method.getDeclaringClass(),
+                            method.getName(),
+                            methodReturnType
+                                .getSimpleName()),
+                    null);
+          }
+          functionReturnType.setTypeName(JPAEdmNameBuilder.build(
+              schemaView, edmEntityType.getName()));
+          break;
+        case SCALAR:
+
+          EdmSimpleTypeKind edmSimpleTypeKind = JPATypeConvertor
+              .convertToEdmSimpleType(methodReturnType, null);
+          functionReturnType.setTypeName(edmSimpleTypeKind
+              .getFullQualifiedName());
+
+          break;
+        case COMPLEX_TYPE:
+          ComplexType complexType = null;
+          if (multiplicity == Multiplicity.ONE) {
+            complexType = jpaEdmComplexTypeView
+                .searchEdmComplexType(methodReturnType
+                    .getName());
+          } else if (multiplicity == Multiplicity.MANY) {
+            complexType = jpaEdmComplexTypeView
+                .searchEdmComplexType(getReturnTypeName(method));
+          }
+          if (complexType == null) {
+            throw ODataJPAModelException
+                .throwException(
+                    ODataJPAModelException.FUNC_RETURN_TYPE_ENTITY_NOT_FOUND
+                        .addContent(
+                            method.getDeclaringClass(),
+                            method.getName(),
+                            methodReturnType
+                                .getSimpleName()),
+                    null);
+          }
+          functionReturnType.setTypeName(JPAEdmNameBuilder.build(
+              schemaView, complexType.getName()));
+          break;
+        default:
+          break;
+        }
+        functionImport.setReturnType(functionReturnType);
+      }
+    }
+
+    private String getReturnTypeName(final Method method) {
+      try {
+        ParameterizedType pt = (ParameterizedType) method
+            .getGenericReturnType();
+        Type t = pt.getActualTypeArguments()[0];
+        return ((Class<?>) t).getName();
+      } catch (ClassCastException e) {
+        return method.getReturnType().getName();
+      }
+    }
+
+    private String getReturnTypeSimpleName(final Method method) {
+      try {
+        ParameterizedType pt = (ParameterizedType) method
+            .getGenericReturnType();
+        Type t = pt.getActualTypeArguments()[0];
+        return ((Class<?>) t).getSimpleName();
+      } catch (ClassCastException e) {
+        return method.getReturnType().getSimpleName();
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKey.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKey.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKey.java
new file mode 100644
index 0000000..bc4a370
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKey.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+
+public class JPAEdmKey extends JPAEdmBaseViewImpl implements JPAEdmKeyView {
+
+  private JPAEdmPropertyView propertyView;
+  private JPAEdmComplexTypeView complexTypeView = null;
+  private boolean isBuildModeComplexType = false;
+  private Key key;
+
+  public JPAEdmKey(final JPAEdmProperty view) {
+    super(view);
+    propertyView = view;
+  }
+
+  public JPAEdmKey(final JPAEdmComplexTypeView complexTypeView,
+      final JPAEdmPropertyView propertyView) {
+    super(complexTypeView);
+    this.propertyView = propertyView;
+    this.complexTypeView = complexTypeView;
+    isBuildModeComplexType = true;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmKeyBuider();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public Key getEdmKey() {
+    return key;
+  }
+
+  private class JPAEdmKeyBuider implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException {
+
+      List<PropertyRef> propertyRefList = null;
+      if (key == null) {
+        key = new Key();
+      }
+
+      if (key.getKeys() == null) {
+        propertyRefList = new ArrayList<PropertyRef>();
+        key.setKeys(propertyRefList);
+      } else {
+        propertyRefList = key.getKeys();
+      }
+
+      if (isBuildModeComplexType) {
+        ComplexType complexType = complexTypeView
+            .searchEdmComplexType(propertyView
+                .getJPAAttribute().getJavaType().getName());
+        normalizeComplexKey(complexType, propertyRefList);
+      } else {
+        PropertyRef propertyRef = new PropertyRef();
+        propertyRef.setName(propertyView.getEdmSimpleProperty().getName());
+        Facets facets = (Facets) propertyView.getEdmSimpleProperty().getFacets();
+        if (facets == null) {
+          propertyView.getEdmSimpleProperty().setFacets(new Facets().setNullable(false));
+        } else {
+          facets.setNullable(false);
+        }
+        propertyRefList.add(propertyRef);
+      }
+
+    }
+
+    //TODO think how to stop the recursion if A includes B and B includes A!!!!!!
+    public void normalizeComplexKey(final ComplexType complexType, final List<PropertyRef> propertyRefList) {
+      for (Property property : complexType.getProperties()) {
+        try {
+
+          SimpleProperty simpleProperty = (SimpleProperty) property;
+          Facets facets = (Facets) simpleProperty.getFacets();
+          if (facets == null) {
+            simpleProperty.setFacets(new Facets().setNullable(false));
+          } else {
+            facets.setNullable(false);
+          }
+          PropertyRef propertyRef = new PropertyRef();
+          propertyRef.setName(simpleProperty.getName());
+          propertyRefList.add(propertyRef);
+
+        } catch (ClassCastException e) {
+          ComplexProperty complexProperty = (ComplexProperty) property;
+          normalizeComplexKey(complexTypeView.searchEdmComplexType(complexProperty.getType()), propertyRefList);
+        }
+
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmMappingImpl.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmMappingImpl.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmMappingImpl.java
new file mode 100644
index 0000000..cc40fad
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmMappingImpl.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+
+public class JPAEdmMappingImpl extends Mapping implements JPAEdmMapping {
+
+  private String columnName = null;
+  private Class<?> type = null;
+
+  @Override
+  public void setJPAColumnName(final String name) {
+    columnName = name;
+
+  }
+
+  @Override
+  public String getJPAColumnName() {
+    return columnName;
+  }
+
+  @Override
+  public void setJPAType(final Class<?> type) {
+    this.type = type;
+
+  }
+
+  @Override
+  public Class<?> getJPAType() {
+    return type;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModel.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModel.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModel.java
new file mode 100644
index 0000000..a307fa1
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModel.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import javax.persistence.metamodel.Metamodel;
+
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+
+public class JPAEdmModel extends JPAEdmBaseViewImpl implements JPAEdmModelView {
+
+  protected JPAEdmSchemaView schemaView;
+
+  public JPAEdmModel(final Metamodel metaModel, final String pUnitName) {
+    super(metaModel, pUnitName);
+  }
+
+  public JPAEdmModel(final ODataJPAContext ctx) {
+    super(ctx);
+  }
+
+  @Override
+  public JPAEdmSchemaView getEdmSchemaView() {
+    return schemaView;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmModelBuilder();
+    }
+
+    return builder;
+  }
+
+  private class JPAEdmModelBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException, ODataJPARuntimeException {
+      schemaView = new JPAEdmSchema(JPAEdmModel.this);
+      schemaView.getBuilder().build();
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationProperty.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationProperty.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationProperty.java
new file mode 100644
index 0000000..d5e16f6
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationProperty.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmNavigationProperty extends JPAEdmBaseViewImpl implements
+    JPAEdmNavigationPropertyView {
+
+  private JPAEdmAssociationView associationView = null;
+  private NavigationProperty currentNavigationProperty = null;
+  private JPAEdmPropertyView propertyView = null;
+  private List<NavigationProperty> consistentNavigationProperties = null;
+  private int count;
+
+  public JPAEdmNavigationProperty(final JPAEdmAssociationView associationView,
+      final JPAEdmPropertyView propertyView, final int countNumber) {
+    super(associationView);
+    this.associationView = associationView;
+    this.propertyView = propertyView;
+    count = countNumber;
+    if (consistentNavigationProperties == null)
+    {
+      consistentNavigationProperties = new ArrayList<NavigationProperty>();
+    }
+  }
+
+  public JPAEdmNavigationProperty(final JPAEdmSchemaView schemaView) {
+    super(schemaView);
+    consistentNavigationProperties = new ArrayList<NavigationProperty>();
+
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmNavigationPropertyBuilder();
+    }
+
+    return builder;
+  }
+
+  private class JPAEdmNavigationPropertyBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException {
+
+      currentNavigationProperty = new NavigationProperty();
+      JPAEdmNameBuilder.build(associationView, propertyView,
+          JPAEdmNavigationProperty.this, count);
+      consistentNavigationProperties.add(currentNavigationProperty);
+    }
+
+  }
+
+  @Override
+  public NavigationProperty getEdmNavigationProperty() {
+    return currentNavigationProperty;
+  }
+
+  @Override
+  public List<NavigationProperty> getConsistentEdmNavigationProperties() {
+    return consistentNavigationProperties;
+  }
+
+  @Override
+  public void addJPAEdmNavigationPropertyView(
+      final JPAEdmNavigationPropertyView view) {
+    if (view != null && view.isConsistent()) {
+      currentNavigationProperty = view.getEdmNavigationProperty();
+      consistentNavigationProperties.add(currentNavigationProperty);
+
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmProperty.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmProperty.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmProperty.java
new file mode 100644
index 0000000..7d96345
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmProperty.java
@@ -0,0 +1,405 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.Attribute.PersistentAttributeType;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPATypeConvertor;
+
+public class JPAEdmProperty extends JPAEdmBaseViewImpl implements
+    JPAEdmPropertyView, JPAEdmComplexPropertyView {
+
+  private JPAEdmSchemaView schemaView;
+  private JPAEdmEntityTypeView entityTypeView;
+  private JPAEdmComplexTypeView complexTypeView;
+  private JPAEdmNavigationPropertyView navigationPropertyView = null;
+
+  private JPAEdmKeyView keyView;
+  private List<Property> properties;
+  private SimpleProperty currentSimpleProperty = null;
+  private ComplexProperty currentComplexProperty = null;
+  private Attribute<?, ?> currentAttribute;
+  private boolean isBuildModeComplexType;
+  private Map<String, Integer> associationCount;
+
+  public JPAEdmProperty(final JPAEdmSchemaView view) {
+    super(view);
+    schemaView = view;
+    entityTypeView = schemaView.getJPAEdmEntityContainerView()
+        .getJPAEdmEntitySetView().getJPAEdmEntityTypeView();
+    complexTypeView = schemaView.getJPAEdmComplexTypeView();
+    navigationPropertyView = new JPAEdmNavigationProperty(schemaView);
+    isBuildModeComplexType = false;
+    associationCount = new HashMap<String, Integer>();
+  }
+
+  public JPAEdmProperty(final JPAEdmSchemaView schemaView,
+      final JPAEdmComplexTypeView view) {
+    super(view);
+    this.schemaView = schemaView;
+    complexTypeView = view;
+    isBuildModeComplexType = true;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmPropertyBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public List<Property> getEdmPropertyList() {
+    return properties;
+  }
+
+  @Override
+  public JPAEdmKeyView getJPAEdmKeyView() {
+    return keyView;
+  }
+
+  @Override
+  public SimpleProperty getEdmSimpleProperty() {
+    return currentSimpleProperty;
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return currentAttribute;
+  }
+
+  @Override
+  public ComplexProperty getEdmComplexProperty() {
+    return currentComplexProperty;
+  }
+
+  @Override
+  public JPAEdmNavigationPropertyView getJPAEdmNavigationPropertyView()
+  {
+    return navigationPropertyView;
+  }
+
+  private class JPAEdmPropertyBuilder implements JPAEdmBuilder {
+    /*
+     * 
+     * Each call to build method creates a new EDM Property List. 
+     * The Property List can be created either by an Entity type or
+     * ComplexType. The flag isBuildModeComplexType tells if the
+     * Properties are built for complex type or for Entity Type.
+     * 
+     * While Building Properties Associations are built. However
+     * the associations thus built does not contain Referential
+     * constraint. Associations thus built only contains
+     * information about Referential constraints. Adding of
+     * referential constraints to Associations is the taken care
+     * by Schema.
+     * 
+     * Building Properties is divided into four parts
+     * 	A) Building Simple Properties
+     * 	B) Building Complex Properties
+     * 	C) Building Associations
+     * 	D) Building Navigation Properties
+     *  
+     * ************************************************************
+     * 					Build EDM Schema - STEPS
+     * ************************************************************
+     * A) 	Building Simple Properties:
+     * 
+     * 	1) 	Fetch JPA Attribute List from 
+     * 			A) Complex Type
+     * 			B) Entity Type
+     * 	  	depending on isBuildModeComplexType.
+     * B)	Building Complex Properties
+     * C)	Building Associations
+     * D)	Building Navigation Properties
+    	
+     * ************************************************************
+     * 					Build EDM Schema - STEPS
+     * ************************************************************
+     *
+     */
+    @Override
+    public void build() throws ODataJPAModelException, ODataJPARuntimeException {
+
+      JPAEdmBuilder keyViewBuilder = null;
+
+      properties = new ArrayList<Property>();
+
+      List<Attribute<?, ?>> jpaAttributes = null;
+      String currentEntityName = null;
+      String targetEntityName = null;
+      String entityTypeName = null;
+      if (isBuildModeComplexType) {
+        jpaAttributes = sortInAscendingOrder(complexTypeView.getJPAEmbeddableType()
+            .getAttributes());
+        entityTypeName = complexTypeView.getJPAEmbeddableType().getJavaType()
+            .getSimpleName();
+      } else {
+        jpaAttributes = sortInAscendingOrder(entityTypeView.getJPAEntityType()
+            .getAttributes());
+        entityTypeName = entityTypeView.getJPAEntityType().getName();
+      }
+
+      for (Object jpaAttribute : jpaAttributes) {
+        currentAttribute = (Attribute<?, ?>) jpaAttribute;
+
+        // Check for need to Exclude 
+        if (isExcluded((JPAEdmPropertyView) JPAEdmProperty.this, entityTypeName, currentAttribute.getName())) {
+          continue;
+        }
+
+        PersistentAttributeType attributeType = currentAttribute
+            .getPersistentAttributeType();
+
+        switch (attributeType) {
+        case BASIC:
+
+          currentSimpleProperty = new SimpleProperty();
+          JPAEdmNameBuilder
+              .build((JPAEdmPropertyView) JPAEdmProperty.this, isBuildModeComplexType);
+
+          EdmSimpleTypeKind simpleTypeKind = JPATypeConvertor
+              .convertToEdmSimpleType(currentAttribute
+                  .getJavaType(), currentAttribute);
+
+          currentSimpleProperty.setType(simpleTypeKind);
+          currentSimpleProperty
+              .setFacets(setFacets(currentAttribute));
+
+          properties.add(currentSimpleProperty);
+
+          if (((SingularAttribute<?, ?>) currentAttribute).isId()) {
+            if (keyView == null) {
+              keyView = new JPAEdmKey(JPAEdmProperty.this);
+              keyViewBuilder = keyView.getBuilder();
+            }
+
+            keyViewBuilder.build();
+          }
+
+          break;
+        case EMBEDDED:
+          ComplexType complexType = complexTypeView
+              .searchEdmComplexType(currentAttribute.getJavaType().getName());
+
+          if (complexType == null) {
+            JPAEdmComplexTypeView complexTypeViewLocal = new JPAEdmComplexType(
+                schemaView, currentAttribute);
+            complexTypeViewLocal.getBuilder().build();
+            complexType = complexTypeViewLocal.getEdmComplexType();
+            complexTypeView.addJPAEdmCompleTypeView(complexTypeViewLocal);
+
+          }
+
+          if (isBuildModeComplexType == false
+              && entityTypeView.getJPAEntityType().getIdType()
+                  .getJavaType()
+                  .equals(currentAttribute.getJavaType())) {
+
+            if (keyView == null) {
+              keyView = new JPAEdmKey(complexTypeView,
+                  JPAEdmProperty.this);
+            }
+            keyView.getBuilder().build();
+            complexTypeView.expandEdmComplexType(complexType, properties, currentAttribute.getName());
+          }
+          else {
+            currentComplexProperty = new ComplexProperty();
+            if (isBuildModeComplexType) {
+              JPAEdmNameBuilder
+                  .build((JPAEdmComplexPropertyView) JPAEdmProperty.this,
+                      complexTypeView.getJPAEmbeddableType().getJavaType().getSimpleName());
+            } else {
+              JPAEdmNameBuilder
+                  .build((JPAEdmComplexPropertyView) JPAEdmProperty.this,
+                      JPAEdmProperty.this);
+            }
+            currentComplexProperty.setType(new FullQualifiedName(
+                schemaView.getEdmSchema().getNamespace(),
+                complexType.getName()));
+            currentComplexProperty
+                .setFacets(setFacets(currentAttribute));
+            properties.add(currentComplexProperty);
+            List<String> nonKeyComplexTypes = schemaView.getNonKeyComplexTypeList();
+            if (!nonKeyComplexTypes.contains(currentComplexProperty.getType().getName()))
+            {
+              schemaView.addNonKeyComplexName(currentComplexProperty.getType().getName());
+            }
+          }
+
+          break;
+        case MANY_TO_MANY:
+        case ONE_TO_MANY:
+        case ONE_TO_ONE:
+        case MANY_TO_ONE:
+
+          JPAEdmAssociationEndView associationEndView = new JPAEdmAssociationEnd(entityTypeView, JPAEdmProperty.this);
+          associationEndView.getBuilder().build();
+          JPAEdmAssociationView associationView = schemaView.getJPAEdmAssociationView();
+          if (associationView.searchAssociation(associationEndView) == null) {
+            int count = associationView.getNumberOfAssociationsWithSimilarEndPoints(associationEndView);
+            JPAEdmAssociationView associationViewLocal = new JPAEdmAssociation(associationEndView, entityTypeView, JPAEdmProperty.this, count);
+            associationViewLocal.getBuilder().build();
+            associationView.addJPAEdmAssociationView(associationViewLocal, associationEndView);
+          }
+
+          JPAEdmReferentialConstraintView refConstraintView = new JPAEdmReferentialConstraint(
+              associationView, entityTypeView, JPAEdmProperty.this);
+          refConstraintView.getBuilder().build();
+
+          if (refConstraintView.isExists()) {
+            associationView.addJPAEdmRefConstraintView(refConstraintView);
+          }
+
+          if (navigationPropertyView == null)
+          {
+            navigationPropertyView = new JPAEdmNavigationProperty(schemaView);
+          }
+          currentEntityName = entityTypeView.getJPAEntityType().getName();
+          targetEntityName = currentAttribute.getJavaType().getSimpleName();
+          Integer sequenceNumber = associationCount.get(currentEntityName + targetEntityName);
+          if (sequenceNumber == null) {
+            sequenceNumber = new Integer(1);
+          } else {
+            sequenceNumber = new Integer(sequenceNumber.intValue() + 1);
+          }
+          associationCount.put(currentEntityName + targetEntityName, sequenceNumber);
+          JPAEdmNavigationPropertyView localNavigationPropertyView = new JPAEdmNavigationProperty(associationView, JPAEdmProperty.this, sequenceNumber.intValue());
+          localNavigationPropertyView.getBuilder().build();
+          navigationPropertyView.addJPAEdmNavigationPropertyView(localNavigationPropertyView);
+          break;
+        default:
+          break;
+        }
+      }
+
+    }
+
+    @SuppressWarnings("rawtypes")
+    private List<Attribute<?, ?>> sortInAscendingOrder(final Set<?> jpaAttributes) {
+      List<Attribute<?, ?>> jpaAttributeList = new ArrayList<Attribute<?, ?>>();
+      Iterator itr = null;
+      Attribute<?, ?> smallestJpaAttribute;
+      Attribute<?, ?> currentJpaAttribute;
+      while (!jpaAttributes.isEmpty()) {
+        itr = jpaAttributes.iterator();
+        smallestJpaAttribute = (Attribute<?, ?>) itr.next();
+        while (itr.hasNext()) {
+          currentJpaAttribute = (Attribute<?, ?>) itr.next();
+          if (smallestJpaAttribute.getName().compareTo(currentJpaAttribute.getName()) > 0) {
+            smallestJpaAttribute = currentJpaAttribute;
+          }
+        }
+        jpaAttributeList.add(smallestJpaAttribute);
+        jpaAttributes.remove(smallestJpaAttribute);
+      }
+      return jpaAttributeList;
+    }
+
+    private EdmFacets setFacets(final Attribute<?, ?> jpaAttribute)
+        throws ODataJPAModelException, ODataJPARuntimeException {
+
+      Facets facets = new Facets();
+      if (jpaAttribute.getJavaMember() instanceof AnnotatedElement) {
+        Column column = ((AnnotatedElement) jpaAttribute
+            .getJavaMember()).getAnnotation(Column.class);
+        if (column != null) {
+          EdmSimpleTypeKind attrEmdType = JPATypeConvertor
+              .convertToEdmSimpleType(jpaAttribute.getJavaType(), jpaAttribute);
+          if (column.nullable()) {
+            facets.setNullable(true);
+          } else {
+            facets.setNullable(false);
+          }
+          if (column.length() != 0
+              && attrEmdType.equals(EdmSimpleTypeKind.String)) {
+            facets.setMaxLength(column.length());
+          }
+          if (column.precision() != 0
+              && attrEmdType.equals(EdmSimpleTypeKind.Double)) {
+            facets.setPrecision(column.precision());
+          }
+        }
+        return facets;
+      }
+      return facets;
+    }
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return entityTypeView;
+  }
+
+  @Override
+  public JPAEdmComplexTypeView getJPAEdmComplexTypeView() {
+    return complexTypeView;
+  }
+
+  private boolean isExcluded(final JPAEdmPropertyView jpaEdmPropertyView, final String jpaEntityTypeName, final String jpaAttributeName) {
+    JPAEdmMappingModelAccess mappingModelAccess = jpaEdmPropertyView
+        .getJPAEdmMappingModelAccess();
+    boolean isExcluded = false;
+    if (mappingModelAccess != null && mappingModelAccess.isMappingModelExists()) {
+      // Exclusion of a simple property in a complex type
+      if (isBuildModeComplexType && mappingModelAccess.checkExclusionOfJPAEmbeddableAttributeType(jpaEntityTypeName, jpaAttributeName)
+          // Exclusion of a simple property of an Entity Type
+          || (!isBuildModeComplexType && mappingModelAccess.checkExclusionOfJPAAttributeType(jpaEntityTypeName, jpaAttributeName))) {
+        isExcluded = true;
+      }
+    }
+    return isExcluded;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraint.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraint.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraint.java
new file mode 100644
index 0000000..df39fc3
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraint.java
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView.RoleType;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView;
+
+public class JPAEdmReferentialConstraint extends JPAEdmBaseViewImpl implements
+    JPAEdmReferentialConstraintView {
+
+  private JPAEdmRefConstraintBuilder builder = null;
+
+  private boolean exists = false;
+  private boolean firstBuild = true;
+
+  private JPAEdmAssociationView associationView;
+  private JPAEdmPropertyView propertyView;
+  private JPAEdmEntityTypeView entityTypeView;
+
+  private ReferentialConstraint referentialConstraint;
+
+  private JPAEdmReferentialConstraintRoleView principalRoleView;
+  private JPAEdmReferentialConstraintRoleView dependentRoleView;
+
+  private String relationShipName;
+
+  public JPAEdmReferentialConstraint(final JPAEdmAssociationView associationView,
+      final JPAEdmEntityTypeView entityTypeView, final JPAEdmPropertyView propertyView) {
+    super(associationView);
+    this.associationView = associationView;
+    this.propertyView = propertyView;
+    this.entityTypeView = entityTypeView;
+
+    relationShipName = associationView.getEdmAssociation().getName();
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmRefConstraintBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public ReferentialConstraint getEdmReferentialConstraint() {
+    return referentialConstraint;
+  }
+
+  @Override
+  public boolean isExists() {
+    return exists;
+  }
+
+  @Override
+  public String getEdmRelationShipName() {
+    return relationShipName;
+  }
+
+  private class JPAEdmRefConstraintBuilder implements JPAEdmBuilder {
+    /*
+     * Check if Ref Constraint was already Built. If Ref constraint was
+     * already built consistently then do not build referential constraint.
+     * 
+     * For Ref Constraint to be consistently built Principal and Dependent
+     * roles must be consistently built. If Principal or Dependent roles are
+     * not consistently built then try building them again.
+     * 
+     * The Principal and Dependent roles could be have been built
+     * inconsistently if the required EDM Entity Types or EDM properties are
+     * yet to be built. In such cases rebuilding these roles would make them
+     * consistent.
+     */
+    @Override
+    public void build() throws ODataJPAModelException, ODataJPARuntimeException {
+
+      if (firstBuild) {
+        firstBuild();
+      } else {
+        if (exists && !firstBuild
+            && principalRoleView.isConsistent() == false) {
+          principalRoleView.getBuilder().build();
+        }
+
+        if (exists && !firstBuild
+            && dependentRoleView.isConsistent() == false) {
+          dependentRoleView.getBuilder().build();
+        }
+      }
+
+      if (principalRoleView.isConsistent()) {
+        referentialConstraint.setPrincipal(principalRoleView
+            .getEdmReferentialConstraintRole());
+      }
+
+      if (dependentRoleView.isConsistent()) {
+        referentialConstraint.setDependent(dependentRoleView
+            .getEdmReferentialConstraintRole());
+      }
+
+      exists = principalRoleView.isExists()
+          & dependentRoleView.isExists();
+
+      isConsistent = principalRoleView.isConsistent()
+          & dependentRoleView.isConsistent();
+
+    }
+
+    private void firstBuild() throws ODataJPAModelException, ODataJPARuntimeException {
+      firstBuild = false;
+      if (principalRoleView == null && dependentRoleView == null) {
+
+        principalRoleView = new JPAEdmReferentialConstraintRole(
+            RoleType.PRINCIPAL, entityTypeView, propertyView,
+            associationView);
+        principalRoleView.getBuilder().build();
+
+        dependentRoleView = new JPAEdmReferentialConstraintRole(
+            RoleType.DEPENDENT, entityTypeView, propertyView,
+            associationView);
+        dependentRoleView.getBuilder().build();
+
+        if (referentialConstraint == null) {
+          referentialConstraint = new ReferentialConstraint();
+        }
+      }
+
+    }
+  }
+
+}


[36/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainerTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainerTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainerTest.java
new file mode 100644
index 0000000..11a011e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityContainerTest.java
@@ -0,0 +1,238 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEntityTypeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPASingularAttributeMock;
+
+public class JPAEdmEntityContainerTest extends JPAEdmTestModelView {
+
+  private JPAEdmEntityContainer objJPAEdmEntityContainer;
+  private JPAEdmEntityContainerTest objJPAEdmEntityContainerTest;
+
+  @Before
+  public void setUp() {
+    objJPAEdmEntityContainerTest = new JPAEdmEntityContainerTest();
+    objJPAEdmEntityContainer = new JPAEdmEntityContainer(objJPAEdmEntityContainerTest);
+    try {
+      objJPAEdmEntityContainer.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmEntityContainer.getBuilder());
+  }
+
+  @Test
+  public void testGetEdmEntityContainer() {
+    assertNotNull(objJPAEdmEntityContainer.getEdmEntityContainer());
+    assertTrue(objJPAEdmEntityContainer.getEdmEntityContainer().getEntitySets().size() > 0);
+  }
+
+  @Test
+  public void testGetConsistentEdmEntityContainerList() {
+    assertNotNull(objJPAEdmEntityContainer.getConsistentEdmEntityContainerList());
+    assertTrue(objJPAEdmEntityContainer.getConsistentEdmEntityContainerList().size() > 0);
+
+  }
+
+  @Test
+  public void testGetJPAEdmEntitySetView() {
+    assertNotNull(objJPAEdmEntityContainer.getJPAEdmEntitySetView());
+    assertEquals("salesorderprocessing", objJPAEdmEntityContainer.getJPAEdmEntitySetView().getpUnitName());
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertTrue(objJPAEdmEntityContainer.isConsistent());
+    objJPAEdmEntityContainer.clean();
+    assertFalse(objJPAEdmEntityContainer.isConsistent());
+  }
+
+  @Test
+  public void testGetEdmAssociationSetView() {
+    assertNotNull(objJPAEdmEntityContainer.getEdmAssociationSetView());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmEntityContainer.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmEntityContainer.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAEdmMetaModel();
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return this;
+  }
+
+  @Override
+  public EntityType<?> getJPAEntityType() {
+    return new JPAEdmEntityType<String>();
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return this;
+  }
+
+  @Override
+  public Schema getEdmSchema() {
+    Schema schema = new Schema();
+    schema.setNamespace("salesordereprocessing");
+    return schema;
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+  @Override
+  public JPAEdmAssociationView getJPAEdmAssociationView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    return new JPAEdmBuilder() {
+
+      @Override
+      public void build() {
+        //Nothing to do?
+      }
+    };
+  }
+
+  private class JPAEdmMetaModel extends JPAMetaModelMock
+  {
+    Set<EntityType<?>> entities;
+
+    public JPAEdmMetaModel() {
+      entities = new HashSet<EntityType<?>>();
+    }
+
+    @Override
+    public Set<EntityType<?>> getEntities() {
+      entities.add(new JPAEdmEntityType());
+      return entities;
+    }
+
+    private class JPAEdmEntityType extends JPAEntityTypeMock<String> {
+      @Override
+      public String getName() {
+        return "SalesOrderHeader";
+      }
+    }
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEntityType<String> extends JPAEntityTypeMock<String> {
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet()
+    {
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SOID"));
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    private class JPAEdmAttribute<Object, String> extends JPASingularAttributeMock<Object, String>
+    {
+
+      @Override
+      public PersistentAttributeType getPersistentAttributeType() {
+        return PersistentAttributeType.BASIC;
+      }
+
+      Class<String> clazz;
+      java.lang.String attributeName;
+
+      public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+        this.clazz = javaType;
+        this.attributeName = name;
+
+      }
+
+      @Override
+      public Class<String> getJavaType() {
+        return clazz;
+      }
+
+      @Override
+      public java.lang.String getName() {
+        return this.attributeName;
+      }
+
+      @Override
+      public boolean isId() {
+        return true;
+      }
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySetTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySetTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySetTest.java
new file mode 100644
index 0000000..76e0342
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntitySetTest.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEntityTypeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPASingularAttributeMock;
+
+public class JPAEdmEntitySetTest extends JPAEdmTestModelView {
+
+  private static JPAEdmEntitySet objJPAEdmEntitySet;
+  private static JPAEdmEntitySetTest objJPAEdmEntitySetTest;
+
+  @Before
+  public void setUp() {
+    objJPAEdmEntitySetTest = new JPAEdmEntitySetTest();
+    objJPAEdmEntitySet = new JPAEdmEntitySet(objJPAEdmEntitySetTest);
+    try {
+      objJPAEdmEntitySet.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmEntitySet.getBuilder());
+  }
+
+  @Test
+  public void testGetEdmEntitySet() {
+    assertNotNull(objJPAEdmEntitySet.getEdmEntitySet());
+    assertNotNull(objJPAEdmEntitySet.getEdmEntitySet().getEntityType());
+  }
+
+  @Test
+  public void testGetConsistentEntitySetList() {
+    assertTrue(objJPAEdmEntitySet.getConsistentEdmEntitySetList().size() > 0);
+  }
+
+  @Test
+  public void testGetJPAEdmEntityTypeView() {
+    assertNotNull(objJPAEdmEntitySet.getJPAEdmEntityTypeView());
+    assertEquals("salesorderprocessing", objJPAEdmEntitySet.getJPAEdmEntityTypeView().getpUnitName());
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertTrue(objJPAEdmEntitySet.isConsistent());
+
+    objJPAEdmEntitySet.getJPAEdmEntityTypeView().clean();
+    assertFalse(objJPAEdmEntitySet.getJPAEdmEntityTypeView().isConsistent());
+
+    objJPAEdmEntitySet.clean();
+    assertFalse(objJPAEdmEntitySet.isConsistent());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmEntitySet.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmEntitySet.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAEdmMetaModel();
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return this;
+  }
+
+  @Override
+  public EntityType<?> getJPAEntityType() {
+    return new JPAEdmEntityType<String>();
+  }
+
+  @Override
+  public JPAEdmKeyView getJPAEdmKeyView() {
+    return this;
+  }
+
+  @Override
+  public Schema getEdmSchema() {
+    Schema schema = new Schema();
+    schema.setNamespace("salesordereprocessing");
+    return schema;
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEntityType<String> extends JPAEntityTypeMock<String> {
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet()
+    {
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SOID"));
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public java.lang.String getName() {
+      return "SalesOrderHeader";
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    private class JPAEdmAttribute<Object, String> extends JPASingularAttributeMock<Object, String>
+    {
+
+      @Override
+      public PersistentAttributeType getPersistentAttributeType() {
+        return PersistentAttributeType.BASIC;
+      }
+
+      Class<String> clazz;
+      java.lang.String attributeName;
+
+      public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+        this.clazz = javaType;
+        this.attributeName = name;
+
+      }
+
+      @Override
+      public Class<String> getJavaType() {
+        return clazz;
+      }
+
+      @Override
+      public java.lang.String getName() {
+        return this.attributeName;
+      }
+
+      @Override
+      public boolean isId() {
+        return true;
+      }
+    }
+  }
+
+  private class JPAEdmMetaModel extends JPAMetaModelMock
+  {
+    Set<EntityType<?>> entities;
+
+    public JPAEdmMetaModel() {
+      entities = new HashSet<EntityType<?>>();
+    }
+
+    @Override
+    public Set<EntityType<?>> getEntities() {
+      entities.add(new JPAEdmEntityType());
+      return entities;
+    }
+
+    private class JPAEdmEntityType extends JPAEntityTypeMock<String> {
+      @Override
+      public String getName() {
+        return "SalesOrderHeader";
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityTypeTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityTypeTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityTypeTest.java
new file mode 100644
index 0000000..0f09637
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmEntityTypeTest.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEntityTypeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPASingularAttributeMock;
+
+public class JPAEdmEntityTypeTest extends JPAEdmTestModelView {
+
+  private static JPAEdmEntityTypeTest objJPAEdmEntityTypeTest;
+  private static JPAEdmEntityType objJPAEdmEntityType;
+
+  @Before
+  public void setUp() {
+    objJPAEdmEntityTypeTest = new JPAEdmEntityTypeTest();
+    objJPAEdmEntityType = new JPAEdmEntityType(objJPAEdmEntityTypeTest);
+    try {
+      objJPAEdmEntityType.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmEntityType.getBuilder());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmEntityType.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmEntityType.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetEdmEntityType() {
+    assertNotNull(objJPAEdmEntityType.getEdmEntityType());
+    assertNotNull(objJPAEdmEntityType.getEdmEntityType().getKey());
+  }
+
+  @Test
+  public void testGetJPAEntityType() {
+    assertNotNull(objJPAEdmEntityType.getJPAEntityType());
+
+  }
+
+  @Test
+  public void testGetConsistentEdmEntityTypes() {
+    assertTrue(objJPAEdmEntityType.getConsistentEdmEntityTypes().size() > 0);
+  }
+
+  @Test
+  public void testSearchEdmEntityType() {
+    assertNotNull(objJPAEdmEntityType.searchEdmEntityType("SalesOrderHeader"));
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertTrue(objJPAEdmEntityType.isConsistent());
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAEdmMetaModel();
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return this;
+  }
+
+  @Override
+  public EntityType<?> getJPAEntityType() {
+    return new JPAEdmEntityTypeLocal<String>();
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return this;
+  }
+
+  private class JPAEdmMetaModel extends JPAMetaModelMock
+  {
+    Set<EntityType<?>> entities;
+
+    public JPAEdmMetaModel() {
+      entities = new HashSet<EntityType<?>>();
+    }
+
+    @Override
+    public Set<EntityType<?>> getEntities() {
+      entities.add(new JPAEdmEntityType());
+      return entities;
+    }
+
+    private class JPAEdmEntityType extends JPAEntityTypeMock<String> {
+      @Override
+      public String getName() {
+        return "SalesOrderHeader";
+      }
+    }
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEntityTypeLocal<String> extends JPAEntityTypeMock<String> {
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet()
+    {
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SOID"));
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    private class JPAEdmAttribute<Object, String> extends JPASingularAttributeMock<Object, String>
+    {
+
+      @Override
+      public PersistentAttributeType getPersistentAttributeType() {
+        return PersistentAttributeType.BASIC;
+      }
+
+      Class<String> clazz;
+      java.lang.String attributeName;
+
+      public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+        this.clazz = javaType;
+        this.attributeName = name;
+
+      }
+
+      @Override
+      public Class<String> getJavaType() {
+        return clazz;
+      }
+
+      @Override
+      public java.lang.String getName() {
+        return this.attributeName;
+      }
+
+      @Override
+      public boolean isId() {
+        return true;
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImportTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImportTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImportTest.java
new file mode 100644
index 0000000..edc12d0
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmFunctionImportTest.java
@@ -0,0 +1,627 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+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 java.util.HashMap;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.annotation.edm.Parameter.Mode;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.ReturnType;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.ODataJPAContextMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPACustomProcessorMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPACustomProcessorNegativeMock;
+
+public class JPAEdmFunctionImportTest extends JPAEdmTestModelView {
+  private static final int METHOD_COUNT = 6;
+  private static int VARIANT = 0;
+  private JPAEdmFunctionImport jpaEdmfunctionImport;
+
+  @Before
+  public void setup() {
+    jpaEdmfunctionImport = new JPAEdmFunctionImport(this);
+  }
+
+  /**
+   * Test Case - Function Import Basic test - Positive Case
+   */
+  @Test
+  public void testFunctionImportBasic() {
+    VARIANT = 0;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+    for (FunctionImport functionImport : functionImportList) {
+      assertEquals(functionImport.getName(), "Method1");
+      assertNotNull(functionImport.getMapping());
+      Mapping mapping = new Mapping();
+      mapping.setInternalName("method1");
+
+      assertEquals(mapping.getInternalName(), functionImport.getMapping()
+          .getInternalName());
+
+      ReturnType returnType = functionImport.getReturnType();
+      assertNotNull(returnType);
+      assertEquals(EdmMultiplicity.MANY, returnType.getMultiplicity());
+
+      List<FunctionImportParameter> funcImpList = functionImport
+          .getParameters();
+      assertEquals(2, funcImpList.size());
+      assertEquals("Param1", funcImpList.get(0).getName());
+      assertEquals(EdmSimpleTypeKind.String, funcImpList.get(0).getType());
+      assertEquals(Mode.IN.toString(), funcImpList.get(0).getMode());
+
+      assertEquals("Param3", funcImpList.get(1).getName());
+      assertEquals(EdmSimpleTypeKind.Double, funcImpList.get(1).getType());
+      assertEquals(Mode.IN.toString(), funcImpList.get(1).getMode());
+
+    }
+
+  }
+
+  /**
+   * Test Case - Enable a method that does not exists
+   */
+  @Test
+  public void testFunctionImportNoSuchMethod() {
+    VARIANT = 1;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 0);
+
+  }
+
+  /**
+   * Test Case - Enable all annotated methods in a class as function imports
+   */
+  @Test
+  public void testFunctionImportAllMethods() {
+    VARIANT = 2;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(METHOD_COUNT, functionImportList.size());
+
+  }
+
+  /**
+   * Test Case - Function Import with no names. Default name is Java method
+   * name.
+   */
+  @Test
+  public void testFunctionImportNoName() {
+    VARIANT = 3;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+
+    FunctionImport functionImport = functionImportList.get(0);
+    assertEquals(functionImport.getName(), "method3");
+    assertNotNull(functionImport.getMapping());
+
+    ReturnType returnType = functionImport.getReturnType();
+    assertNotNull(returnType);
+    assertEquals(EdmMultiplicity.ONE, returnType.getMultiplicity());
+    assertEquals(returnType.getTypeName().toString(),
+        EdmSimpleTypeKind.Int32.getFullQualifiedName().toString());
+  }
+
+  /**
+   * Test Case - Function Import with No return type defined - Negative case
+   */
+  @Test
+  public void testNoReturnType() {
+    VARIANT = 4;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 0);
+
+    // FunctionImport functionImport = functionImportList.get(0);
+    // assertEquals(functionImport.getName(), "method4");
+    // assertNotNull(functionImport.getMapping());
+    //
+    // assertNull(functionImport.getReturnType());
+
+  }
+
+  /**
+   * Test Case - Function Import with return type as Entity and Multiplicity
+   * as Many but no Entity set defined. --> Negative Case
+   */
+  @Test
+  public void testNoEntitySet() {
+    VARIANT = 5;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(ODataJPAModelException.FUNC_ENTITYSET_EXP.getKey(), e
+          .getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+  }
+
+  /**
+   * Test Case - Function Import with return type as Entity Type but method
+   * has returns void. --> Negative Case
+   */
+  @Test
+  public void testNoReturnTypeButAnnotated() {
+    VARIANT = 6;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(ODataJPAModelException.FUNC_RETURN_TYPE_EXP.getKey(),
+          e.getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+  }
+
+  /**
+   * Test Case - Function Import that returns an Entity Type with Multiplicity
+   * as ONE. -->Positive Case
+   */
+  @Test
+  public void testFunctionImportEntityTypeSingleReturn() {
+    VARIANT = 7;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+
+    FunctionImport functionImport = functionImportList.get(0);
+    assertEquals(functionImport.getName(), "method7");
+    assertNotNull(functionImport.getMapping());
+    JPAEdmMapping mapping = (JPAEdmMapping) functionImport.getMapping();
+    assertEquals(JPACustomProcessorMock.class, mapping.getJPAType());
+
+    ReturnType returnType = functionImport.getReturnType();
+    assertNotNull(returnType);
+    assertEquals(EdmMultiplicity.ONE, returnType.getMultiplicity());
+    assertEquals(returnType.getTypeName().toString(),
+        ODataJPAContextMock.PERSISTENCE_UNIT_NAME + "."
+            + JPACustomProcessorMock.edmName);
+  }
+
+  /**
+   * Test Case - Function Import that returns an Entity Type that is not found
+   * in JPA Model
+   */
+  @Test
+  public void testFunctionImportEntityTypeInvalid() {
+    VARIANT = 8;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(
+          ODataJPAModelException.FUNC_RETURN_TYPE_ENTITY_NOT_FOUND
+              .getKey(),
+          e.getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+
+  }
+
+  /**
+   * Test Case - Function Import that returns a complex Type
+   */
+  @Test
+  public void testFunctionImportComplexType() {
+    VARIANT = 9;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+
+    FunctionImport functionImport = functionImportList.get(0);
+    assertEquals(functionImport.getName(), "method9");
+    assertNotNull(functionImport.getMapping());
+
+    ReturnType returnType = functionImport.getReturnType();
+    assertNotNull(returnType);
+    assertEquals(EdmMultiplicity.ONE, returnType.getMultiplicity());
+    assertEquals(returnType.getTypeName().toString(),
+        ODataJPAContextMock.PERSISTENCE_UNIT_NAME + "."
+            + JPACustomProcessorMock.edmName);
+
+  }
+
+  /**
+   * Test Case - Function Import that returns a complex Type with multiplicity
+   * Many
+   */
+  @Test
+  public void testFunctionImportComplexTypeMany() {
+    VARIANT = 10;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+
+    FunctionImport functionImport = functionImportList.get(0);
+    assertEquals(functionImport.getName(), "method10");
+    assertNotNull(functionImport.getMapping());
+
+    ReturnType returnType = functionImport.getReturnType();
+    assertNotNull(returnType);
+    assertEquals(EdmMultiplicity.MANY, returnType.getMultiplicity());
+    assertEquals(returnType.getTypeName().toString(),
+        ODataJPAContextMock.PERSISTENCE_UNIT_NAME + "."
+            + JPACustomProcessorMock.edmName);
+
+  }
+
+  /**
+   * Test Case - Function Import that returns an Complex Type that is not
+   * found in JPA Model
+   */
+  @Test
+  public void testFunctionImportComplexTypeInvalid() {
+    VARIANT = 11;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(
+          ODataJPAModelException.FUNC_RETURN_TYPE_ENTITY_NOT_FOUND
+              .getKey(),
+          e.getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+
+  }
+
+  /**
+   * Test Case - Function Import that returns an scalar Type that is not valid
+   */
+  @Test
+  public void testFunctionImportScalarTypeInvalid() {
+    VARIANT = 12;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(ODataJPAModelException.TYPE_NOT_SUPPORTED.getKey(), e
+          .getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+
+  }
+
+  /**
+   * Test Case - Function Import that takes a parameter with no name
+   */
+  @Test
+  public void testFunctionImportParamNoName() {
+    VARIANT = 13;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(ODataJPAModelException.FUNC_PARAM_NAME_EXP.getKey(), e
+          .getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+
+  }
+
+  /**
+   * Test Case - Function Import test for facets
+   */
+  @Test
+  public void testFunctionImportParamFacets() {
+    VARIANT = 14;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+
+    List<FunctionImportParameter> funcImpParamList = functionImportList
+        .get(0).getParameters();
+    EdmFacets facets = funcImpParamList.get(0).getFacets();
+    assertNotNull(facets);
+    assertEquals(2, facets.getMaxLength().intValue());
+    assertEquals(true, facets.isNullable());
+
+    facets = funcImpParamList.get(1).getFacets();
+    assertNotNull(facets);
+    assertEquals(false, facets.isNullable());
+    assertEquals(10, facets.getPrecision().intValue());
+    assertEquals(2, facets.getScale().intValue());
+
+  }
+
+  /**
+   * Test Case - Function Import test for default facets
+   */
+  @Test
+  public void testFunctionImportParamFacetsDefault() {
+    VARIANT = 15;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 1);
+
+    List<FunctionImportParameter> funcImpParamList = functionImportList
+        .get(0).getParameters();
+    EdmFacets facets = funcImpParamList.get(0).getFacets();
+    assertNotNull(facets);
+    assertNull(facets.getMaxLength());
+    assertEquals(false, facets.isNullable());
+    assertNull(facets.getPrecision());
+    assertNull(facets.getScale());
+
+  }
+
+  /**
+   * Test Case - Function Import test for ReturnType.SCALAR but method returns
+   * void
+   */
+  @Test
+  public void testWrongReturnTypeScalar() {
+    VARIANT = 16;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(ODataJPAModelException.FUNC_RETURN_TYPE_EXP.getKey(), e
+          .getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+
+  }
+
+  /**
+   * Test Case - Function Import test for ReturnType.COMPLEX but method returns
+   * void
+   */
+  @Test
+  public void testWrongReturnTypeComplex() {
+    VARIANT = 17;
+
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+      fail("Exception Expected");
+    } catch (ODataJPAModelException e) {
+      assertEquals(ODataJPAModelException.FUNC_RETURN_TYPE_EXP.getKey(), e
+          .getMessageReference().getKey());
+    } catch (ODataJPARuntimeException e) {
+      fail("Model Exception Expected");
+    }
+
+  }
+
+  @Test
+  public void testNoFunctionImport() {
+    VARIANT = 99;
+
+    build();
+
+    List<FunctionImport> functionImportList = jpaEdmfunctionImport
+        .getConsistentFunctionImportList();
+
+    assertEquals(functionImportList.size(), 0);
+
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmFunctionImport jpaEdmfunctionImport = new JPAEdmFunctionImport(
+        this);
+
+    JPAEdmBuilder builder1 = jpaEdmfunctionImport.getBuilder();
+    JPAEdmBuilder builder2 = jpaEdmfunctionImport.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Override
+  public HashMap<Class<?>, String[]> getRegisteredOperations() {
+
+    HashMap<Class<?>, String[]> customOperations = new HashMap<Class<?>, String[]>();
+
+    if (VARIANT == 0) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method1" });
+    } else if (VARIANT == 1) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "XYX" });
+    } else if (VARIANT == 2) {
+      customOperations.put(JPACustomProcessorMock.class, null);
+    } else if (VARIANT == 3) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method3" });
+    } else if (VARIANT == 4) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method4" });
+    } else if (VARIANT == 5) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method5" });
+    } else if (VARIANT == 6) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method6" });
+    } else if (VARIANT == 7) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method7" });
+    } else if (VARIANT == 8) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method8" });
+    } else if (VARIANT == 9) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method9" });
+    } else if (VARIANT == 10) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method10" });
+    } else if (VARIANT == 11) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method11" });
+    } else if (VARIANT == 12) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method12" });
+    } else if (VARIANT == 13) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method13" });
+    } else if (VARIANT == 14) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method1" });
+    } else if (VARIANT == 15) {
+      customOperations.put(JPACustomProcessorMock.class,
+          new String[] { "method3" });
+    } else if (VARIANT == 16) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method16" });
+    } else if (VARIANT == 17) {
+      customOperations.put(JPACustomProcessorNegativeMock.class,
+          new String[] { "method17" });
+    } else {
+      return null;
+    }
+
+    return customOperations;
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmComplexTypeView getJPAEdmComplexTypeView() {
+    return this;
+  }
+
+  @Override
+  public EntityType searchEdmEntityType(final String arg0) {
+    if (arg0.equals(JPACustomProcessorMock.class.getSimpleName())) {
+      return new EntityType().setName(JPACustomProcessorMock.edmName);
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final String arg0) {
+    if (arg0.equals(JPACustomProcessorMock.class.getName())) {
+      return new ComplexType().setName(JPACustomProcessorMock.edmName);
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public String getpUnitName() {
+    return ODataJPAContextMock.PERSISTENCE_UNIT_NAME;
+  }
+
+  private void build() {
+    try {
+      jpaEdmfunctionImport.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKeyTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKeyTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKeyTest.java
new file mode 100644
index 0000000..80be3ce
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmKeyTest.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.metamodel.Attribute;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.ODataJPAContextMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.ComplexType.ComplexTypeA;
+
+public class JPAEdmKeyTest extends JPAEdmTestModelView {
+
+  private static JPAEdmKeyView keyView;
+  private static JPAEdmKeyTest objJpaEdmKeyTest;
+
+  @BeforeClass
+  public static void setup() {
+    objJpaEdmKeyTest = new JPAEdmKeyTest();
+    keyView = new JPAEdmKey(objJpaEdmKeyTest, objJpaEdmKeyTest);
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAAttributeA<Object, ComplexTypeA> extends
+      JPAAttributeMock<Object, ComplexTypeA> {
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<ComplexTypeA> getJavaType() {
+      return (Class<ComplexTypeA>) JPAEdmMockData.ComplexType.ComplexTypeA.class;
+    }
+  }
+
+  @Test
+  public void testBuildComplexKey() {
+    try {
+      keyView.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    Key key = keyView.getEdmKey();
+
+    assertEquals(
+        JPAEdmMockData.ComplexType.ComplexTypeA.Property.PROPERTY_A,
+        key.getKeys().get(0).getName());
+    assertEquals(
+        JPAEdmMockData.ComplexType.ComplexTypeA.Property.PROPERTY_B,
+        key.getKeys().get(1).getName());
+    assertEquals(
+        JPAEdmMockData.ComplexType.ComplexTypeB.Property.PROPERTY_D,
+        key.getKeys().get(2).getName());
+    assertEquals(
+        JPAEdmMockData.ComplexType.ComplexTypeB.Property.PROPERTY_E,
+        key.getKeys().get(3).getName());
+
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = keyView.getBuilder();
+    JPAEdmBuilder builder2 = keyView.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return new JPAAttributeA<Object, ComplexTypeA>();
+
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final FullQualifiedName arg0) {
+    return searchEdmComplexType(arg0.getName());
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final String arg0) {
+    if (arg0.equals(JPAEdmMockData.ComplexType.ComplexTypeA.class.getName())) {
+      return buildComplexTypeA();
+    } else if (arg0.equals(JPAEdmMockData.ComplexType.ComplexTypeB.class
+        .getSimpleName())) {
+      return buildComplexTypeB();
+    }
+
+    return null;
+
+  }
+
+  private ComplexType buildComplexTypeB() {
+    ComplexType complexType = new ComplexType();
+    complexType.setProperties(buildPropertiesB());
+
+    return complexType;
+  }
+
+  private List<Property> buildPropertiesB() {
+    List<Property> propertyList = new ArrayList<Property>();
+
+    SimpleProperty property = new SimpleProperty();
+    property.setName(JPAEdmMockData.ComplexType.ComplexTypeB.Property.PROPERTY_D);
+    property.setType(EdmSimpleTypeKind.Int16);
+
+    propertyList.add(property);
+
+    property = new SimpleProperty();
+    property.setName(JPAEdmMockData.ComplexType.ComplexTypeB.Property.PROPERTY_E);
+    property.setType(EdmSimpleTypeKind.Int16);
+
+    propertyList.add(property);
+
+    return propertyList;
+  }
+
+  private ComplexType buildComplexTypeA() {
+    ComplexType complexType = new ComplexType();
+    complexType.setProperties(buildPropertiesA());
+
+    return complexType;
+  }
+
+  private List<Property> buildPropertiesA() {
+
+    List<Property> propertyList = new ArrayList<Property>();
+
+    SimpleProperty property = new SimpleProperty();
+    property.setName(JPAEdmMockData.ComplexType.ComplexTypeA.Property.PROPERTY_A);
+    property.setType(EdmSimpleTypeKind.Int16);
+
+    propertyList.add(property);
+
+    property = new SimpleProperty();
+    property.setName(JPAEdmMockData.ComplexType.ComplexTypeA.Property.PROPERTY_B);
+    property.setType(EdmSimpleTypeKind.Int16);
+
+    propertyList.add(property);
+
+    ComplexProperty complexProperty = new ComplexProperty();
+    complexProperty
+        .setName(JPAEdmMockData.ComplexType.ComplexTypeA.Property.PROPERTY_C);
+    complexProperty.setType(new FullQualifiedName(ODataJPAContextMock.NAMESPACE,
+        JPAEdmMockData.ComplexType.ComplexTypeB.name));
+
+    propertyList.add(complexProperty);
+    return propertyList;
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModelTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModelTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModelTest.java
new file mode 100644
index 0000000..7f732c7
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmModelTest.java
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEmbeddableMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPASingularAttributeMock;
+
+public class JPAEdmModelTest extends JPAEdmTestModelView {
+
+  private JPAEdmModel objJPAEdmModel;
+
+  @Before
+  public void setUp() {
+    objJPAEdmModel = new JPAEdmModel(getJPAMetaModel(), "salesorderprocessing");
+    try {
+      objJPAEdmModel.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetEdmSchemaView() {
+    assertNotNull(objJPAEdmModel.getEdmSchemaView());
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmModel.getBuilder());
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAEdmMetaModel();
+  }
+
+  private class JPAEdmMetaModel extends JPAMetaModelMock
+  {
+    Set<EmbeddableType<?>> embeddableSet;
+
+    public JPAEdmMetaModel() {
+      embeddableSet = new HashSet<EmbeddableType<?>>();
+    }
+
+    @Override
+    public Set<EmbeddableType<?>> getEmbeddables() {
+      embeddableSet.add(new JPAEdmEmbeddable<String>());
+      return embeddableSet;
+    }
+
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEmbeddable<String> extends JPAEmbeddableMock<String>
+  {
+
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet()
+    {
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SOID"));
+      attributeSet.add((Attribute<? super String, String>) new JPAEdmAttribute(java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmAttribute<Object, String> extends JPASingularAttributeMock<Object, String>
+  {
+
+    @Override
+    public PersistentAttributeType getPersistentAttributeType() {
+      return PersistentAttributeType.BASIC;
+    }
+
+    Class<String> clazz;
+    java.lang.String attributeName;
+
+    public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+      this.clazz = javaType;
+      this.attributeName = name;
+
+    }
+
+    @Override
+    public Class<String> getJavaType() {
+      return clazz;
+    }
+
+    @Override
+    public java.lang.String getName() {
+      return this.attributeName;
+    }
+
+    @Override
+    public boolean isId() {
+      return false;
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationPropertyTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationPropertyTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationPropertyTest.java
new file mode 100644
index 0000000..17c1984
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmNavigationPropertyTest.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EntityType;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEntityTypeMock;
+
+public class JPAEdmNavigationPropertyTest extends JPAEdmTestModelView {
+
+  private static JPAEdmNavigationProperty objNavigationProperty;
+  private static JPAEdmNavigationPropertyTest navPropView;
+
+  @BeforeClass
+  public static void setup() {
+    JPAEdmNavigationPropertyTest localView = new JPAEdmNavigationPropertyTest();
+    navPropView = new JPAEdmNavigationPropertyTest();
+    objNavigationProperty = new JPAEdmNavigationProperty(localView,
+        localView, 1);
+    try {
+      objNavigationProperty.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return this;
+  }
+
+  @Override
+  public EntityType<?> getJPAEntityType() {
+    return new JPAEdmEntityType();
+  }
+
+  private Attribute<?, ?> getJPAAttributeLocal() {
+    AttributeMock<Object, String> attr = new AttributeMock<Object, String>();
+    return attr;
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return getJPAAttributeLocal();
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+
+    Association association = new Association();
+    association.setName("Assoc_SalesOrderHeader_SalesOrderItem");
+    association.setEnd1(new AssociationEnd().setType(
+        new FullQualifiedName("salesorderprocessing", "String"))
+        .setRole("SalesOrderHeader"));
+    association.setEnd2(new AssociationEnd()
+        .setType(
+            new FullQualifiedName("salesorderprocessing",
+                "SalesOrderItem")).setRole("SalesOrderItem"));
+    return association;
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objNavigationProperty.getBuilder());
+
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objNavigationProperty.getBuilder();
+    JPAEdmBuilder builder2 = objNavigationProperty.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetEdmNavigationProperty() {
+    if (objNavigationProperty == null || objNavigationProperty.getEdmNavigationProperty() == null) {
+      JPAEdmNavigationPropertyTest localView = new JPAEdmNavigationPropertyTest();
+      navPropView = new JPAEdmNavigationPropertyTest();
+      objNavigationProperty = new JPAEdmNavigationProperty(localView,
+          localView, 1);
+      try {
+        objNavigationProperty.getBuilder().build();
+      } catch (ODataJPAModelException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (ODataJPARuntimeException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+    assertEquals(
+        objNavigationProperty.getEdmNavigationProperty().getName(),
+        "StringDetails");
+  }
+
+  @Test
+  public void testGetConsistentEdmNavigationProperties() {
+    assertTrue(objNavigationProperty.getConsistentEdmNavigationProperties()
+        .size() > 0);
+  }
+
+  @Test
+  public void testAddJPAEdmNavigationPropertyView() {
+    JPAEdmNavigationPropertyTest localView = new JPAEdmNavigationPropertyTest();
+    navPropView = new JPAEdmNavigationPropertyTest();
+    objNavigationProperty = new JPAEdmNavigationProperty(localView,
+        localView, 1);
+    try {
+      objNavigationProperty.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    objNavigationProperty.addJPAEdmNavigationPropertyView(navPropView);
+    assertTrue(objNavigationProperty.getConsistentEdmNavigationProperties()
+        .size() > 1);
+  }
+
+  @Override
+  public boolean isConsistent() {
+    return true;
+  }
+
+  @Test
+  public void testBuildNavigationProperty() {
+
+    try {
+      objNavigationProperty.getBuilder().build();
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals(objNavigationProperty.getEdmNavigationProperty()
+        .getFromRole(), "SalesOrderItem");
+    assertEquals(objNavigationProperty.getEdmNavigationProperty()
+        .getToRole(), "SalesOrderHeader");
+
+  }
+
+  @SuppressWarnings("hiding")
+  private class AttributeMock<Object, String> extends
+      JPAAttributeMock<Object, String> {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+
+  }
+
+  private class JPAEdmEntityType extends JPAEntityTypeMock<String> {
+    @Override
+    public String getName() {
+      return "SalesOrderHeader";
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmPropertyTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmPropertyTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmPropertyTest.java
new file mode 100644
index 0000000..4313f8e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmPropertyTest.java
@@ -0,0 +1,403 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.ComplexType;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEdmMockData.SimpleType;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEmbeddableTypeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEntityTypeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPASingularAttributeMock;
+
+public class JPAEdmPropertyTest extends JPAEdmTestModelView {
+
+  private JPAEdmPropertyTest objJPAEdmPropertyTest;
+  private JPAEdmProperty objJPAEdmProperty;
+
+  private static int ATTRIBUTE_TYPE = 1;
+
+  @Before
+  public void setUp() {
+    objJPAEdmPropertyTest = new JPAEdmPropertyTest();
+    objJPAEdmProperty = new JPAEdmProperty(objJPAEdmPropertyTest);
+    try {
+      objJPAEdmProperty.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmProperty.getBuilder());
+
+    // builder for complex type
+    objJPAEdmPropertyTest = new JPAEdmPropertyTest();
+    objJPAEdmProperty = new JPAEdmProperty(objJPAEdmPropertyTest,
+        objJPAEdmPropertyTest);
+    try {
+      objJPAEdmProperty.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmProperty.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmProperty.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetPropertyList() {
+    assertNotNull(objJPAEdmProperty.getEdmPropertyList());
+    assertTrue(objJPAEdmProperty.getEdmPropertyList().size() > 0);
+  }
+
+  @Test
+  public void testGetJPAEdmKeyView() {
+    assertNotNull(objJPAEdmProperty.getJPAEdmKeyView());
+  }
+
+  @Test
+  public void testGetSimpleProperty() {
+    assertNotNull(objJPAEdmProperty.getEdmSimpleProperty());
+  }
+
+  @Test
+  public void testGetJPAAttribute() {
+    assertNotNull(objJPAEdmProperty.getJPAAttribute());
+  }
+
+  @Test
+  public void testGetEdmComplexProperty() {
+    assertNull(objJPAEdmProperty.getEdmComplexProperty());
+  }
+
+  @Test
+  public void testGetJPAEdmNavigationPropertyView() {
+    assertNotNull(objJPAEdmProperty.getJPAEdmNavigationPropertyView());
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertNotNull(objJPAEdmProperty.isConsistent());
+  }
+
+  @Test
+  public void testClean() {
+    objJPAEdmProperty.clean();
+    assertFalse(objJPAEdmProperty.isConsistent());
+  }
+
+  @Test
+  public void testBuildManyToOne() {
+    ATTRIBUTE_TYPE = 3;
+    objJPAEdmPropertyTest = new JPAEdmPropertyTest();
+    objJPAEdmProperty = new JPAEdmProperty(objJPAEdmPropertyTest);
+    try {
+      objJPAEdmProperty.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    ATTRIBUTE_TYPE = 1;
+    objJPAEdmPropertyTest = new JPAEdmPropertyTest();
+    objJPAEdmProperty = new JPAEdmProperty(objJPAEdmPropertyTest);
+    try {
+      objJPAEdmProperty.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAEdmMetaModel();
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return this;
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return this;
+  }
+
+  @Override
+  public EntityType<?> getJPAEntityType() {
+    return new JPAEdmEntityType<String>();
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return this;
+  }
+
+  @Override
+  public org.apache.olingo.odata2.api.edm.provider.EntityType getEdmEntityType() {
+    /*EntityType entityType = new EntityType();
+    entityType.setName("SalesOrderHeader");
+    return entityType;*/
+    org.apache.olingo.odata2.api.edm.provider.EntityType entityType = new org.apache.olingo.odata2.api.edm.provider.EntityType();
+    entityType.setName("SalesOrderHeader");
+
+    return entityType;
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    Association association = new Association();
+    association.setEnd1(new AssociationEnd().setType(new FullQualifiedName(
+        "salesorderprocessing", "SalesOrderHeader")));
+    association.setEnd2(new AssociationEnd().setType(new FullQualifiedName(
+        "salesorderprocessing", "String")));
+
+    return association;
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+  @Override
+  public JPAEdmAssociationView getJPAEdmAssociationView() {
+    return this;
+  }
+
+  @Override
+  public EmbeddableType<?> getJPAEmbeddableType() {
+    return new JPAEdmEmbeddable<java.lang.String>();
+  }
+
+  @Override
+  public JPAEdmComplexTypeView getJPAEdmComplexTypeView() {
+    return this;
+  }
+
+  private class JPAEdmMetaModel extends JPAMetaModelMock {
+    Set<EntityType<?>> entities;
+    Set<EmbeddableType<?>> embeddableSet;
+
+    public JPAEdmMetaModel() {
+      entities = new HashSet<EntityType<?>>();
+      embeddableSet = new HashSet<EmbeddableType<?>>();
+    }
+
+    @Override
+    public Set<EntityType<?>> getEntities() {
+      entities.add(new JPAEdmEntityType());
+      return entities;
+    }
+
+    @Override
+    public Set<EmbeddableType<?>> getEmbeddables() {
+      embeddableSet.add(new JPAEdmEmbeddable<String>());
+      return embeddableSet;
+    }
+
+    private class JPAEdmEntityType extends JPAEntityTypeMock<String> {
+      @Override
+      public String getName() {
+        return "SalesOrderHeader";
+      }
+    }
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEntityType<String> extends JPAEntityTypeMock<String> {
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet() {
+      attributeSet
+          .add((Attribute<? super String, String>) new JPAEdmAttribute(
+              java.lang.String.class, "SOID"));
+      attributeSet
+          .add((Attribute<? super String, String>) new JPAEdmAttribute(
+              java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    private class JPAEdmAttribute<Object, String> extends
+        JPASingularAttributeMock<Object, String> {
+
+      @Override
+      public PersistentAttributeType getPersistentAttributeType() {
+        if (ATTRIBUTE_TYPE == 1) {
+          return PersistentAttributeType.BASIC;
+        } else if (ATTRIBUTE_TYPE == 2) {
+          return PersistentAttributeType.EMBEDDED;
+        } else {
+          return PersistentAttributeType.MANY_TO_ONE;
+        }
+      }
+
+      Class<String> clazz;
+      java.lang.String attributeName;
+
+      public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+        this.clazz = javaType;
+        this.attributeName = name;
+
+      }
+
+      @Override
+      public Class<String> getJavaType() {
+        return clazz;
+      }
+
+      @Override
+      public java.lang.String getName() {
+        return this.attributeName;
+      }
+
+      @Override
+      public boolean isId() {
+        return true;
+      }
+    }
+  }
+
+  @SuppressWarnings("hiding")
+  private class JPAEdmEmbeddable<String> extends
+      JPAEmbeddableTypeMock<String> {
+
+    Set<Attribute<? super String, ?>> attributeSet = new HashSet<Attribute<? super String, ?>>();
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private void setValuesToSet() {
+      attributeSet
+          .add((Attribute<? super String, String>) new JPAEdmAttribute(
+              java.lang.String.class, "SOID"));
+      attributeSet
+          .add((Attribute<? super String, String>) new JPAEdmAttribute(
+              java.lang.String.class, "SONAME"));
+    }
+
+    @Override
+    public Set<Attribute<? super String, ?>> getAttributes() {
+      setValuesToSet();
+      return attributeSet;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      Class<?> clazz = null;
+      if (ATTRIBUTE_TYPE == 1) {
+        clazz = (Class<java.lang.String>) SimpleType.SimpleTypeA.clazz;
+      } else {
+        clazz = (Class<?>) ComplexType.ComplexTypeA.clazz;
+      }
+      return (Class<String>) clazz;
+    }
+
+    private class JPAEdmAttribute<Object, String> extends
+        JPASingularAttributeMock<Object, String> {
+
+      @Override
+      public PersistentAttributeType getPersistentAttributeType() {
+        if (ATTRIBUTE_TYPE == 1) {
+          return PersistentAttributeType.BASIC;
+        } else if (ATTRIBUTE_TYPE == 2) {
+          return PersistentAttributeType.EMBEDDED;
+        } else {
+          return PersistentAttributeType.MANY_TO_ONE;
+        }
+      }
+
+      Class<String> clazz;
+      java.lang.String attributeName;
+
+      public JPAEdmAttribute(final Class<String> javaType, final java.lang.String name) {
+        this.clazz = javaType;
+        this.attributeName = name;
+
+      }
+
+      @Override
+      public Class<String> getJavaType() {
+        return clazz;
+      }
+
+      @Override
+      public java.lang.String getName() {
+        return this.attributeName;
+      }
+
+      @Override
+      public boolean isId() {
+        return true;
+      }
+    }
+
+  }
+
+}


[17/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
new file mode 100644
index 0000000..283d81a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityPropertyInfo.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.ep.aggregator;
+
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+/**
+ * Collects informations about a property of an entity.
+ * @author SAP AG
+ */
+public class EntityPropertyInfo {
+  private String name;
+  private EdmType type;
+  private EdmFacets facets;
+  private EdmCustomizableFeedMappings customMapping;
+  private String mimeType;
+  private EdmMapping mapping;
+
+  EntityPropertyInfo(final String name, final EdmType type, final EdmFacets facets, final EdmCustomizableFeedMappings customizableFeedMapping, final String mimeType, final EdmMapping mapping) {
+    this.name = name;
+    this.type = type;
+    this.facets = facets;
+    customMapping = customizableFeedMapping;
+    this.mimeType = mimeType;
+    this.mapping = mapping;
+  }
+
+  static EntityPropertyInfo create(final EdmProperty property) throws EdmException {
+    return new EntityPropertyInfo(
+        property.getName(),
+        property.getType(),
+        property.getFacets(),
+        property.getCustomizableFeedMappings(),
+        property.getMimeType(),
+        property.getMapping());
+  }
+
+  public boolean isMandatory() {
+    if (facets == null) {
+      return false;
+    } else if (facets.isNullable() == null) {
+      return false;
+    } else {
+      return !facets.isNullable();
+    }
+  }
+
+  public boolean isComplex() {
+    return false;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public EdmType getType() {
+    return type;
+  }
+
+  public EdmFacets getFacets() {
+    return facets;
+  }
+
+  public EdmCustomizableFeedMappings getCustomMapping() {
+    return customMapping;
+  }
+
+  public String getMimeType() {
+    return mimeType;
+  }
+
+  public EdmMapping getMapping() {
+    return mapping;
+  }
+
+  @Override
+  public String toString() {
+    return name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
new file mode 100644
index 0000000..ba82f30
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityTypeMapping.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.ep.aggregator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+
+/**
+ * @author SAP AG
+ */
+public class EntityTypeMapping {
+  private static final EntityTypeMapping ENTITY_TYPE_MAPPING = new EntityTypeMapping();
+  final String propertyName;
+  final Class<?> mapping;
+  final List<EntityTypeMapping> mappings;
+
+  private EntityTypeMapping() {
+    this(null, Object.class);
+  }
+
+  private EntityTypeMapping(final String name, final Class<?> mappingClass) {
+    propertyName = name;
+    mapping = mappingClass;
+    mappings = Collections.emptyList();
+  }
+
+  private EntityTypeMapping(final String name, final List<EntityTypeMapping> typeMappings) {
+    propertyName = name;
+    mapping = EntityTypeMapping.class;
+    List<EntityTypeMapping> tmp = new ArrayList<EntityTypeMapping>();
+    for (EntityTypeMapping typeMapping : typeMappings) {
+      tmp.add(typeMapping);
+    }
+    mappings = Collections.unmodifiableList(tmp);
+  }
+
+  public static EntityTypeMapping create(final Map<String, Object> mappings) throws EntityProviderException {
+    return create(null, mappings);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static EntityTypeMapping create(final String name, final Map<String, Object> mappings) throws EntityProviderException {
+    if (mappings == null) {
+      return ENTITY_TYPE_MAPPING;
+    }
+    List<EntityTypeMapping> typeMappings = new ArrayList<EntityTypeMapping>();
+    Set<Entry<String, Object>> entries = mappings.entrySet();
+    for (Entry<String, Object> entry : entries) {
+      EntityTypeMapping typeMapping;
+      Object value = entry.getValue();
+      if (value instanceof Map) {
+        typeMapping = create(entry.getKey(), (Map<String, Object>) value);
+      } else if (value instanceof Class) {
+        typeMapping = new EntityTypeMapping(entry.getKey(), (Class<?>) value);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(entry.getKey()));
+      }
+      typeMappings.add(typeMapping);
+    }
+
+    return new EntityTypeMapping(name, typeMappings);
+  }
+
+  boolean isComplex() {
+    return mappings != null && mapping == EntityTypeMapping.class;
+  }
+
+  /**
+   * If this {@link EntityTypeMapping} is complex the mapping for the property
+   * with the given <code>name</code> is returned; otherwise an empty
+   * {@link EntityTypeMapping} is returned.
+   * @param name
+   * @return the mapping for this entity type
+   */
+  public EntityTypeMapping getEntityTypeMapping(final String name) {
+    if (isComplex()) {
+      for (EntityTypeMapping mapping : mappings) {
+        if (mapping.propertyName.equals(name)) {
+          return mapping;
+        }
+      }
+    }
+    return ENTITY_TYPE_MAPPING;
+  }
+
+  /**
+   * If this {@link EntityTypeMapping} is complex the mapping {@link Class} for the property
+   * with the given <code>name</code> is returned; otherwise <code>NULL</code> is returned.
+   * @param name
+   * @return mapping {@link Class} for the property with given <code>name</code> or <code>NULL</code>.
+   */
+  public Class<?> getMappingClass(final String name) {
+    if (isComplex()) {
+      for (EntityTypeMapping mapping : mappings) {
+        if (mapping.propertyName.equals(name)) {
+          return mapping.mapping;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    if (isComplex()) {
+      return "{'" + propertyName + "'->" + mappings.toString() + "}";
+    }
+    return "{'" + propertyName + "' as " + (mapping == null ? "NULL" : mapping.getSimpleName()) + "}";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
new file mode 100644
index 0000000..7918a69
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/NavigationPropertyInfo.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.ep.aggregator;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+
+public final class NavigationPropertyInfo {
+  private String name;
+  private EdmMultiplicity multiplicity;
+
+  static NavigationPropertyInfo create(final EdmNavigationProperty property) throws EdmException {
+    NavigationPropertyInfo info = new NavigationPropertyInfo();
+    info.name = property.getName();
+    info.multiplicity = property.getMultiplicity();
+    return info;
+  }
+
+  @Override
+  public String toString() {
+    return name + "; multiplicity=" + multiplicity;
+  }
+
+  public EdmMultiplicity getMultiplicity() {
+    return multiplicity;
+  }
+
+  public String getName() {
+    return name;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
new file mode 100644
index 0000000..716c4bb
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/AtomServiceDocumentConsumer.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.servicedocument.Accept;
+import org.apache.olingo.odata2.api.servicedocument.Categories;
+import org.apache.olingo.odata2.api.servicedocument.Category;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionAttribute;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Fixed;
+import org.apache.olingo.odata2.api.servicedocument.Workspace;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+import org.apache.olingo.odata2.core.servicedocument.AcceptImpl;
+import org.apache.olingo.odata2.core.servicedocument.AtomInfoImpl;
+import org.apache.olingo.odata2.core.servicedocument.CategoriesImpl;
+import org.apache.olingo.odata2.core.servicedocument.CategoryImpl;
+import org.apache.olingo.odata2.core.servicedocument.CollectionImpl;
+import org.apache.olingo.odata2.core.servicedocument.CommonAttributesImpl;
+import org.apache.olingo.odata2.core.servicedocument.ExtensionAttributeImpl;
+import org.apache.olingo.odata2.core.servicedocument.ExtensionElementImpl;
+import org.apache.olingo.odata2.core.servicedocument.ServiceDocumentImpl;
+import org.apache.olingo.odata2.core.servicedocument.TitleImpl;
+import org.apache.olingo.odata2.core.servicedocument.WorkspaceImpl;
+
+public class AtomServiceDocumentConsumer {
+  private String currentHandledStartTagName;
+  private static final String DEFAULT_PREFIX = "";
+
+  public ServiceDocumentImpl readServiceDokument(final XMLStreamReader reader) throws EntityProviderException {
+    AtomInfoImpl atomInfo = new AtomInfoImpl();
+    ServiceDocumentImpl serviceDocument = new ServiceDocumentImpl();
+    List<Workspace> workspaces = new ArrayList<Workspace>();
+    List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+    CommonAttributesImpl attributes = new CommonAttributesImpl();
+    try {
+      while (reader.hasNext()
+          && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_SERVICE.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          currentHandledStartTagName = reader.getLocalName();
+          if (FormatXml.APP_SERVICE.equals(currentHandledStartTagName)) {
+            attributes = parseCommonAttribute(reader);
+          } else if (FormatXml.APP_WORKSPACE.equals(currentHandledStartTagName)) {
+            workspaces.add(parseWorkspace(reader));
+          } else {
+            ExtensionElementImpl extElement = parseExtensionElement(reader);
+            if (extElement != null) {
+              extElements.add(extElement);
+            }
+          }
+        }
+      }
+      if (workspaces.isEmpty()) {
+        throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Service element must contain at least one workspace element"));
+      }
+      reader.close();
+      atomInfo.setWorkspaces(workspaces).setCommonAttributes(attributes).setExtesionElements(extElements);
+
+      serviceDocument.setAtomInfo(atomInfo);
+      serviceDocument.setEntitySetsInfo(atomInfo.getEntitySetsInfo());
+      return serviceDocument;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private CommonAttributesImpl parseCommonAttribute(final XMLStreamReader reader) {
+    CommonAttributesImpl attribute = new CommonAttributesImpl();
+    List<ExtensionAttribute> extAttributes = new ArrayList<ExtensionAttribute>();
+    attribute.setBase(reader.getAttributeValue(null, FormatXml.XML_BASE));
+    attribute.setLang(reader.getAttributeValue(null, FormatXml.XML_LANG));
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      if (!(FormatXml.XML_BASE.equals(reader.getAttributeLocalName(i)) && Edm.PREFIX_XML.equals(reader.getAttributePrefix(i))
+          || (FormatXml.XML_LANG.equals(reader.getAttributeLocalName(i)) && Edm.PREFIX_XML.equals(reader.getAttributePrefix(i)))
+          || ("local".equals(reader.getAttributeNamespace(i)) || DEFAULT_PREFIX.equals(reader.getAttributePrefix(i))))) {
+        extAttributes.add(new ExtensionAttributeImpl()
+            .setName(reader.getAttributeLocalName(i))
+            .setNamespace(reader.getAttributeNamespace(i))
+            .setPrefix(reader.getAttributePrefix(i))
+            .setText(reader.getAttributeValue(i)));
+      }
+    }
+
+    return attribute.setAttributes(extAttributes);
+  }
+
+  private WorkspaceImpl parseWorkspace(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_WORKSPACE);
+
+    TitleImpl title = null;
+    List<Collection> collections = new ArrayList<Collection>();
+    List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+    CommonAttributesImpl attributes = parseCommonAttribute(reader);
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_WORKSPACE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (FormatXml.APP_COLLECTION.equals(currentHandledStartTagName)) {
+          collections.add(parseCollection(reader));
+        } else if (FormatXml.ATOM_TITLE.equals(currentHandledStartTagName)) {
+          title = parseTitle(reader);
+        } else {
+          extElements.add(parseExtensionSansTitleElement(reader));
+        }
+      }
+    }
+    if (title == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Missing element title for workspace"));
+    }
+    return new WorkspaceImpl().setTitle(title).setCollections(collections).setAttributes(attributes).setExtesionElements(extElements);
+  }
+
+  private CollectionImpl parseCollection(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_COLLECTION);
+    TitleImpl title = null;
+    String resourceIdentifier = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+    CommonAttributesImpl attributes = parseCommonAttribute(reader);
+    List<ExtensionElement> extElements = new ArrayList<ExtensionElement>();
+    List<Accept> acceptList = new ArrayList<Accept>();
+    List<Categories> categories = new ArrayList<Categories>();
+    if (resourceIdentifier == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("href"));
+    }
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_COLLECTION.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (FormatXml.ATOM_TITLE.equals(currentHandledStartTagName)) {
+          title = parseTitle(reader);
+        } else if (FormatXml.APP_ACCEPT.equals(currentHandledStartTagName)) {
+          acceptList.add(parseAccept(reader));
+        } else if (FormatXml.APP_CATEGORIES.equals(currentHandledStartTagName)) {
+          categories.add(parseCategories(reader));
+        } else {
+          extElements.add(parseExtensionSansTitleElement(reader));
+        }
+      }
+    }
+    return new CollectionImpl().setHref(resourceIdentifier).setTitle(title).setCommonAttributes(attributes).setExtesionElements(extElements).setAcceptElements(acceptList).setCategories(categories);
+  }
+
+  private TitleImpl parseTitle(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_TITLE);
+    String text = "";
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI()) && FormatXml.ATOM_TITLE.equals(reader.getLocalName()))) {
+      if (reader.isCharacters()) {
+        text += reader.getText();
+      }
+      reader.next();
+    }
+    return new TitleImpl().setText(text);
+  }
+
+  private AcceptImpl parseAccept(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_ACCEPT);
+    CommonAttributesImpl commonAttributes = parseCommonAttribute(reader);
+    String text = "";
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_ACCEPT.equals(reader.getLocalName()))) {
+      if (reader.isCharacters()) {
+        text += reader.getText();
+      }
+      reader.next();
+    }
+    return new AcceptImpl().setCommonAttributes(commonAttributes).setText(text);
+  }
+
+  private CategoriesImpl parseCategories(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_APP_2007, FormatXml.APP_CATEGORIES);
+    CategoriesImpl categories = new CategoriesImpl();
+    String href = reader.getAttributeValue(null, FormatXml.ATOM_HREF);
+    String fixed = reader.getAttributeValue(null, FormatXml.APP_CATEGORIES_FIXED);
+    categories.setScheme(reader.getAttributeValue(null, FormatXml.APP_CATEGORIES_SCHEME));
+    categories.setHref(href);
+    if (href == null) {
+      for (int i = 0; i < Fixed.values().length; i++) {
+        if (Fixed.values()[i].name().equalsIgnoreCase(fixed)) {
+          categories.setFixed(Fixed.values()[i]);
+        }
+      }
+      if (categories.getFixed() == null) {
+        categories.setFixed(Fixed.NO);
+      }
+      List<Category> categoriesList = new ArrayList<Category>();
+      while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI()) && FormatXml.APP_CATEGORIES.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          currentHandledStartTagName = reader.getLocalName();
+          if (FormatXml.ATOM_CATEGORY.equals(currentHandledStartTagName)) {
+            categoriesList.add(parseCategory(reader));
+          }
+        }
+      }
+      categories.setCategoryList(categoriesList);
+    }
+    if ((href != null && fixed != null && categories.getScheme() != null) ||
+        (href == null && fixed == null && categories.getScheme() == null)) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("for the element categories"));
+    }
+    return categories;
+  }
+
+  private CategoryImpl parseCategory(final XMLStreamReader reader) throws XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_CATEGORY);
+    CategoryImpl category = new CategoryImpl();
+    category.setScheme(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_SCHEME));
+    category.setTerm(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_TERM));
+    category.setLabel(reader.getAttributeValue(null, FormatXml.ATOM_CATEGORY_LABEL));
+    CommonAttributesImpl attributes = parseCommonAttribute(reader);
+    return category.setCommonAttributes(attributes);
+  }
+
+  private ExtensionElementImpl parseExtensionSansTitleElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    ExtensionElementImpl extElement = new ExtensionElementImpl();
+    if (!(Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI())
+    || (FormatXml.ATOM_TITLE.equals(reader.getLocalName()) && Edm.NAMESPACE_ATOM_2005.equals(reader.getNamespaceURI())))) {
+      extElement = parseElement(reader);
+    }
+    return extElement;
+  }
+
+  private ExtensionElementImpl parseExtensionElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    ExtensionElementImpl extElement = null;
+    if (!Edm.NAMESPACE_APP_2007.equals(reader.getNamespaceURI())) {
+      extElement = parseElement(reader);
+    }
+    return extElement;
+  }
+
+  private ExtensionElementImpl parseElement(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    List<ExtensionElement> extensionElements = new ArrayList<ExtensionElement>();
+    ExtensionElementImpl extElement = new ExtensionElementImpl().setName(reader.getLocalName()).setNamespace(reader.getNamespaceURI()).setPrefix(reader.getPrefix());
+    extElement.setAttributes(parseAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && extElement.getName() != null && extElement.getName().equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isCharacters()) {
+        extElement.setText(reader.getText());
+      } else if (reader.isStartElement()) {
+        extensionElements.add(parseExtensionElement(reader));
+      }
+    }
+    extElement.setElements(extensionElements);
+    if (extElement.getText() == null && extElement.getAttributes().isEmpty() && extElement.getElements().isEmpty()) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Invalid extension element"));
+    }
+    return extElement;
+  }
+
+  private List<ExtensionAttribute> parseAttribute(final XMLStreamReader reader) {
+    List<ExtensionAttribute> extAttributes = new ArrayList<ExtensionAttribute>();
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      {
+        extAttributes.add(new ExtensionAttributeImpl()
+            .setName(reader.getAttributeLocalName(i))
+            .setNamespace(reader.getAttributeNamespace(i))
+            .setPrefix(reader.getAttributePrefix(i))
+            .setText(reader.getAttributeValue(i)));
+      }
+    }
+
+    return extAttributes;
+  }
+
+  public ServiceDocumentImpl parseXml(final InputStream in) throws EntityProviderException {
+    return readServiceDokument(createStreamReader(in));
+  }
+
+  private XMLStreamReader createStreamReader(final InputStream in) throws EntityProviderException {
+    if (in != null) {
+      XMLInputFactory factory = XMLInputFactory.newInstance();
+      factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+      factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+      XMLStreamReader streamReader;
+      try {
+        streamReader = factory.createXMLStreamReader(in);
+      } catch (XMLStreamException e) {
+        throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      }
+      return streamReader;
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent("Null InputStream"));
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
new file mode 100644
index 0000000..9185ad0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntityConsumer.java
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+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.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntityConsumer {
+
+  /** Default used charset for reader */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(content);
+
+      JsonEntryConsumer jec = new JsonEntryConsumer(reader, eia, properties);
+      ODataEntry result = jec.readSingleEntry();
+      return result;
+    } catch (UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet);
+      reader = createJsonReader(content);
+
+      JsonFeedConsumer jfc = new JsonFeedConsumer(reader, eia, readProperties);
+      ODataFeed result = jfc.readFeedStandalone();
+
+      return result;
+    } catch (UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public Map<String, Object> readProperty(final EdmProperty property, final InputStream content, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(content);
+      return new JsonPropertyConsumer().readPropertyStandalone(reader, property, readProperties);
+    } catch (final UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public String readLink(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(content);
+      return new JsonLinkConsumer().readLink(reader, entitySet);
+    } catch (final UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  public List<String> readLinks(final EdmEntitySet entitySet, final Object content) throws EntityProviderException {
+    JsonReader reader = null;
+    EntityProviderException cachedException = null;
+
+    try {
+      reader = createJsonReader(content);
+      return new JsonLinkConsumer().readLinks(reader, entitySet);
+    } catch (final UnsupportedEncodingException e) {
+      cachedException = new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      if (reader != null) {
+        try {
+          reader.close();
+        } catch (final IOException e) {
+          if (cachedException != null) {
+            throw cachedException;
+          } else {
+            throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+          }
+        }
+      }
+    }
+  }
+
+  private JsonReader createJsonReader(final Object content) throws EntityProviderException, UnsupportedEncodingException {
+
+    if (content == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+          .addContent("Got not supported NULL object as content to de-serialize."));
+    }
+
+    if (content instanceof InputStream) {
+      return new JsonReader(new InputStreamReader((InputStream) content, DEFAULT_CHARSET));
+    }
+    throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT
+        .addContent("Found not supported content of class '" + content.getClass() + "' to de-serialize."));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
new file mode 100644
index 0000000..6d54f5c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonEntryConsumer.java
@@ -0,0 +1,311 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+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.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.NavigationPropertyInfo;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntryConsumer {
+
+  private final Map<String, Object> properties = new HashMap<String, Object>();
+  private final MediaMetadataImpl mediaMetadata = new MediaMetadataImpl();
+  private final EntryMetadataImpl entryMetadata = new EntryMetadataImpl();
+  private final ExpandSelectTreeNodeImpl expandSelectTree = new ExpandSelectTreeNodeImpl();
+  private final Map<String, Object> typeMappings;
+  private final EntityInfoAggregator eia;
+  private final JsonReader reader;
+  private final EntityProviderReadProperties readProperties;
+  private final ODataEntryImpl entryResult;
+
+  public JsonEntryConsumer(final JsonReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) {
+    typeMappings = readProperties.getTypeMappings();
+    this.eia = eia;
+    this.readProperties = readProperties;
+    this.reader = reader;
+    entryResult = new ODataEntryImpl(properties, mediaMetadata, entryMetadata, expandSelectTree);
+  }
+
+  public ODataEntry readSingleEntry() throws EntityProviderException {
+    try {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        readEntryContent();
+        reader.endObject();
+      } else {
+        handleName(nextName);
+        readEntryContent();
+      }
+      reader.endObject();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek().toString()));
+      }
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+    return entryResult;
+  }
+
+  public ODataEntry readFeedEntry() throws EdmException, EntityProviderException, IOException {
+    reader.beginObject();
+    readEntryContent();
+    reader.endObject();
+    return entryResult;
+  }
+
+  private void readEntryContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      String name = reader.nextName();
+      handleName(name);
+    }
+
+    //TODO: validate created entry
+  }
+
+  private void handleName(final String name) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.METADATA.equals(name)) {
+      readMetadata();
+      validateMetadata();
+    } else {
+      EntityPropertyInfo propertyInfo = eia.getPropertyInfo(name);
+      if (propertyInfo != null) {
+        JsonPropertyConsumer jpc = new JsonPropertyConsumer();
+        Object propertyValue = jpc.readPropertyValue(reader, propertyInfo, typeMappings.get(name));
+        if (properties.containsKey(name)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(name));
+        }
+        properties.put(name, propertyValue);
+      } else {
+        readNavigationProperty(name);
+      }
+    }
+  }
+
+  private void readMetadata() throws IOException, EdmException, EntityProviderException {
+    String name = null;
+    String value = null;
+    reader.beginObject();
+    while (reader.hasNext()) {
+      name = reader.nextName();
+
+      if (FormatJson.PROPERTIES.equals(name)) {
+        reader.skipValue();
+        continue;
+      }
+
+      value = reader.nextString();
+      if (FormatJson.ID.equals(name)) {
+        entryMetadata.setId(value);
+      } else if (FormatJson.URI.equals(name)) {
+        entryMetadata.setUri(value);
+      } else if (FormatJson.TYPE.equals(name)) {
+        String fullQualifiedName = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
+        if (!fullQualifiedName.equals(value)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(fullQualifiedName).addContent(value));
+        }
+      } else if (FormatJson.ETAG.equals(name)) {
+        entryMetadata.setEtag(value);
+      } else if (FormatJson.EDIT_MEDIA.equals(name)) {
+        mediaMetadata.setEditLink(value);
+      } else if (FormatJson.MEDIA_SRC.equals(name)) {
+        mediaMetadata.setSourceLink(value);
+      } else if (FormatJson.MEDIA_ETAG.equals(name)) {
+        mediaMetadata.setEtag(value);
+      } else if (FormatJson.CONTENT_TYPE.equals(name)) {
+        mediaMetadata.setContentType(value);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(name).addContent(FormatJson.METADATA));
+      }
+    }
+
+    reader.endObject();
+  }
+
+  private void validateMetadata() throws EdmException, EntityProviderException {
+    if (eia.getEntityType().hasStream()) {
+      if (mediaMetadata.getSourceLink() == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.MEDIA_SRC).addContent(FormatJson.METADATA));
+      }
+      if (mediaMetadata.getContentType() == null) {
+        throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.CONTENT_TYPE).addContent(FormatJson.METADATA));
+      }
+      //TODO Mime Type Mapping
+    } else {
+      if (mediaMetadata.getContentType() != null || mediaMetadata.getEditLink() != null
+          || mediaMetadata.getEtag() != null || mediaMetadata.getSourceLink() != null) {
+        throw new EntityProviderException(EntityProviderException.MEDIA_DATA_NOT_INITIAL);
+      }
+    }
+  }
+
+  private void readNavigationProperty(final String navigationPropertyName) throws IOException, EntityProviderException, EdmException {
+    NavigationPropertyInfo navigationPropertyInfo = eia.getNavigationPropertyInfo(navigationPropertyName);
+    if (navigationPropertyInfo == null) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(navigationPropertyName));
+    }
+
+    if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+      reader.beginObject();
+      String name = reader.nextName();
+      if (FormatJson.DEFERRED.equals(name)) {
+        reader.beginObject();
+        String uri = reader.nextName();
+        if (FormatJson.URI.equals(uri)) {
+          String value = reader.nextString();
+          entryMetadata.putAssociationUri(navigationPropertyInfo.getName(), value);
+        } else {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(uri));
+        }
+        reader.endObject();
+      } else {
+        EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+        EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet);
+        EntityProviderReadProperties inlineReadProperties;
+        OnReadInlineContent callback = readProperties.getCallback();
+        try {
+          if (callback == null) {
+            inlineReadProperties = EntityProviderReadProperties.init().mergeSemantic(readProperties.getMergeSemantic()).build();
+
+          } else {
+            inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+          }
+
+          if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+            JsonFeedConsumer inlineConsumer = new JsonFeedConsumer(reader, inlineEia, inlineReadProperties);
+            ODataFeed feed = inlineConsumer.readStartedInlineFeed(name);
+            updateExpandSelectTree(navigationPropertyName, feed);
+            if (callback == null) {
+              properties.put(navigationPropertyName, feed);
+              entryResult.setContainsInlineEntry(true);
+            } else {
+              ReadFeedResult result = new ReadFeedResult(inlineReadProperties, navigationProperty, feed);
+              callback.handleReadFeed(result);
+            }
+          } else {
+            JsonEntryConsumer inlineConsumer = new JsonEntryConsumer(reader, inlineEia, inlineReadProperties);
+            ODataEntry entry = inlineConsumer.readInlineEntry(name);
+            updateExpandSelectTree(navigationPropertyName, entry);
+            if (callback == null) {
+              properties.put(navigationPropertyName, entry);
+              entryResult.setContainsInlineEntry(true);
+            } else {
+              ReadEntryResult result = new ReadEntryResult(inlineReadProperties, navigationProperty, entry);
+              callback.handleReadEntry(result);
+            }
+          }
+
+        } catch (ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+        }
+      }
+      reader.endObject();
+    } else {
+      final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+      final EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navigationProperty);
+      final EntityInfoAggregator inlineInfo = EntityInfoAggregator.create(inlineEntitySet);
+      OnReadInlineContent callback = readProperties.getCallback();
+      EntityProviderReadProperties inlineReadProperties;
+      if (callback == null) {
+        inlineReadProperties = EntityProviderReadProperties.init().mergeSemantic(readProperties.getMergeSemantic()).build();
+      } else {
+        try {
+          inlineReadProperties = callback.receiveReadProperties(readProperties, navigationProperty);
+        } catch (final ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+        }
+      }
+      ODataFeed feed = new JsonFeedConsumer(reader, inlineInfo, inlineReadProperties).readInlineFeedStandalone();
+      updateExpandSelectTree(navigationPropertyName, feed);
+      if (callback == null) {
+        properties.put(navigationPropertyName, feed);
+        entryResult.setContainsInlineEntry(true);
+      } else {
+        ReadFeedResult result = new ReadFeedResult(inlineReadProperties, navigationProperty, feed);
+        try {
+          callback.handleReadFeed(result);
+        } catch (final ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+        }
+      }
+    }
+  }
+
+  private void updateExpandSelectTree(final String navigationPropertyName, final ODataFeed feed) {
+    List<ODataEntry> entries = feed.getEntries();
+    if (entries.size() > 0) {
+      updateExpandSelectTree(navigationPropertyName, entries.get(0));
+    } else {
+      expandSelectTree.setExpanded();
+      expandSelectTree.setExplicitlySelected();
+      expandSelectTree.putLink(navigationPropertyName, new ExpandSelectTreeNodeImpl());
+    }
+  }
+
+  private void updateExpandSelectTree(final String navigationPropertyName, final ODataEntry entry) {
+    expandSelectTree.setExpanded();
+    expandSelectTree.setExplicitlySelected();
+    expandSelectTree.putLink(navigationPropertyName, (ExpandSelectTreeNodeImpl) entry.getExpandSelectTree());
+  }
+
+  private ODataEntry readInlineEntry(final String name) throws EdmException, EntityProviderException, IOException {
+    //consume the already started content
+    handleName(name);
+    //consume the rest of the entry content
+    readEntryContent();
+    return entryResult;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
new file mode 100644
index 0000000..4da0420
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonFeedConsumer.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.EdmException;
+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.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataFeedImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonFeedConsumer {
+
+  private JsonReader reader;
+  private EntityInfoAggregator eia;
+  private EntityProviderReadProperties readProperties;
+  private List<ODataEntry> entries = new ArrayList<ODataEntry>();
+  private FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+  private boolean resultsArrayPresent = false;
+
+  public JsonFeedConsumer(final JsonReader reader, final EntityInfoAggregator eia, final EntityProviderReadProperties readProperties) {
+    this.reader = reader;
+    this.eia = eia;
+    this.readProperties = readProperties;
+  }
+
+  public ODataFeed readFeedStandalone() throws EntityProviderException {
+    try {
+      readFeed();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek().toString()));
+      }
+
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return new ODataFeedImpl(entries, feedMetadata);
+  }
+
+  private void readFeed() throws IOException, EdmException, EntityProviderException {
+    if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+      readArrayContent();
+    } else {
+      reader.beginObject();
+      final String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+          readArrayContent();
+        } else {
+          reader.beginObject();
+          readFeedContent();
+          reader.endObject();
+        }
+      } else {
+        handleName(nextName);
+        readFeedContent();
+      }
+
+      reader.endObject();
+    }
+  }
+
+  private void readFeedContent() throws IOException, EdmException, EntityProviderException {
+    while (reader.hasNext()) {
+      final String nextName = reader.nextName();
+      handleName(nextName);
+    }
+
+    if (!resultsArrayPresent) {
+      throw new EntityProviderException(EntityProviderException.MISSING_RESULTS_ARRAY);
+    }
+  }
+
+  private void handleName(final String nextName) throws IOException, EdmException, EntityProviderException {
+    if (FormatJson.RESULTS.equals(nextName)) {
+      resultsArrayPresent = true;
+      readArrayContent();
+
+    } else if (FormatJson.COUNT.equals(nextName)) {
+      readInlineCount(reader, feedMetadata);
+
+    } else if (FormatJson.NEXT.equals(nextName)) {
+      if (reader.peek() == JsonToken.STRING && feedMetadata.getNextLink() == null) {
+        String nextLink = reader.nextString();
+        feedMetadata.setNextLink(nextLink);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent("JsonFeed"));
+      }
+
+    } else if (FormatJson.DELTA.equals(nextName)) {
+      if (reader.peek() == JsonToken.STRING && feedMetadata.getDeltaLink() == null) {
+        String deltaLink = reader.nextString();
+        feedMetadata.setDeltaLink(deltaLink);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent("JsonFeed"));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(nextName).addContent("JsonFeed"));
+    }
+  }
+
+  private void readArrayContent() throws IOException, EdmException, EntityProviderException {
+    reader.beginArray();
+    while (reader.hasNext()) {
+      final ODataEntry entry = new JsonEntryConsumer(reader, eia, readProperties).readFeedEntry();
+      entries.add(entry);
+    }
+    reader.endArray();
+  }
+
+  protected static void readInlineCount(final JsonReader reader, final FeedMetadataImpl feedMetadata) throws IOException, EntityProviderException {
+    if (reader.peek() == JsonToken.STRING && feedMetadata.getInlineCount() == null) {
+      int inlineCount;
+      try {
+        inlineCount = reader.nextInt();
+      } catch (final NumberFormatException e) {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(""), e);
+      }
+      if (inlineCount >= 0) {
+        feedMetadata.setInlineCount(inlineCount);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(inlineCount));
+      }
+    } else {
+      throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID.addContent(reader.peek()));
+    }
+  }
+
+  protected ODataFeed readStartedInlineFeed(final String name) throws EdmException, EntityProviderException, IOException {
+    //consume the already started content
+    handleName(name);
+    //consume the rest of the entry content
+    readFeedContent();
+    return new ODataFeedImpl(entries, feedMetadata);
+  }
+
+  protected ODataFeed readInlineFeedStandalone() throws EdmException, EntityProviderException, IOException {
+    readFeed();
+    return new ODataFeedImpl(entries, feedMetadata);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.java
new file mode 100644
index 0000000..f82328c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonLinkConsumer.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.core.ep.consumer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonLinkConsumer {
+
+  /**
+   * Reads single link with format <code>{"d":{"uri":"http://somelink"}}</code>
+   * or <code>{"uri":"http://somelink"}</code>.
+   * @param reader
+   * @param entitySet
+   * @return link as string object
+   * @throws EntityProviderException
+   */
+  public String readLink(final JsonReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+    try {
+      String result;
+      reader.beginObject();
+      String nextName = reader.nextName();
+      final boolean wrapped = FormatJson.D.equals(nextName);
+      if (wrapped) {
+        reader.beginObject();
+        nextName = reader.nextName();
+      }
+      if (FormatJson.URI.equals(nextName) && reader.peek() == JsonToken.STRING) {
+        result = reader.nextString();
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.D + " or " + FormatJson.URI).addContent(nextName));
+      }
+      reader.endObject();
+      if (wrapped) {
+        reader.endObject();
+      }
+
+      reader.peek(); // to assert end of structure or document
+
+      return result;
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  /**
+   * Reads a collection of links, optionally wrapped in a "d" object,
+   * and optionally wrapped in an "results" object, where an additional "__count"
+   * object could appear on the same level as the "results".
+   * @param reader
+   * @param entitySet
+   * @return links as List of Strings
+   * @throws EntityProviderException
+   */
+  public List<String> readLinks(final JsonReader reader, final EdmEntitySet entitySet) throws EntityProviderException {
+    List<String> links = null;
+    int openedObjects = 0;
+
+    try {
+      String nextName;
+      if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+        nextName = FormatJson.RESULTS;
+      } else {
+        reader.beginObject();
+        openedObjects++;
+        nextName = reader.nextName();
+      }
+      if (FormatJson.D.equals(nextName)) {
+        if (reader.peek() == JsonToken.BEGIN_ARRAY) {
+          nextName = FormatJson.RESULTS;
+        } else {
+          reader.beginObject();
+          openedObjects++;
+          nextName = reader.nextName();
+        }
+      }
+      FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+      if (FormatJson.COUNT.equals(nextName)) {
+        JsonFeedConsumer.readInlineCount(reader, feedMetadata);
+        nextName = reader.nextName();
+      }
+      if (FormatJson.RESULTS.equals(nextName)) {
+        links = readLinksArray(reader);
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.RESULTS).addContent(nextName));
+      }
+      if (reader.hasNext() && reader.peek() == JsonToken.NAME) {
+        if (FormatJson.COUNT.equals(reader.nextName())) {
+          JsonFeedConsumer.readInlineCount(reader, feedMetadata);
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.COUNT).addContent(nextName));
+        }
+      }
+      for (; openedObjects > 0; openedObjects--) {
+        reader.endObject();
+      }
+
+      reader.peek(); // to assert end of document
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+    return links;
+  }
+
+  private List<String> readLinksArray(final JsonReader reader) throws IOException, EntityProviderException {
+    List<String> links = new ArrayList<String>();
+
+    reader.beginArray();
+    while (reader.hasNext()) {
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.URI.equals(nextName) && reader.peek() == JsonToken.STRING) {
+        links.add(reader.nextString());
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_CONTENT.addContent(FormatJson.URI).addContent(nextName));
+      }
+      reader.endObject();
+    }
+    reader.endArray();
+
+    return links;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
new file mode 100644
index 0000000..2a3327c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonPropertyConsumer.java
@@ -0,0 +1,190 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonToken;
+import org.apache.olingo.odata2.api.edm.Edm;
+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.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+
+/**
+ * @author SAP AG
+ */
+public class JsonPropertyConsumer {
+
+  public Map<String, Object> readPropertyStandalone(final JsonReader reader, final EdmProperty property, final EntityProviderReadProperties readProperties) throws EntityProviderException {
+    try {
+      EntityPropertyInfo entityPropertyInfo = EntityInfoAggregator.create(property);
+      Map<String, Object> typeMappings = readProperties == null ? null : readProperties.getTypeMappings();
+      Map<String, Object> result = new HashMap<String, Object>();
+
+      reader.beginObject();
+      String nextName = reader.nextName();
+      if (FormatJson.D.equals(nextName)) {
+        reader.beginObject();
+        nextName = reader.nextName();
+        handleName(reader, typeMappings, entityPropertyInfo, result, nextName);
+        reader.endObject();
+      } else {
+        handleName(reader, typeMappings, entityPropertyInfo, result, nextName);
+      }
+      reader.endObject();
+
+      if (reader.peek() != JsonToken.END_DOCUMENT) {
+        throw new EntityProviderException(EntityProviderException.END_DOCUMENT_EXPECTED.addContent(reader.peek().toString()));
+      }
+
+      return result;
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private void handleName(final JsonReader reader, final Map<String, Object> typeMappings, final EntityPropertyInfo entityPropertyInfo, final Map<String, Object> result, final String nextName) throws EntityProviderException {
+    if (!entityPropertyInfo.getName().equals(nextName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent(nextName));
+    }
+    Object mapping = null;
+    if (typeMappings != null) {
+      mapping = typeMappings.get(nextName);
+    }
+    Object propertyValue = readPropertyValue(reader, entityPropertyInfo, mapping);
+    result.put(nextName, propertyValue);
+  }
+
+  protected Object readPropertyValue(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo, final Object typeMapping) throws EntityProviderException {
+    try {
+      return entityPropertyInfo.isComplex() ?
+          readComplexProperty(reader, (EntityComplexPropertyInfo) entityPropertyInfo, typeMapping) :
+          readSimpleProperty(reader, entityPropertyInfo, typeMapping);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private Object readSimpleProperty(final JsonReader reader, final EntityPropertyInfo entityPropertyInfo, final Object typeMapping) throws EdmException, EntityProviderException, IOException {
+    final EdmSimpleType type = (EdmSimpleType) entityPropertyInfo.getType();
+    Object value = null;
+    final JsonToken tokenType = reader.peek();
+    if (tokenType == JsonToken.NULL) {
+      reader.nextNull();
+    } else {
+      switch (EdmSimpleTypeKind.valueOf(type.getName())) {
+      case Boolean:
+        if (tokenType == JsonToken.BOOLEAN) {
+          value = reader.nextBoolean();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      case Byte:
+      case SByte:
+      case Int16:
+      case Int32:
+        if (tokenType == JsonToken.NUMBER) {
+          value = reader.nextInt();
+          value = value.toString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      default:
+        if (tokenType == JsonToken.STRING) {
+          value = reader.nextString();
+        } else {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY_VALUE.addContent(entityPropertyInfo.getName()));
+        }
+        break;
+      }
+    }
+
+    final Class<?> typeMappingClass = typeMapping == null ? type.getDefaultType() : (Class<?>) typeMapping;
+    return type.valueOfString((String) value, EdmLiteralKind.JSON, entityPropertyInfo.getFacets(), typeMappingClass);
+  }
+
+  @SuppressWarnings("unchecked")
+  private Object readComplexProperty(final JsonReader reader, final EntityComplexPropertyInfo complexPropertyInfo, final Object typeMapping) throws EdmException, EntityProviderException, IOException {
+    if (reader.peek().equals(JsonToken.NULL)) {
+      reader.nextNull();
+      return null;
+    }
+
+    reader.beginObject();
+    Map<String, Object> data = new HashMap<String, Object>();
+
+    Map<String, Object> mapping;
+    if (typeMapping != null) {
+      if (typeMapping instanceof Map) {
+        mapping = (Map<String, Object>) typeMapping;
+      } else {
+        throw new EntityProviderException(EntityProviderException.INVALID_MAPPING.addContent(complexPropertyInfo.getName()));
+      }
+    } else {
+      mapping = new HashMap<String, Object>();
+    }
+
+    while (reader.hasNext()) {
+      String childName = reader.nextName();
+      if (FormatJson.METADATA.equals(childName)) {
+        reader.beginObject();
+        childName = reader.nextName();
+        if (!FormatJson.TYPE.equals(childName)) {
+          throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent(FormatJson.TYPE).addContent(FormatJson.METADATA));
+        }
+        String actualTypeName = reader.nextString();
+        String expectedTypeName = complexPropertyInfo.getType().getNamespace() + Edm.DELIMITER + complexPropertyInfo.getType().getName();
+        if (!expectedTypeName.equals(actualTypeName)) {
+          throw new EntityProviderException(EntityProviderException.INVALID_ENTITYTYPE.addContent(expectedTypeName).addContent(actualTypeName));
+        }
+        reader.endObject();
+      } else {
+        EntityPropertyInfo childPropertyInfo = complexPropertyInfo.getPropertyInfo(childName);
+        if (childPropertyInfo == null) {
+          throw new EntityProviderException(EntityProviderException.INVALID_PROPERTY.addContent(childName));
+        }
+        Object childData = readPropertyValue(reader, childPropertyInfo, mapping.get(childName));
+        if (data.containsKey(childName)) {
+          throw new EntityProviderException(EntityProviderException.DOUBLE_PROPERTY.addContent(childName));
+        }
+        data.put(childName, childData);
+      }
+    }
+    reader.endObject();
+    return data;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
new file mode 100644
index 0000000..b0fbb25
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/consumer/JsonServiceDocumentConsumer.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.google.gson.stream.JsonReader;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.edm.provider.EdmEntitySetInfoImplProv;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.servicedocument.ServiceDocumentImpl;
+
+/**
+ * Reads the OData service document (JSON).
+ * @author SAP AG
+ */
+public class JsonServiceDocumentConsumer {
+  private static final String DEFAULT_CHARSET = "UTF-8";
+  List<EdmEntitySetInfo> entitySets = new ArrayList<EdmEntitySetInfo>();
+  private String currentHandledObjectName;
+
+  public ServiceDocumentImpl parseJson(final InputStream in) throws EntityProviderException {
+    return readServiceDocument(createJsonReader(in));
+  }
+
+  private ServiceDocumentImpl readServiceDocument(final JsonReader reader) throws EntityProviderException {
+    try {
+      reader.beginObject();
+      currentHandledObjectName = reader.nextName();
+      if (FormatJson.D.equals(currentHandledObjectName)) {
+        reader.beginObject();
+        readContent(reader);
+        reader.endObject();
+      }
+      reader.endObject();
+      reader.peek();
+      reader.close();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final IllegalStateException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return new ServiceDocumentImpl().setEntitySetsInfo(entitySets);
+  }
+
+  private void readContent(final JsonReader reader) throws IOException, EdmException, EntityProviderException {
+    currentHandledObjectName = reader.nextName();
+    if (FormatJson.ENTITY_SETS.equals(currentHandledObjectName)) {
+      reader.beginArray();
+      readEntitySets(reader);
+      reader.endArray();
+    }
+  }
+
+  private void readEntitySets(final JsonReader reader) throws IOException, EntityProviderException, EdmException {
+    while (reader.hasNext()) {
+      currentHandledObjectName = reader.nextString();
+      if (currentHandledObjectName != null) {
+        // Looking for the last dot: "\\.(?=[^.]+$)"
+        String[] names = currentHandledObjectName.split("\\" + Edm.DELIMITER + "(?=[^" + Edm.DELIMITER + "]+$)");
+        if (names.length == 1) {
+          EntitySet entitySet = new EntitySet().setName(names[0]);
+          EntityContainerInfo container = new EntityContainerInfo().setDefaultEntityContainer(true);
+          EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+          entitySets.add(entitySetInfo);
+        } else {
+          EntitySet entitySet = new EntitySet().setName(names[1]);
+          EntityContainerInfo container = new EntityContainerInfo().setName(names[0]).setDefaultEntityContainer(false);
+          EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+          entitySets.add(entitySetInfo);
+        }
+      }
+    }
+  }
+
+  private JsonReader createJsonReader(final InputStream in) throws EntityProviderException {
+    if (in == null) {
+      throw new EntityProviderException(EntityProviderException.INVALID_STATE.addContent(("Got not supported NULL object as content to de-serialize.")));
+    }
+    InputStreamReader isReader;
+    try {
+      isReader = new InputStreamReader(in, DEFAULT_CHARSET);
+    } catch (final UnsupportedEncodingException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return new JsonReader(isReader);
+  }
+}


[22/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRequest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRequest.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRequest.java
new file mode 100644
index 0000000..3f7d0e2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRequest.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoRequest implements DebugInfo {
+
+  private final String method;
+  private final URI uri;
+  private final Map<String, List<String>> headers;
+
+  public DebugInfoRequest(final String method, final URI uri, final Map<String, List<String>> headers) {
+    this.method = method;
+    this.uri = uri;
+    this.headers = headers;
+  }
+
+  @Override
+  public String getName() {
+    return "Request";
+  }
+
+  @Override
+  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+    jsonStreamWriter.beginObject()
+        .namedStringValueRaw("method", method).separator()
+        .namedStringValue("uri", uri.toString());
+
+    if (!headers.isEmpty()) {
+      jsonStreamWriter.separator()
+          .name("headers")
+          .beginObject();
+      boolean first = true;
+      for (final String name : headers.keySet()) {
+        for (final String value : headers.get(name)) {
+          if (!first) {
+            jsonStreamWriter.separator();
+          }
+          first = false;
+          jsonStreamWriter.namedStringValue(name, value);
+        }
+      }
+      jsonStreamWriter.endObject();
+    }
+
+    jsonStreamWriter.endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoResponse.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoResponse.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoResponse.java
new file mode 100644
index 0000000..9407710
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoResponse.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoResponse implements DebugInfo {
+
+  private final HttpStatusCodes status;
+  private final Map<String, String> headers;
+
+  public DebugInfoResponse(final HttpStatusCodes status, final Map<String, String> headers) {
+    this.status = status;
+    this.headers = headers;
+  }
+
+  @Override
+  public String getName() {
+    return "Response";
+  }
+
+  @Override
+  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+    jsonStreamWriter.beginObject();
+
+    if (status != null) {
+      jsonStreamWriter.name("status")
+          .beginObject()
+          .name("code").unquotedValue(Integer.toString(status.getStatusCode())).separator()
+          .namedStringValueRaw("info", status.getInfo())
+          .endObject();
+    }
+
+    if (!headers.isEmpty()) {
+      if (status != null) {
+        jsonStreamWriter.separator();
+      }
+
+      jsonStreamWriter.name("headers")
+          .beginObject();
+      boolean first = true;
+      for (final String name : headers.keySet()) {
+        if (!first) {
+          jsonStreamWriter.separator();
+        }
+        first = false;
+        jsonStreamWriter.namedStringValue(name, headers.get(name));
+      }
+      jsonStreamWriter.endObject();
+    }
+
+    jsonStreamWriter.endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRuntime.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRuntime.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRuntime.java
new file mode 100644
index 0000000..543ef7c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoRuntime.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.processor.ODataContext.RuntimeMeasurement;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoRuntime implements DebugInfo {
+
+  private class RuntimeNode {
+    protected String className;
+    protected String methodName;
+    protected long timeStarted;
+    protected long timeStopped;
+    protected List<RuntimeNode> children = new ArrayList<RuntimeNode>();
+    public long memoryStarted;
+    public long memoryStopped;
+
+    protected RuntimeNode() {
+      timeStarted = 0;
+      timeStopped = Long.MAX_VALUE;
+      memoryStarted = 0;
+      memoryStopped = 0;
+    }
+
+    private RuntimeNode(final RuntimeMeasurement runtimeMeasurement) {
+      className = runtimeMeasurement.getClassName();
+      methodName = runtimeMeasurement.getMethodName();
+      timeStarted = runtimeMeasurement.getTimeStarted();
+      timeStopped = runtimeMeasurement.getTimeStopped();
+      memoryStarted = runtimeMeasurement.getMemoryStarted();
+      memoryStopped = runtimeMeasurement.getMemoryStopped();
+    }
+
+    protected boolean add(final RuntimeMeasurement runtimeMeasurement) {
+      if (timeStarted <= runtimeMeasurement.getTimeStarted()
+          && timeStopped != 0 && timeStopped >= runtimeMeasurement.getTimeStopped()) {
+        for (RuntimeNode candidate : children) {
+          if (candidate.add(runtimeMeasurement)) {
+            return true;
+          }
+        }
+        children.add(new RuntimeNode(runtimeMeasurement));
+        return true;
+      } else {
+        return false;
+      }
+    }
+
+    /**
+     * Combines runtime measurements with identical class names and method
+     * names into one measurement, assuming that they originate from a loop
+     * or a similar construct where a summary measurement has been intended.
+     */
+    protected void combineRuntimeMeasurements() {
+      RuntimeNode preceding = null;
+      for (Iterator<RuntimeNode> iterator = children.iterator(); iterator.hasNext();) {
+        final RuntimeNode child = iterator.next();
+        if (preceding != null
+            && preceding.timeStopped != 0 && child.timeStopped != 0
+            && preceding.timeStopped <= child.timeStarted
+            && preceding.children.isEmpty() && child.children.isEmpty()
+            && preceding.methodName.equals(child.methodName)
+            && preceding.className.equals(child.className)) {
+          preceding.timeStarted = child.timeStarted - (preceding.timeStopped - preceding.timeStarted);
+          preceding.timeStopped = child.timeStopped;
+
+          preceding.memoryStarted = child.memoryStarted - (preceding.memoryStopped - preceding.memoryStarted);
+          preceding.memoryStopped = child.memoryStopped;
+
+          iterator.remove();
+        } else {
+          preceding = child;
+          child.combineRuntimeMeasurements();
+        }
+      }
+    }
+  }
+
+  private final RuntimeNode rootNode;
+
+  public DebugInfoRuntime(final List<RuntimeMeasurement> runtimeMeasurements) {
+    rootNode = new RuntimeNode();
+    for (final RuntimeMeasurement runtimeMeasurement : runtimeMeasurements) {
+      rootNode.add(runtimeMeasurement);
+    }
+    rootNode.combineRuntimeMeasurements();
+  }
+
+  @Override
+  public String getName() {
+    return "Runtime";
+  }
+
+  @Override
+  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+    appendJsonChildren(jsonStreamWriter, rootNode);
+  }
+
+  private static void appendJsonNode(final JsonStreamWriter jsonStreamWriter, final RuntimeNode node) throws IOException {
+    jsonStreamWriter.beginObject()
+        .namedStringValueRaw("class", node.className).separator()
+        .namedStringValueRaw("method", node.methodName).separator()
+        .name("duration")
+        .unquotedValue(node.timeStopped == 0 ? null :
+            Long.toString((node.timeStopped - node.timeStarted) / 1000))
+        .separator()
+        .name("memory")
+        .unquotedValue(node.memoryStopped == 0 ? null :
+            Long.toString((node.memoryStopped - node.memoryStarted) / 1000))
+        .separator()
+        .name("children");
+    appendJsonChildren(jsonStreamWriter, node);
+    jsonStreamWriter.endObject();
+  }
+
+  private static void appendJsonChildren(final JsonStreamWriter jsonStreamWriter, final RuntimeNode node) throws IOException {
+    jsonStreamWriter.beginArray();
+    boolean first = true;
+    for (final RuntimeNode childNode : node.children) {
+      if (!first) {
+        jsonStreamWriter.separator();
+      }
+      first = false;
+      appendJsonNode(jsonStreamWriter, childNode);
+    }
+    jsonStreamWriter.endArray();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoUri.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoUri.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoUri.java
new file mode 100644
index 0000000..6893e97
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoUri.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeCreator;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+import org.apache.olingo.odata2.core.uri.expression.JsonVisitor;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoUri implements DebugInfo {
+
+  private final UriInfo uriInfo;
+  private final ExpressionParserException exception;
+
+  public DebugInfoUri(final UriInfo uriInfo, final Exception exception) {
+    this.uriInfo = uriInfo;
+
+    Throwable candidate = exception;
+    while (candidate != null && !(candidate instanceof ExpressionParserException)) {
+      candidate = candidate.getCause();
+    }
+    this.exception = (ExpressionParserException) candidate;
+  }
+
+  @Override
+  public String getName() {
+    return "URI";
+  }
+
+  @Override
+  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+    jsonStreamWriter.beginObject();
+
+    if (exception != null) {
+      jsonStreamWriter.name("error")
+          .beginObject();
+      if (exception.getFilterTree() != null) {
+        jsonStreamWriter.namedStringValue("filter", exception.getFilterTree().getUriLiteral());
+      }
+      jsonStreamWriter.endObject();
+    }
+
+    if (uriInfo != null) {
+      if (exception != null
+          && (uriInfo.getFilter() != null || uriInfo.getOrderBy() != null
+              || !uriInfo.getExpand().isEmpty() || !uriInfo.getSelect().isEmpty())) {
+        jsonStreamWriter.separator();
+      }
+
+      final FilterExpression filter = uriInfo.getFilter();
+      if (filter != null) {
+        String filterString;
+        try {
+          filterString = (String) filter.accept(new JsonVisitor());
+        } catch (final ExceptionVisitExpression e) {
+          filterString = null;
+        } catch (final ODataApplicationException e) {
+          filterString = null;
+        }
+        jsonStreamWriter.name("filter").unquotedValue(filterString);
+        if (uriInfo.getOrderBy() != null
+            || !uriInfo.getExpand().isEmpty() || !uriInfo.getSelect().isEmpty()) {
+          jsonStreamWriter.separator();
+        }
+      }
+
+      final OrderByExpression orderBy = uriInfo.getOrderBy();
+      if (orderBy != null) {
+        String orderByString;
+        try {
+          orderByString = (String) orderBy.accept(new JsonVisitor());
+        } catch (final ExceptionVisitExpression e) {
+          orderByString = null;
+        } catch (final ODataApplicationException e) {
+          orderByString = null;
+        }
+        jsonStreamWriter.name("orderby").unquotedValue(orderByString);
+        if (!uriInfo.getExpand().isEmpty() || !uriInfo.getSelect().isEmpty()) {
+          jsonStreamWriter.separator();
+        }
+      }
+
+      if (!uriInfo.getExpand().isEmpty() || !uriInfo.getSelect().isEmpty()) {
+        String expandSelectString;
+        try {
+          ExpandSelectTreeCreator expandSelectCreator = new ExpandSelectTreeCreator(uriInfo.getSelect(), uriInfo.getExpand());
+          final ExpandSelectTreeNodeImpl expandSelectTree = expandSelectCreator.create();
+          expandSelectString = expandSelectTree.toJsonString();
+        } catch (final EdmException e) {
+          expandSelectString = null;
+        }
+        jsonStreamWriter.name("expand/select").unquotedValue(expandSelectString);
+      }
+    }
+
+    jsonStreamWriter.endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapper.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapper.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapper.java
new file mode 100644
index 0000000..e99d730
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapper.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+import org.apache.olingo.odata2.core.exception.MessageService;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * Wraps an OData response into an OData response containing additional
+ * information useful for support purposes.
+ * @author SAP AG
+ */
+public class ODataDebugResponseWrapper {
+
+  public static final String ODATA_DEBUG_QUERY_PARAMETER = "odata-debug";
+  public static final String ODATA_DEBUG_JSON = "json";
+
+  private final ODataContext context;
+  private final ODataResponse response;
+  private final UriInfo uriInfo;
+  private final Exception exception;
+  private final boolean isJson;
+
+  public ODataDebugResponseWrapper(final ODataContext context, final ODataResponse response, final UriInfo uriInfo, final Exception exception, final String debugValue) {
+    this.context = context;
+    this.response = response;
+    this.uriInfo = uriInfo;
+    this.exception = exception;
+    isJson = ODATA_DEBUG_JSON.equals(debugValue);
+  }
+
+  public ODataResponse wrapResponse() {
+    try {
+      return ODataResponse.status(HttpStatusCodes.OK)
+          .entity(isJson ? wrapInJson(createParts()) : null)
+          .contentHeader(isJson ? HttpContentType.APPLICATION_JSON : null)
+          .build();
+    } catch (final ODataException e) {
+      throw new ODataRuntimeException("Should not happen", e);
+    } catch (final IOException e) {
+      throw new ODataRuntimeException("Should not happen", e);
+    }
+  }
+
+  private List<DebugInfo> createParts() throws ODataException {
+    List<DebugInfo> parts = new ArrayList<DebugInfo>();
+
+    // body
+    if (response.getContentHeader() != null && response.getEntity() != null) {
+      parts.add(new DebugInfoBody(response));
+    }
+
+    // request
+    parts.add(new DebugInfoRequest(context.getHttpMethod(),
+        context.getPathInfo().getRequestUri(),
+        context.getRequestHeaders()));
+
+    // response
+    Map<String, String> responseHeaders = new HashMap<String, String>();
+    for (final String name : response.getHeaderNames()) {
+      responseHeaders.put(name, response.getHeader(name));
+    }
+    parts.add(new DebugInfoResponse(response.getStatus(), responseHeaders));
+
+    // URI
+    if (uriInfo != null
+        && (uriInfo.getFilter() != null || uriInfo.getOrderBy() != null
+            || !uriInfo.getExpand().isEmpty() || !uriInfo.getSelect().isEmpty())) {
+      parts.add(new DebugInfoUri(uriInfo, exception));
+    }
+
+    // runtime measurements
+    if (context.getRuntimeMeasurements() != null) {
+      parts.add(new DebugInfoRuntime(context.getRuntimeMeasurements()));
+    }
+
+    // exceptions
+    if (exception != null) {
+      final Locale locale = MessageService.getSupportedLocale(context.getAcceptableLanguages(), Locale.ENGLISH);
+      parts.add(new DebugInfoException(exception, locale));
+    }
+
+    return parts;
+  }
+
+  private InputStream wrapInJson(final List<DebugInfo> parts) throws IOException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(csb.getOutputStream(), "UTF-8"));
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+    jsonStreamWriter.beginObject();
+    boolean first = true;
+    for (final DebugInfo part : parts) {
+      if (!first) {
+        jsonStreamWriter.separator();
+      }
+      first = false;
+      jsonStreamWriter.name(part.getName().toLowerCase(Locale.ROOT));
+      part.appendJson(jsonStreamWriter);
+    }
+    jsonStreamWriter.endObject();
+    writer.flush();
+    csb.closeWrite();
+    return csb.getInputStream();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/AbstractSimpleType.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/AbstractSimpleType.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/AbstractSimpleType.java
new file mode 100644
index 0000000..09057c0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/AbstractSimpleType.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+
+/**
+ * Abstract implementation of the EDM simple-type interface.
+ * @author SAP AG
+ */
+public abstract class AbstractSimpleType implements EdmSimpleType {
+
+  @Override
+  public boolean equals(final Object obj) {
+    return this == obj || (obj != null && getClass() == obj.getClass());
+  }
+
+  @Override
+  public int hashCode() {
+    return getClass().hashCode();
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return EDM_NAMESPACE;
+  }
+
+  @Override
+  public EdmTypeKind getKind() {
+    return EdmTypeKind.SIMPLE;
+  }
+
+  @Override
+  public String getName() throws EdmException {
+    final String name = getClass().getSimpleName();
+    return name.startsWith(EDM_NAMESPACE) ? name.substring(3) : name;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return equals(simpleType);
+  }
+
+  @Override
+  public boolean validate(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
+    try {
+      valueOfString(value, literalKind, facets, getDefaultType());
+      return true;
+    } catch (final EdmSimpleTypeException e) {
+      return false;
+    }
+  }
+
+  @Override
+  public final <T> T valueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    if (value == null) {
+      if (facets == null || facets.isNullable() == null || facets.isNullable()) {
+        return null;
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_NULL_NOT_ALLOWED);
+      }
+    }
+
+    if (literalKind == null) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_KIND_MISSING);
+    }
+
+    return internalValueOfString(value, literalKind, facets, returnType);
+  }
+
+  protected abstract <T> T internalValueOfString(String value, EdmLiteralKind literalKind, EdmFacets facets, Class<T> returnType) throws EdmSimpleTypeException;
+
+  @Override
+  public final String valueToString(final Object value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value == null) {
+      if (facets == null || facets.isNullable() == null || facets.isNullable()) {
+        return null;
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_NULL_NOT_ALLOWED);
+      }
+    }
+
+    if (literalKind == null) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_KIND_MISSING);
+    }
+
+    final String result = internalValueToString(value, literalKind, facets);
+    return literalKind == EdmLiteralKind.URI ? toUriLiteral(result) : result;
+  }
+
+  protected abstract <T> String internalValueToString(T value, EdmLiteralKind literalKind, EdmFacets facets) throws EdmSimpleTypeException;
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    return literal;
+  }
+
+  @Override
+  public String toString() {
+    try {
+      return getNamespace() + Edm.DELIMITER + getName();
+    } catch (final EdmException e) {
+      return super.toString();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Bit.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Bit.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Bit.java
new file mode 100644
index 0000000..a131195
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Bit.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the internal simple type Bit.
+ * @author SAP AG
+ */
+public class Bit extends AbstractSimpleType {
+
+  private static final Bit instance = new Bit();
+
+  public static Bit getInstance() {
+    return instance;
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return SYSTEM_NAMESPACE;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Byte.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    return EdmSByte.getInstance().internalValueOfString(value, literalKind, facets, returnType);
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    return EdmSByte.getInstance().internalValueToString(value, literalKind, facets);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
new file mode 100644
index 0000000..21c7ed1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBinary.java
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.Locale;
+
+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;
+
+/**
+ * Implementation of the EDM simple type Binary.
+ * @author SAP AG
+ */
+public class EdmBinary extends AbstractSimpleType {
+
+  private static final EdmBinary instance = new EdmBinary();
+
+  public static EdmBinary getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return byte[].class;
+  }
+
+  @Override
+  public boolean validate(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
+    if (value == null) {
+      return facets == null || facets.isNullable() == null || facets.isNullable();
+    }
+
+    if (literalKind == null) {
+      return false;
+    }
+
+    return validateLiteral(value, literalKind) && validateMaxLength(value, literalKind, facets);
+  }
+
+  private static boolean validateLiteral(final String value, final EdmLiteralKind literalKind) {
+    return literalKind == EdmLiteralKind.URI ?
+        value.matches("(?:X|binary)'(?:\\p{XDigit}{2})*'") : Base64.isBase64(value);
+  }
+
+  private static boolean validateMaxLength(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
+    return facets == null || facets.getMaxLength() == null ? true :
+        literalKind == EdmLiteralKind.URI ?
+            // In URI representation, each byte is represented as two hexadecimal digits;
+            // additionally, we have to account for the prefix and the surrounding "'"s.
+            facets.getMaxLength() >= (value.length() - (value.startsWith("X") ? 3 : 8)) / 2
+            :
+            // In default representation, every three bytes are represented as four base-64 characters.
+            // Additionally, there could be up to two padding "=" characters if the number of bytes is
+            // not a multiple of three, and there could be carriage return/line feed combinations.
+            facets.getMaxLength() >= value.length() * 3 / 4 - (value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0) - crlfLength(value);
+  }
+
+  private static int crlfLength(final String value) {
+    int result = 0;
+    int index = 0;
+    while (index >= 0) {
+      index = value.indexOf("\r\n", index);
+      if (index > 0) {
+        result++;
+        index++;
+      }
+    }
+    return result * 2;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    if (!validateLiteral(value, literalKind)) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+    }
+    if (!validateMaxLength(value, literalKind, facets)) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    byte[] result;
+    if (literalKind == EdmLiteralKind.URI) {
+      try {
+        result = Hex.decodeHex(value.substring(value.startsWith("X") ? 2 : 7, value.length() - 1).toCharArray());
+      } catch (final DecoderException e) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+      }
+    } else {
+      result = Base64.decodeBase64(value);
+    }
+
+    if (returnType.isAssignableFrom(byte[].class)) {
+      return returnType.cast(result);
+    } else if (returnType.isAssignableFrom(Byte[].class)) {
+      Byte[] byteArray = new Byte[result.length];
+      for (int i = 0; i < result.length; i++) {
+        byteArray[i] = result[i];
+      }
+      return returnType.cast(byteArray);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    byte[] byteArrayValue;
+    if (value instanceof byte[]) {
+      byteArrayValue = (byte[]) value;
+    } else if (value instanceof Byte[]) {
+      final int length = ((Byte[]) value).length;
+      byteArrayValue = new byte[length];
+      for (int i = 0; i < length; i++) {
+        byteArrayValue[i] = ((Byte[]) value)[i].byteValue();
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+
+    if (facets != null && facets.getMaxLength() != null && byteArrayValue.length > facets.getMaxLength()) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    return Base64.encodeBase64String(byteArrayValue);
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    return "binary'" + Hex.encodeHexString(Base64.decodeBase64(literal)).toUpperCase(Locale.ROOT) + "'";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBoolean.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBoolean.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBoolean.java
new file mode 100644
index 0000000..0c8d8d9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmBoolean.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Boolean.
+ * @author SAP AG
+ */
+public class EdmBoolean extends AbstractSimpleType {
+
+  private static final EdmBoolean instance = new EdmBoolean();
+
+  public static EdmBoolean getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit || simpleType instanceof EdmBoolean;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Boolean.class;
+  }
+
+  @Override
+  public boolean validate(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
+    return value == null ?
+        facets == null || facets.isNullable() == null || facets.isNullable() :
+        validateLiteral(value);
+  }
+
+  private static boolean validateLiteral(final String value) {
+    return "true".equals(value) || "1".equals(value)
+        || "false".equals(value) || "0".equals(value);
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    if (validateLiteral(value)) {
+      if (returnType.isAssignableFrom(Boolean.class)) {
+        return returnType.cast(Boolean.valueOf("true".equals(value) || "1".equals(value)));
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Boolean) {
+      return Boolean.toString((Boolean) value);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmByte.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmByte.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmByte.java
new file mode 100644
index 0000000..8196b46
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmByte.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Byte.
+ * @author SAP AG
+ */
+public class EdmByte extends AbstractSimpleType {
+
+  private static final EdmByte instance = new EdmByte();
+
+  public static EdmByte getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Short.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Short valueShort;
+    try {
+      valueShort = Short.parseShort(value);
+    } catch (final NumberFormatException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+    }
+    if (valueShort < 0 || valueShort > 255) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+    }
+
+    if (returnType.isAssignableFrom(Short.class)) {
+      return returnType.cast(valueShort);
+    } else if (returnType.isAssignableFrom(Byte.class)) {
+      if (valueShort <= Byte.MAX_VALUE) {
+        return returnType.cast(valueShort.byteValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Integer.class)) {
+      return returnType.cast(valueShort.intValue());
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueShort.longValue());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
+      if (((Number) value).longValue() >= 0 && ((Number) value).longValue() <= 255) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTime.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTime.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTime.java
new file mode 100644
index 0000000..1834b83
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTime.java
@@ -0,0 +1,236 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type DateTime.
+ * @author SAP AG
+ */
+public class EdmDateTime extends AbstractSimpleType {
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "(\\p{Digit}{1,4})-(\\p{Digit}{1,2})-(\\p{Digit}{1,2})"
+          + "T(\\p{Digit}{1,2}):(\\p{Digit}{1,2})(?::(\\p{Digit}{1,2})(\\.(\\p{Digit}{0,3}?)0*)?)?");
+  private static final Pattern JSON_PATTERN = Pattern.compile("/Date\\((-?\\p{Digit}+)\\)/");
+  private static final EdmDateTime instance = new EdmDateTime();
+
+  public static EdmDateTime getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Calendar.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    // In JSON, we allow also the XML literal form, so there is on purpose
+    // no exception if the JSON pattern does not match.
+    if (literalKind == EdmLiteralKind.JSON) {
+      final Matcher matcher = JSON_PATTERN.matcher(value);
+      if (matcher.matches()) {
+        long millis;
+        try {
+          millis = Long.parseLong(matcher.group(1));
+        } catch (final NumberFormatException e) {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+        }
+        if (returnType.isAssignableFrom(Long.class)) {
+          return returnType.cast(millis);
+        } else if (returnType.isAssignableFrom(Date.class)) {
+          return returnType.cast(new Date(millis));
+        } else if (returnType.isAssignableFrom(Calendar.class)) {
+          Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+          dateTimeValue.clear();
+          dateTimeValue.setTimeInMillis(millis);
+          return returnType.cast(dateTimeValue);
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+        }
+      }
+    }
+
+    Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    dateTimeValue.clear();
+
+    if (literalKind == EdmLiteralKind.URI) {
+      if (value.length() > 10 && value.startsWith("datetime'") && value.endsWith("'")) {
+        parseLiteral(value.substring(9, value.length() - 1), facets, dateTimeValue);
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      parseLiteral(value, facets, dateTimeValue);
+    }
+
+    if (returnType.isAssignableFrom(Calendar.class)) {
+      return returnType.cast(dateTimeValue);
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(dateTimeValue.getTimeInMillis());
+    } else if (returnType.isAssignableFrom(Date.class)) {
+      return returnType.cast(dateTimeValue.getTime());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  /**
+   * Parses a formatted date/time value and sets the values of a
+   * {@link Calendar} object accordingly. 
+   * @param value         the formatted date/time value as String
+   * @param facets        additional constraints for parsing (optional)
+   * @param dateTimeValue the Calendar object to be set to the parsed value
+   * @throws EdmSimpleTypeException
+   */
+  protected static void parseLiteral(final String value, final EdmFacets facets, final Calendar dateTimeValue) throws EdmSimpleTypeException {
+    final Matcher matcher = PATTERN.matcher(value);
+    if (!matcher.matches()) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+    }
+
+    dateTimeValue.set(
+        Short.parseShort(matcher.group(1)),
+        Byte.parseByte(matcher.group(2)) - 1, // month is zero-based
+        Byte.parseByte(matcher.group(3)),
+        Byte.parseByte(matcher.group(4)),
+        Byte.parseByte(matcher.group(5)),
+        matcher.group(6) == null ? 0 : Byte.parseByte(matcher.group(6)));
+
+    if (matcher.group(7) != null) {
+      if (matcher.group(7).length() == 1 || matcher.group(7).length() > 8) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+      final String decimals = matcher.group(8);
+      if (facets != null && facets.getPrecision() != null && facets.getPrecision() < decimals.length()) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
+      }
+      final String milliSeconds = decimals + "000".substring(decimals.length());
+      dateTimeValue.set(Calendar.MILLISECOND, Short.parseShort(milliSeconds));
+    }
+
+    // The Calendar class does not check any values until a get method is called,
+    // so we do just that to validate the fields set above, not because we want
+    // to return something else.  For strict checks, the lenient mode is switched
+    // off temporarily.
+    dateTimeValue.setLenient(false);
+    try {
+      dateTimeValue.getTimeInMillis();
+    } catch (final IllegalArgumentException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+    }
+    dateTimeValue.setLenient(true);
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    long timeInMillis;
+    if (value instanceof Date) {
+      timeInMillis = ((Date) value).getTime();
+    } else if (value instanceof Calendar) {
+      timeInMillis = ((Calendar) value).getTimeInMillis();
+    } else if (value instanceof Long) {
+      timeInMillis = ((Long) value).longValue();
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+
+    if (literalKind == EdmLiteralKind.JSON) {
+      return "/Date(" + timeInMillis + ")/";
+    }
+
+    Calendar dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+    dateTimeValue.setTimeInMillis(timeInMillis);
+
+    StringBuilder result = new StringBuilder(23); // 23 characters are enough for millisecond precision.
+    final int year = dateTimeValue.get(Calendar.YEAR);
+    appendTwoDigits(result, year / 100);
+    appendTwoDigits(result, year % 100);
+    result.append('-');
+    appendTwoDigits(result, dateTimeValue.get(Calendar.MONTH) + 1); // month is zero-based
+    result.append('-');
+    appendTwoDigits(result, dateTimeValue.get(Calendar.DAY_OF_MONTH));
+    result.append('T');
+    appendTwoDigits(result, dateTimeValue.get(Calendar.HOUR_OF_DAY));
+    result.append(':');
+    appendTwoDigits(result, dateTimeValue.get(Calendar.MINUTE));
+    result.append(':');
+    appendTwoDigits(result, dateTimeValue.get(Calendar.SECOND));
+
+    try {
+      appendMilliseconds(result, timeInMillis, facets);
+    } catch (final IllegalArgumentException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets), e);
+    }
+
+    return result.toString();
+  }
+
+  /**
+   * Appends the given number to the given string builder,
+   * assuming that the number has at most two digits, performance-optimized.
+   * @param result a {@link StringBuilder}
+   * @param number an integer that must satisfy <code>0 <= number <= 99</code>
+   */
+  private static void appendTwoDigits(final StringBuilder result, final int number) {
+    result.append((char) ('0' + number / 10));
+    result.append((char) ('0' + number % 10));
+  }
+
+  protected static void appendMilliseconds(final StringBuilder result, final long milliseconds, final EdmFacets facets) throws IllegalArgumentException {
+    final int digits = milliseconds % 1000 == 0 ? 0 : milliseconds % 100 == 0 ? 1 : milliseconds % 10 == 0 ? 2 : 3;
+    if (digits > 0) {
+      result.append('.');
+      for (int d = 100; d > 0; d /= 10) {
+        final byte digit = (byte) (milliseconds % (d * 10) / d);
+        if (digit > 0 || milliseconds % d > 0) {
+          result.append((char) ('0' + digit));
+        }
+      }
+    }
+
+    if (facets != null && facets.getPrecision() != null) {
+      final int precision = facets.getPrecision();
+      if (digits > precision) {
+        throw new IllegalArgumentException();
+      }
+      if (digits == 0 && precision > 0) {
+        result.append('.');
+      }
+      for (int i = digits; i < precision; i++) {
+        result.append('0');
+      }
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    return "datetime'" + literal + "'";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTimeOffset.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTimeOffset.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTimeOffset.java
new file mode 100644
index 0000000..9958238
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDateTimeOffset.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type DateTimeOffset.
+ * 
+ * Details about parsing of time strings to {@link EdmDateTimeOffset} objects can be found in {@link org.apache.olingo.odata2.api.edm.EdmSimpleType} documentation.
+ * 
+ * @author SAP AG
+ */
+public class EdmDateTimeOffset extends AbstractSimpleType {
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "\\p{Digit}{1,4}-\\p{Digit}{1,2}-\\p{Digit}{1,2}"
+          + "T\\p{Digit}{1,2}:\\p{Digit}{1,2}(?::\\p{Digit}{1,2}(?:\\.\\p{Digit}{1,7})?)?"
+          + "(Z|([-+]\\p{Digit}{1,2}:\\p{Digit}{2}))?");
+  private static final Pattern JSON_PATTERN = Pattern.compile(
+      "/Date\\((-?\\p{Digit}+)(?:(\\+|-)(\\p{Digit}{1,4}))?\\)/");
+  private static final EdmDateTimeOffset instance = new EdmDateTimeOffset();
+
+  public static EdmDateTimeOffset getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Calendar.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    if (literalKind == EdmLiteralKind.URI) {
+      if (value.length() > 16 && value.startsWith("datetimeoffset'") && value.endsWith("'")) {
+        return internalValueOfString(value.substring(15, value.length() - 1), EdmLiteralKind.DEFAULT, facets, returnType);
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    }
+
+    Calendar dateTimeValue = null;
+
+    if (literalKind == EdmLiteralKind.JSON) {
+      final Matcher matcher = JSON_PATTERN.matcher(value);
+      if (matcher.matches()) {
+        long millis;
+        try {
+          millis = Long.parseLong(matcher.group(1));
+        } catch (final NumberFormatException e) {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+        }
+        String timeZone = "GMT";
+        if (matcher.group(2) != null) {
+          final int offsetInMinutes = Integer.parseInt(matcher.group(3));
+          if (offsetInMinutes >= 24 * 60) {
+            throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+          }
+          if (offsetInMinutes != 0) {
+            timeZone += matcher.group(2) + String.valueOf(offsetInMinutes / 60)
+                + ":" + String.format("%02d", offsetInMinutes % 60);
+            // Convert the local-time milliseconds to UTC.
+            millis -= (matcher.group(2).equals("+") ? 1 : -1) * offsetInMinutes * 60 * 1000;
+          }
+        }
+        dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone(timeZone));
+        dateTimeValue.clear();
+        dateTimeValue.setTimeInMillis(millis);
+      }
+    }
+
+    if (dateTimeValue == null) {
+      final Matcher matcher = PATTERN.matcher(value);
+      if (!matcher.matches()) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+
+      final String timeZoneOffset = matcher.group(1) != null && matcher.group(2) != null && !matcher.group(2).matches("[-+]0+:0+") ? matcher.group(2) : null;
+      dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT" + timeZoneOffset));
+      if (dateTimeValue.get(Calendar.ZONE_OFFSET) == 0 && timeZoneOffset != null) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+      dateTimeValue.clear();
+      EdmDateTime.parseLiteral(value.substring(0, matcher.group(1) == null ? value.length() : matcher.start(1)), facets, dateTimeValue);
+    }
+
+    if (returnType.isAssignableFrom(Calendar.class)) {
+      return returnType.cast(dateTimeValue);
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(dateTimeValue.getTimeInMillis());
+    } else if (returnType.isAssignableFrom(Date.class)) {
+      return returnType.cast(dateTimeValue.getTime());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    Long milliSeconds; // number of milliseconds since 1970-01-01T00:00:00Z
+    int offset; // offset in milliseconds from GMT to the requested time zone
+    if (value instanceof Date) {
+      milliSeconds = ((Date) value).getTime();
+      // Although java.util.Date, as stated in its documentation,
+      // "is intended to reflect coordinated universal time (UTC)",
+      // its toString() method uses the default time zone. And so do we.
+      Calendar dateTimeValue = Calendar.getInstance();
+      dateTimeValue.setTime((Date) value);
+      offset = dateTimeValue.get(Calendar.ZONE_OFFSET) + dateTimeValue.get(Calendar.DST_OFFSET);
+    } else if (value instanceof Calendar) {
+      final Calendar dateTimeValue = (Calendar) ((Calendar) value).clone();
+      milliSeconds = dateTimeValue.getTimeInMillis();
+      offset = dateTimeValue.get(Calendar.ZONE_OFFSET) + dateTimeValue.get(Calendar.DST_OFFSET);
+    } else if (value instanceof Long) {
+      milliSeconds = (Long) value;
+      offset = 0;
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+
+    milliSeconds += offset; // Convert from UTC to local time.
+    final int offsetInMinutes = offset / 60 / 1000;
+
+    if (literalKind == EdmLiteralKind.JSON) {
+      return "/Date(" + milliSeconds + (offset == 0 ? "" : String.format("%+05d", offsetInMinutes)) + ")/";
+
+    } else {
+      final String localTimeString = EdmDateTime.getInstance().valueToString(milliSeconds, EdmLiteralKind.DEFAULT, facets);
+      final int offsetHours = offsetInMinutes / 60;
+      final int offsetMinutes = Math.abs(offsetInMinutes % 60);
+      final String offsetString = offset == 0 ? "Z" : String.format("%+03d:%02d", offsetHours, offsetMinutes);
+
+      return localTimeString + offsetString;
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    return "datetimeoffset'" + literal + "'";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDecimal.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDecimal.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDecimal.java
new file mode 100644
index 0000000..4f31be9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDecimal.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Decimal.
+ * @author SAP AG
+ */
+public class EdmDecimal extends AbstractSimpleType {
+
+  // value-range limitation according to the CSDL document
+  private static final int MAX_DIGITS = 29;
+
+  private static final Pattern PATTERN = Pattern.compile("(?:\\+|-)?(?:0*(\\p{Digit}{1,29}?))(?:\\.(\\p{Digit}{1,29}?)0*)?(M|m)?");
+  private static final EdmDecimal instance = new EdmDecimal();
+
+  public static EdmDecimal getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16
+        || simpleType instanceof EdmInt32
+        || simpleType instanceof EdmInt64
+        || simpleType instanceof EdmSingle
+        || simpleType instanceof EdmDouble
+        || simpleType instanceof EdmDecimal;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return BigDecimal.class;
+  }
+
+  @Override
+  public boolean validate(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
+    if (value == null) {
+      return facets == null || facets.isNullable() == null || facets.isNullable();
+    }
+
+    if (literalKind == null) {
+      return false;
+    }
+
+    return validateLiteral(value, literalKind) && validatePrecisionAndScale(value, facets);
+  }
+
+  private static boolean validateLiteral(final String value, final EdmLiteralKind literalKind) {
+    final Matcher matcher = PATTERN.matcher(value);
+    return matcher.matches()
+        && (literalKind == EdmLiteralKind.URI) != (matcher.group(3) == null);
+  }
+
+  private static final boolean validatePrecisionAndScale(final String value, final EdmFacets facets) {
+    if (facets == null || facets.getPrecision() == null && facets.getScale() == null) {
+      return true;
+    }
+
+    final Matcher matcher = PATTERN.matcher(value);
+    matcher.matches();
+    final int significantIntegerDigits = matcher.group(1).equals("0") ? 0 : matcher.group(1).length();
+    final int decimals = matcher.group(2) == null ? 0 : matcher.group(2).length();
+    return (facets.getPrecision() == null || facets.getPrecision() >= significantIntegerDigits + decimals)
+        && (facets.getScale() == null || facets.getScale() >= decimals);
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    if (!validateLiteral(value, literalKind)) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+    }
+    if (!validatePrecisionAndScale(value, facets)) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    final BigDecimal valueBigDecimal = new BigDecimal(
+        literalKind == EdmLiteralKind.URI ? value.substring(0, value.length() - 1) : value);
+
+    if (returnType.isAssignableFrom(BigDecimal.class)) {
+      return returnType.cast(valueBigDecimal);
+    } else if (returnType.isAssignableFrom(Double.class)) {
+      if (BigDecimal.valueOf(valueBigDecimal.doubleValue()).compareTo(valueBigDecimal) == 0) {
+        return returnType.cast(valueBigDecimal.doubleValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Float.class)) {
+      if (BigDecimal.valueOf(valueBigDecimal.floatValue()).compareTo(valueBigDecimal) == 0) {
+        return returnType.cast(valueBigDecimal.floatValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else {
+      try {
+        if (returnType.isAssignableFrom(BigInteger.class)) {
+          return returnType.cast(valueBigDecimal.toBigIntegerExact());
+        } else if (returnType.isAssignableFrom(Long.class)) {
+          return returnType.cast(valueBigDecimal.longValueExact());
+        } else if (returnType.isAssignableFrom(Integer.class)) {
+          return returnType.cast(valueBigDecimal.intValueExact());
+        } else if (returnType.isAssignableFrom(Short.class)) {
+          return returnType.cast(valueBigDecimal.shortValueExact());
+        } else if (returnType.isAssignableFrom(Byte.class)) {
+          return returnType.cast(valueBigDecimal.byteValueExact());
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+        }
+      } catch (final ArithmeticException e) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType), e);
+      }
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    String result;
+    if (value instanceof Long || value instanceof Integer || value instanceof Short || value instanceof Byte || value instanceof BigInteger) {
+      result = value.toString();
+      final int digits = result.startsWith("-") ? result.length() - 1 : result.length();
+      if (digits > MAX_DIGITS) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+      if (facets != null && facets.getPrecision() != null && facets.getPrecision() < digits) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets));
+      }
+
+    } else if (value instanceof Double || value instanceof Float || value instanceof BigDecimal) {
+      BigDecimal bigDecimalValue;
+      try {
+        if (value instanceof Double) {
+          bigDecimalValue = BigDecimal.valueOf((Double) value);
+        } else if (value instanceof Float) {
+          bigDecimalValue = BigDecimal.valueOf((Float) value);
+        } else {
+          bigDecimalValue = (BigDecimal) value;
+        }
+      } catch (final NumberFormatException e) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value), e);
+      }
+
+      if (bigDecimalValue.precision() - bigDecimalValue.scale() > MAX_DIGITS
+          || bigDecimalValue.scale() > MAX_DIGITS) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+
+      final int digits = bigDecimalValue.scale() >= 0 ?
+          Math.max(bigDecimalValue.precision(), bigDecimalValue.scale()) :
+          bigDecimalValue.precision() - bigDecimalValue.scale();
+      if (facets == null
+          || (facets.getPrecision() == null || facets.getPrecision() >= digits)
+          && (facets.getScale() == null || facets.getScale() >= bigDecimalValue.scale())) {
+        result = bigDecimalValue.toPlainString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets));
+      }
+
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+
+    return result;
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    return literal + "M";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDouble.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDouble.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDouble.java
new file mode 100644
index 0000000..2f299b9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmDouble.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Double.
+ * @author SAP AG
+ */
+public class EdmDouble extends AbstractSimpleType {
+
+  // value-range limitations according to the CSDL document
+  private static final int MAX_PRECISION = 15;
+  private static final int MAX_SCALE = 308;
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "(?:\\+|-)?\\p{Digit}{1,15}(?:\\.\\p{Digit}{1,15})?(?:(?:E|e)(?:\\+|-)?\\p{Digit}{1,3})?(D|d)?");
+  private static final EdmDouble instance = new EdmDouble();
+
+  public static EdmDouble getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16
+        || simpleType instanceof EdmInt32
+        || simpleType instanceof EdmInt64
+        || simpleType instanceof EdmSingle
+        || simpleType instanceof EdmDouble;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Double.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    String valueString = value;
+    Double result = null;
+    // Handle special values first.
+    if (value.equals("-INF")) {
+      result = Double.NEGATIVE_INFINITY;
+    } else if (value.equals("INF")) {
+      result = Double.POSITIVE_INFINITY;
+    } else if (value.equals("NaN")) {
+      result = Double.NaN;
+    } else {
+      // Now only "normal" numbers remain.
+      final Matcher matcher = PATTERN.matcher(value);
+      if (!matcher.matches()
+          || (literalKind == EdmLiteralKind.URI) == (matcher.group(1) == null)) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+
+      if (literalKind == EdmLiteralKind.URI) {
+        valueString = value.substring(0, value.length() - 1);
+      }
+
+      // The number format is checked above, so we don't have to catch NumberFormatException.
+      result = Double.valueOf(valueString);
+      // "Real" infinite values have been treated already above, so we can throw an exception
+      // if the conversion to a float results in an infinite value.
+      if (result.isInfinite()) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    }
+
+    if (returnType.isAssignableFrom(Double.class)) {
+      return returnType.cast(result);
+    } else if (returnType.isAssignableFrom(Float.class)) {
+      if (result.floatValue() == result) {
+        return returnType.cast(result.floatValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (result.isInfinite() || result.isNaN()) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+    } else {
+      try {
+        final BigDecimal valueBigDecimal = new BigDecimal(valueString);
+        if (returnType.isAssignableFrom(BigDecimal.class)) {
+          return returnType.cast(valueBigDecimal);
+        } else if (returnType.isAssignableFrom(Long.class)) {
+          return returnType.cast(valueBigDecimal.longValueExact());
+        } else if (returnType.isAssignableFrom(Integer.class)) {
+          return returnType.cast(valueBigDecimal.intValueExact());
+        } else if (returnType.isAssignableFrom(Short.class)) {
+          return returnType.cast(valueBigDecimal.shortValueExact());
+        } else if (returnType.isAssignableFrom(Byte.class)) {
+          return returnType.cast(valueBigDecimal.byteValueExact());
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+        }
+
+      } catch (final ArithmeticException e) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType), e);
+      }
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Long) {
+      if (Math.abs((Long) value) < Math.pow(10, MAX_PRECISION)) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else if (value instanceof Integer || value instanceof Short || value instanceof Byte) {
+      return value.toString();
+    } else if (value instanceof Double) {
+      final String result = value.toString();
+      return ((Double) value).isInfinite() ? result.toUpperCase(Locale.ROOT).substring(0, value.toString().length() - 5) : result;
+    } else if (value instanceof Float) {
+      final String result = value.toString();
+      return ((Float) value).isInfinite() ? result.toUpperCase(Locale.ROOT).substring(0, value.toString().length() - 5) : result;
+    } else if (value instanceof BigDecimal) {
+      if (((BigDecimal) value).precision() <= MAX_PRECISION && Math.abs(((BigDecimal) value).scale()) <= MAX_SCALE) {
+        return ((BigDecimal) value).toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return literal.equals("-INF") || literal.equals("INF") || literal.equals("NaN") ?
+        literal : literal + "D";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmGuid.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmGuid.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmGuid.java
new file mode 100644
index 0000000..4387ef2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmGuid.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.UUID;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Guid.
+ * @author SAP AG
+ */
+public class EdmGuid extends AbstractSimpleType {
+
+  private static final String PATTERN = "\\p{XDigit}{8}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{4}-\\p{XDigit}{12}";
+  private static final EdmGuid instance = new EdmGuid();
+
+  public static EdmGuid getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return UUID.class;
+  }
+
+  @Override
+  public boolean validate(final String value, final EdmLiteralKind literalKind, final EdmFacets facets) {
+    return value == null ?
+        facets == null || facets.isNullable() == null || facets.isNullable() :
+        validateLiteral(value, literalKind);
+  }
+
+  private boolean validateLiteral(final String value, final EdmLiteralKind literalKind) {
+    return value.matches(literalKind == EdmLiteralKind.URI ? toUriLiteral(PATTERN) : PATTERN);
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    UUID result;
+    if (validateLiteral(value, literalKind)) {
+      result = UUID.fromString(
+          literalKind == EdmLiteralKind.URI ? value.substring(5, value.length() - 1) : value);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+    }
+
+    if (returnType.isAssignableFrom(UUID.class)) {
+      return returnType.cast(result);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof UUID) {
+      return ((UUID) value).toString();
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return "guid'" + literal + "'";
+  }
+}


[28/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataResponse.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataResponse.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataResponse.java
new file mode 100644
index 0000000..f84e272
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataResponse.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * <p>An <code>ODataResponse</code> is usually created by an {@link ODataProcessor}
+ * during request handling.</p>
+ * <p>The handler can use a serializer to create an 
+ * OData body (== response entity) and can set various response headers.
+ * A response can be created using the builder pattern:
+ * <pre>
+ * {@code
+ * ODataResponse response = ODataResponse.entity("hello world").setStatus(HttpStatusCodes.OK).build();
+ * }
+ * </pre>
+ * @author SAP AG
+ */
+public abstract class ODataResponse {
+
+  /**
+   * Do not subclass ODataResponse!
+   */
+  protected ODataResponse() {}
+
+  /**
+   * @return HTTP status code of this response
+   */
+  public abstract HttpStatusCodes getStatus();
+
+  /**
+   * @return a response entity which becomes the body part of a response message
+   */
+  public abstract Object getEntity();
+
+  /**
+   * Close the underlying entity input stream (if such a stream is available) and release all with this repsonse associated resources.
+   * 
+   * @throws IOException if something goes wrong during close of {@link ODataResponse}
+   */
+  public abstract void close() throws IOException;
+
+  /**
+   * @param name HTTP response header name
+   * @return a header value or null if not set
+   */
+  public abstract String getHeader(String name);
+
+  /**
+   * @return Content-Type header value or null if not set
+   */
+  public abstract String getContentHeader();
+
+  /**
+   * @return Location header value or null if not set
+   */
+  public abstract String getIdLiteral();
+
+  /**
+   * @return ETag header value or null if not available
+   */
+  public abstract String getETag();
+
+  /**
+   * @return a set of all available header names
+   */
+  public abstract Set<String> getHeaderNames();
+
+  /**
+   * Case insensitive check if the header is available in this ODataResponse
+   * @param header header name
+   * @return true/false
+   */
+  public abstract boolean containsHeader(String header);
+
+  /**
+   * @param status HTTP status code
+   * @return a builder object
+   */
+  public static ODataResponseBuilder status(final HttpStatusCodes status) {
+    return newBuilder().status(status);
+  }
+
+  /**
+   * @param response
+   * @return a new builder object
+   */
+  public static ODataResponseBuilder fromResponse(final ODataResponse response) {
+    return newBuilder().fromResponse(response);
+  }
+
+  /**
+   * @param entity
+   * @return a builder object
+   */
+  public static ODataResponseBuilder entity(final Object entity) {
+    return newBuilder().entity(entity);
+  }
+
+  /**
+   * @param name  HTTP header name
+   * @param value associated value
+   * @return a builder object
+   */
+  public static ODataResponseBuilder header(final String name, final String value) {
+    return newBuilder().header(name, value);
+  }
+
+  /**
+   * @param value content header value
+   * @return a builder object
+   */
+  public static ODataResponseBuilder contentHeader(final String value) {
+    return newBuilder().contentHeader(value);
+  }
+
+  /**
+   * @return returns a new builder object
+   */
+  public static ODataResponseBuilder newBuilder() {
+    return ODataResponseBuilder.newInstance();
+  }
+
+  /**
+   * Implementation of the builder pattern to create instances of this type of object. 
+   * @author SAP AG
+   */
+  public static abstract class ODataResponseBuilder {
+
+    protected ODataResponseBuilder() {}
+
+    private static ODataResponseBuilder newInstance() {
+      return RuntimeDelegate.createODataResponseBuilder();
+    }
+
+    public abstract ODataResponse build();
+
+    public abstract ODataResponseBuilder status(HttpStatusCodes status);
+
+    public abstract ODataResponseBuilder entity(Object entity);
+
+    public abstract ODataResponseBuilder header(String name, String value);
+
+    public abstract ODataResponseBuilder idLiteral(String idLiteral);
+
+    public abstract ODataResponseBuilder eTag(String eTag);
+
+    public abstract ODataResponseBuilder contentHeader(String contentHeader);
+
+    protected abstract ODataResponseBuilder fromResponse(ODataResponse response);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataSingleProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataSingleProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataSingleProcessor.java
new file mode 100644
index 0000000..6932ecc
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataSingleProcessor.java
@@ -0,0 +1,375 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.ODataServiceVersion;
+import org.apache.olingo.odata2.api.batch.BatchHandler;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpHeaders;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.processor.feature.CustomContentType;
+import org.apache.olingo.odata2.api.processor.part.BatchProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityComplexPropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.MetadataProcessor;
+import org.apache.olingo.odata2.api.processor.part.ServiceDocumentProcessor;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetComplexPropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetMediaResourceUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetMetadataUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetServiceDocumentUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetSimplePropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * <p>A default {@link ODataProcessor} that implements all processor features in a single class.</p>
+ * <p>It is recommended to derive from this class and it is required by the
+ * {@link org.apache.olingo.odata2.api.ODataServiceFactory} to build an {@link org.apache.olingo.odata2.api.ODataService}.</p>
+ * <p>This abstract class provides a default behavior, returning the correct response
+ * for requests for the service or the metadata document, respectively, and throwing an
+ * {@link ODataNotImplementedException} for all other requests.
+ * Sub classes have to override only methods they want to support.</p> 
+ * 
+ * @author SAP AG
+ */
+public abstract class ODataSingleProcessor implements MetadataProcessor, ServiceDocumentProcessor, EntityProcessor, EntitySetProcessor, EntityComplexPropertyProcessor, EntityLinkProcessor, EntityLinksProcessor, EntityMediaProcessor, EntitySimplePropertyProcessor, EntitySimplePropertyValueProcessor, FunctionImportProcessor, FunctionImportValueProcessor, BatchProcessor, CustomContentType {
+
+  /**
+   * A request context object usually injected by the OData library.
+   */
+  private ODataContext context;
+
+  /**
+   * @see ODataProcessor
+   */
+  @Override
+  public void setContext(final ODataContext context) {
+    this.context = context;
+  }
+
+  /**
+   * @see ODataProcessor
+   */
+  @Override
+  public ODataContext getContext() {
+    return context;
+  }
+
+  /**
+   * @see BatchProcessor
+   */
+  @Override
+  public ODataResponse executeBatch(final BatchHandler handler, final String contentType, final InputStream content) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @throws ODataNotImplementedException 
+   * @see BatchProcessor
+   */
+  @Override
+  public BatchResponsePart executeChangeSet(final BatchHandler handler, final List<ODataRequest> requests) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see FunctionImportProcessor
+   */
+  @Override
+  public ODataResponse executeFunctionImport(final GetFunctionImportUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see FunctionImportValueProcessor
+   */
+  @Override
+  public ODataResponse executeFunctionImportValue(final GetFunctionImportUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySimplePropertyValueProcessor
+   */
+  @Override
+  public ODataResponse readEntitySimplePropertyValue(final GetSimplePropertyUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySimplePropertyValueProcessor
+   */
+  @Override
+  public ODataResponse updateEntitySimplePropertyValue(final PutMergePatchUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySimplePropertyValueProcessor
+   */
+  @Override
+  public ODataResponse deleteEntitySimplePropertyValue(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySimplePropertyProcessor
+   */
+  @Override
+  public ODataResponse readEntitySimpleProperty(final GetSimplePropertyUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySimplePropertyProcessor
+   */
+  @Override
+  public ODataResponse updateEntitySimpleProperty(final PutMergePatchUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityMediaProcessor
+   */
+  @Override
+  public ODataResponse readEntityMedia(final GetMediaResourceUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityMediaProcessor
+   */
+  @Override
+  public ODataResponse updateEntityMedia(final PutMergePatchUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityMediaProcessor
+   */
+  @Override
+  public ODataResponse deleteEntityMedia(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinksProcessor
+   */
+  @Override
+  public ODataResponse readEntityLinks(final GetEntitySetLinksUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinksProcessor
+   */
+  @Override
+  public ODataResponse countEntityLinks(final GetEntitySetLinksCountUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinkProcessor
+   */
+  @Override
+  public ODataResponse createEntityLink(final PostUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinkProcessor
+   */
+  @Override
+  public ODataResponse readEntityLink(final GetEntityLinkUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinkProcessor
+   */
+  @Override
+  public ODataResponse existsEntityLink(final GetEntityLinkCountUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinkProcessor
+   */
+  @Override
+  public ODataResponse updateEntityLink(final PutMergePatchUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityLinkProcessor
+   */
+  @Override
+  public ODataResponse deleteEntityLink(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityComplexPropertyProcessor
+   */
+  @Override
+  public ODataResponse readEntityComplexProperty(final GetComplexPropertyUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityComplexPropertyProcessor
+   */
+  @Override
+  public ODataResponse updateEntityComplexProperty(final PutMergePatchUriInfo uriInfo, final InputStream content, final String requestContentType, final boolean merge, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySetProcessor
+   */
+  @Override
+  public ODataResponse readEntitySet(final GetEntitySetUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySetProcessor
+   */
+  @Override
+  public ODataResponse countEntitySet(final GetEntitySetCountUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntitySetProcessor
+   */
+  @Override
+  public ODataResponse createEntity(final PostUriInfo uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityProcessor
+   */
+  @Override
+  public ODataResponse readEntity(final GetEntityUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityProcessor
+   */
+  @Override
+  public ODataResponse existsEntity(final GetEntityCountUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityProcessor
+   */
+  @Override
+  public ODataResponse updateEntity(final PutMergePatchUriInfo uriInfo, final InputStream content, final String requestContentType, final boolean merge, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see EntityProcessor
+   */
+  @Override
+  public ODataResponse deleteEntity(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * @see ServiceDocumentProcessor
+   */
+  @Override
+  public ODataResponse readServiceDocument(final GetServiceDocumentUriInfo uriInfo, final String contentType) throws ODataException {
+    final Edm entityDataModel = getContext().getService().getEntityDataModel();
+    final String serviceRoot = getContext().getPathInfo().getServiceRoot().toASCIIString();
+
+    final ODataResponse response = EntityProvider.writeServiceDocument(contentType, entityDataModel, serviceRoot);
+    final ODataResponseBuilder odataResponseBuilder = ODataResponse.fromResponse(response).header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10);
+    if (isContentTypeUpdateNecessary(contentType, response)) {
+      odataResponseBuilder.contentHeader(contentType);
+    }
+    return odataResponseBuilder.build();
+  }
+
+  /**
+   * Simple check whether the content type for the {@link ODataResponse} needs adapted or not (based on requested content type).
+   * 
+   * @param contentType
+   * @param response
+   * @return true if an update is necessary
+   */
+  private boolean isContentTypeUpdateNecessary(final String contentType, final ODataResponse response) {
+    boolean contentTypeAlreadySet = contentType.equals(response.getContentHeader());
+    boolean requestedAtomAndRespondAtomSvc = contentType.contains("atom") && response.getContentHeader().contains("atomsvc");
+
+    return !(contentTypeAlreadySet || requestedAtomAndRespondAtomSvc);
+  }
+
+  /**
+   * @see MetadataProcessor
+   */
+  @Override
+  public ODataResponse readMetadata(final GetMetadataUriInfo uriInfo, final String contentType) throws ODataException {
+    final EdmServiceMetadata edmServiceMetadata = getContext().getService().getEntityDataModel().getServiceMetadata();
+
+    return ODataResponse.status(HttpStatusCodes.OK).header(HttpHeaders.CONTENT_TYPE, contentType).header(ODataHttpHeaders.DATASERVICEVERSION, edmServiceMetadata.getDataServiceVersion()).entity(edmServiceMetadata.getMetadata()).build();
+  }
+
+  /**
+   * @see CustomContentType
+   */
+  @Override
+  public List<String> getCustomContentTypes(final Class<? extends ODataProcessor> processorFeature) throws ODataException {
+    return Collections.emptyList();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/CustomContentType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/CustomContentType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/CustomContentType.java
new file mode 100644
index 0000000..813bd00
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/CustomContentType.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.api.processor.feature;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+
+/**
+ * Data processor feature if processor supports custom content types. By default the OData library supports
+ * various types like Json (application/json), Atom (application/xml+atom) and XML (application/xml). But
+ * the OData specification allows also other types like e.g. CSV or plain text.  
+ * 
+ * @author SAP AG
+ */
+public interface CustomContentType extends ODataProcessorFeature {
+
+  /**
+   * The OData library will consider these additional content types during negotiation of http content type header.
+   * @param processorFeature
+   * @return a list of additional supported content types in the format "type/sub type"
+   * @throws ODataException
+   */
+  public List<String> getCustomContentTypes(Class<? extends ODataProcessor> processorFeature) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/ODataProcessorFeature.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/ODataProcessorFeature.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/ODataProcessorFeature.java
new file mode 100644
index 0000000..3692737
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/ODataProcessorFeature.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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.api.processor.feature;
+
+/**
+ * Marker interface for data processor features. A feature is like a call back where 
+ * the OData library can request additional information from the processor to change
+ * control over request handling. 
+ * 
+ * @author SAP AG
+ */
+public interface ODataProcessorFeature {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/package-info.java
new file mode 100644
index 0000000..15d4eda
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/feature/package-info.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Processor Features<p>
+ * 
+ * Optional feature interfaces. Can be implemented by custom data processors. 
+ */
+package org.apache.olingo.odata2.api.processor.feature;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/package-info.java
new file mode 100644
index 0000000..484abd1
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/package-info.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Data Processor<p>
+ * 
+ * A data processor implements all create, read, update and delete (CRUD) methods of an OData service. A processor as 
+ * part of a OData service implementation is created by the service factory and then called during request handling. 
+ * In dependency of the http context (http method, requestheaders ...) and the parsed uri semantic the OData Library 
+ * will call an appropriate processor method. Within this method a service can perform operations on data. In a final
+ * step the data result can be transformed using a {@link org.apache.olingo.odata2.api.ep.EntityProvider} (for Json, Atom and XML) and is returned as 
+ * a {@link org.apache.olingo.odata2.api.processor.ODataResponse}.
+ * <p>
+ * A processor gets access to context information either via method parameters or a {@link org.apache.olingo.odata2.api.processor.ODataContext} which is attached 
+ * to the processor object.
+ * <p>
+ * A processor can support optional features {@link org.apache.olingo.odata2.api.processor.feature} and implement 
+ * parts {@link org.apache.olingo.odata2.api.processor.part} which is more or less a grouping for different OData CRUD operations.
+ * <p>
+ * {@link org.apache.olingo.odata2.api.processor.ODataSingleProcessor} is a convenience abstract class that implements all interface parts and has default implementations 
+ * for handling OData service document and metadata. Usually the {@link org.apache.olingo.odata2.api.processor.ODataSingleProcessor} is used together with a 
+ * <code>ODataSingleService</code> default implementation.
+ *  
+ */
+package org.apache.olingo.odata2.api.processor;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/BatchProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/BatchProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/BatchProcessor.java
new file mode 100644
index 0000000..427a549
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/BatchProcessor.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchHandler;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+/**
+ * Execute a OData batch request. 
+ * 
+ * @author SAP AG
+ *
+ */
+public interface BatchProcessor extends ODataProcessor {
+
+  /**
+   * Executes a OData batch request and provide Batch Response as {@link ODataResponse} 
+   * @param handler batch handler
+   * @param contentType the content type of the request
+   * @param content Batch Request body
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse executeBatch(BatchHandler handler, String contentType, InputStream content) throws ODataException;
+
+  /**
+   * Executes a Change Set and provide BatchResponsePart as {@link BatchResponsePart} that contains the responses to change requests.
+   * The method has to define a rollback semantic that may be applied when a request within a Change Set fails (all-or-nothing requirement).
+   * If a request within a Change Set fails, instead of Change Set Response should be returned the error response 
+   * @param handler batch handler
+   * @param requests list of single change requests
+   * @return a {@link BatchResponsePart} object
+   * @throws ODataException 
+   */
+  BatchResponsePart executeChangeSet(BatchHandler handler, List<ODataRequest> requests) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityComplexPropertyProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityComplexPropertyProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityComplexPropertyProcessor.java
new file mode 100644
index 0000000..a27766a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityComplexPropertyProcessor.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetComplexPropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Execute a OData complex property request. 
+ * 
+ * @author SAP AG
+ */
+public interface EntityComplexPropertyProcessor extends ODataProcessor {
+  /**
+   * Reads a complex property of an entity.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntityComplexProperty(GetComplexPropertyUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Updates a complex property of an entity.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the updated property data
+   * @param requestContentType the content type of the request body
+   * @param merge if <code>true</code>, properties not present in the data are left unchanged;
+   *              if <code>false</code>, they are reset
+   * @param contentType the content type of the response
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse updateEntityComplexProperty(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType, boolean merge, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinkProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinkProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinkProcessor.java
new file mode 100644
index 0000000..b9c36db
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinkProcessor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Execute an OData entity link request. 
+ * 
+ * @author SAP AG
+ */
+public interface EntityLinkProcessor extends ODataProcessor {
+  /**
+   * Reads the URI of the target entity of a navigation property.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntityLink(GetEntityLinkUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Returns whether the target entity of a navigation property exists.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse existsEntityLink(GetEntityLinkCountUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Updates the link to the target entity of a navigation property.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the new URI
+   * @param requestContentType the content type of the request body
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse updateEntityLink(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType, String contentType) throws ODataException;
+
+  /**
+   * Deletes the link to the target entity of a navigation property.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse deleteEntityLink(DeleteUriInfo uriInfo, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinksProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinksProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinksProcessor.java
new file mode 100644
index 0000000..9aaad4a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityLinksProcessor.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+
+/**
+ * Execute a OData entity links request. 
+ * 
+ * @author SAP AG
+ */
+public interface EntityLinksProcessor extends ODataProcessor {
+  /**
+   * Reads the URIs of the target entities of a navigation property.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an OData response object
+   * @throws ODataException
+   */
+  ODataResponse readEntityLinks(GetEntitySetLinksUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Counts the number of target entities of a navigation property.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an OData response object
+   * @throws ODataException
+   */
+  ODataResponse countEntityLinks(GetEntitySetLinksCountUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Creates a new link to a target entity of a navigation property.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the link data
+   * @param requestContentType the content type of the request body
+   * @param contentType the content type of the response
+   * @return an OData response object
+   * @throws ODataException
+   */
+  ODataResponse createEntityLink(PostUriInfo uriInfo, InputStream content, String requestContentType, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityMediaProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityMediaProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityMediaProcessor.java
new file mode 100644
index 0000000..b9e7c3e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityMediaProcessor.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetMediaResourceUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Execute an OData entity media request
+ * @author SAP AG
+ */
+public interface EntityMediaProcessor extends ODataProcessor {
+
+  /**
+   * Reads the media resource of an entity.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntityMedia(GetMediaResourceUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Updates the media resource of an entity.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request
+   * @param requestContentType the content type of the request body
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse updateEntityMedia(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType, String contentType) throws ODataException;
+
+  /**
+   * Deletes the media resource of an entity.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse deleteEntityMedia(DeleteUriInfo uriInfo, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityProcessor.java
new file mode 100644
index 0000000..c1a69a3
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntityProcessor.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Execute a OData entity request. 
+ * 
+ * @author SAP AG
+ */
+public interface EntityProcessor extends ODataProcessor {
+
+  /**
+   * Reads an entity.
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntity(GetEntityUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Checks whether an entity exists.
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse existsEntity(GetEntityCountUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Updates an entity.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the updated entity data
+   * @param requestContentType the content type of the request body
+   * @param merge if <code>true</code>, properties not present in the data are left unchanged;
+   *              if <code>false</code>, they are reset
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse updateEntity(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType, boolean merge, String contentType) throws ODataException;
+
+  /**
+   * Deletes an entity.
+   * @param uriInfo  a {@link DeleteUriInfo} object with information from the URI parser
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse deleteEntity(DeleteUriInfo uriInfo, String contentType) throws ODataException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySetProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySetProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySetProcessor.java
new file mode 100644
index 0000000..b42a940
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySetProcessor.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+
+/**
+ * Execute a OData entity set request. 
+ * 
+ * @author SAP AG
+ *
+ */
+public interface EntitySetProcessor extends ODataProcessor {
+
+  /**
+   * Reads entities.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntitySet(GetEntitySetUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Counts the number of requested entities.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse countEntitySet(GetEntitySetCountUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Creates an entity.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the data of the new entity
+   * @param requestContentType the content type of the request body
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse createEntity(PostUriInfo uriInfo, InputStream content, String requestContentType, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyProcessor.java
new file mode 100644
index 0000000..20a0b0d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyProcessor.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetSimplePropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Execute a OData entity simple property request. 
+ * 
+ * @author SAP AG
+ */
+public interface EntitySimplePropertyProcessor extends ODataProcessor {
+
+  /**
+   * Reads a simple property of an entity.
+   * @param contentType the content type of the response
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntitySimpleProperty(GetSimplePropertyUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Updates a simple property of an entity.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the updated property data
+   * @param requestContentType the content type of the request body
+   * @param contentType the content type of the response
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse updateEntitySimpleProperty(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyValueProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyValueProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyValueProcessor.java
new file mode 100644
index 0000000..b641fcf
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/EntitySimplePropertyValueProcessor.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetSimplePropertyUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+
+/**
+ * Execute a OData entity simple property value request. 
+ * 
+ * @author SAP AG
+ */
+public interface EntitySimplePropertyValueProcessor extends ODataProcessor {
+
+  /**
+   * Reads the unformatted value of a simple property of an entity.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readEntitySimplePropertyValue(GetSimplePropertyUriInfo uriInfo, String contentType) throws ODataException;
+
+  /**
+   * Updates a simple property of an entity with an unformatted value.
+   * @param uriInfo information about the request URI
+   * @param content the content of the request, containing the new value
+   * @param requestContentType the content type of the request body
+   *                           (important for a binary property)
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse updateEntitySimplePropertyValue(PutMergePatchUriInfo uriInfo, InputStream content, String requestContentType, String contentType) throws ODataException;
+
+  /**
+   * Deletes the value of a simple property of an entity.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse deleteEntitySimplePropertyValue(DeleteUriInfo uriInfo, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportProcessor.java
new file mode 100644
index 0000000..7e50553
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportProcessor.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+
+/**
+ * Execute an OData function import request. 
+ * @author SAP AG
+ */
+public interface FunctionImportProcessor extends ODataProcessor {
+  /**
+   * Executes a function import and returns the result.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse executeFunctionImport(GetFunctionImportUriInfo uriInfo, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportValueProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportValueProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportValueProcessor.java
new file mode 100644
index 0000000..3d2fbbc
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/FunctionImportValueProcessor.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+
+/**
+ * Execute an OData function import value request.
+ * @author SAP AG
+ */
+public interface FunctionImportValueProcessor extends ODataProcessor {
+  /**
+   * Returns the unformatted value of a function import.
+   * @param uriInfo information about the request URI
+   * @param contentType the content type of the response
+   * @return an {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse executeFunctionImportValue(GetFunctionImportUriInfo uriInfo, String contentType) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/MetadataProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/MetadataProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/MetadataProcessor.java
new file mode 100644
index 0000000..307d202
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/MetadataProcessor.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetMetadataUriInfo;
+
+/**
+ * Execute a OData metadata request. 
+ * 
+ * @author SAP AG
+ */
+public interface MetadataProcessor extends ODataProcessor {
+
+  /**
+   * @param contentType 
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readMetadata(GetMetadataUriInfo uriInfo, String contentType) throws ODataException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/ServiceDocumentProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/ServiceDocumentProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/ServiceDocumentProcessor.java
new file mode 100644
index 0000000..94db07b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/ServiceDocumentProcessor.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.api.processor.part;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.GetServiceDocumentUriInfo;
+
+/**
+ * Execute a OData service document request. 
+ * 
+ * @author SAP AG
+ */
+public interface ServiceDocumentProcessor extends ODataProcessor {
+
+  /**
+   * @param contentType 
+   * @return a {@link ODataResponse} object
+   * @throws ODataException
+   */
+  ODataResponse readServiceDocument(GetServiceDocumentUriInfo uriInfo, String contentType) throws ODataException;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/package-info.java
new file mode 100644
index 0000000..16ca1c0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/part/package-info.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Processor Parts<p>
+ */
+package org.apache.olingo.odata2.api.processor.part;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
new file mode 100644
index 0000000..af0f74f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/RuntimeDelegate.java
@@ -0,0 +1,188 @@
+/*******************************************************************************
+ * 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.api.rt;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart.BatchResponsePartBuilder;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.ep.EntityProvider.EntityProviderInterface;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataRequest.ODataRequestBuilder;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.api.uri.UriParser;
+
+/**
+ * Provides access to core implementation classes for interfaces. This class is used 
+ * by internal abstract API implementations and it is not intended to be used by others. 
+ * 
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public abstract class RuntimeDelegate {
+
+  private static final String IMPLEMENTATION = "org.apache.olingo.odata2.core.rt.RuntimeDelegateImpl";
+
+  /**
+   * Create a runtime delegate instance from the core library. The core 
+   * library (org.apache.olingo.odata2.core.jar) needs to be included into the classpath
+   * of the using application.
+   * @return an implementation object
+   */
+  private static RuntimeDelegateInstance getInstance() {
+    RuntimeDelegateInstance delegate;
+
+    try {
+      final Class<?> clazz = Class.forName(RuntimeDelegate.IMPLEMENTATION);
+
+      /*
+       * We explicitly do not use the singleton pattern to keep the server state free
+       * and avoid class loading issues also during hot deployment. 
+       */
+      final Object object = clazz.newInstance();
+      delegate = (RuntimeDelegateInstance) object;
+
+    } catch (final Exception e) {
+      throw new RuntimeDelegateException(e);
+    }
+    return delegate;
+  }
+
+  /**
+   * An implementation is available in the core library.
+   * @org.apache.olingo.odata2.DoNotImplement
+   */
+  public static abstract class RuntimeDelegateInstance {
+
+    protected abstract ODataResponseBuilder createODataResponseBuilder();
+
+    protected abstract EdmSimpleType getEdmSimpleType(EdmSimpleTypeKind edmSimpleTypeKind);
+
+    protected abstract UriParser getUriParser(Edm edm);
+
+    protected abstract EdmSimpleTypeFacade getSimpleTypeFacade();
+
+    protected abstract Edm createEdm(EdmProvider provider);
+
+    protected abstract EntityProviderInterface createEntityProvider();
+
+    protected abstract ODataService createODataSingleProcessorService(EdmProvider provider, ODataSingleProcessor processor);
+
+    protected abstract EdmProvider createEdmProvider(InputStream metadataXml, boolean validate) throws EntityProviderException;
+
+    protected abstract BatchResponsePartBuilder createBatchResponsePartBuilder();
+
+    protected abstract ODataRequestBuilder createODataRequestBuilder();
+
+  }
+
+  /**
+   * Returns a simple type object for given type kind.
+   * @param edmSimpleTypeKind type kind
+   * @return an implementation object
+   */
+  public static EdmSimpleType getEdmSimpleType(final EdmSimpleTypeKind edmSimpleTypeKind) {
+    return RuntimeDelegate.getInstance().getEdmSimpleType(edmSimpleTypeKind);
+  }
+
+  /**
+   * Returns an implementation of the EDM simple-type facade.
+   * @return an implementation object
+   */
+  public static EdmSimpleTypeFacade getSimpleTypeFacade() {
+    return RuntimeDelegate.getInstance().getSimpleTypeFacade();
+  }
+
+  /**
+   * Returns a builder for creating response objects with variable parameter sets.
+   * @return an implementation object
+   */
+  public static ODataResponseBuilder createODataResponseBuilder() {
+    return RuntimeDelegate.getInstance().createODataResponseBuilder();
+  }
+
+  /**
+   * Creates and returns an entity data model.
+   * @param provider a provider implemented by the OData service
+   * @return an implementation object
+   */
+  public static Edm createEdm(final EdmProvider provider) {
+    return RuntimeDelegate.getInstance().createEdm(provider);
+  }
+
+  /**
+   * Returns an parser which can parse OData uris based on metadata.
+   * @param edm metadata of the implemented service
+   * @return an implementation object
+   */
+  public static UriParser getUriParser(final Edm edm) {
+    return RuntimeDelegate.getInstance().getUriParser(edm);
+  }
+
+  /**
+   * Creates and returns a http entity provider. 
+   * @return an implementation object
+   */
+  public static EntityProviderInterface createEntityProvider() {
+    return RuntimeDelegate.getInstance().createEntityProvider();
+  }
+
+  /**
+   * Creates and returns a single processor service. 
+   * @param provider a provider implementation for the metadata of the OData service
+   * @param processor a single data processor implementation of the OData service
+   * @return a implementation object
+   */
+  public static ODataService createODataSingleProcessorService(final EdmProvider provider, final ODataSingleProcessor processor) {
+    return RuntimeDelegate.getInstance().createODataSingleProcessorService(provider, processor);
+  }
+
+  /**
+   * Creates and returns an edm provider. 
+   * @param metadataXml a metadata xml input stream (means the metadata document)
+   * @param validate true if semantic checks for metadata input stream shall be done
+   * @return an instance of EdmProvider
+   */
+  public static EdmProvider createEdmProvider(final InputStream metadataXml, final boolean validate) throws EntityProviderException {
+    return RuntimeDelegate.getInstance().createEdmProvider(metadataXml, validate);
+  }
+
+  private static class RuntimeDelegateException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public RuntimeDelegateException(final Exception e) {
+      super(e);
+    }
+  }
+
+  public static BatchResponsePartBuilder createBatchResponsePartBuilder() {
+    return RuntimeDelegate.getInstance().createBatchResponsePartBuilder();
+  }
+
+  public static ODataRequestBuilder createODataRequestBuilder() {
+    return RuntimeDelegate.getInstance().createODataRequestBuilder();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/package-info.java
new file mode 100644
index 0000000..51c14c0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/rt/package-info.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Runtime Support<p> 
+ * 
+ * Provides a mechanism for loading of implementation classes for interfaces. 
+ */
+package org.apache.olingo.odata2.api.rt;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Accept.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Accept.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Accept.java
new file mode 100644
index 0000000..187212f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/servicedocument/Accept.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.api.servicedocument;
+
+/**
+ * An Accept element
+ * <p>Accept element indicates the types of representation accepted by the Collection
+ * @author SAP AG
+ */
+public interface Accept {
+
+  /**
+   * Get the media range
+   * 
+   * @return value as String
+   */
+  public String getValue();
+
+  /**
+   * Get common attributes
+   * 
+   * @return {@link CommonAttributes}
+   */
+  public CommonAttributes getCommonAttributes();
+}


[42/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRole.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRole.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRole.java
new file mode 100644
index 0000000..54ccfec
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRole.java
@@ -0,0 +1,279 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.metamodel.Attribute;
+
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+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.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraintRole;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView;
+
+public class JPAEdmReferentialConstraintRole extends JPAEdmBaseViewImpl
+    implements JPAEdmReferentialConstraintRoleView {
+  /*
+   * Static Buffer
+   */
+  private static Attribute<?, ?> bufferedJPAAttribute = null;
+  private static ArrayList<JoinColumn> bufferedJoinColumns = new ArrayList<JoinColumn>();
+  /*
+   * Static Buffer
+   */
+
+  private boolean firstBuild = true;
+
+  private JPAEdmEntityTypeView entityTypeView;
+  private JPAEdmReferentialConstraintRoleView.RoleType roleType;
+
+  private Attribute<?, ?> jpaAttribute;
+  private ArrayList<String> jpaColumnNames;
+  private Association association;
+
+  private boolean roleExists = false;
+
+  private JPAEdmRefConstraintRoleBuilder builder;
+  private ReferentialConstraintRole currentRole;
+
+  public JPAEdmReferentialConstraintRole(
+      final JPAEdmReferentialConstraintRoleView.RoleType roleType,
+      final JPAEdmEntityTypeView entityTypeView,
+      final JPAEdmPropertyView propertyView,
+      final JPAEdmAssociationView associationView) {
+
+    super(entityTypeView);
+    this.entityTypeView = entityTypeView;
+    this.roleType = roleType;
+
+    jpaAttribute = propertyView.getJPAAttribute();
+    association = associationView.getEdmAssociation();
+
+  }
+
+  @Override
+  public boolean isExists() {
+    return roleExists;
+
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmRefConstraintRoleBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public RoleType getRoleType() {
+    return roleType;
+  }
+
+  @Override
+  public ReferentialConstraintRole getEdmReferentialConstraintRole() {
+    return currentRole;
+  }
+
+  @Override
+  public String getJPAColumnName() {
+    return null;
+  }
+
+  @Override
+  public String getEdmEntityTypeName() {
+    return null;
+  }
+
+  @Override
+  public String getEdmAssociationName() {
+    return null;
+  }
+
+  private class JPAEdmRefConstraintRoleBuilder implements JPAEdmBuilder {
+
+    @Override
+    public void build() throws ODataJPAModelException {
+      if (firstBuild) {
+        firstBuild();
+      } else if (roleExists) {
+        try {
+          buildRole();
+        } catch (SecurityException e) {
+          throw ODataJPAModelException.throwException(
+              ODataJPAModelException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (NoSuchFieldException e) {
+          throw ODataJPAModelException.throwException(
+              ODataJPAModelException.GENERAL.addContent(e
+                  .getMessage()), e);
+        }
+      }
+
+    }
+
+    private void firstBuild() {
+      firstBuild = false;
+      isConsistent = false;
+
+      extractJoinColumns();
+
+      if (!roleExists) {
+        return;
+      }
+
+      jpaColumnNames = new ArrayList<String>();
+
+      for (JoinColumn joinColumn : bufferedJoinColumns) {
+        if (roleType == RoleType.PRINCIPAL) {
+          jpaColumnNames.add(joinColumn.referencedColumnName());
+        } else if (roleType == RoleType.DEPENDENT) {
+          jpaColumnNames.add(joinColumn.name());
+        }
+      }
+
+    }
+
+    private void buildRole() throws SecurityException, NoSuchFieldException {
+
+      if (currentRole == null) {
+        currentRole = new ReferentialConstraintRole();
+        String jpaAttributeType = null;
+        EntityType edmEntityType = null;
+
+        if (roleType == RoleType.PRINCIPAL) {
+          jpaAttributeType = jpaAttribute.getJavaType()
+              .getSimpleName();
+          if (jpaAttributeType.equals("List")) {
+            Type type = ((ParameterizedType) jpaAttribute
+                .getJavaMember().getDeclaringClass()
+                .getDeclaredField(jpaAttribute.getName())
+                .getGenericType()).getActualTypeArguments()[0];
+            int lastIndexOfDot = type.toString().lastIndexOf(".");
+            jpaAttributeType = type.toString().substring(
+                lastIndexOfDot + 1);
+          }
+          edmEntityType = entityTypeView
+              .searchEdmEntityType(jpaAttributeType);
+
+        }
+
+        else if (roleType == RoleType.DEPENDENT) {
+          edmEntityType = entityTypeView
+              .searchEdmEntityType(jpaAttribute
+                  .getDeclaringType().getJavaType()
+                  .getSimpleName());
+        }
+
+        List<PropertyRef> propertyRefs = new ArrayList<PropertyRef>();
+        if (edmEntityType != null) {
+          for (String columnName : jpaColumnNames) {
+            for (Property property : edmEntityType.getProperties()) {
+              if (columnName.equals(((JPAEdmMapping) property
+                  .getMapping()).getJPAColumnName())) {
+                PropertyRef propertyRef = new PropertyRef();
+                propertyRef.setName(property.getName());
+                propertyRefs.add(propertyRef);
+                break;
+              }
+            }
+          }
+          currentRole.setPropertyRefs(propertyRefs);
+          if (propertyRefs.isEmpty()) {
+            isConsistent = false;
+            return;
+          }
+          AssociationEnd end = association.getEnd1();
+          if (end.getType().getName().equals(edmEntityType.getName())) {
+            currentRole.setRole(end.getRole());
+            isConsistent = true;
+          } else {
+            end = association.getEnd2();
+            if (end.getType().getName()
+                .equals(edmEntityType.getName())) {
+              currentRole.setRole(end.getRole());
+              isConsistent = true;
+            }
+          }
+        }
+
+      }
+    }
+
+    private void extractJoinColumns() {
+      /*
+       * Check against Static Buffer whether the join column was already
+       * extracted.
+       */
+      if (!jpaAttribute.equals(bufferedJPAAttribute)) {
+        bufferedJPAAttribute = jpaAttribute;
+        bufferedJoinColumns.clear();
+      } else if (bufferedJoinColumns.isEmpty()) {
+        roleExists = false;
+        return;
+      } else {
+        roleExists = true;
+        return;
+      }
+
+      AnnotatedElement annotatedElement = (AnnotatedElement) jpaAttribute
+          .getJavaMember();
+
+      if (annotatedElement == null) {
+        return;
+      }
+
+      JoinColumn joinColumn = annotatedElement
+          .getAnnotation(JoinColumn.class);
+      if (joinColumn == null) {
+        JoinColumns joinColumns = annotatedElement
+            .getAnnotation(JoinColumns.class);
+
+        if (joinColumns != null) {
+          JoinColumn[] joinColumnArray = joinColumns.value();
+
+          for (JoinColumn element : joinColumnArray) {
+            bufferedJoinColumns.add(element);
+          }
+        } else {
+          return;
+        }
+      } else {
+        bufferedJoinColumns.add(joinColumn);
+      }
+      roleExists = true;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchema.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchema.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchema.java
new file mode 100644
index 0000000..40a92a3
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchema.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.processor.core.jpa.access.model.JPAEdmNameBuilder;
+
+public class JPAEdmSchema extends JPAEdmBaseViewImpl implements
+    JPAEdmSchemaView {
+
+  private Schema schema;
+  private JPAEdmComplexTypeView complexTypeView;
+  private JPAEdmEntityContainerView entityContainerView;
+  private JPAEdmAssociationView associationView = null;
+  private List<String> nonKeyComplexList = null;
+  private HashMap<Class<?>, String[]> customOperations = null;
+
+  public JPAEdmSchema(final JPAEdmModelView modelView) {
+    super(modelView);
+    if (nonKeyComplexList == null) {
+      nonKeyComplexList = new ArrayList<String>();
+    }
+  }
+
+  @Override
+  public List<String> getNonKeyComplexTypeList() {
+    return nonKeyComplexList;
+  }
+
+  @Override
+  public void addNonKeyComplexName(final String complexTypeName) {
+    nonKeyComplexList.add(complexTypeName);
+  }
+
+  @Override
+  public Schema getEdmSchema() {
+    return schema;
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return entityContainerView;
+  }
+
+  @Override
+  public JPAEdmComplexTypeView getJPAEdmComplexTypeView() {
+    return complexTypeView;
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    if (builder == null) {
+      builder = new JPAEdmSchemaBuilder();
+    }
+
+    return builder;
+  }
+
+  @Override
+  public void clean() {
+    super.clean();
+    schema = null;
+  }
+
+  private class JPAEdmSchemaBuilder implements JPAEdmBuilder {
+    /*
+     * 
+     * Each call to build method creates a new EDM Schema. The newly created
+     * schema is built with Entity Containers, associations, Complex Types
+     * and Entity Types.
+     * 
+     * ************************************************************ Build
+     * EDM Schema - STEPS
+     * ************************************************************ 1) Build
+     * Name for EDM Schema 2) Build EDM Complex Types from JPA Embeddable
+     * Types 3) Add EDM Complex Types to EDM Schema 4) Build EDM Entity
+     * Container 5) Add EDM Entity Container to EDM Schema 6) Fetch Built
+     * EDM Entity Types from EDM Entity Container 7) Add EDM Entity Types to
+     * EDM Schema 8) Fetch Built EDM Association Sets from EDM Entity
+     * Container 9) Fetch Built EDM Associations from EDM Association Set
+     * 10) Add EDM Association to EDM Schema
+     * ************************************************************ Build
+     * EDM Schema - STEPS
+     * ************************************************************
+     */
+    @Override
+    public void build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+
+      schema = new Schema();
+      JPAEdmNameBuilder.build(JPAEdmSchema.this);
+
+      associationView = new JPAEdmAssociation(JPAEdmSchema.this);
+
+      complexTypeView = new JPAEdmComplexType(JPAEdmSchema.this);
+      complexTypeView.getBuilder().build();
+
+      if (getJPAEdmExtension() != null) {
+        getJPAEdmExtension()
+            .extend(JPAEdmSchema.this);
+      }
+
+      entityContainerView = new JPAEdmEntityContainer(JPAEdmSchema.this);
+      entityContainerView.getBuilder().build();
+      schema.setEntityContainers(entityContainerView
+          .getConsistentEdmEntityContainerList());
+
+      JPAEdmEntitySetView entitySetView = entityContainerView
+          .getJPAEdmEntitySetView();
+      if (entitySetView.isConsistent()
+          && entitySetView.getJPAEdmEntityTypeView() != null) {
+        JPAEdmEntityTypeView entityTypeView = entitySetView
+            .getJPAEdmEntityTypeView();
+        if (entityTypeView.isConsistent()
+            && !entityTypeView.getConsistentEdmEntityTypes()
+                .isEmpty()) {
+          schema.setEntityTypes(entityTypeView
+              .getConsistentEdmEntityTypes());
+        }
+      }
+      if (complexTypeView.isConsistent()) {
+        List<ComplexType> complexTypes = complexTypeView
+            .getConsistentEdmComplexTypes();
+        List<ComplexType> existingComplexTypes = new ArrayList<ComplexType>();
+        for (ComplexType complexType : complexTypes) {
+          if (complexType != null && nonKeyComplexList.contains(complexType.getName())) {//null check for exclude
+            existingComplexTypes.add(complexType);
+          }
+        }
+        if (!existingComplexTypes.isEmpty()) {
+          schema.setComplexTypes(existingComplexTypes);
+        }
+      }
+
+      List<String> existingAssociationList = new ArrayList<String>();
+      if (associationView.isConsistent()
+          && !associationView.getConsistentEdmAssociationList()
+              .isEmpty()) {
+
+        List<Association> consistentAssociationList = associationView
+            .getConsistentEdmAssociationList();
+        schema.setAssociations(consistentAssociationList);
+        for (Association association : consistentAssociationList) {
+          existingAssociationList.add(association.getName());
+        }
+
+      }
+      List<EntityType> entityTypes = entityContainerView
+          .getJPAEdmEntitySetView().getJPAEdmEntityTypeView()
+          .getConsistentEdmEntityTypes();
+      List<NavigationProperty> navigationProperties;
+      if (entityTypes != null && !entityTypes.isEmpty()) {
+        for (EntityType entityType : entityTypes) {
+
+          List<NavigationProperty> consistentNavigationProperties = null;
+          navigationProperties = entityType.getNavigationProperties();
+          if (navigationProperties != null) {
+            consistentNavigationProperties = new ArrayList<NavigationProperty>();
+            for (NavigationProperty navigationProperty : navigationProperties) {
+              if (existingAssociationList
+                  .contains(navigationProperty
+                      .getRelationship().getName())) {
+                consistentNavigationProperties
+                    .add(navigationProperty);
+              }
+            }
+            if (consistentNavigationProperties.isEmpty()) {
+              entityType.setNavigationProperties(null);
+            } else {
+              entityType
+                  .setNavigationProperties(consistentNavigationProperties);
+            }
+          }
+
+        }
+      }
+
+    }
+
+  }
+
+  @Override
+  public final JPAEdmAssociationView getJPAEdmAssociationView() {
+    return associationView;
+  }
+
+  @Override
+  public void registerOperations(final Class<?> customClass, final String[] methodNames) {
+    if (customOperations == null) {
+      customOperations = new HashMap<Class<?>, String[]>();
+    }
+
+    customOperations.put(customClass, methodNames);
+
+  }
+
+  @Override
+  public HashMap<Class<?>, String[]> getRegisteredOperations() {
+    return customOperations;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/resources/jpaprocessor_msg.properties
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/resources/jpaprocessor_msg.properties b/jpa-core/src/main/resources/jpaprocessor_msg.properties
new file mode 100644
index 0000000..5eb96fb
--- /dev/null
+++ b/jpa-core/src/main/resources/jpaprocessor_msg.properties
@@ -0,0 +1,61 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# Fall Back translations
+#
+
+#JPA EDM Provider Errors
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.GENERAL="OData - JPA Metadata: Internal error [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INNER_EXCEPTION="%1$s: %2$s.\n"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INVALID_ENTITY_TYPE="OData - JPA Model Processor: Invalid Entity Type [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INVALID_COMPLEX_TYPE="OData - JPA Model Processor: Invalid Complex Type [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INVALID_ASSOCIATION ="OData - JPA Model Processor: Invalid Association [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INVALID_ENTITYSET="OData - JPA Model Processor: Invalid Entity set [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INVALID_ENTITYCONTAINER="OData - JPA Model Processor: Invalid Entity Container [%1$s]"
+org.apache.olingo.odata2.processor.jap.exception.ODataJPAModelException.INVALID_ASSOCIATION_SET="OData - JPA Model Processor: Invalid Association Set [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.INVALID_FUNC_IMPORT="OData - JPA Model Processor: Invalid Function Import [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.BUILDER_NULL="OData - JPA Model Processor: JPA Builder not initialized"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.FUNC_ENTITYSET_EXP="OData - JPA Model Processor: Entity Set expected for Function Import with return type as Entity Type with Multiplicity Many"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.FUNC_RETURN_TYPE_EXP="OData - JPA Model Processor: Return type expected. Class: [%1$s], Method: [%2$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.FUNC_RETURN_TYPE_ENTITY_NOT_FOUND="OData - JPA Model Processor: Return type not found. Class: [%1$s], Method: [%2$s], Type: [%3$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.FUNC_PARAM_NAME_EXP="OData - JPA Model Processor: Parameter Name for function import expected. Class: [%1$s]", Method: [%2$s]"
+
+#JPA Type converter Errors
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException.TYPE_NOT_SUPPORTED="OData - JPA Type Converter: Type [%1$s] not supported"
+
+#JPA Runtime Errors
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ENTITY_MANAGER_NOT_INITIALIZED="OData - JPA Service Factory: Java Persistence Entity Manager not initialized"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.GENERAL="OData - JPA Runtime: Internal error [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.INNER_EXCEPTION="%1$s: %2$s.\n"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.JOIN_CLAUSE_EXPECTED="OData - JPA Runtime: Join Clause expected"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.RESOURCE_NOT_FOUND="OData - JPA Runtime: Resource not found"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_ODATA_FILTER_CONDITION="OData - JPA Runtime: Filter condition not correct"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE="OData - JPA Runtime: JPA query syntax is not correct"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_CREATE_REQUEST="OData - JPA Runtime: JPA create request is not correct"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_UPDATE_REQUEST="OData - JPA Runtime: JPA update request is not correct"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_DELETE_REQUEST="OData - JPA Runtime: JPA delete URL is not correct"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_KEY_VALUE="Key parameter value is not correct for [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_PARAM_VALUE="Parameter value is not correct for [%1$s]"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_UNIQUE_CONSTRAINT="Violation of unique constraint"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQL_INTEGRITY_CONSTRAINT="Integrity constraint violation"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.RELATIONSHIP_INVALID="OData - JPA Runtime: Invalid link"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.RESOURCE_X_NOT_FOUND="OData - JPA Runtime: Resource [%1$s] not found"
+
+#JPA Common Errors
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAException.ODATA_JPACTX_NULL="OData JPA: OData JPA Context cannot be null"
+org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException.ERROR_JPQLCTXBLDR_CREATE="OData JPA: Error creating JPQL Context Builder"

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/META-INF/MANIFEST.MF b/jpa-core/src/test/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/jpa-core/src/test/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/JPAEntityParserTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/JPAEntityParserTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/JPAEntityParserTest.java
new file mode 100644
index 0000000..454b64e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/JPAEntityParserTest.java
@@ -0,0 +1,652 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntityParser;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPAEntityParserTest {
+  /*
+   * TestCase - JPAResultParser is a singleton class Check if the same
+   * instance is returned when create method is called
+   */
+  @Test
+  public void testCreate() {
+    JPAEntityParser resultParser1 = JPAEntityParser.create();
+    JPAEntityParser resultParser2 = JPAEntityParser.create();
+
+    assertEquals(resultParser1, resultParser2);
+  }
+
+  @Test
+  public void testparse2EdmPropertyValueMap() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    Object jpaEntity = new demoItem("abc", 10);
+    EdmStructuralType structuralType = EasyMock
+        .createMock(EdmStructuralType.class);
+    EdmProperty edmTyped = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType = EasyMock.createMock(EdmType.class);
+    EdmProperty edmTyped01 = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType01 = EasyMock.createMock(EdmType.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EdmMapping edmMapping01 = EasyMock.createMock(EdmMapping.class);
+
+    try {
+      EasyMock.expect(edmType.getKind())
+          .andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmTyped.getName()).andStubReturn("identifier");
+      EasyMock.replay(edmType);
+      EasyMock.expect(edmMapping.getInternalName()).andStubReturn("id");
+      EasyMock.replay(edmMapping);
+      EasyMock.expect(edmTyped.getType()).andStubReturn(edmType);
+      EasyMock.expect(edmTyped.getMapping()).andStubReturn(edmMapping);
+      EasyMock.replay(edmTyped);
+      EasyMock.expect(structuralType.getProperty("identifier"))
+          .andStubReturn(edmTyped);
+
+      EasyMock.expect(edmType01.getKind()).andStubReturn(
+          EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmTyped01.getName()).andStubReturn("Value");
+      EasyMock.replay(edmType01);
+      EasyMock.expect(edmMapping01.getInternalName()).andStubReturn(
+          "value");
+      EasyMock.replay(edmMapping01);
+      EasyMock.expect(edmTyped01.getType()).andStubReturn(edmType01);
+      EasyMock.expect(edmTyped01.getMapping())
+          .andStubReturn(edmMapping01);
+      EasyMock.replay(edmTyped01);
+      EasyMock.expect(structuralType.getProperty("value")).andStubReturn(
+          edmTyped01);
+
+      List<String> propNames = new ArrayList<String>();
+      propNames.add("identifier");
+      propNames.add("value");
+      EasyMock.expect(structuralType.getPropertyNames()).andReturn(
+          propNames);
+      EasyMock.replay(structuralType);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    try {
+      Map<String, Object> result = resultParser.parse2EdmPropertyValueMap(jpaEntity, structuralType);
+      assertEquals(2, result.size());
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testparse2EdmPropertyValueMapEdmExcep() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    Object jpaEntity = new demoItem("abc", 10);
+    EdmStructuralType structuralType = EasyMock
+        .createMock(EdmStructuralType.class);
+    EdmProperty edmTyped = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType = EasyMock.createMock(EdmType.class);
+    EdmProperty edmTyped01 = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType01 = EasyMock.createMock(EdmType.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EdmMapping edmMapping01 = EasyMock.createMock(EdmMapping.class);
+
+    try {
+      EasyMock.expect(edmType.getKind())
+          .andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmType.getName()).andStubThrow(
+          new EdmException(null));
+      EasyMock.replay(edmType);
+      EasyMock.expect(edmMapping.getInternalName()).andStubReturn("id");
+      EasyMock.replay(edmMapping);
+      EasyMock.expect(edmTyped.getType()).andStubThrow(
+          new EdmException(null));
+      EasyMock.expect(edmTyped.getMapping()).andStubReturn(edmMapping);
+      EasyMock.replay(edmTyped);
+      EasyMock.expect(structuralType.getProperty("identifier"))
+          .andStubReturn(edmTyped);
+
+      EasyMock.expect(edmType01.getKind()).andStubReturn(
+          EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmType01.getName()).andStubReturn("value");
+      EasyMock.replay(edmType01);
+      EasyMock.expect(edmMapping01.getInternalName()).andStubReturn(
+          "value");
+      EasyMock.replay(edmMapping01);
+      EasyMock.expect(edmTyped01.getType()).andStubReturn(edmType01);
+      EasyMock.expect(edmTyped01.getMapping())
+          .andStubReturn(edmMapping01);
+      EasyMock.replay(edmTyped01);
+      EasyMock.expect(structuralType.getProperty("value")).andStubReturn(
+          edmTyped01);
+
+      List<String> propNames = new ArrayList<String>();
+      propNames.add("identifier");
+      propNames.add("value");
+      EasyMock.expect(structuralType.getPropertyNames()).andReturn(
+          propNames);
+      EasyMock.replay(structuralType);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2); // assertTrue(false);
+    }
+
+    try {
+      resultParser.parse2EdmPropertyValueMap(jpaEntity, structuralType);
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);
+    }
+
+  }
+
+  @Test
+  public void testparse2EdmPropertyListMap()
+  {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    Map<String, Object> edmEntity = new HashMap<String, Object>();
+    edmEntity.put("SoId", 1);
+    DemoRelatedEntity relatedEntity = new DemoRelatedEntity("NewOrder");
+    demoItem jpaEntity = new demoItem("laptop", 1);
+    jpaEntity.setRelatedEntity(relatedEntity);
+    List<EdmNavigationProperty> navigationPropertyList = new ArrayList<EdmNavigationProperty>();
+    // Mocking a navigation property and its mapping object
+    EdmNavigationProperty navigationProperty = EasyMock.createMock(EdmNavigationProperty.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    try {
+      EasyMock.expect(edmMapping.getInternalName()).andStubReturn("relatedEntity");
+      EasyMock.replay(edmMapping);
+      EasyMock.expect(navigationProperty.getName()).andStubReturn("RelatedEntities");
+      EasyMock.expect(navigationProperty.getMapping()).andStubReturn(edmMapping);
+      EasyMock.replay(navigationProperty);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    navigationPropertyList.add(navigationProperty);
+    try {
+      HashMap<String, Object> result = resultParser.parse2EdmNavigationValueMap(jpaEntity, navigationPropertyList);
+      assertEquals(relatedEntity, result.get("RelatedEntities"));
+
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testparse2EdmPropertyValueMapFromList()
+  {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    demoItem jpaEntity = new demoItem("laptop", 1);
+    DemoRelatedEntity relatedEntity = new DemoRelatedEntity("DemoOrder");
+    jpaEntity.setRelatedEntity(relatedEntity);
+    List<EdmProperty> selectPropertyList = new ArrayList<EdmProperty>();
+    // Mocking EdmProperties
+    EdmProperty edmProperty1 = EasyMock.createMock(EdmProperty.class);
+    EdmProperty edmProperty2 = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType1 = EasyMock.createMock(EdmType.class);
+    EdmType edmType2 = EasyMock.createMock(EdmType.class);
+    EdmMapping mapping1 = EasyMock.createMock(EdmMapping.class);
+    EdmMapping mapping2 = EasyMock.createMock(EdmMapping.class);
+    try {
+      EasyMock.expect(edmType1.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.replay(edmType1);
+      EasyMock.expect(mapping1.getInternalName()).andStubReturn("id");
+      EasyMock.replay(mapping1);
+      EasyMock.expect(edmProperty1.getName()).andStubReturn("Id");
+      EasyMock.expect(edmProperty1.getMapping()).andStubReturn(mapping1);
+      EasyMock.expect(edmProperty1.getType()).andStubReturn(edmType1);
+      EasyMock.replay(edmProperty1);
+      EasyMock.expect(edmType2.getKind()).andStubReturn(EdmTypeKind.COMPLEX);
+      EasyMock.replay(edmType2);
+      EasyMock.expect(mapping2.getInternalName()).andStubReturn("relatedEntity.order");
+      EasyMock.replay(mapping2);
+      EasyMock.expect(edmProperty2.getName()).andStubReturn("Order");
+      EasyMock.expect(edmProperty2.getMapping()).andStubReturn(mapping2);
+      EasyMock.expect(edmProperty2.getType()).andStubReturn(edmType2);
+      EasyMock.replay(edmProperty2);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    selectPropertyList.add(edmProperty1);
+    selectPropertyList.add(edmProperty2);
+    try {
+      Map<String, Object> result = resultParser.parse2EdmPropertyValueMap(jpaEntity, selectPropertyList);
+      assertEquals("DemoOrder", result.get("Order"));
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  // This unit tests when there is a complex type in the select list
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testparse2EdmPropertyValueMapFromListComplex()
+  {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    demoItem jpaEntity = new demoItem("laptop", 1);
+    DemoRelatedEntity relatedEntity = new DemoRelatedEntity("DemoOrder");
+    jpaEntity.setRelatedEntity(relatedEntity);
+    List<EdmProperty> selectPropertyList = new ArrayList<EdmProperty>();
+    // Mocking EdmProperties
+    EdmProperty edmProperty1 = EasyMock.createMock(EdmProperty.class);
+    EdmProperty edmProperty2 = EasyMock.createMock(EdmProperty.class);
+    EdmProperty edmComplexProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType1 = EasyMock.createMock(EdmType.class);
+    EdmStructuralType edmType2 = EasyMock.createMock(EdmStructuralType.class);
+    EdmType edmComplexType = EasyMock.createMock(EdmType.class);
+    EdmMapping mapping1 = EasyMock.createMock(EdmMapping.class);
+    EdmMapping mapping2 = EasyMock.createMock(EdmMapping.class);
+    EdmMapping complexMapping = EasyMock.createMock(EdmMapping.class);
+    try {
+      EasyMock.expect(edmType1.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.replay(edmType1);
+      EasyMock.expect(mapping1.getInternalName()).andStubReturn("id");
+      EasyMock.replay(mapping1);
+      EasyMock.expect(edmProperty1.getName()).andStubReturn("Id");
+      EasyMock.expect(edmProperty1.getMapping()).andStubReturn(mapping1);
+      EasyMock.expect(edmProperty1.getType()).andStubReturn(edmType1);
+      EasyMock.replay(edmProperty1);
+      // Mocking the complex properties
+      EasyMock.expect(edmComplexType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.replay(edmComplexType);
+      EasyMock.expect(complexMapping.getInternalName()).andStubReturn("order");
+      EasyMock.replay(complexMapping);
+      EasyMock.expect(edmComplexProperty.getName()).andStubReturn("OrderName");
+      EasyMock.expect(edmComplexProperty.getMapping()).andStubReturn(complexMapping);
+      EasyMock.expect(edmComplexProperty.getType()).andStubReturn(edmComplexType);
+      EasyMock.replay(edmComplexProperty);
+      EasyMock.expect(edmType2.getKind()).andStubReturn(EdmTypeKind.COMPLEX);
+      EasyMock.expect(edmType2.getProperty("OrderName")).andStubReturn(edmComplexProperty);
+      List<String> propertyNames = new ArrayList<String>();
+      propertyNames.add("OrderName");
+      EasyMock.expect(edmType2.getPropertyNames()).andStubReturn(propertyNames);
+      EasyMock.replay(edmType2);
+      EasyMock.expect(mapping2.getInternalName()).andStubReturn("relatedEntity");
+      EasyMock.replay(mapping2);
+      EasyMock.expect(edmProperty2.getName()).andStubReturn("Order");
+      EasyMock.expect(edmProperty2.getMapping()).andStubReturn(mapping2);
+      EasyMock.expect(edmProperty2.getType()).andStubReturn(edmType2);
+      EasyMock.replay(edmProperty2);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    selectPropertyList.add(edmProperty1);
+    selectPropertyList.add(edmProperty2);
+    try {
+      Map<String, Object> result = resultParser.parse2EdmPropertyValueMap(jpaEntity, selectPropertyList);
+      assertEquals(1, ((HashMap<String, Object>) result.get("Order")).size());
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  /*
+   * TestCase - getGetterName is a private method in JPAResultParser. The
+   * method is uses reflection to derive the property access methods from
+   * EdmProperty
+   */
+  @Test
+  public void testGetGettersWithOutMapping() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    try {
+
+      /*
+       * Case 1 - Property having No mapping
+       */
+      Class<?>[] pars = { String.class, EdmMapping.class, String.class };
+      Object[] params = { "Field1", null, "get" };
+      Method getGetterName = resultParser.getClass().getDeclaredMethod(
+          "getAccessModifierName", pars);
+      getGetterName.setAccessible(true);
+      String name = (String) getGetterName.invoke(resultParser,
+          params);
+
+      assertEquals("getField1", name);
+
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+
+    }
+  }
+
+  @Test
+  public void testGetGettersWithNullPropname() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    try {
+
+      /*
+       * Case 1 - Property having No mapping and no name
+       */
+      Class<?>[] pars = { String.class, EdmMapping.class, String.class };
+      Object[] params = { null, null, null };
+      Method getGetterName = resultParser.getClass().getDeclaredMethod(
+          "getAccessModifierName", pars);
+      getGetterName.setAccessible(true);
+
+      String name = (String) getGetterName.invoke(resultParser,
+          params);
+      assertNull(name);
+
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+
+    }
+  }
+
+  /*
+   * TestCase - getGetterName is a private method in JPAResultParser. The
+   * method is uses reflection to derive the property access methods from
+   * EdmProperty
+   * 
+   * EdmProperty name could have been modified. Then mapping object of
+   * EdmProperty should be used for deriving the name
+   */
+  @Test
+  public void testGetGettersWithMapping() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("field1");
+    EasyMock.replay(edmMapping);
+    try {
+
+      Class<?>[] pars = { String.class, EdmMapping.class, String.class };
+      Object[] params = { "myField", edmMapping, "get" };
+      Method getGetterName = resultParser.getClass().getDeclaredMethod(
+          "getAccessModifierName", pars);
+      getGetterName.setAccessible(true);
+
+      String name = (String) getGetterName.invoke(resultParser,
+          params);
+      assertEquals("getField1", name);
+
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+
+    }
+  }
+
+  @Test
+  public void testGetGettersNoSuchMethodException() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    try {
+
+      Method getGetterName = resultParser.getClass().getDeclaredMethod(
+          "getGetterName1", EdmProperty.class);
+      getGetterName.setAccessible(true);
+
+    } catch (NoSuchMethodException e) {
+      assertEquals(
+          "org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntityParser.getGetterName1(org.apache.olingo.odata2.api.edm.EdmProperty)",
+          e.getMessage());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+
+    }
+  }
+
+  @Test
+  public void testParse2EdmPropertyValueMap() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    Object jpaEntity = new DemoItem2("abc");
+    try {
+      resultParser.parse2EdmPropertyValueMap(jpaEntity, getEdmPropertyList());
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetGetterEdmException() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    Object jpaEntity = new demoItem("abc", 10);
+    EdmStructuralType structuralType = EasyMock
+        .createMock(EdmStructuralType.class);
+    try {
+      EasyMock.expect(structuralType.getPropertyNames()).andStubThrow(
+          new EdmException(null));
+      EasyMock.replay(structuralType);
+      Method getGetters = resultParser.getClass().getDeclaredMethod(
+          "getGetters", Object.class, EdmStructuralType.class);
+      getGetters.setAccessible(true);
+      try {
+        getGetters.invoke(resultParser, jpaEntity, structuralType);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        assertTrue(true);
+      }
+    } catch (NoSuchMethodException e) {
+      assertEquals(
+          "org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntityParser.getGetters(java.lang.Object, org.apache.olingo.odata2.api.edm.EdmStructuralType)",
+          e.getMessage());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testForNullJPAEntity() {
+    JPAEntityParser resultParser = JPAEntityParser.create();
+    EdmStructuralType structuralType = EasyMock
+        .createMock(EdmStructuralType.class);
+    Object map;
+    try {
+      map = resultParser.parse2EdmPropertyValueMap(null,
+          structuralType);
+      assertNull(map);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  class demoItem {
+    private String id;
+    private int value;
+    private DemoRelatedEntity relatedEntity;
+
+    public String getId() {
+      return id;
+    }
+
+    public void setId(final String id) {
+      this.id = id;
+    }
+
+    public DemoRelatedEntity getRelatedEntity() {
+      return relatedEntity;
+    }
+
+    public void setRelatedEntity(final DemoRelatedEntity relatedEntity) {
+      this.relatedEntity = relatedEntity;
+    }
+
+    public int getValue() {
+      return value;
+    }
+
+    public void setValue(final int value) {
+      this.value = value;
+    }
+
+    demoItem(final String id, final int value) {
+      this.id = id;
+      this.value = value;
+    }
+
+  }
+
+  class DemoRelatedEntity
+  {
+    String order;
+
+    public String getOrder() {
+      return order;
+    }
+
+    public void setOrder(final String order) {
+      this.order = order;
+    }
+
+    public DemoRelatedEntity(final String order) {
+      super();
+      this.order = order;
+    }
+
+  }
+
+  private List<EdmProperty> getEdmPropertyList() {
+    List<EdmProperty> properties = new ArrayList<EdmProperty>();
+    properties.add(getEdmProperty());
+    return properties;
+  }
+
+  class DemoItem2
+  {
+    private String field1;
+
+    public String getField1() {
+      return field1;
+    }
+
+    public void setField1(final String field) {
+      field1 = field;
+    }
+
+    public DemoItem2(final String field)
+    {
+      field1 = field;
+    }
+
+  }
+
+  private EdmProperty getEdmProperty() {
+    EdmProperty edmTyped = EasyMock.createMock(EdmProperty.class);
+
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn(
+        "Field1");
+    EasyMock.replay(edmMapping);
+
+    EdmType edmType = EasyMock.createMock(EdmType.class);
+
+    try {
+      EasyMock.expect(edmType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmType.getName()).andStubReturn("identifier");
+      EasyMock.expect(edmTyped.getName()).andStubReturn("SalesOrderHeader");
+      EasyMock.expect(edmTyped.getMapping())
+          .andStubReturn(edmMapping);
+
+      EasyMock.expect(edmTyped.getType()).andStubReturn(edmType);
+      EasyMock.expect(edmTyped.getMapping()).andStubReturn(edmMapping);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmType);
+    EasyMock.replay(edmTyped);
+    return edmTyped;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImplTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImplTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImplTest.java
new file mode 100644
index 0000000..5c2d59e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImplTest.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.core.jpa.edm.ODataJPAEdmProvider;
+import org.apache.olingo.odata2.processor.core.jpa.mock.ODataJPAContextMock;
+
+public class ODataJPAContextImplTest {
+
+  private ODataContext odataContext = null;
+  private ODataJPAContext odataJPAContext = null;
+  private EdmProvider edmProvider = null;
+  private EntityManagerFactory emf = null;
+  private EntityManager em = null;
+  private ODataProcessor processor = null;
+
+  @Before
+  public void setup() {
+
+    edmProvider = new ODataJPAEdmProvider();
+    emf = EasyMock.createMock(EntityManagerFactory.class);
+    em = EasyMock.createMock(EntityManager.class);
+    EasyMock.replay(em);
+
+    EasyMock.expect(emf.createEntityManager()).andStubReturn(em);
+    EasyMock.replay(emf);
+
+    odataContext = EasyMock.createMock(ODataContext.class);
+    List<Locale> listLocale = new ArrayList<Locale>();
+    listLocale.add(Locale.ENGLISH);
+    listLocale.add(Locale.GERMAN);
+
+    EasyMock.expect(odataContext.getAcceptableLanguages()).andStubReturn(listLocale);
+    EasyMock.replay(odataContext);
+
+    processor = EasyMock.createMock(ODataProcessor.class);
+    EasyMock.replay(processor);
+
+    odataJPAContext = new ODataJPAContextImpl();
+    odataJPAContext.setEdmProvider(edmProvider);
+    odataJPAContext.setEntityManagerFactory(emf);
+    odataJPAContext.setODataContext(odataContext);
+    odataJPAContext.setODataProcessor(processor);
+    odataJPAContext
+        .setPersistenceUnitName(ODataJPAContextMock.PERSISTENCE_UNIT_NAME);
+    odataJPAContext.setJPAEdmMappingModel(ODataJPAContextMock.MAPPING_MODEL);
+  }
+
+  @Test
+  public void testgetMethodsOfODataJPAContext() {
+
+    assertEquals(odataJPAContext.getEdmProvider().hashCode(), edmProvider.hashCode());
+    assertEquals(odataJPAContext.getEntityManagerFactory().hashCode(), emf.hashCode());
+    assertEquals(odataJPAContext.getODataContext().hashCode(), odataContext.hashCode());
+    assertEquals(odataJPAContext.getODataProcessor().hashCode(), processor.hashCode());
+    assertEquals(odataJPAContext.getPersistenceUnitName(),
+        ODataJPAContextMock.PERSISTENCE_UNIT_NAME);
+    assertEquals(odataJPAContext.getJPAEdmMappingModel(), ODataJPAContextMock.MAPPING_MODEL);
+
+    EntityManager em1 = odataJPAContext.getEntityManager();
+    EntityManager em2 = odataJPAContext.getEntityManager();
+    if (em1 != null && em2 != null) {
+      assertEquals(em1.hashCode(), em2.hashCode());
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefaultTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefaultTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefaultTest.java
new file mode 100644
index 0000000..d9fa5d7
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefaultTest.java
@@ -0,0 +1,569 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Query;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmTestModelView;
+
+public class ODataJPAProcessorDefaultTest extends JPAEdmTestModelView {
+
+  ODataJPAProcessorDefault objODataJPAProcessorDefault;
+  ODataJPAProcessorDefaultTest objODataJPAProcessorDefaultTest;
+
+  private static final String STR_LOCAL_URI = "http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/";
+  private static final String SALESORDERPROCESSING_CONTAINER = "salesorderprocessingContainer";
+  private static final String SO_ID = "SoId";
+  private static final String SALES_ORDER = "SalesOrder";
+  private static final String SALES_ORDER_HEADERS = "SalesOrderHeaders";
+  private static final String TEXT_PLAIN_CHARSET_UTF_8 = "text/plain;charset=utf-8";
+  private static final String STR_CONTENT_TYPE = "Content-Type";
+
+  @Before
+  public void setUp() {
+    objODataJPAProcessorDefaultTest = new ODataJPAProcessorDefaultTest();
+    objODataJPAProcessorDefault = new ODataJPAProcessorDefault(getLocalmockODataJPAContext());
+  }
+
+  @Test
+  public void testReadEntitySetGetEntitySetUriInfoString() {
+    try {
+      GetEntityUriInfo getEntityView = getEntityUriInfo();
+      Assert.assertNotNull(objODataJPAProcessorDefault.readEntity(getEntityView, HttpContentType.APPLICATION_XML));
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e1) {//Expected
+      assertTrue(true);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testcountEntitySet() {
+    try {
+      Assert.assertNotNull(objODataJPAProcessorDefault.countEntitySet(getEntitySetCountUriInfo(), HttpContentType.APPLICATION_XML));
+      Assert.assertEquals(TEXT_PLAIN_CHARSET_UTF_8,
+          objODataJPAProcessorDefault.countEntitySet(getEntitySetCountUriInfo(), HttpContentType.APPLICATION_XML).getHeader(STR_CONTENT_TYPE));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (Exception e)
+    {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testExistsEntity() {
+    try {
+      Assert.assertNotNull(objODataJPAProcessorDefault.existsEntity(getEntityCountCountUriInfo(), HttpContentType.APPLICATION_XML));
+      Assert.assertEquals(TEXT_PLAIN_CHARSET_UTF_8,
+          objODataJPAProcessorDefault.existsEntity(getEntityCountCountUriInfo(), HttpContentType.APPLICATION_XML).getHeader(STR_CONTENT_TYPE));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (Exception e)
+    {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testDeleteEntity() {
+    try {
+      Assert.assertNotNull(objODataJPAProcessorDefault.deleteEntity(getDeletetUriInfo(), HttpContentType.APPLICATION_XML));
+      Assert.assertEquals(TEXT_PLAIN_CHARSET_UTF_8,
+          objODataJPAProcessorDefault.countEntitySet(getEntitySetCountUriInfo(), HttpContentType.APPLICATION_XML).getHeader(STR_CONTENT_TYPE));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testCreateEntity() {
+    try {
+      Assert.assertNotNull(objODataJPAProcessorDefault.createEntity(getPostUriInfo(), getMockedInputStreamContent(), HttpContentType.APPLICATION_XML, HttpContentType.APPLICATION_XML));
+    } catch (ODataException e) {
+      Assert.assertTrue(true); //Expected TODO - need to revisit
+    }
+  }
+
+  @Test
+  public void testUpdateEntity() {
+    try {
+      Assert.assertNotNull(objODataJPAProcessorDefault.updateEntity(getPutUriInfo(), getMockedInputStreamContent(), HttpContentType.APPLICATION_XML, false, HttpContentType.APPLICATION_XML));
+    } catch (ODataException e) {
+      Assert.assertTrue(true); //Expected TODO - need to revisit
+    }
+  }
+
+  private PutMergePatchUriInfo getPutUriInfo() {
+    return (PutMergePatchUriInfo) getDeletetUriInfo();
+  }
+
+  private PostUriInfo getPostUriInfo() {
+    return (PostUriInfo) getDeletetUriInfo();
+  }
+
+  private InputStream getMockedInputStreamContent() {
+    return new ByteArrayInputStream(getEntityBody().getBytes());
+  }
+
+  private String getEntityBody() {
+    return
+    "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\" xmlns:d=\"http://schemas.microsoft.com/ado/2007/08/dataservices\" xml:base=\"http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/SalesOrderProcessing.svc/\">"
+        + "<content type=\"application/xml\">"
+        + "<m:properties>"
+        + "<d:ID>2</d:ID>"
+        + "<d:CreationDate>2013-01-02T00:00:00</d:CreationDate>"
+        + "<d:CurrencyCode>Code_555</d:CurrencyCode>"
+        + "<d:BuyerAddressInfo m:type=\"SalesOrderProcessing.AddressInfo\">"
+        + "<d:Street>Test_Street_Name_055</d:Street>"
+        + "<d:Number>2</d:Number>"
+        + "<d:Country>Test_Country_2</d:Country>"
+        + "<d:City>Test_City_2</d:City>"
+        + "</d:BuyerAddressInfo>"
+        + "<d:GrossAmount>0.0</d:GrossAmount>"
+        + "<d:BuyerId>2</d:BuyerId>"
+        + "<d:DeliveryStatus>true</d:DeliveryStatus>"
+        + "<d:BuyerName>buyerName_2</d:BuyerName>"
+        + "<d:NetAmount>0.0</d:NetAmount>"
+        + "</m:properties>"
+        + "</content>"
+        + "</entry>";
+  }
+
+  private GetEntitySetCountUriInfo getEntitySetCountUriInfo() {
+    return getLocalUriInfo();
+  }
+
+  private GetEntityCountUriInfo getEntityCountCountUriInfo() {
+    return getLocalUriInfo();
+  }
+
+  private DeleteUriInfo getDeletetUriInfo() {
+    UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
+    EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
+    EasyMock.expect(objUriInfo.getTop()).andStubReturn(getTop());
+    EasyMock.expect(objUriInfo.getSkip()).andStubReturn(getSkip());
+    EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
+    EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
+    EasyMock.expect(objUriInfo.getKeyPredicates()).andStubReturn(getKeyPredicates());
+    EasyMock.replay(objUriInfo);
+    return objUriInfo;
+  }
+
+  private List<KeyPredicate> getKeyPredicates() {
+    List<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    return keyPredicates;
+  }
+
+  /**
+   * @return
+   */
+  private UriInfo getLocalUriInfo() {
+    UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
+    EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
+    EasyMock.expect(objUriInfo.getTop()).andStubReturn(getTop());
+    EasyMock.expect(objUriInfo.getSkip()).andStubReturn(getSkip());
+    EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
+    EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
+    EasyMock.expect(objUriInfo.getFunctionImport()).andStubReturn(null);
+    EasyMock.replay(objUriInfo);
+    return objUriInfo;
+  }
+
+  /**
+   * @return
+   * @throws EdmException
+   */
+  private EdmEntitySet getLocalEdmEntitySet() {
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(edmEntitySet.getName()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntitySet.getEntityContainer()).andStubReturn(getLocalEdmEntityContainer());
+      EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(getLocalEdmEntityType());
+      EasyMock.replay(edmEntitySet);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return edmEntitySet;
+  }
+
+  /**
+   * @return
+   * @throws EdmException
+   */
+  private EdmEntityType getLocalEdmEntityType() {
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    try {
+      EasyMock.expect(edmEntityType.getKeyProperties()).andStubReturn(new ArrayList<EdmProperty>());
+      EasyMock.expect(edmEntityType.getPropertyNames()).andStubReturn(getLocalPropertyNames());
+      EasyMock.expect(edmEntityType.getProperty(SO_ID)).andStubReturn(getEdmTypedMockedObj(SALES_ORDER));
+      EasyMock.expect(edmEntityType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmEntityType.getNamespace()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntityType.getName()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntityType.hasStream()).andStubReturn(false);
+      EasyMock.expect(edmEntityType.getNavigationPropertyNames()).andStubReturn(new ArrayList<String>());
+      EasyMock.expect(edmEntityType.getKeyPropertyNames()).andStubReturn(new ArrayList<String>());
+      EasyMock.expect(edmEntityType.getMapping()).andStubReturn(getEdmMappingMockedObj(SALES_ORDER));// ID vs Salesorder ID
+      EasyMock.replay(edmEntityType);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return edmEntityType;
+  }
+
+  private InlineCount getInlineCount() {
+    return InlineCount.NONE;
+  }
+
+  private FilterExpression getFilter() {
+    return null;
+  }
+
+  private Integer getSkip() {
+    return null;
+  }
+
+  private Integer getTop() {
+    return null;
+  }
+
+  private OrderByExpression getOrderByExpression() {
+    return null;
+  }
+
+  private ODataJPAContext getLocalmockODataJPAContext() {
+    ODataJPAContext odataJPAContext = EasyMock.createMock(ODataJPAContext.class);
+    EasyMock.expect(odataJPAContext.getPersistenceUnitName()).andStubReturn("salesorderprocessing");
+    EasyMock.expect(odataJPAContext.getEntityManagerFactory()).andStubReturn(mockEntityManagerFactory());
+    EasyMock.expect(odataJPAContext.getODataContext()).andStubReturn(getLocalODataContext());
+    EasyMock.expect(odataJPAContext.getEntityManager()).andStubReturn(getLocalEntityManager());
+    EasyMock.replay(odataJPAContext);
+    return odataJPAContext;
+  }
+
+  private EntityManagerFactory mockEntityManagerFactory() {
+    EntityManagerFactory emf = EasyMock.createMock(EntityManagerFactory.class);
+    EasyMock.expect(emf.getMetamodel()).andStubReturn(mockMetaModel());
+    EasyMock.expect(emf.createEntityManager()).andStubReturn(getLocalEntityManager());
+    EasyMock.replay(emf);
+    return emf;
+  }
+
+  private EntityManagerFactory mockEntityManagerFactory2() {// For create, to avoid stackoverflow
+    EntityManagerFactory emf = EasyMock.createMock(EntityManagerFactory.class);
+    EasyMock.expect(emf.getMetamodel()).andStubReturn(mockMetaModel());
+    EasyMock.replay(emf);
+    return emf;
+  }
+
+  private EntityManager getLocalEntityManager() {
+    EntityManager em = EasyMock.createMock(EntityManager.class);
+    EasyMock.expect(em.createQuery("SELECT E1 FROM SalesOrderHeaders E1")).andStubReturn(getQuery());
+    EasyMock.expect(em.createQuery("SELECT COUNT ( E1 ) FROM SalesOrderHeaders E1")).andStubReturn(getQueryForSelectCount());
+    EasyMock.expect(em.getEntityManagerFactory()).andStubReturn(mockEntityManagerFactory2());// For create
+    EasyMock.expect(em.getTransaction()).andStubReturn(getLocalTransaction()); //For Delete
+    Address obj = new Address();
+    em.remove(obj);// testing void method
+    em.flush();
+    EasyMock.replay(em);
+    return em;
+  }
+
+  private EntityTransaction getLocalTransaction() {
+    EntityTransaction entityTransaction = EasyMock.createMock(EntityTransaction.class);
+    entityTransaction.begin(); // testing void method
+    entityTransaction.commit();// testing void method
+    entityTransaction.rollback();// testing void method
+    EasyMock.replay(entityTransaction);
+    return entityTransaction;
+  }
+
+  private Query getQuery() {
+    Query query = EasyMock.createMock(Query.class);
+    EasyMock.expect(query.getResultList()).andStubReturn(getResultList());
+    EasyMock.replay(query);
+    return query;
+  }
+
+  private Query getQueryForSelectCount() {
+    Query query = EasyMock.createMock(Query.class);
+    EasyMock.expect(query.getResultList()).andStubReturn(getResultListForSelectCount());
+    EasyMock.replay(query);
+    return query;
+  }
+
+  private List<?> getResultList() {
+    List<Object> list = new ArrayList<Object>();
+    list.add(new Address());
+    return list;
+  }
+
+  private List<?> getResultListForSelectCount() {
+    List<Object> list = new ArrayList<Object>();
+    list.add(new Long(11));
+    return list;
+  }
+
+  class Address {
+    private String soId = "12";
+
+    public String getSoId() {
+      return soId;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+      boolean isEqual = false;
+      if (obj instanceof Address)
+      {
+        isEqual = getSoId().equalsIgnoreCase(((Address) obj).getSoId());//
+      }
+      return isEqual;
+    }
+  }
+
+  private Metamodel mockMetaModel() {
+    Metamodel metaModel = EasyMock.createMock(Metamodel.class);
+    EasyMock.expect(metaModel.getEntities()).andStubReturn(getLocalEntities());
+    EasyMock.replay(metaModel);
+    return metaModel;
+  }
+
+  private Set<EntityType<?>> getLocalEntities() {
+    Set<EntityType<?>> entityTypeSet = new HashSet<EntityType<?>>();
+    entityTypeSet.add(getLocalJPAEntityType());
+    return entityTypeSet;
+  }
+
+  @SuppressWarnings("rawtypes")
+  private EntityType<EntityType> getLocalJPAEntityType() {
+    @SuppressWarnings("unchecked")
+    EntityType<EntityType> entityType = EasyMock.createMock(EntityType.class);
+    EasyMock.expect(entityType.getJavaType()).andStubReturn(EntityType.class);
+    EasyMock.replay(entityType);
+    return entityType;
+  }
+
+  private GetEntityUriInfo getEntityUriInfo() {
+    GetEntityUriInfo getEntityView = EasyMock
+        .createMock(GetEntityUriInfo.class);
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    try {
+      EasyMock.expect(getEntityView.getExpand()).andStubReturn(null);
+      EasyMock.expect(edmEntityType.getKeyProperties()).andStubReturn(
+          new ArrayList<EdmProperty>());
+      EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(
+          edmEntityType);
+      EasyMock.expect(edmEntitySet.getName()).andStubReturn(SALES_ORDER_HEADERS);
+
+      EasyMock.expect(getEntityView.getSelect()).andStubReturn(null);
+      EasyMock.expect(getEntityView.getTargetEntitySet()).andStubReturn(
+          edmEntitySet);
+      EasyMock.expect(edmEntityType.getPropertyNames()).andStubReturn(getLocalPropertyNames());
+      EasyMock.expect(edmEntityType.getProperty(SO_ID)).andStubReturn(getEdmTypedMockedObj(SO_ID));
+
+      EasyMock.expect(edmEntityType.getMapping()).andStubReturn(getEdmMappingMockedObj(SALES_ORDER));
+
+      EasyMock.expect(edmEntityType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmEntityType.getNamespace()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntityType.getName()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntityType.hasStream()).andStubReturn(false);
+      EasyMock.expect(edmEntityType.getNavigationPropertyNames()).andStubReturn(new ArrayList<String>());
+      EasyMock.expect(edmEntityType.getKeyPropertyNames()).andStubReturn(new ArrayList<String>());
+
+      EasyMock.expect(edmEntitySet.getEntityContainer()).andStubReturn(getLocalEdmEntityContainer());
+
+      EasyMock.replay(edmEntityType, edmEntitySet);
+      EasyMock.expect(getEntityView.getKeyPredicates()).andStubReturn(
+          new ArrayList<KeyPredicate>());
+      List<NavigationSegment> navigationSegments = new ArrayList<NavigationSegment>();
+      EasyMock.expect(getEntityView.getNavigationSegments()).andReturn(
+          navigationSegments);
+      EasyMock.expect(getEntityView.getStartEntitySet()).andReturn(edmEntitySet);
+
+      EasyMock.replay(getEntityView);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return getEntityView;
+  }
+
+  private EdmEntityContainer getLocalEdmEntityContainer() {
+    EdmEntityContainer edmEntityContainer = EasyMock.createMock(EdmEntityContainer.class);
+    EasyMock.expect(edmEntityContainer.isDefaultEntityContainer()).andStubReturn(true);
+    try {
+      EasyMock.expect(edmEntityContainer.getName()).andStubReturn(SALESORDERPROCESSING_CONTAINER);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    EasyMock.replay(edmEntityContainer);
+    return edmEntityContainer;
+  }
+
+  private EdmTyped getEdmTypedMockedObj(final String propertyName) {
+    EdmProperty mockedEdmProperty = EasyMock.createMock(EdmProperty.class);
+    try {
+      EasyMock.expect(mockedEdmProperty.getMapping())
+          .andStubReturn(getEdmMappingMockedObj(propertyName));
+      EdmType edmType = EasyMock.createMock(EdmType.class);
+      EasyMock.expect(edmType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.replay(edmType);
+      EasyMock.expect(mockedEdmProperty.getName()).andStubReturn("identifier");
+      EasyMock.expect(mockedEdmProperty.getType()).andStubReturn(edmType);
+      EasyMock.expect(mockedEdmProperty.getFacets()).andStubReturn(getEdmFacetsMockedObj());
+
+      EasyMock.replay(mockedEdmProperty);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return mockedEdmProperty;
+  }
+
+  private EdmFacets getEdmFacetsMockedObj() {
+    EdmFacets facets = EasyMock.createMock(EdmFacets.class);
+    EasyMock.expect(facets.getConcurrencyMode()).andStubReturn(EdmConcurrencyMode.Fixed);
+
+    EasyMock.replay(facets);
+    return facets;
+  }
+
+  private EdmMapping getEdmMappingMockedObj(final String propertyName) {
+    EdmMapping mockedEdmMapping = EasyMock.createMock(EdmMapping.class);
+    if (propertyName.equalsIgnoreCase(SALES_ORDER)) {
+      EasyMock.expect(mockedEdmMapping.getInternalName())
+          .andStubReturn(SALES_ORDER_HEADERS);
+    } else {
+      EasyMock.expect(mockedEdmMapping.getInternalName())
+          .andStubReturn(propertyName);
+    }
+    EasyMock.replay(mockedEdmMapping);
+    return mockedEdmMapping;
+  }
+
+  private List<String> getLocalPropertyNames() {
+    List<String> list = new ArrayList<String>();
+    list.add(SO_ID);
+    return list;
+  }
+
+  private ODataContext getLocalODataContext() {
+    ODataContext objODataContext = EasyMock.createMock(ODataContext.class);
+    try {
+      EasyMock.expect(objODataContext.getPathInfo()).andStubReturn(getLocalPathInfo());
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(objODataContext);
+    return objODataContext;
+  }
+
+  private PathInfo getLocalPathInfo() {
+    PathInfo pathInfo = EasyMock.createMock(PathInfo.class);
+    EasyMock.expect(pathInfo.getServiceRoot()).andStubReturn(getLocalURI());
+    EasyMock.replay(pathInfo);
+    return pathInfo;
+  }
+
+  private URI getLocalURI() {
+    URI uri = null;
+    try {
+      uri = new URI(STR_LOCAL_URI);
+    } catch (URISyntaxException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return uri;
+  }
+
+}


[06/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/ContentTypeTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/ContentTypeTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/ContentTypeTest.java
new file mode 100644
index 0000000..91b9ddf
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/ContentTypeTest.java
@@ -0,0 +1,928 @@
+/*******************************************************************************
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ws.rs.core.MediaType;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+// 14.1 Accept
+//
+// The Accept request-header field can be used to specify certain media types which are acceptable for the response.
+// Accept headers can be used to indicate that the request is specifically limited to a small set of desired types, as
+// in the case of a request for an in-line image.
+//
+// Accept = "Accept" ":"
+// #( media-range [ accept-params ] )
+// media-range = ( "*/*"
+// | ( type "/" "*" )
+// | ( type "/" subtype )
+// ) *( ";" parameter )
+// accept-params = ";" "q" "=" qvalue *( accept-extension )
+// accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+
+/**
+ * @author SAP AG
+ */
+public class ContentTypeTest extends BaseTest {
+
+  @Test
+  public void testMe() {
+    MediaType t = new MediaType("*", "xml");
+    assertNotNull(t);
+    assertTrue(t.isCompatible(new MediaType("app", "xml")));
+  }
+
+  @Test
+  public void parseable() {
+    assertTrue(ContentType.isParseable("application/xml"));
+    assertTrue(ContentType.isParseable("text/plain"));
+    assertTrue(ContentType.isParseable("application/atom+xml; charset=UTF-8"));
+
+    // see: https://jtrack/browse/ODATAFORSAP-65
+    assertFalse(ContentType.isParseable("application/  atom+xml; charset=UTF-8"));
+    assertFalse(ContentType.isParseable("application   /atom+xml; charset=UTF-8"));
+    //
+    assertFalse(ContentType.isParseable("app/app/moreapp"));
+    //assertFalse(ContentType.isParseable("application/atom+xml; charset   =   UTF-8"));
+    assertFalse(ContentType.isParseable(null));
+  }
+
+  @Test
+  public void parseNotThrow() {
+    assertNotNull(ContentType.parse("application/xml"));
+    assertNotNull(ContentType.parse("text/plain"));
+    assertNotNull(ContentType.parse("application/atom+xml; charset=UTF-8"));
+
+    // see: https://jtrack/browse/ODATAFORSAP-65
+    assertFalse(ContentType.isParseable("application/  atom+xml; charset=UTF-8"));
+    assertFalse(ContentType.isParseable("application   /atom+xml; charset=UTF-8"));
+    //
+    assertNull(ContentType.parse("app/app/moreapp"));
+    //assertFalse(ContentType.isParseable("application/atom+xml; charset   =   UTF-8"));
+    assertNull(ContentType.parse(null));
+  }
+
+  @Test
+  public void creationContentTypeImageJpeg() {
+    ContentType mt = ContentType.create("image/jpeg");
+
+    assertEquals("image", mt.getType());
+    assertEquals("jpeg", mt.getSubtype());
+    assertEquals("image/jpeg", mt.toString());
+    assertEquals(ODataFormat.MIME, mt.getODataFormat());
+  }
+
+  @Test
+  public void creationFromHttpContentTypeAtomXmlEntry() {
+    ContentType mt = ContentType.create(HttpContentType.APPLICATION_ATOM_XML_ENTRY_UTF8);
+
+    assertEquals("application", mt.getType());
+    assertEquals("atom+xml", mt.getSubtype());
+    assertEquals("application/atom+xml;charset=utf-8;type=entry", mt.toString());
+    assertEquals(ODataFormat.ATOM, mt.getODataFormat());
+    assertEquals(2, mt.getParameters().size());
+    assertEquals("entry", mt.getParameters().get("type"));
+    assertEquals("utf-8", mt.getParameters().get("charset"));
+    assertEquals(ContentType.APPLICATION_ATOM_XML_ENTRY_CS_UTF_8, mt);
+  }
+
+  @Test
+  public void creationFromHttpContentTypeMultipartMixed() {
+    ContentType mt = ContentType.create(HttpContentType.MULTIPART_MIXED);
+
+    assertEquals("multipart", mt.getType());
+    assertEquals("mixed", mt.getSubtype());
+    assertEquals("multipart/mixed", mt.toString());
+    assertEquals(ODataFormat.MIME, mt.getODataFormat());
+    assertEquals(0, mt.getParameters().size());
+    assertEquals(ContentType.MULTIPART_MIXED, mt);
+    assertTrue(ContentType.MULTIPART_MIXED.isCompatible(mt));
+  }
+
+  @Test
+  public void creationFromHttpContentTypeMultipartMixedWithParameters() {
+    String boundary = UUID.randomUUID().toString();
+    ContentType mt = ContentType.create(HttpContentType.MULTIPART_MIXED + "; boundary=" + boundary);
+
+    assertEquals("multipart", mt.getType());
+    assertEquals("mixed", mt.getSubtype());
+    assertEquals("multipart/mixed;boundary=" + boundary, mt.toString());
+    assertEquals(ODataFormat.MIME, mt.getODataFormat());
+    assertEquals(1, mt.getParameters().size());
+    assertEquals(boundary, mt.getParameters().get("boundary"));
+    assertTrue(ContentType.MULTIPART_MIXED.isCompatible(mt));
+  }
+
+  @Test
+  public void creationFromHttpContentTypeApplicationXml() {
+    ContentType mt = ContentType.create(HttpContentType.APPLICATION_XML_UTF8);
+
+    assertEquals("application", mt.getType());
+    assertEquals("xml", mt.getSubtype());
+    assertEquals("application/xml;charset=utf-8", mt.toString());
+    assertEquals(ODataFormat.XML, mt.getODataFormat());
+    assertEquals(1, mt.getParameters().size());
+    assertEquals(ContentType.create(ContentType.APPLICATION_XML, "charset", "utf-8"), mt);
+  }
+
+  @Test
+  public void creationFromHttpContentTypeApplicationJson() {
+    ContentType mt = ContentType.create(HttpContentType.APPLICATION_JSON_UTF8);
+
+    assertEquals("application", mt.getType());
+    assertEquals("json", mt.getSubtype());
+    assertEquals("application/json;charset=utf-8", mt.toString());
+    assertEquals(ODataFormat.JSON, mt.getODataFormat());
+    assertEquals(1, mt.getParameters().size());
+    assertEquals(ContentType.create(ContentType.APPLICATION_JSON, "charset", "utf-8"), mt);
+  }
+
+  @Test
+  public void testContentTypeCreation() {
+    ContentType mt = ContentType.create("type", "subtype");
+
+    assertEquals("type", mt.getType());
+    assertEquals("subtype", mt.getSubtype());
+    assertEquals("type/subtype", mt.toString());
+    assertEquals(ODataFormat.CUSTOM, mt.getODataFormat());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testContentTypeCreationWildcardType() {
+    ContentType.create("*", "subtype");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testContentTypeCreationWildcardTypeSingleFormat() {
+    ContentType.create("*/subtype");
+  }
+
+  /**
+   * See: https://jtrack/browse/ODATAFORSAP-65
+   * and: 
+   * <p>
+   * RFC 2616:
+   * The type, subtype, and parameter attribute names are case-insensitive. Parameter values might or might not be case-sensitive,
+   * depending on the semantics of the parameter name. Linear white space (LWS) MUST NOT be used between the type and subtype, 
+   * nor between an attribute and its value.
+   * </p>
+   * @throws Throwable 
+   */
+  @Test
+  public void testContentTypeCreationInvalidWithSpaces() throws Throwable {
+    failContentTypeCreation("app/  space", IllegalArgumentException.class);
+    failContentTypeCreation("app    /space", IllegalArgumentException.class);
+    failContentTypeCreation("app    /   space", IllegalArgumentException.class);
+  }
+
+  private void failContentTypeCreation(final String contentType, final Class<? extends Exception> expectedExceptionClass) throws Exception {
+    try {
+      ContentType.create(contentType);
+      Assert.fail("Expected exception class " + expectedExceptionClass +
+          " was not thrown for creation of content type based on '" + contentType + "'.");
+    } catch (Exception e) {
+      assertEquals(expectedExceptionClass, e.getClass());
+    }
+  }
+
+  @Test
+  public void testContentTypeCreationWildcardSubType() {
+    ContentType mt = ContentType.create("type", "*");
+
+    assertEquals("type", mt.getType());
+    assertEquals("*", mt.getSubtype());
+    assertEquals("type/*", mt.toString());
+    assertEquals(ODataFormat.CUSTOM, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationWildcardSubTypeSingleFormat() {
+    ContentType mt = ContentType.create("type/*");
+
+    assertEquals("type", mt.getType());
+    assertEquals("*", mt.getSubtype());
+    assertEquals("type/*", mt.toString());
+    assertEquals(ODataFormat.CUSTOM, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationAtom() {
+    ContentType mt = ContentType.create("application", "atom+xml");
+
+    assertEquals("application", mt.getType());
+    assertEquals("atom+xml", mt.getSubtype());
+    assertEquals("application/atom+xml", mt.toString());
+    assertEquals(ODataFormat.ATOM, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationXml() {
+    ContentType mt = ContentType.create("application", "xml");
+
+    assertEquals("application", mt.getType());
+    assertEquals("xml", mt.getSubtype());
+    assertEquals("application/xml", mt.toString());
+    assertEquals(ODataFormat.XML, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationJson() {
+    ContentType mt = ContentType.create("application", "json");
+
+    assertEquals("application", mt.getType());
+    assertEquals("json", mt.getSubtype());
+    assertEquals("application/json", mt.toString());
+    assertEquals(ODataFormat.JSON, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationOneString() {
+    ContentType mt = ContentType.create("type/subtype");
+
+    assertEquals("type", mt.getType());
+    assertEquals("subtype", mt.getSubtype());
+    assertEquals("type/subtype", mt.toString());
+    assertEquals(ODataFormat.CUSTOM, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationAtomOneString() {
+    ContentType mt = ContentType.create("application/atom+xml");
+
+    assertEquals("application", mt.getType());
+    assertEquals("atom+xml", mt.getSubtype());
+    assertEquals("application/atom+xml", mt.toString());
+    assertEquals(ODataFormat.ATOM, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationXmlOneString() {
+    ContentType mt = ContentType.create("application/xml");
+
+    assertEquals("application", mt.getType());
+    assertEquals("xml", mt.getSubtype());
+    assertEquals("application/xml", mt.toString());
+    assertEquals(ODataFormat.XML, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationXmlWithParaOneString() {
+    ContentType mt = ContentType.create("application/xml;q=0.9");
+
+    assertEquals("application", mt.getType());
+    assertEquals("xml", mt.getSubtype());
+    assertEquals("application/xml", mt.toString());
+    assertEquals(ODataFormat.XML, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationJsonOneString() {
+    ContentType mt = ContentType.create("application/json");
+
+    assertEquals("application", mt.getType());
+    assertEquals("json", mt.getSubtype());
+    assertEquals("application/json", mt.toString());
+    assertEquals(ODataFormat.JSON, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeCreationFromStrings() {
+    List<ContentType> types = ContentType.create(Arrays.asList("type/subtype", "application/xml", "application/json;key=value"));
+
+    assertEquals(3, types.size());
+
+    ContentType first = types.get(0);
+    assertEquals("type", first.getType());
+    assertEquals("subtype", first.getSubtype());
+    assertEquals("type/subtype", first.toString());
+    assertEquals(ODataFormat.CUSTOM, first.getODataFormat());
+
+    ContentType second = types.get(1);
+    assertEquals("application", second.getType());
+    assertEquals("xml", second.getSubtype());
+    assertEquals("application/xml", second.toString());
+    assertEquals(ODataFormat.XML, second.getODataFormat());
+
+    ContentType third = types.get(2);
+    assertEquals("application", third.getType());
+    assertEquals("json", third.getSubtype());
+    assertEquals("application/json;key=value", third.toString());
+    assertEquals("value", third.getParameters().get("key"));
+    assertEquals(ODataFormat.JSON, third.getODataFormat());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testContentTypeCreationFromStringsFail() {
+    List<ContentType> types = ContentType.create(Arrays.asList("type/subtype", "application/xml", "application/json/FAIL;key=value"));
+
+    assertEquals(3, types.size());
+  }
+
+  @Test
+  public void testEnsureCharsetParameter() {
+    ContentType mt = ContentType.create("application/json");
+
+    mt = mt.receiveWithCharsetParameter("utf-8");
+
+    assertEquals("application", mt.getType());
+    assertEquals("json", mt.getSubtype());
+    assertEquals("application/json;charset=utf-8", mt.toString());
+    assertEquals("utf-8", mt.getParameters().get("charset"));
+    assertEquals(ODataFormat.JSON, mt.getODataFormat());
+  }
+
+  @Test
+  public void testEnsureCharsetParameterIso() {
+    ContentType mt = ContentType.create("application/xml");
+
+    mt = mt.receiveWithCharsetParameter("iso-8859-1");
+
+    assertEquals("application", mt.getType());
+    assertEquals("xml", mt.getSubtype());
+    assertEquals("application/xml;charset=iso-8859-1", mt.toString());
+    assertEquals("iso-8859-1", mt.getParameters().get("charset"));
+    assertEquals(ODataFormat.XML, mt.getODataFormat());
+  }
+
+  @Test
+  public void testEnsureCharsetParameterAlreadySet() {
+    ContentType mt = ContentType.create("application/json;charset=utf-8");
+
+    mt = mt.receiveWithCharsetParameter("utf-8");
+
+    assertEquals("application", mt.getType());
+    assertEquals("json", mt.getSubtype());
+    assertEquals("application/json;charset=utf-8", mt.toString());
+    assertEquals("utf-8", mt.getParameters().get("charset"));
+    assertEquals(ODataFormat.JSON, mt.getODataFormat());
+  }
+
+  @Test
+  public void testEnsureCharsetParameterAlreadySetDiffValue() {
+    ContentType mt = ContentType.create("application/json;charset=utf-8");
+
+    mt = mt.receiveWithCharsetParameter("iso-8859-1");
+
+    assertEquals("application", mt.getType());
+    assertEquals("json", mt.getSubtype());
+    assertEquals("application/json;charset=utf-8", mt.toString());
+    assertEquals("utf-8", mt.getParameters().get("charset"));
+    assertEquals(ODataFormat.JSON, mt.getODataFormat());
+  }
+
+  @Test
+  public void testContentTypeWithParameterCreation() {
+    ContentType mt = ContentType.create("type", "subtype", addParameters("key", "value"));
+
+    assertEquals("type", mt.getType());
+    assertEquals("subtype", mt.getSubtype());
+    assertEquals(1, mt.getParameters().size());
+    assertEquals("value", mt.getParameters().get("key"));
+    assertEquals("type/subtype;key=value", mt.toString());
+  }
+
+  @Test
+  public void testContentTypeWithParametersCreation() {
+    ContentType mt = ContentType.create("type", "subtype", addParameters("key1", "value1", "key2", "value2"));
+    assertEquals("type", mt.getType());
+    assertEquals("subtype", mt.getSubtype());
+    assertEquals(2, mt.getParameters().size());
+    assertEquals("value1", mt.getParameters().get("key1"));
+    assertEquals("value2", mt.getParameters().get("key2"));
+    assertEquals("type/subtype;key1=value1;key2=value2", mt.toString());
+  }
+
+  @Test
+  public void testFormatParserValidInputType() {
+    ContentType t = ContentType.create("aaa");
+
+    assertEquals("aaa", t.getType());
+    assertEquals("*", t.getSubtype());
+    assertEquals(0, t.getParameters().size());
+  }
+
+  @Test
+  public void testFormatParserValidInputTypeSubtype() {
+    ContentType t = ContentType.create("aaa/bbb");
+    assertEquals("aaa", t.getType());
+    assertEquals("bbb", t.getSubtype());
+    assertEquals(0, t.getParameters().size());
+  }
+
+  @Test
+  public void testFormatParserValidInputTypeSybtypePara() {
+    ContentType t = ContentType.create("aaa/bbb;x=y");
+    assertEquals("aaa", t.getType());
+    assertEquals("bbb", t.getSubtype());
+    assertEquals(1, t.getParameters().size());
+  }
+
+  @Test
+  public void testFormatParserValidInputTypeSubtypeParas() {
+    ContentType t = ContentType.create("aaa/bbb;x=y;a=b");
+    assertEquals("aaa", t.getType());
+    assertEquals("bbb", t.getSubtype());
+    assertEquals(2, t.getParameters().size());
+  }
+
+  @Test
+  public void testFormatParserValidInputTypeSubtypeNullPara() {
+    ContentType t = ContentType.create("aaa/bbb;x=y;a");
+
+    assertEquals("aaa", t.getType());
+    assertEquals("bbb", t.getSubtype());
+    assertEquals(2, t.getParameters().size());
+  }
+
+  @Test
+  public void testFormatParserValidInputTypeNullPara() {
+    ContentType t = ContentType.create("aaa;x=y;a");
+
+    assertEquals("aaa", t.getType());
+    assertEquals("*", t.getSubtype());
+    assertEquals(2, t.getParameters().size());
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testFormatParserInvalidParameterWithSpaces() {
+    ContentType.create("aaa/bbb;x= y;a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testFormatParserInvalidParameterWithLineFeed() {
+    ContentType.create("aaa/bbb;x=\ny;a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testFormatParserInvalidParameterWithCarriageReturn() {
+    ContentType.create("aaa/bbb;x=\ry;a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testFormatParserInvalidParameterWithTabs() {
+    ContentType.create("aaa/bbb;x=\ty;a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testFormatParserInvalidParameterWithAllLws() {
+    ContentType.create("aaa/bbb;x=\t \n \ry;a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testFormatParserInvalidParameterWithAllLws2() {
+    ContentType.create("aaa/bbb;x=\n \ry;a= \tbla  ");
+  }
+
+  @Test
+  public void testSimpleEqual() {
+    ContentType t1 = ContentType.create("aaa/bbb");
+    ContentType t2 = ContentType.create("aaa/bbb");
+
+    assertEquals(t1, t2);
+  }
+
+  @Test
+  public void testEqualWithParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y;a");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithParametersIgnoreCase() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=YY");
+    ContentType t2 = ContentType.create("aaa/bbb;x=yy");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithUnsortedParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y;a=b");
+    ContentType t2 = ContentType.create("aaa/bbb;a=b;x=y");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithUnsortedParametersIgnoreCase() {
+    ContentType t1 = ContentType.create("aaa/bbb;xx=y;a=BB");
+    ContentType t2 = ContentType.create("aaa/bbb;a=bb;XX=y");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithWildcard() {
+    ContentType t1 = ContentType.create("aaa/bbb");
+    ContentType t2 = ContentType.create("*");
+
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+    assertEquals(t1, t2);
+  }
+
+  @Test
+  public void testEqualWithWildcardSubtype() {
+    ContentType t1 = ContentType.create("aaa/bbb");
+    ContentType t2 = ContentType.create("aaa/*");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithDiffTypeWildcardSubtype() {
+    ContentType t1 = ContentType.create("ccc/bbb");
+    ContentType t2 = ContentType.create("aaa/*");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testIllegalSubTypeWildcardSubtype() {
+    ContentType t1 = ContentType.create("*/bbb");
+    assertNull(t1);
+  }
+
+  @Test
+  public void testEqualWithWildcardAndParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y;a");
+    ContentType t2 = ContentType.create("*");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithWildcardSubtypeAndParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y;a");
+    ContentType t2 = ContentType.create("aaa/*");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualWithWildcardSubtypeAndParametersBoth() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y");
+    ContentType t2 = ContentType.create("aaa/*;x=y");
+
+    assertEquals(t1, t2);
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  @Ignore("If ContentType contains wildcards parameters are ignored.")
+  public void testUnEqualWithWildcardSubtypeAndDiffParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=z");
+    ContentType t2 = ContentType.create("aaa/*;x=y");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testUnSimpleEqual() {
+    ContentType t1 = ContentType.create("aaa/ccc");
+    ContentType t2 = ContentType.create("aaa/bbb");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testUnEqualTypesWithParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y;a");
+    ContentType t2 = ContentType.create("ccc/bbb;x=y;a");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testUnEqualParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=y;a");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testUnEqualParametersCounts() {
+    ContentType t1 = ContentType.create("aaa/bbb");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testUnEqualParametersCountsIgnoreQ() {
+    ContentType t1 = ContentType.create("aaa/bbb;q=0.9");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualParametersCountsIgnoreQ() {
+    ContentType t1 = ContentType.create("aaa/bbb;q=0.9;x=y;a=b");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testEqualParametersCountsWithQ() {
+    ContentType t1 = ContentType.create("aaa", "bbb", addParameters("a", "b", "x", "y", "q", "0.9"));
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testUnEqualWithUnsortedParameters() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType t2 = ContentType.create("aaa/bbb;a=b;x=y");
+
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testCompareSame() {
+    ContentType t1 = ContentType.create("aaa/bbb");
+    ContentType t2 = ContentType.create("aaa/bbb");
+
+    assertEquals(0, t1.compareWildcardCounts(t2));
+    assertEquals(0, t2.compareWildcardCounts(t1));
+  }
+
+  @Test
+  public void testCompareTwoWildcard() {
+    ContentType t1 = ContentType.create("*/*");
+    ContentType t2 = ContentType.create("aaa/bbb");
+
+    assertEquals(3, t1.compareWildcardCounts(t2));
+    assertEquals(-3, t2.compareWildcardCounts(t1));
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testCompareSubWildcard() {
+    ContentType t1 = ContentType.create("aaa/*");
+    ContentType t2 = ContentType.create("aaa/bbb");
+
+    assertEquals(1, t1.compareWildcardCounts(t2));
+    assertEquals(-1, t2.compareWildcardCounts(t1));
+    assertTrue(t1.equals(t2));
+    assertTrue(t2.equals(t1));
+  }
+
+  @Test
+  public void testCompareSubTypeWildcard() {
+    ContentType t1 = ContentType.create("aaa/*");
+    ContentType t2 = ContentType.create("xxx/*");
+
+    assertEquals(0, t1.compareWildcardCounts(t2));
+    assertEquals(0, t2.compareWildcardCounts(t1));
+    assertFalse(t1.equals(t2));
+    assertFalse(t2.equals(t1));
+  }
+
+  @Test
+  public void testNonEqualCharset() {
+    ContentType t1 = ContentType.create("aaa/bbb;charset=c1");
+    ContentType t2 = ContentType.create("aaa/bbb;charset=c2");
+
+    assertFalse(t1.equals(t2));
+  }
+
+  @Test
+  public void testCompatible() {
+    ContentType t1 = ContentType.create("aaa/bbb");
+    ContentType t2 = ContentType.create("aaa/bbb");
+
+    assertTrue(t1.isCompatible(t2));
+    assertTrue(t2.isCompatible(t1));
+    //
+    assertTrue(t1.equals(t2));
+  }
+
+  @Test
+  public void testCompatibleQ_ParametersSet() {
+    ContentType t1 = ContentType.create("aaa/bbb;q=0.9;x=y;a=b");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertTrue(t1.isCompatible(t2));
+    assertTrue(t2.isCompatible(t1));
+    //
+    assertTrue(t1.equals(t2));
+  }
+
+  @Test
+  public void testCompatibleDiffParameterValuesSet() {
+    ContentType t1 = ContentType.create("aaa/bbb;x=z;a=c");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertTrue(t1.isCompatible(t2));
+    assertTrue(t2.isCompatible(t1));
+    //
+    assertFalse(t1.equals(t2));
+  }
+
+  @Test
+  public void testCompatibleDiffParameterCountSet() {
+    ContentType t1 = ContentType.create("aaa/bbb;a=b");
+    ContentType t2 = ContentType.create("aaa/bbb;x=y;a=b");
+
+    assertTrue(t1.isCompatible(t2));
+    assertTrue(t2.isCompatible(t1));
+    //
+    assertFalse(t1.equals(t2));
+  }
+
+  @Test
+  public void testMatchSimple() {
+    ContentType m1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType m2 = ContentType.create("aaa/ccc");
+    ContentType m3 = ContentType.create("foo/me");
+    List<ContentType> toMatchContentTypes = new ArrayList<ContentType>();
+    toMatchContentTypes.add(m1);
+    toMatchContentTypes.add(m2);
+    toMatchContentTypes.add(m3);
+
+    ContentType check = ContentType.create("foo/me");
+
+    ContentType match = check.match(toMatchContentTypes);
+
+    assertEquals(ContentType.create("foo/me"), match);
+    assertEquals("foo/me", match.toContentTypeString());
+  }
+
+  @Test
+  public void testMatchNoMatch() {
+    ContentType m1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType m2 = ContentType.create("aaa/ccc");
+    ContentType m3 = ContentType.create("foo/me");
+    List<ContentType> toMatchContentTypes = new ArrayList<ContentType>();
+    toMatchContentTypes.add(m1);
+    toMatchContentTypes.add(m2);
+    toMatchContentTypes.add(m3);
+
+    ContentType check = ContentType.create("for/me");
+
+    ContentType match = check.match(toMatchContentTypes);
+
+    assertTrue(match == null);
+  }
+
+  @Test
+  public void testHasMatchSimple() {
+    ContentType m1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType m2 = ContentType.create("aaa/ccc");
+    ContentType m3 = ContentType.create("foo/me");
+    List<ContentType> toMatchContentTypes = new ArrayList<ContentType>();
+    toMatchContentTypes.add(m1);
+    toMatchContentTypes.add(m2);
+    toMatchContentTypes.add(m3);
+
+    ContentType check = ContentType.create("foo/me");
+
+    boolean match = check.hasMatch(toMatchContentTypes);
+    assertTrue(match);
+  }
+
+  @Test
+  public void testHasMatchNoMatch() {
+    ContentType m1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType m2 = ContentType.create("aaa/ccc");
+    ContentType m3 = ContentType.create("foo/me");
+    List<ContentType> toMatchContentTypes = new ArrayList<ContentType>();
+    toMatchContentTypes.add(m1);
+    toMatchContentTypes.add(m2);
+    toMatchContentTypes.add(m3);
+
+    ContentType check = ContentType.create("for/me");
+
+    boolean match = check.hasMatch(toMatchContentTypes);
+    assertFalse(match);
+  }
+
+  @Test
+  public void testMatchCompatibleSimple() {
+    ContentType m1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType m2 = ContentType.create("aaa/ccc");
+    ContentType m3 = ContentType.create("foo/me");
+    List<ContentType> toMatchContentTypes = new ArrayList<ContentType>();
+    toMatchContentTypes.add(m1);
+    toMatchContentTypes.add(m2);
+    toMatchContentTypes.add(m3);
+
+    ContentType check = ContentType.create("foo/me");
+
+    ContentType match = check.matchCompatible(toMatchContentTypes);
+
+    assertEquals(ContentType.create("foo/me"), match);
+    assertEquals("foo/me", match.toContentTypeString());
+  }
+
+  @Test
+  public void testMatchCompatibleNoMatch() {
+    ContentType m1 = ContentType.create("aaa/bbb;x=z;a=b");
+    ContentType m2 = ContentType.create("aaa/ccc");
+    ContentType m3 = ContentType.create("foo/me");
+    List<ContentType> toMatchContentTypes = new ArrayList<ContentType>();
+    toMatchContentTypes.add(m1);
+    toMatchContentTypes.add(m2);
+    toMatchContentTypes.add(m3);
+
+    ContentType check = ContentType.create("for/me");
+
+    ContentType match = check.matchCompatible(toMatchContentTypes);
+
+    assertTrue(match == null);
+  }
+
+  @Test
+  public void testIsWildcard() {
+    assertFalse(ContentType.create("aaa/bbb;x=y;a").isWildcard());
+    assertFalse(ContentType.create("aaa/*;x=y;a").isWildcard());
+    assertTrue(ContentType.create("*/*;x=y;a").isWildcard());
+    assertTrue(ContentType.create("*/*").isWildcard());
+  }
+
+  @Test
+  public void testHasWildcard() {
+    assertFalse(ContentType.create("aaa/bbb;x=y;a").hasWildcard());
+    assertTrue(ContentType.create("aaa/*;x=y;a").hasWildcard());
+    assertTrue(ContentType.create("*/*;x=y;a").hasWildcard());
+    assertTrue(ContentType.create("*/*").hasWildcard());
+  }
+
+  private Map<String, String> addParameters(final String... content) {
+    Map<String, String> map = new HashMap<String, String>();
+    for (int i = 0; i < content.length - 1; i += 2) {
+      String key = content[i];
+      String value = content[i + 1];
+      map.put(key, value);
+    }
+    return map;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/DecoderTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/DecoderTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/DecoderTest.java
new file mode 100644
index 0000000..cb06bb7
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/DecoderTest.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class DecoderTest extends BaseTest {
+
+  @Test
+  public void asciiCharacters() {
+    assertNull(Decoder.decode(null));
+
+    String s = "azAZ019";
+    assertEquals(s, Decoder.decode(s));
+
+    s = "\"\\`{}|";
+    assertEquals(s, Decoder.decode(s));
+  }
+
+  @Test
+  public void asciiControl() {
+    assertEquals("\u0000\b\t\n\r", Decoder.decode("%00%08%09%0a%0d"));
+  }
+
+  @Test
+  public void asciiEncoded() {
+    assertEquals("<>%&", Decoder.decode("%3c%3e%25%26"));
+    assertEquals(":/?#[]@", Decoder.decode("%3a%2f%3f%23%5b%5d%40"));
+    assertEquals(" !\"$'()*+,-.", Decoder.decode("%20%21%22%24%27%28%29%2A%2B%2C%2D%2E"));
+  }
+
+  @Test
+  public void unicodeCharacters() {
+    assertEquals("€", Decoder.decode("%E2%82%AC"));
+    assertEquals("\uFDFC", Decoder.decode("%EF%B7%BC"));
+  }
+
+  @Test
+  public void charactersOutsideBmp() {
+    assertEquals(String.valueOf(Character.toChars(0x1F603)), Decoder.decode("%f0%9f%98%83"));
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void wrongCharacter() {
+    Decoder.decode("%20ä");
+  }
+
+  @Test(expected = NumberFormatException.class)
+  public void wrongPercentNumber() {
+    Decoder.decode("%-3");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void wrongPercentPercent() {
+    Decoder.decode("%%a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void unfinishedPercent() {
+    Decoder.decode("%a");
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void nullByte() {
+    Decoder.decode("%\u0000ff");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/EncoderTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/EncoderTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/EncoderTest.java
new file mode 100644
index 0000000..ecd24be
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/commons/EncoderTest.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * 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 static org.junit.Assert.assertEquals;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * Tests for percent-encoding.
+ * @author SAP AG
+ */
+public class EncoderTest extends BaseTest {
+
+  private final static String RFC3986_UNRESERVED = "-._~"; // + ALPHA + DIGIT
+  private final static String RFC3986_GEN_DELIMS = ":/?#[]@";
+  private final static String RFC3986_SUB_DELIMS = "!$&'()*+,;=";
+  private final static String RFC3986_RESERVED = RFC3986_GEN_DELIMS + RFC3986_SUB_DELIMS;
+
+  @Test
+  public void asciiCharacters() {
+    final String s = "azAZ019";
+    assertEquals(s, Encoder.encode(s));
+    assertEquals(s, Encoder.encode(s));
+  }
+
+  @Test
+  public void asciiControl() {
+    assertEquals("%08%09%0A%0D", Encoder.encode("\b\t\n\r"));
+  }
+
+  @Test
+  public void unsafe() {
+    assertEquals("%3C%3E%25%26", Encoder.encode("<>%&"));
+    assertEquals("%22%5C%60%7B%7D%7C", Encoder.encode("\"\\`{}|"));
+  }
+
+  @Test
+  public void rfc3986Unreserved() {
+    assertEquals(RFC3986_UNRESERVED, Encoder.encode(RFC3986_UNRESERVED));
+  }
+
+  @Test
+  public void rfc3986GenDelims() {
+    assertEquals("%3A%2F%3F%23%5B%5D%40", Encoder.encode(RFC3986_GEN_DELIMS));
+  }
+
+  @Test
+  public void rfc3986SubDelims() {
+    assertEquals("%21%24%26'%28%29%2A%2B%2C%3B%3D", Encoder.encode(RFC3986_SUB_DELIMS));
+  }
+
+  @Test
+  public void rfc3986Reserved() {
+    assertEquals("%3A%2F%3F%23%5B%5D%40%21%24%26'%28%29%2A%2B%2C%3B%3D", Encoder.encode(RFC3986_RESERVED));
+  }
+
+  @Test
+  public void unicodeCharacters() {
+    assertEquals("%E2%82%AC", Encoder.encode("€"));
+    assertEquals("%EF%B7%BC", Encoder.encode("\uFDFC")); // RIAL SIGN
+  }
+
+  @Test
+  public void charactersOutsideBmp() {
+    // Unicode characters outside the Basic Multilingual Plane are stored
+    // in a Java String in two surrogate characters.
+    final String s = String.valueOf(Character.toChars(0x1F603));
+    assertEquals("%F0%9F%98%83", Encoder.encode(s));
+  }
+
+  @Test
+  public void uriDecoding() throws URISyntaxException {
+    final String decodedValue = RFC3986_UNRESERVED + RFC3986_RESERVED + "0..1..a..z..A..Z..@"
+        + "\u2323\uFDFC" + String.valueOf(Character.toChars(0x1F603));
+
+    final String encodedPath = Encoder.encode(decodedValue) + "/" + Encoder.encode(decodedValue);
+    final String encodedQuery = Encoder.encode(decodedValue);
+    final URI uri = new URI("http://host:80/" + encodedPath + "?" + encodedQuery + "=" + encodedQuery);
+
+    assertEquals(uri.getPath(), "/" + decodedValue + "/" + decodedValue);
+    assertEquals(uri.getQuery(), decodedValue + "=" + decodedValue);
+
+    assertEquals(uri.getRawPath(), "/" + encodedPath);
+    assertEquals(uri.getRawQuery(), encodedQuery + "=" + encodedQuery);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
new file mode 100644
index 0000000..c434675
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/DebugInfoBodyTest.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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.debug;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
+import org.apache.commons.codec.binary.Base64;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoBodyTest {
+
+  private static final String STRING_CONTENT = "StringContent";
+  private static final String STRING_CONTENT_JSON = "\"" + STRING_CONTENT + "\"";
+
+  @Test
+  public void jsonStringContent() throws Exception {
+    ODataResponse response = mock(ODataResponse.class);
+    when(response.getEntity()).thenReturn(STRING_CONTENT);
+    when(response.getContentHeader()).thenReturn(HttpContentType.APPLICATION_OCTET_STREAM);
+    assertEquals(STRING_CONTENT_JSON, appendJson(response));
+
+    when(response.getContentHeader()).thenReturn("image/png");
+    assertEquals(STRING_CONTENT_JSON, appendJson(response));
+  }
+
+  @Test
+  public void jsonInputStreamContent() throws Exception {
+    ODataResponse response = mock(ODataResponse.class);
+    ByteArrayInputStream in = new ByteArrayInputStream(STRING_CONTENT.getBytes());
+    when(response.getEntity()).thenReturn(in);
+    when(response.getContentHeader()).thenReturn(HttpContentType.APPLICATION_OCTET_STREAM);
+    assertEquals(STRING_CONTENT_JSON, appendJson(response));
+
+    in = new ByteArrayInputStream(STRING_CONTENT.getBytes());
+    when(response.getEntity()).thenReturn(in);
+    when(response.getContentHeader()).thenReturn("image/png");
+    assertEquals("\"" + Base64.encodeBase64String(STRING_CONTENT.getBytes()) + "\"",
+        appendJson(response));
+  }
+
+  @Test(expected = ClassCastException.class)
+  public void jsonUnsupportedContent() throws Exception {
+    ODataResponse response = mock(ODataResponse.class);
+    when(response.getEntity()).thenReturn(new Object());
+    when(response.getContentHeader()).thenReturn(HttpContentType.APPLICATION_OCTET_STREAM);
+
+    appendJson(response);
+  }
+
+  private String appendJson(final ODataResponse response) throws IOException {
+    Writer writer = new StringWriter();
+    DebugInfoBody body = new DebugInfoBody(response);
+    body.appendJson(new JsonStreamWriter(writer));
+    return writer.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapperTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapperTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapperTest.java
new file mode 100644
index 0000000..08b7901
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/debug/ODataDebugResponseWrapperTest.java
@@ -0,0 +1,299 @@
+/*******************************************************************************
+ * 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.debug;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataContext.RuntimeMeasurement;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+
+/**
+ * Tests for the debug information output.
+ * @author SAP AG
+ */
+public class ODataDebugResponseWrapperTest extends BaseTest {
+
+  private static final String EXPECTED = "{"
+      + "\"request\":{\"method\":\"GET\",\"uri\":\"http://test/entity\"},"
+      + "\"response\":{\"status\":{\"code\":200,\"info\":\"OK\"}}}";
+
+  private ODataContext mockContext(final ODataHttpMethod method) throws ODataException {
+    ODataContext context = mock(ODataContext.class);
+    when(context.getHttpMethod()).thenReturn(method.name());
+    PathInfo pathInfo = mock(PathInfo.class);
+    when(pathInfo.getRequestUri()).thenReturn(URI.create("http://test/entity"));
+    when(context.getPathInfo()).thenReturn(pathInfo);
+    when(context.getRuntimeMeasurements()).thenReturn(null);
+    return context;
+  }
+
+  private ODataResponse mockResponse(final HttpStatusCodes status, final String body, final String contentType) {
+    ODataResponse response = mock(ODataResponse.class);
+    when(response.getStatus()).thenReturn(status);
+    when(response.getEntity()).thenReturn(body);
+    if (contentType != null) {
+      when(response.getHeaderNames()).thenReturn(new HashSet<String>(Arrays.asList(HttpHeaders.CONTENT_TYPE)));
+      when(response.getHeader(HttpHeaders.CONTENT_TYPE)).thenReturn(contentType);
+      when(response.getContentHeader()).thenReturn(contentType);
+    }
+    return response;
+  }
+
+  private RuntimeMeasurement mockRuntimeMeasurement(final String method, final long startTime, final long stopTime, final long startMemory, final long stopMemory) {
+    RuntimeMeasurement measurement = mock(RuntimeMeasurement.class);
+    when(measurement.getClassName()).thenReturn("class");
+    when(measurement.getMethodName()).thenReturn(method);
+    when(measurement.getTimeStarted()).thenReturn(startTime);
+    when(measurement.getTimeStopped()).thenReturn(stopTime);
+    when(measurement.getMemoryStarted()).thenReturn(startMemory);
+    when(measurement.getMemoryStopped()).thenReturn(stopMemory);
+    return measurement;
+  }
+
+  private RuntimeMeasurement mockRuntimeMeasurement(final String method, final long start, final long stop) {
+    return mockRuntimeMeasurement(method, start, stop, 1000, 4000);
+  }
+
+  @Test
+  public void minimal() throws Exception {
+    final ODataContext context = mockContext(ODataHttpMethod.PUT);
+    final ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.NO_CONTENT, null, null);
+
+    final ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String actualJson = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace(ODataHttpMethod.GET.name(), ODataHttpMethod.PUT.name())
+        .replace(Integer.toString(HttpStatusCodes.OK.getStatusCode()), Integer.toString(HttpStatusCodes.NO_CONTENT.getStatusCode()))
+        .replace(HttpStatusCodes.OK.getInfo(), HttpStatusCodes.NO_CONTENT.getInfo()),
+        actualJson);
+  }
+
+  @Test
+  public void body() throws Exception {
+    final ODataContext context = mockContext(ODataHttpMethod.GET);
+    ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.OK, "\"test\"", HttpContentType.APPLICATION_JSON);
+
+    ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("{\"request", "{\"body\":\"test\",\"request")
+        .replace("}}}", "},\"headers\":{\"" + HttpHeaders.CONTENT_TYPE + "\":\"" + HttpContentType.APPLICATION_JSON + "\"}}}"),
+        entity);
+
+    wrappedResponse = mockResponse(HttpStatusCodes.OK, "test", HttpContentType.TEXT_PLAIN);
+    response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("{\"request", "{\"body\":\"test\",\"request")
+        .replace("}}}", "},\"headers\":{\"" + HttpHeaders.CONTENT_TYPE + "\":\"" + HttpContentType.TEXT_PLAIN + "\"}}}"),
+        entity);
+
+    wrappedResponse = mockResponse(HttpStatusCodes.OK, null, "image/png");
+    when(wrappedResponse.getEntity()).thenReturn(new ByteArrayInputStream("test".getBytes()));
+    response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("{\"request", "{\"body\":\"dGVzdA==\",\"request")
+        .replace("}}}", "},\"headers\":{\"" + HttpHeaders.CONTENT_TYPE + "\":\"image/png\"}}}"),
+        entity);
+  }
+
+  @Test
+  public void headers() throws Exception {
+    ODataContext context = mockContext(ODataHttpMethod.GET);
+    Map<String, List<String>> headers = new HashMap<String, List<String>>();
+    headers.put(HttpHeaders.CONTENT_TYPE, Arrays.asList(HttpContentType.APPLICATION_JSON));
+    when(context.getRequestHeaders()).thenReturn(headers);
+
+    final ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.OK, null, HttpContentType.APPLICATION_JSON);
+
+    final ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("},\"response", ",\"headers\":{\"" + HttpHeaders.CONTENT_TYPE + "\":\"" + HttpContentType.APPLICATION_JSON + "\"}},\"response")
+        .replace("}}}", "},\"headers\":{\"" + HttpHeaders.CONTENT_TYPE + "\":\"" + HttpContentType.APPLICATION_JSON + "\"}}}"),
+        entity);
+  }
+
+  @Test
+  public void uri() throws Exception {
+    final ODataContext context = mockContext(ODataHttpMethod.GET);
+    final ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.OK, null, null);
+
+    UriInfo uriInfo = mock(UriInfo.class);
+    final FilterExpression filter = UriParser.parseFilter(null, null, "true");
+    when(uriInfo.getFilter()).thenReturn(filter);
+    final OrderByExpression orderBy = UriParser.parseOrderBy(null, null, "true");
+    when(uriInfo.getOrderBy()).thenReturn(orderBy);
+    List<ArrayList<NavigationPropertySegment>> expand = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    NavigationPropertySegment segment = mock(NavigationPropertySegment.class);
+    EdmNavigationProperty navigationProperty = mock(EdmNavigationProperty.class);
+    when(navigationProperty.getName()).thenReturn("nav");
+    when(segment.getNavigationProperty()).thenReturn(navigationProperty);
+    ArrayList<NavigationPropertySegment> segments = new ArrayList<NavigationPropertySegment>();
+    segments.add(segment);
+    expand.add(segments);
+    when(uriInfo.getExpand()).thenReturn(expand);
+    SelectItem select1 = mock(SelectItem.class);
+    SelectItem select2 = mock(SelectItem.class);
+    EdmProperty property = mock(EdmProperty.class);
+    when(property.getName()).thenReturn("property");
+    when(select1.getProperty()).thenReturn(property);
+    when(select2.getProperty()).thenReturn(property);
+    when(select2.getNavigationPropertySegments()).thenReturn(segments);
+    when(uriInfo.getSelect()).thenReturn(Arrays.asList(select1, select2));
+
+    final ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, uriInfo, null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("}}}",
+        "}},\"uri\":{\"filter\":{\"nodeType\":\"LITERAL\",\"type\":\"Edm.Boolean\",\"value\":\"true\"},"
+            + "\"orderby\":{\"nodeType\":\"order collection\","
+            + "\"orders\":[{\"nodeType\":\"ORDER\",\"sortorder\":\"asc\","
+            + "\"expression\":{\"nodeType\":\"LITERAL\",\"type\":\"Edm.Boolean\",\"value\":\"true\"}}]},"
+            + "\"expand/select\":{\"all\":false,\"properties\":[\"property\"],"
+            + "\"links\":[{\"nav\":{\"all\":false,\"properties\":[\"property\"],\"links\":[]}}]}}}"),
+        entity);
+  }
+
+  @Test
+  public void uriWithException() throws Exception {
+    final ODataContext context = mockContext(ODataHttpMethod.GET);
+    final ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.OK, null, null);
+
+    UriInfo uriInfo = mock(UriInfo.class);
+    FilterExpression filter = mock(FilterExpression.class);
+    when(filter.getExpressionString()).thenReturn("wrong");
+    when(uriInfo.getFilter()).thenReturn(filter);
+    ExpressionParserException exception = mock(ExpressionParserException.class);
+    when(exception.getMessageReference()).thenReturn(ExpressionParserException.COMMON_ERROR);
+    when(exception.getStackTrace()).thenReturn(new StackTraceElement[] {
+        new StackTraceElement("class", "method", "file", 42) });
+    CommonExpression filterTree = mock(CommonExpression.class);
+    when(filterTree.getUriLiteral()).thenReturn("wrong");
+    when(exception.getFilterTree()).thenReturn(filterTree);
+
+    final ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, uriInfo, exception, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("}}}",
+        "}},\"uri\":{\"error\":{\"filter\":\"wrong\"},\"filter\":null},"
+            + "\"stacktrace\":{\"exceptions\":[{\"class\":\"" + exception.getClass().getName() + "\","
+            + "\"message\":\"Error while parsing a ODATA expression.\","
+            + "\"invocation\":{\"class\":\"class\",\"method\":\"method\",\"line\":42}}],"
+            + "\"stacktrace\":[{\"class\":\"class\",\"method\":\"method\",\"line\":42}]}}"),
+        entity);
+  }
+
+  @Test
+  public void runtime() throws Exception {
+    ODataContext context = mockContext(ODataHttpMethod.GET);
+    List<RuntimeMeasurement> runtimeMeasurements = new ArrayList<RuntimeMeasurement>();
+    runtimeMeasurements.add(mockRuntimeMeasurement("method", 1000, 42000));
+    runtimeMeasurements.add(mockRuntimeMeasurement("inner", 2000, 5000));
+    runtimeMeasurements.add(mockRuntimeMeasurement("inner", 7000, 12000));
+    runtimeMeasurements.add(mockRuntimeMeasurement("inner", 13000, 16000));
+    runtimeMeasurements.add(mockRuntimeMeasurement("inner2", 14000, 15000));
+    runtimeMeasurements.add(mockRuntimeMeasurement("child", 17000, 21000));
+    runtimeMeasurements.add(mockRuntimeMeasurement("second", 45000, 99000));
+    when(context.getRuntimeMeasurements()).thenReturn(runtimeMeasurements);
+
+    final ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.OK, null, null);
+
+    ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), null, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED.replace("}}}",
+        "}},\"runtime\":[{\"class\":\"class\",\"method\":\"method\",\"duration\":41,\"memory\":3,"
+            + "\"children\":[{\"class\":\"class\",\"method\":\"inner\",\"duration\":8,\"memory\":6,\"children\":[]},"
+            + "{\"class\":\"class\",\"method\":\"inner\",\"duration\":3,\"memory\":3,\"children\":["
+            + "{\"class\":\"class\",\"method\":\"inner2\",\"duration\":1,\"memory\":3,\"children\":[]}]},"
+            + "{\"class\":\"class\",\"method\":\"child\",\"duration\":4,\"memory\":3,\"children\":[]}]},"
+            + "{\"class\":\"class\",\"method\":\"second\",\"duration\":54,\"memory\":3,\"children\":[]}]}"),
+        entity);
+  }
+
+  @Test
+  public void exception() throws Exception {
+    final ODataContext context = mockContext(ODataHttpMethod.GET);
+    final ODataResponse wrappedResponse = mockResponse(HttpStatusCodes.BAD_REQUEST, null, null);
+
+    ODataMessageException exception = mock(ODataMessageException.class);
+    when(exception.getMessageReference()).thenReturn(ODataMessageException.COMMON);
+    RuntimeException innerException = mock(RuntimeException.class);
+    when(innerException.getLocalizedMessage()).thenReturn("error");
+    final StackTraceElement[] stackTrace = new StackTraceElement[] {
+        new StackTraceElement("innerClass", "innerMethod", "innerFile", 99),
+        new StackTraceElement("class", "method", "file", 42),
+        new StackTraceElement("outerClass", "outerMethod", "outerFile", 11) };
+    when(innerException.getStackTrace()).thenReturn(stackTrace);
+    when(exception.getCause()).thenReturn(innerException);
+    when(exception.getStackTrace()).thenReturn(Arrays.copyOfRange(stackTrace, 1, 3));
+
+    final ODataResponse response = new ODataDebugResponseWrapper(context, wrappedResponse, mock(UriInfo.class), exception, ODataDebugResponseWrapper.ODATA_DEBUG_JSON)
+        .wrapResponse();
+    String entity = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(EXPECTED
+        .replace(Integer.toString(HttpStatusCodes.OK.getStatusCode()), Integer.toString(HttpStatusCodes.BAD_REQUEST.getStatusCode()))
+        .replace(HttpStatusCodes.OK.getInfo(), HttpStatusCodes.BAD_REQUEST.getInfo())
+        .replace("}}}", "}},"
+            + "\"stacktrace\":{\"exceptions\":[{\"class\":\"" + exception.getClass().getName() + "\","
+            + "\"message\":\"Common exception\","
+            + "\"invocation\":{\"class\":\"class\",\"method\":\"method\",\"line\":42}},"
+            + "{\"class\":\"" + innerException.getClass().getName() + "\",\"message\":\"error\","
+            + "\"invocation\":{\"class\":\"innerClass\",\"method\":\"innerMethod\",\"line\":99}}],"
+            + "\"stacktrace\":[{\"class\":\"class\",\"method\":\"method\",\"line\":42},"
+            + "{\"class\":\"outerClass\",\"method\":\"outerMethod\",\"line\":11}]}}"),
+        entity);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmImplTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmImplTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmImplTest.java
new file mode 100644
index 0000000..524cc4f
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmImplTest.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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.edm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmImplTest extends BaseTest {
+
+  private ForEdmImplTest edm;
+
+  @Before
+  public void getEdmImpl() throws EdmException {
+    edm = new ForEdmImplTest();
+  }
+
+  @Test
+  public void testEntityContainerCache() throws EdmException {
+    assertEquals(edm.getEntityContainer("foo"), edm.getEntityContainer("foo"));
+    assertNotSame(edm.getEntityContainer("foo"), edm.getEntityContainer("bar"));
+    assertEquals(edm.getDefaultEntityContainer(), edm.getEntityContainer(null));
+    assertNotSame(edm.getDefaultEntityContainer(), edm.getEntityContainer(""));
+  }
+
+  @Test
+  public void testEntityTypeCache() throws EdmException {
+    assertEquals(edm.getEntityType("foo", "bar"), edm.getEntityType("foo", "bar"));
+    assertNotSame(edm.getEntityType("foo", "bar"), edm.getEntityType("bar", "foo"));
+  }
+
+  @Test
+  public void testComplexTypeCache() throws EdmException {
+    assertEquals(edm.getComplexType("foo", "bar"), edm.getComplexType("foo", "bar"));
+    assertNotSame(edm.getComplexType("foo", "bar"), edm.getComplexType("bar", "foo"));
+  }
+
+  @Test
+  public void testAssociationCache() throws EdmException {
+    assertEquals(edm.getAssociation("foo", "bar"), edm.getAssociation("foo", "bar"));
+    assertNotSame(edm.getAssociation("foo", "bar"), edm.getAssociation("bar", "foo"));
+  }
+
+  private class ForEdmImplTest extends EdmImpl {
+
+    public ForEdmImplTest() {
+      super(null);
+    }
+
+    @Override
+    protected EdmEntityContainer createEntityContainer(final String name) throws ODataException {
+      EdmEntityContainer edmEntityContainer = mock(EdmEntityContainer.class);
+      when(edmEntityContainer.getName()).thenReturn(name);
+      return edmEntityContainer;
+    }
+
+    @Override
+    protected EdmEntityType createEntityType(final FullQualifiedName fqName) throws ODataException {
+      EdmEntityType edmEntityType = mock(EdmEntityType.class);
+      when(edmEntityType.getNamespace()).thenReturn(fqName.getNamespace());
+      when(edmEntityType.getName()).thenReturn(fqName.getName());
+      return edmEntityType;
+    }
+
+    @Override
+    protected EdmComplexType createComplexType(final FullQualifiedName fqName) throws ODataException {
+      EdmComplexType edmComplexType = mock(EdmComplexType.class);
+      when(edmComplexType.getNamespace()).thenReturn(fqName.getNamespace());
+      when(edmComplexType.getName()).thenReturn(fqName.getName());
+      return edmComplexType;
+    }
+
+    @Override
+    protected EdmAssociation createAssociation(final FullQualifiedName fqName) throws ODataException {
+      EdmAssociation edmAssociation = mock(EdmAssociation.class);
+      when(edmAssociation.getNamespace()).thenReturn(fqName.getNamespace());
+      when(edmAssociation.getName()).thenReturn(fqName.getName());
+      return edmAssociation;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeTest.java
new file mode 100644
index 0000000..d584b15
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeTest.java
@@ -0,0 +1,389 @@
+/*******************************************************************************
+ * 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.edm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.uri.UriSyntaxException;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * Tests for the parsing of URI literals
+ * @author SAP AG
+ */
+public class EdmSimpleTypeFacadeTest extends BaseTest {
+
+  public static void parse(final String literal, final EdmSimpleType expectedType) throws EdmLiteralException {
+    final EdmLiteral uriLiteral = EdmSimpleTypeKind.parseUriLiteral(literal);
+    assertNotNull(uriLiteral);
+    if (!expectedType.equals(EdmNull.getInstance())) {
+      assertNotNull(uriLiteral.getLiteral());
+      assertTrue(uriLiteral.getLiteral().length() > 0);
+    }
+    assertNotNull(uriLiteral.getType());
+    assertEquals(expectedType, uriLiteral.getType());
+  }
+
+  public static void compare(final EdmSimpleTypeKind simpleType) {
+    final EdmSimpleType bin1 = simpleType.getEdmSimpleTypeInstance();
+    assertNotNull(bin1);
+
+    final EdmSimpleType bin2 = simpleType.getEdmSimpleTypeInstance();
+    assertNotNull(bin2);
+
+    assertEquals(bin1, bin2);
+  }
+
+  @Test
+  public void parseUriLiteralBinary() throws EdmLiteralException {
+    parse("X'Fa12aAA1'", EdmBinary.getInstance());
+    parse("binary'FA12AAA1'", EdmBinary.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralBoolean() throws EdmLiteralException {
+    parse("true", EdmBoolean.getInstance());
+    parse("false", EdmBoolean.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralBit() throws EdmLiteralException {
+    parse("1", Bit.getInstance());
+    parse("0", Bit.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralByte() throws EdmLiteralException {
+    parse("255", EdmByte.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralUint7() throws EdmLiteralException {
+    parse("123", Uint7.getInstance());
+    parse("111", Uint7.getInstance());
+    parse("42", Uint7.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralDateTime() throws EdmLiteralException {
+    parse("datetime'2009-12-26T21:23:38'", EdmDateTime.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralDateTimeOffset() throws EdmLiteralException {
+    parse("datetimeoffset'2009-12-26T21:23:38Z'", EdmDateTimeOffset.getInstance());
+    parse("datetimeoffset'2002-10-10T12:00:00-05:00'", EdmDateTimeOffset.getInstance());
+    parse("datetimeoffset'2009-12-26T21:23:38'", EdmDateTimeOffset.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralDecimal() throws EdmLiteralException {
+    parse("4.5m", EdmDecimal.getInstance());
+    parse("4.5M", EdmDecimal.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralDouble() throws EdmLiteralException {
+    parse("4.5d", EdmDouble.getInstance());
+    parse("4.5D", EdmDouble.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralGuid() throws EdmLiteralException {
+    parse("guid'1225c695-cfb8-4ebb-aaaa-80da344efa6a'", EdmGuid.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralInt16() throws EdmLiteralException {
+    parse("-32768", EdmInt16.getInstance());
+    parse("3276", EdmInt16.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralInt32() throws EdmLiteralException {
+    parse("-327687", EdmInt32.getInstance());
+    parse("32768", EdmInt32.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralInt64() throws EdmLiteralException {
+    parse("64l", EdmInt64.getInstance());
+    parse("64L", EdmInt64.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralNull() throws EdmLiteralException {
+    parse(null, EdmNull.getInstance());
+    parse("null", EdmNull.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralSByte() throws EdmLiteralException {
+    parse("-123", EdmSByte.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralSingle() throws EdmLiteralException {
+    parse("4.5f", EdmSingle.getInstance());
+    parse("4.5F", EdmSingle.getInstance());
+    parse("-INF", EdmSingle.getInstance());
+    parse("INF", EdmSingle.getInstance());
+    parse("NaN", EdmSingle.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralString() throws EdmLiteralException {
+    parse("'abc'", EdmString.getInstance());
+  }
+
+  @Test
+  public void parseUriLiteralTime() throws EdmLiteralException {
+    parse("time'PT120S'", EdmTime.getInstance());
+  }
+
+  @Test
+  public void compareTypes() {
+    compare(EdmSimpleTypeKind.Binary);
+    compare(EdmSimpleTypeKind.Boolean);
+    compare(EdmSimpleTypeKind.Byte);
+    compare(EdmSimpleTypeKind.SByte);
+    compare(EdmSimpleTypeKind.DateTime);
+    compare(EdmSimpleTypeKind.DateTimeOffset);
+    compare(EdmSimpleTypeKind.Decimal);
+    compare(EdmSimpleTypeKind.Double);
+    compare(EdmSimpleTypeKind.Guid);
+    compare(EdmSimpleTypeKind.Int16);
+    compare(EdmSimpleTypeKind.Int32);
+    compare(EdmSimpleTypeKind.Int64);
+    compare(EdmSimpleTypeKind.Single);
+    compare(EdmSimpleTypeKind.Time);
+  }
+
+  /**
+   * Parse a URI literal value string and assert that it is compatible
+   * to the given EDM simple type and has the correct parsed value.
+   * 
+   * @param literal
+   *          the URI literal value to be parsed as string
+   * @param typeKind
+   *          the {@link EdmSimpleTypeKind} the URI literal should be compatible to
+   * @param expectedLiteral
+   *          the expected literal value
+   * @throws UriSyntaxException 
+   * @throws EdmException
+   */
+  private void parseLiteral(final String literal, final EdmSimpleTypeKind typeKind, final String expectedLiteral) throws UriSyntaxException, EdmException {
+    final EdmLiteral uriLiteral = EdmSimpleTypeKind.parseUriLiteral(literal);
+
+    assertTrue(typeKind.getEdmSimpleTypeInstance().isCompatible(uriLiteral.getType()));
+    assertEquals(expectedLiteral, uriLiteral.getLiteral());
+  }
+
+  @Test
+  public void parseDecimal() throws Exception {
+    parseLiteral("4.5m", EdmSimpleTypeKind.Decimal, "4.5");
+    parseLiteral("4.5M", EdmSimpleTypeKind.Decimal, "4.5");
+    parseLiteral("1", EdmSimpleTypeKind.Decimal, "1");
+    parseLiteral("255", EdmSimpleTypeKind.Decimal, "255");
+    parseLiteral("-32768", EdmSimpleTypeKind.Decimal, "-32768");
+    parseLiteral("32768", EdmSimpleTypeKind.Decimal, "32768");
+    parseLiteral("3000000", EdmSimpleTypeKind.Decimal, "3000000");
+    parseLiteral("4.5d", EdmSimpleTypeKind.Decimal, "4.5");
+    parseLiteral("4.2E9F", EdmSimpleTypeKind.Decimal, "4.2E9");
+    parseLiteral("1234567890", EdmSimpleTypeKind.Decimal, "1234567890");
+  }
+
+  @Test
+  public void parseInt16() throws Exception {
+    parseLiteral("16", EdmSimpleTypeKind.Int16, "16");
+    parseLiteral("-16", EdmSimpleTypeKind.Int16, "-16");
+    parseLiteral("255", EdmSimpleTypeKind.Int16, "255");
+    parseLiteral("-32768", EdmSimpleTypeKind.Int16, "-32768");
+
+  }
+
+  @Test
+  public void parseInt32() throws Exception {
+    parseLiteral("32", EdmSimpleTypeKind.Int32, "32");
+    parseLiteral("-127", EdmSimpleTypeKind.Int32, "-127");
+    parseLiteral("255", EdmSimpleTypeKind.Int32, "255");
+    parseLiteral("32767", EdmSimpleTypeKind.Int32, "32767");
+    parseLiteral("-32769", EdmSimpleTypeKind.Int32, "-32769");
+  }
+
+  @Test
+  public void parseInt64() throws Exception {
+    parseLiteral("64", EdmSimpleTypeKind.Int64, "64");
+    parseLiteral("255", EdmSimpleTypeKind.Int64, "255");
+    parseLiteral("1000", EdmSimpleTypeKind.Int64, "1000");
+    parseLiteral("100000", EdmSimpleTypeKind.Int64, "100000");
+    parseLiteral("-64L", EdmSimpleTypeKind.Int64, "-64");
+    parseLiteral("" + Long.MAX_VALUE + "L", EdmSimpleTypeKind.Int64, "" + Long.MAX_VALUE);
+    parseLiteral("" + Long.MIN_VALUE + "l", EdmSimpleTypeKind.Int64, "" + Long.MIN_VALUE);
+  }
+
+  @Test
+  public void parseString() throws Exception {
+    parseLiteral("'abc'", EdmSimpleTypeKind.String, "abc");
+    parseLiteral("'true'", EdmSimpleTypeKind.String, "true");
+    parseLiteral("''", EdmSimpleTypeKind.String, "");
+  }
+
+  @Test
+  public void parseSingle() throws Exception {
+    parseLiteral("45", EdmSimpleTypeKind.Single, "45");
+    parseLiteral("255", EdmSimpleTypeKind.Single, "255");
+    parseLiteral("-32768", EdmSimpleTypeKind.Single, "-32768");
+    parseLiteral("32768", EdmSimpleTypeKind.Single, "32768");
+    parseLiteral("1L", EdmSimpleTypeKind.Single, "1");
+    parseLiteral("4.5f", EdmSimpleTypeKind.Single, "4.5");
+    parseLiteral("4.5F", EdmSimpleTypeKind.Single, "4.5");
+    parseLiteral("4.5e9f", EdmSimpleTypeKind.Single, "4.5e9");
+    parseLiteral("-INF", EdmSimpleTypeKind.Single, "-INF");
+    parseLiteral("INF", EdmSimpleTypeKind.Single, "INF");
+    parseLiteral("NaN", EdmSimpleTypeKind.Single, "NaN");
+  }
+
+  @Test
+  public void parseDouble() throws Exception {
+    parseLiteral("45", EdmSimpleTypeKind.Double, "45");
+    parseLiteral("255", EdmSimpleTypeKind.Double, "255");
+    parseLiteral("-32768", EdmSimpleTypeKind.Double, "-32768");
+    parseLiteral("32768", EdmSimpleTypeKind.Double, "32768");
+    parseLiteral("1l", EdmSimpleTypeKind.Double, "1");
+    parseLiteral("4.5d", EdmSimpleTypeKind.Double, "4.5");
+    parseLiteral("4.5D", EdmSimpleTypeKind.Double, "4.5");
+    parseLiteral("4.5e21f", EdmSimpleTypeKind.Double, "4.5e21");
+  }
+
+  @Test
+  public void parseByte() throws Exception {
+    parseLiteral("255", EdmSimpleTypeKind.Byte, "255");
+    parseLiteral("123", EdmSimpleTypeKind.Byte, "123");
+  }
+
+  @Test
+  public void parseGuid() throws Exception {
+    parseLiteral("guid'1225c695-cfb8-4ebb-aaaa-80da344efa6a'", EdmSimpleTypeKind.Guid, "1225c695-cfb8-4ebb-aaaa-80da344efa6a");
+  }
+
+  @Test
+  public void parseTime() throws Exception {
+    parseLiteral("time'PT120S'", EdmSimpleTypeKind.Time, "PT120S");
+  }
+
+  @Test
+  public void parseDatetime() throws Exception {
+    parseLiteral("datetime'2009-12-26T21:23:38'", EdmSimpleTypeKind.DateTime, "2009-12-26T21:23:38");
+  }
+
+  @Test
+  public void parseDatetimeOffset() throws Exception {
+    parseLiteral("datetimeoffset'2009-12-26T21:23:38Z'", EdmSimpleTypeKind.DateTimeOffset, "2009-12-26T21:23:38Z");
+    parseLiteral("datetimeoffset'2002-10-10T12:00:00-05:00'", EdmSimpleTypeKind.DateTimeOffset, "2002-10-10T12:00:00-05:00");
+    parseLiteral("datetimeoffset'2009-12-26T21:23:38'", EdmSimpleTypeKind.DateTimeOffset, "2009-12-26T21:23:38");
+  }
+
+  @Test
+  public void parseBoolean() throws Exception {
+    parseLiteral("true", EdmSimpleTypeKind.Boolean, "true");
+    parseLiteral("false", EdmSimpleTypeKind.Boolean, "false");
+    parseLiteral("1", EdmSimpleTypeKind.Boolean, "1");
+    parseLiteral("0", EdmSimpleTypeKind.Boolean, "0");
+  }
+
+  @Test
+  public void parseSByte() throws Exception {
+    parseLiteral("-123", EdmSimpleTypeKind.SByte, "-123");
+    parseLiteral("12", EdmSimpleTypeKind.SByte, "12");
+  }
+
+  @Test
+  public void parseBinary() throws Exception {
+    parseLiteral("X'Fa12aAA1'", EdmSimpleTypeKind.Binary, "+hKqoQ==");
+    parseLiteral("binary'FA12AAA1'", EdmSimpleTypeKind.Binary, "+hKqoQ==");
+  }
+
+  private void parseWrongLiteralContent(final String literal, final MessageReference messageReference) {
+    try {
+      EdmSimpleTypeKind.parseUriLiteral(literal);
+      fail("Expected EdmLiteralException not thrown");
+    } catch (EdmLiteralException e) {
+      assertNotNull(e);
+      assertEquals(messageReference.getKey(), e.getMessageReference().getKey());
+    }
+  }
+
+  @Test
+  public void parseLiteralWithWrongContent() throws Exception {
+    parseWrongLiteralContent("binary'abcde'", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("'", EdmLiteralException.UNKNOWNLITERAL);
+    parseWrongLiteralContent("'a", EdmLiteralException.UNKNOWNLITERAL);
+    parseWrongLiteralContent("wrongprefix'PT1H2M3S'", EdmLiteralException.UNKNOWNLITERAL);
+    parseWrongLiteralContent("32i", EdmLiteralException.UNKNOWNLITERAL);
+    parseWrongLiteralContent("9876543210", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("-9876543210", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("12345678901234567890L", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("12345678901234567890D", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("1234567890F", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("guid'a'", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("datetime'1'", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("datetimeoffset'2'", EdmLiteralException.LITERALFORMAT);
+    parseWrongLiteralContent("time'3'", EdmLiteralException.LITERALFORMAT);
+  }
+
+  private void parseIncompatibleLiteralContent(final String literal, final EdmSimpleTypeKind typeKind) throws EdmLiteralException {
+    final EdmLiteral uriLiteral = EdmSimpleTypeKind.parseUriLiteral(literal);
+    assertFalse(typeKind.getEdmSimpleTypeInstance().isCompatible(uriLiteral.getType()));
+  }
+
+  @Test
+  public void parseIncompatibleLiteral() throws Exception {
+    parseIncompatibleLiteralContent("1D", EdmSimpleTypeKind.Binary);
+    parseIncompatibleLiteralContent("'0'", EdmSimpleTypeKind.Boolean);
+    parseIncompatibleLiteralContent("'1'", EdmSimpleTypeKind.Boolean);
+    parseIncompatibleLiteralContent("2", EdmSimpleTypeKind.Boolean);
+    parseIncompatibleLiteralContent("-1", EdmSimpleTypeKind.Byte);
+    parseIncompatibleLiteralContent("-129", EdmSimpleTypeKind.Byte);
+    parseIncompatibleLiteralContent("time'PT11H12M13S'", EdmSimpleTypeKind.DateTime);
+    parseIncompatibleLiteralContent("time'PT11H12M13S'", EdmSimpleTypeKind.DateTimeOffset);
+    parseIncompatibleLiteralContent("'1'", EdmSimpleTypeKind.Decimal);
+    parseIncompatibleLiteralContent("1M", EdmSimpleTypeKind.Double);
+    parseIncompatibleLiteralContent("1", EdmSimpleTypeKind.Guid);
+    parseIncompatibleLiteralContent("32768", EdmSimpleTypeKind.Int16);
+    parseIncompatibleLiteralContent("1L", EdmSimpleTypeKind.Int32);
+    parseIncompatibleLiteralContent("1M", EdmSimpleTypeKind.Int64);
+    parseIncompatibleLiteralContent("128", EdmSimpleTypeKind.SByte);
+    parseIncompatibleLiteralContent("1D", EdmSimpleTypeKind.Single);
+    parseIncompatibleLiteralContent("1", EdmSimpleTypeKind.String);
+    parseIncompatibleLiteralContent("datetime'2012-10-10T11:12:13'", EdmSimpleTypeKind.Time);
+  }
+}


[15/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomEntryEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomEntryEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomEntryEntityProducer.java
new file mode 100644
index 0000000..1fc2d90
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomEntryEntityProducer.java
@@ -0,0 +1,527 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmTargetPath;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.Encoder;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.NavigationPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Serializes an ATOM entry.
+ * @author SAP AG
+ */
+public class AtomEntryEntityProducer {
+
+  private String etag;
+  private String location;
+  private final EntityProviderWriteProperties properties;
+
+  public AtomEntryEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data, final boolean isRootElement, final boolean isFeedPart) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_ENTRY);
+
+      if (isRootElement) {
+        writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005);
+        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+        writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08);
+      }
+      if (!isFeedPart) {
+        writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, properties.getServiceRoot().toASCIIString());
+      }
+
+      etag = createETag(eia, data);
+      if (etag != null) {
+        writer.writeAttribute(Edm.NAMESPACE_M_2007_08, FormatXml.M_ETAG, etag);
+      }
+
+      // write all atom infos (mandatory and optional)
+      appendAtomMandatoryParts(writer, eia, data);
+      appendAtomOptionalParts(writer, eia, data);
+
+      if (eia.getEntityType().hasStream()) {
+        // write all links
+        appendAtomEditLink(writer, eia, data);
+        appendAtomContentLink(writer, eia, data, properties.getMediaResourceMimeType());
+        appendAtomNavigationLinks(writer, eia, data);
+        // write properties/content
+        appendCustomProperties(writer, eia, data);
+        appendAtomContentPart(writer, eia, data, properties.getMediaResourceMimeType());
+        appendProperties(writer, eia, data);
+      } else {
+        // write all links
+        appendAtomEditLink(writer, eia, data);
+        appendAtomNavigationLinks(writer, eia, data);
+        // write properties/content
+        appendCustomProperties(writer, eia, data);
+        writer.writeStartElement(FormatXml.ATOM_CONTENT);
+        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_XML.toString());
+        appendProperties(writer, eia, data);
+        writer.writeEndElement();
+      }
+
+      writer.writeEndElement();
+
+      writer.flush();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (URISyntaxException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendCustomProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException {
+    List<String> noneSyndicationTargetPaths = eia.getNoneSyndicationTargetPathNames();
+    for (String tpName : noneSyndicationTargetPaths) {
+      EntityPropertyInfo info = eia.getTargetPathInfo(tpName);
+      final String name = info.getName();
+      XmlPropertyEntityProducer aps = new XmlPropertyEntityProducer();
+      aps.appendCustomProperty(writer, name, info, data.get(name));
+    }
+  }
+
+  protected static String createETag(final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException {
+    try {
+      String etag = null;
+
+      Collection<EntityPropertyInfo> propertyInfos = eia.getETagPropertyInfos();
+      for (EntityPropertyInfo propertyInfo : propertyInfos) {
+        EdmType edmType = propertyInfo.getType();
+        if (edmType instanceof EdmSimpleType) {
+          EdmSimpleType edmSimpleType = (EdmSimpleType) edmType;
+          if (etag == null) {
+            etag = edmSimpleType.valueToString(data.get(propertyInfo.getName()), EdmLiteralKind.DEFAULT, propertyInfo.getFacets());
+          } else {
+            etag = etag + Edm.DELIMITER + edmSimpleType.valueToString(data.get(propertyInfo.getName()), EdmLiteralKind.DEFAULT, propertyInfo.getFacets());
+          }
+        }
+      }
+
+      if (etag != null) {
+        etag = "W/\"" + etag + "\"";
+      }
+
+      return etag;
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomNavigationLinks(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException, EdmException, URISyntaxException {
+    for (String name : eia.getSelectedNavigationPropertyNames()) {
+      NavigationPropertyInfo info = eia.getNavigationPropertyInfo(name);
+      boolean isFeed = (info.getMultiplicity() == EdmMultiplicity.MANY);
+      String self = createSelfLink(eia, data, info.getName());
+      appendAtomNavigationLink(writer, self, info.getName(), isFeed, eia, data);
+    }
+  }
+
+  private void appendAtomNavigationLink(final XMLStreamWriter writer, final String self, final String navigationPropertyName, final boolean isFeed, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException, EdmException, URISyntaxException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, self);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.NAMESPACE_REL_2007_08 + navigationPropertyName);
+      writer.writeAttribute(FormatXml.ATOM_TITLE, navigationPropertyName);
+      if (isFeed) {
+        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_FEED.toString());
+        appendInlineFeed(writer, navigationPropertyName, eia, data, self);
+      } else {
+        writer.writeAttribute(FormatXml.ATOM_TYPE, ContentType.APPLICATION_ATOM_XML_ENTRY.toString());
+        appendInlineEntry(writer, navigationPropertyName, eia, data);
+      }
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendInlineFeed(final XMLStreamWriter writer, final String navigationPropertyName, final EntityInfoAggregator eia, final Map<String, Object> data, final String self) throws EntityProviderException, XMLStreamException, EdmException, URISyntaxException {
+
+    if (eia.getExpandedNavigationPropertyNames().contains(navigationPropertyName)) {
+      if (properties.getCallbacks() != null && properties.getCallbacks().containsKey(navigationPropertyName)) {
+        writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+
+        EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+        WriteFeedCallbackContext context = new WriteFeedCallbackContext();
+        context.setSourceEntitySet(eia.getEntitySet());
+        context.setNavigationProperty(navProp);
+        context.setEntryData(data);
+        ExpandSelectTreeNode subNode = properties.getExpandSelectTree().getLinks().get(navigationPropertyName);
+        context.setCurrentExpandSelectTreeNode(subNode);
+        context.setSelfLink(new URI(self));
+
+        ODataCallback callback = properties.getCallbacks().get(navigationPropertyName);
+        if (callback == null) {
+          throw new EntityProviderException(EntityProviderException.EXPANDNOTSUPPORTED);
+        }
+        WriteFeedCallbackResult result = null;
+        try {
+          result = ((OnWriteFeedContent) callback).retrieveFeedResult(context);
+        } catch (ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.COMMON, e);
+        }
+        List<Map<String, Object>> inlineData = result.getFeedData();
+        if (inlineData == null) {
+          inlineData = new ArrayList<Map<String, Object>>();
+        }
+
+        EntityProviderWriteProperties inlineProperties = result.getInlineProperties();
+        EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp);
+        AtomFeedProducer inlineFeedProducer = new AtomFeedProducer(inlineProperties);
+        EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet, inlineProperties.getExpandSelectTree());
+        inlineFeedProducer.append(writer, inlineEia, inlineData, true);
+
+        writer.writeEndElement();
+      }
+    }
+  }
+
+  private void appendInlineEntry(final XMLStreamWriter writer, final String navigationPropertyName, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException, XMLStreamException, EdmException {
+
+    if (eia.getExpandedNavigationPropertyNames().contains(navigationPropertyName)) {
+      if (properties.getCallbacks() != null && properties.getCallbacks().containsKey(navigationPropertyName)) {
+        writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_INLINE);
+
+        EdmNavigationProperty navProp = (EdmNavigationProperty) eia.getEntityType().getProperty(navigationPropertyName);
+        WriteEntryCallbackContext context = new WriteEntryCallbackContext();
+        context.setSourceEntitySet(eia.getEntitySet());
+        context.setNavigationProperty(navProp);
+        context.setEntryData(data);
+        ExpandSelectTreeNode subNode = properties.getExpandSelectTree().getLinks().get(navigationPropertyName);
+        context.setCurrentExpandSelectTreeNode(subNode);
+
+        ODataCallback callback = properties.getCallbacks().get(navigationPropertyName);
+        if (callback == null) {
+          throw new EntityProviderException(EntityProviderException.EXPANDNOTSUPPORTED);
+        }
+        WriteEntryCallbackResult result = null;
+        try {
+          result = ((OnWriteEntryContent) callback).retrieveEntryResult(context);
+        } catch (ODataApplicationException e) {
+          throw new EntityProviderException(EntityProviderException.COMMON, e);
+        }
+        Map<String, Object> inlineData = result.getEntryData();
+        if (inlineData != null && !inlineData.isEmpty()) {
+          EntityProviderWriteProperties inlineProperties = result.getInlineProperties();
+          EdmEntitySet inlineEntitySet = eia.getEntitySet().getRelatedEntitySet(navProp);
+          AtomEntryEntityProducer inlineProducer = new AtomEntryEntityProducer(inlineProperties);
+          EntityInfoAggregator inlineEia = EntityInfoAggregator.create(inlineEntitySet, inlineProperties.getExpandSelectTree());
+          inlineProducer.append(writer, inlineEia, inlineData, false, false);
+        }
+
+        writer.writeEndElement();
+      }
+    }
+
+  }
+
+  private void appendAtomEditLink(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException {
+    try {
+      String self = createSelfLink(eia, data, null);
+
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, self);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT);
+      writer.writeAttribute(FormatXml.ATOM_TITLE, eia.getEntityType().getName());
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomContentLink(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data, String mediaResourceMimeType) throws EntityProviderException {
+    try {
+      String self = createSelfLink(eia, data, "$value");
+
+      if (mediaResourceMimeType == null) {
+        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+      }
+
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, self);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_EDIT_MEDIA);
+      writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomContentPart(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data, String mediaResourceMimeType) throws EntityProviderException {
+    try {
+      String self = createSelfLink(eia, data, "$value");
+
+      if (mediaResourceMimeType == null) {
+        mediaResourceMimeType = ContentType.APPLICATION_OCTET_STREAM.toString();
+      }
+
+      writer.writeStartElement(FormatXml.ATOM_CONTENT);
+      writer.writeAttribute(FormatXml.ATOM_TYPE, mediaResourceMimeType);
+      writer.writeAttribute(FormatXml.ATOM_SRC, self);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomMandatoryParts(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_ID);
+      location = properties.getServiceRoot().toASCIIString() + createSelfLink(eia, data, null);
+      writer.writeCharacters(location);
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_TITLE);
+      writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT);
+      EntityPropertyInfo titleInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_TITLE);
+      if (titleInfo != null) {
+        EdmSimpleType st = (EdmSimpleType) titleInfo.getType();
+        Object object = data.get(titleInfo.getName());
+        String title = st.valueToString(object, EdmLiteralKind.DEFAULT, titleInfo.getFacets());
+        if (title != null) {
+          writer.writeCharacters(title);
+        }
+      } else {
+        writer.writeCharacters(eia.getEntitySetName());
+      }
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_UPDATED);
+
+      writer.writeCharacters(getUpdatedString(eia, data));
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  String getUpdatedString(final EntityInfoAggregator eia, final Map<String, Object> data) throws EdmSimpleTypeException {
+    Object updateDate = null;
+    EdmFacets updateFacets = null;
+    EntityPropertyInfo updatedInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_UPDATED);
+    if (updatedInfo != null) {
+      updateDate = data.get(updatedInfo.getName());
+      if (updateDate != null) {
+        updateFacets = updatedInfo.getFacets();
+      }
+    }
+    if (updateDate == null) {
+      updateDate = new Date();
+    }
+    String valueToString = EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT, updateFacets);
+    return valueToString;
+  }
+
+  private String getTargetPathValue(final EntityInfoAggregator eia, final String targetPath, final Map<String, Object> data) throws EntityProviderException {
+    try {
+      EntityPropertyInfo info = eia.getTargetPathInfo(targetPath);
+      if (info != null) {
+        EdmSimpleType type = (EdmSimpleType) info.getType();
+        Object value = data.get(info.getName());
+        return type.valueToString(value, EdmLiteralKind.DEFAULT, info.getFacets());
+      }
+      return null;
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomOptionalParts(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException {
+    try {
+      String authorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHOREMAIL, data);
+      String authorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORNAME, data);
+      String authorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_AUTHORURI, data);
+      if (authorEmail != null || authorName != null || authorUri != null) {
+        writer.writeStartElement(FormatXml.ATOM_AUTHOR);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_NAME, authorName, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_EMAIL, authorEmail, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_AUTHOR_URI, authorUri, false);
+        writer.writeEndElement();
+      }
+
+      String summary = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_SUMMARY, data);
+      appendAtomOptionalPart(writer, FormatXml.ATOM_SUMMARY, summary, true);
+
+      String contributorName = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORNAME, data);
+      String contributorEmail = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTOREMAIL, data);
+      String contributorUri = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_CONTRIBUTORURI, data);
+      if (contributorEmail != null || contributorName != null || contributorUri != null) {
+        writer.writeStartElement(FormatXml.ATOM_CONTRIBUTOR);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_NAME, contributorName, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_EMAIL, contributorEmail, false);
+        appendAtomOptionalPart(writer, FormatXml.ATOM_CONTRIBUTOR_URI, contributorUri, false);
+        writer.writeEndElement();
+      }
+
+      String rights = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_RIGHTS, data);
+      appendAtomOptionalPart(writer, FormatXml.ATOM_RIGHTS, rights, true);
+      String published = getTargetPathValue(eia, EdmTargetPath.SYNDICATION_PUBLISHED, data);
+      appendAtomOptionalPart(writer, FormatXml.ATOM_PUBLISHED, published, false);
+
+      String term = eia.getEntityType().getNamespace() + Edm.DELIMITER + eia.getEntityType().getName();
+      writer.writeStartElement(FormatXml.ATOM_CATEGORY);
+      writer.writeAttribute(FormatXml.ATOM_CATEGORY_TERM, term);
+      writer.writeAttribute(FormatXml.ATOM_CATEGORY_SCHEME, Edm.NAMESPACE_SCHEME_2007_08);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomOptionalPart(final XMLStreamWriter writer, final String name, final String value, final boolean writeType) throws EntityProviderException {
+    try {
+      if (value != null) {
+        writer.writeStartElement(name);
+        if (writeType) {
+          writer.writeAttribute(FormatXml.ATOM_TYPE, FormatXml.ATOM_TEXT);
+        }
+        writer.writeCharacters(value);
+        writer.writeEndElement();
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  static String createSelfLink(final EntityInfoAggregator eia, final Map<String, Object> data, final String extension) throws EntityProviderException {
+    StringBuilder sb = new StringBuilder();
+    if (!eia.isDefaultEntityContainer()) {
+      sb.append(Encoder.encode(eia.getEntityContainerName())).append(Edm.DELIMITER);
+    }
+    sb.append(Encoder.encode(eia.getEntitySetName()));
+
+    sb.append("(").append(createEntryKey(eia, data)).append(")").append(extension == null ? "" : ("/" + extension));
+    return sb.toString();
+  }
+
+  private static String createEntryKey(final EntityInfoAggregator entityInfo, final Map<String, Object> data) throws EntityProviderException {
+    final List<EntityPropertyInfo> keyPropertyInfos = entityInfo.getKeyPropertyInfos();
+
+    StringBuilder keys = new StringBuilder();
+    for (final EntityPropertyInfo keyPropertyInfo : keyPropertyInfos) {
+      if (keys.length() > 0) {
+        keys.append(',');
+      }
+
+      final String name = keyPropertyInfo.getName();
+      if (keyPropertyInfos.size() > 1) {
+        keys.append(Encoder.encode(name)).append('=');
+      }
+
+      final EdmSimpleType type = (EdmSimpleType) keyPropertyInfo.getType();
+      try {
+        keys.append(Encoder.encode(type.valueToString(data.get(name), EdmLiteralKind.URI, keyPropertyInfo.getFacets())));
+      } catch (final EdmSimpleTypeException e) {
+        throw new EntityProviderException(EntityProviderException.COMMON, e);
+      }
+    }
+
+    return keys.toString();
+  }
+
+  private void appendProperties(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> data) throws EntityProviderException {
+    try {
+      List<String> propertyNames = eia.getSelectedPropertyNames();
+      if (!propertyNames.isEmpty()) {
+        writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_PROPERTIES);
+
+        for (String propertyName : propertyNames) {
+          EntityPropertyInfo propertyInfo = eia.getPropertyInfo(propertyName);
+
+          if (isNotMappedViaCustomMapping(propertyInfo)) {
+            Object value = data.get(propertyName);
+            XmlPropertyEntityProducer aps = new XmlPropertyEntityProducer();
+            aps.append(writer, propertyInfo.getName(), propertyInfo, value);
+          }
+        }
+
+        writer.writeEndElement();
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private boolean isNotMappedViaCustomMapping(final EntityPropertyInfo propertyInfo) {
+    EdmCustomizableFeedMappings customMapping = propertyInfo.getCustomMapping();
+    if (customMapping != null && customMapping.isFcKeepInContent() != null) {
+      return customMapping.isFcKeepInContent().booleanValue();
+    }
+    return true;
+  }
+
+  public String getETag() {
+    return etag;
+  }
+
+  public String getLocation() {
+    return location;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomFeedProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomFeedProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomFeedProducer.java
new file mode 100644
index 0000000..9049792
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomFeedProducer.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.Edm;
+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.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.api.ep.callback.TombstoneCallbackResult;
+import org.apache.olingo.odata2.core.commons.Encoder;
+import org.apache.olingo.odata2.core.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Serializes an ATOM feed.
+ * @author SAP AG
+ */
+public class AtomFeedProducer {
+
+  private final EntityProviderWriteProperties properties;
+
+  public AtomFeedProducer(final EntityProviderWriteProperties properties) {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final XMLStreamWriter writer, final EntityInfoAggregator eia, final List<Map<String, Object>> data, final boolean isInline) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_FEED);
+      TombstoneCallback callback = null;
+      if (!isInline) {
+        writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005);
+        writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+        writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08);
+        callback = getTombstoneCallback();
+        if (callback != null) {
+          writer.writeNamespace(TombstoneCallback.PREFIX_TOMBSTONE, TombstoneCallback.NAMESPACE_TOMBSTONE);
+        }
+      }
+      writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, properties.getServiceRoot().toASCIIString());
+
+      // write all atom infos (mandatory and optional)
+      appendAtomMandatoryParts(writer, eia);
+      appendAtomSelfLink(writer, eia);
+      if (properties.getInlineCountType() == InlineCount.ALLPAGES) {
+        appendInlineCount(writer, properties.getInlineCount());
+      }
+
+      appendEntries(writer, eia, data);
+
+      if (callback != null) {
+        appendDeletedEntries(writer, eia, callback);
+      }
+
+      if (properties.getNextLink() != null) {
+        appendNextLink(writer, properties.getNextLink());
+      }
+
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private TombstoneCallback getTombstoneCallback() {
+    if (properties.getCallbacks() != null && properties.getCallbacks().containsKey(TombstoneCallback.CALLBACK_KEY_TOMBSTONE)) {
+      TombstoneCallback callback = (TombstoneCallback) properties.getCallbacks().get(TombstoneCallback.CALLBACK_KEY_TOMBSTONE);
+      return callback;
+    } else {
+      return null;
+    }
+  }
+
+  private void appendDeletedEntries(final XMLStreamWriter writer, final EntityInfoAggregator eia, final TombstoneCallback callback) throws EntityProviderException {
+    TombstoneCallbackResult callbackResult = callback.getTombstoneCallbackResult();
+    List<Map<String, Object>> tombstoneData = callbackResult.getDeletedEntriesData();
+    if (tombstoneData != null) {
+      TombstoneProducer tombstoneProducer = new TombstoneProducer();
+      tombstoneProducer.appendTombstones(writer, eia, properties, tombstoneData);
+    }
+
+    String deltaLink = callbackResult.getDeltaLink();
+    if (deltaLink != null) {
+      try {
+        writer.writeStartElement(FormatXml.ATOM_LINK);
+        writer.writeAttribute(FormatXml.ATOM_REL, FormatXml.ATOM_DELTA_LINK);
+        writer.writeAttribute(FormatXml.ATOM_HREF, deltaLink);
+        writer.writeEndElement();
+      } catch (XMLStreamException e) {
+        throw new EntityProviderException(EntityProviderException.COMMON, e);
+      }
+    }
+  }
+
+  private void appendNextLink(final XMLStreamWriter writer, final String nextLink) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, nextLink);
+      writer.writeAttribute(FormatXml.ATOM_REL, FormatXml.ATOM_NEXT_LINK);
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendEntries(final XMLStreamWriter writer, final EntityInfoAggregator eia, final List<Map<String, Object>> data) throws EntityProviderException {
+    AtomEntryEntityProducer entryProvider = new AtomEntryEntityProducer(properties);
+    for (Map<String, Object> singleEntryData : data) {
+      entryProvider.append(writer, eia, singleEntryData, false, true);
+    }
+  }
+
+  private void appendInlineCount(final XMLStreamWriter writer, final Integer inlineCount) throws EntityProviderException {
+    if (inlineCount == null || inlineCount < 0) {
+      throw new EntityProviderException(EntityProviderException.INLINECOUNT_INVALID);
+    }
+    try {
+      writer.writeStartElement(Edm.NAMESPACE_M_2007_08, FormatXml.M_COUNT);
+      writer.writeCharacters(String.valueOf(inlineCount));
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendAtomSelfLink(final XMLStreamWriter writer, final EntityInfoAggregator eia) throws EntityProviderException {
+
+    URI self = properties.getSelfLink();
+    String selfLink = "";
+    if (self == null) {
+      selfLink = createSelfLink(eia);
+    } else {
+      selfLink = self.toASCIIString();
+    }
+    try {
+      writer.writeStartElement(FormatXml.ATOM_LINK);
+      writer.writeAttribute(FormatXml.ATOM_HREF, selfLink);
+      writer.writeAttribute(FormatXml.ATOM_REL, Edm.LINK_REL_SELF);
+      writer.writeAttribute(FormatXml.ATOM_TITLE, eia.getEntitySetName());
+      writer.writeEndElement();
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private String createSelfLink(final EntityInfoAggregator eia) throws EntityProviderException {
+    StringBuilder sb = new StringBuilder();
+    if (!eia.isDefaultEntityContainer()) {
+      final String entityContainerName = Encoder.encode(eia.getEntityContainerName());
+      sb.append(entityContainerName).append(Edm.DELIMITER);
+    }
+    final String entitySetName = Encoder.encode(eia.getEntitySetName());
+    sb.append(entitySetName);
+    return sb.toString();
+  }
+
+  private void appendAtomMandatoryParts(final XMLStreamWriter writer, final EntityInfoAggregator eia) throws EntityProviderException {
+    try {
+      writer.writeStartElement(FormatXml.ATOM_ID);
+      writer.writeCharacters(createAtomId(eia));
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_TITLE);
+      writer.writeAttribute(FormatXml.M_TYPE, FormatXml.ATOM_TEXT);
+      writer.writeCharacters(eia.getEntitySetName());
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_UPDATED);
+
+      Object updateDate = null;
+      EdmFacets updateFacets = null;
+      updateDate = new Date();
+      writer.writeCharacters(EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT, updateFacets));
+      writer.writeEndElement();
+
+      writer.writeStartElement(FormatXml.ATOM_AUTHOR);
+      writer.writeStartElement(FormatXml.ATOM_AUTHOR_NAME);
+      writer.writeEndElement();
+      writer.writeEndElement();
+
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private String createAtomId(final EntityInfoAggregator eia) throws EntityProviderException {
+    return properties.getServiceRoot() + createSelfLink(eia);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomServiceDocumentProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomServiceDocumentProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomServiceDocumentProducer.java
new file mode 100644
index 0000000..a38bb2f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/AtomServiceDocumentProducer.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.Writer;
+import java.util.List;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * Writes the  OData service document in XML.
+ * @author SAP AG
+ */
+public class AtomServiceDocumentProducer {
+
+  private static final String DEFAULT_CHARSET = ContentType.CHARSET_UTF_8;
+  private static final String XML_VERSION = "1.0";
+  private final Edm edm;
+  private final String serviceRoot;
+
+  public AtomServiceDocumentProducer(final Edm edm, final String serviceRoot) {
+    this.edm = edm;
+    this.serviceRoot = serviceRoot;
+  }
+
+  public void writeServiceDocument(final Writer writer) throws EntityProviderException {
+
+    EdmServiceMetadata serviceMetadata = edm.getServiceMetadata();
+
+    try {
+      XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+
+      xmlStreamWriter.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+      xmlStreamWriter.setPrefix(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998);
+      xmlStreamWriter.setPrefix(Edm.PREFIX_ATOM, Edm.NAMESPACE_ATOM_2005);
+      xmlStreamWriter.setDefaultNamespace(Edm.NAMESPACE_APP_2007);
+
+      xmlStreamWriter.writeStartElement(FormatXml.APP_SERVICE);
+      xmlStreamWriter.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, FormatXml.XML_BASE, serviceRoot);
+      xmlStreamWriter.writeDefaultNamespace(Edm.NAMESPACE_APP_2007);
+      xmlStreamWriter.writeNamespace(Edm.PREFIX_ATOM, Edm.NAMESPACE_ATOM_2005);
+
+      xmlStreamWriter.writeStartElement(FormatXml.APP_WORKSPACE);
+      xmlStreamWriter.writeStartElement(Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_TITLE);
+      xmlStreamWriter.writeCharacters(FormatXml.ATOM_TITLE_DEFAULT);
+      xmlStreamWriter.writeEndElement();
+
+      List<EdmEntitySetInfo> entitySetInfos = serviceMetadata.getEntitySetInfos();
+      for (EdmEntitySetInfo info : entitySetInfos) {
+        xmlStreamWriter.writeStartElement(FormatXml.APP_COLLECTION);
+        xmlStreamWriter.writeAttribute(FormatXml.ATOM_HREF, info.getEntitySetUri().toASCIIString());
+        xmlStreamWriter.writeStartElement(Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_TITLE);
+        xmlStreamWriter.writeCharacters(info.getEntitySetName());
+        xmlStreamWriter.writeEndElement();
+        xmlStreamWriter.writeEndElement();
+      }
+
+      //      Collection<Schema> schemas = edmProvider.getSchemas();
+      //      if (schemas != null) {
+      //        for (Schema schema : schemas) {
+      //          Collection<EntityContainer> entityContainers = schema.getEntityContainers();
+      //          if (entityContainers != null) {
+      //            for (EntityContainer entityContainer : entityContainers) {
+      //              Collection<EntitySet> entitySets = entityContainer.getEntitySets();
+      //              for (EntitySet entitySet : entitySets) {
+      //                xmlStreamWriter.writeStartElement(FormatXml.APP_COLLECTION);
+      //                if (entityContainer.isDefaultEntityContainer()) {
+      //                  xmlStreamWriter.writeAttribute(FormatXml.ATOM_HREF, entitySet.getName());
+      //                } else {
+      //                  xmlStreamWriter.writeAttribute(FormatXml.ATOM_HREF, entityContainer.getName() + Edm.DELIMITER + entitySet.getName());
+      //                }
+      //                xmlStreamWriter.writeStartElement(Edm.NAMESPACE_ATOM_2005, FormatXml.ATOM_TITLE);
+      //                xmlStreamWriter.writeCharacters(entitySet.getName());
+      //                xmlStreamWriter.writeEndElement();
+      //                xmlStreamWriter.writeEndElement();
+      //              }
+      //            }
+      //          }
+      //        }
+      //      }
+
+      xmlStreamWriter.writeEndElement();
+      xmlStreamWriter.writeEndElement();
+      xmlStreamWriter.writeEndDocument();
+
+      xmlStreamWriter.flush();
+    } catch (FactoryConfigurationError e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (ODataException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonCollectionEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonCollectionEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonCollectionEntityProducer.java
new file mode 100644
index 0000000..532ea36
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonCollectionEntityProducer.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Provider for writing a collection of simple-type or complex-type instances in JSON.
+ * @author SAP AG
+ */
+public class JsonCollectionEntityProducer {
+
+  public void append(final Writer writer, final EntityPropertyInfo propertyInfo, final List<?> data) throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    try {
+      jsonStreamWriter.beginObject()
+          .name(FormatJson.D)
+          .beginObject();
+
+      jsonStreamWriter.name(FormatJson.METADATA)
+          .beginObject()
+          .namedStringValueRaw(FormatJson.TYPE,
+              "Collection(" + propertyInfo.getType().getNamespace() + Edm.DELIMITER + propertyInfo.getType().getName() + ")")
+          .endObject()
+          .separator();
+
+      jsonStreamWriter.name(FormatJson.RESULTS)
+          .beginArray();
+      boolean first = true;
+      for (final Object item : data) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        JsonPropertyEntityProducer.appendPropertyValue(jsonStreamWriter, propertyInfo, item);
+      }
+      jsonStreamWriter.endArray();
+
+      jsonStreamWriter.endObject()
+          .endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
new file mode 100644
index 0000000..40a0e33
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonEntryEntityProducer.java
@@ -0,0 +1,195 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent;
+import org.apache.olingo.odata2.api.ep.callback.WriteCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.core.commons.Encoder;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing an entity in JSON, also usable for function imports
+ * returning a single instance of an entity type.
+ * @author SAP AG
+ */
+public class JsonEntryEntityProducer {
+
+  private final EntityProviderWriteProperties properties;
+  private String eTag;
+  private String location;
+  private JsonStreamWriter jsonStreamWriter;
+
+  public JsonEntryEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final Writer writer, final EntityInfoAggregator entityInfo, final Map<String, Object> data, final boolean isRootElement) throws EntityProviderException {
+    final EdmEntityType type = entityInfo.getEntityType();
+
+    try {
+      jsonStreamWriter = new JsonStreamWriter(writer);
+      if (isRootElement) {
+        jsonStreamWriter.beginObject().name(FormatJson.D);
+      }
+
+      jsonStreamWriter.beginObject();
+
+      jsonStreamWriter.name(FormatJson.METADATA)
+          .beginObject();
+      final String self = AtomEntryEntityProducer.createSelfLink(entityInfo, data, null);
+      location = (properties.getServiceRoot() == null ? "" : properties.getServiceRoot().toASCIIString()) + self;
+      jsonStreamWriter.namedStringValue(FormatJson.ID, location).separator()
+          .namedStringValue(FormatJson.URI, location).separator()
+          .namedStringValueRaw(FormatJson.TYPE,
+              type.getNamespace() + Edm.DELIMITER + type.getName());
+      eTag = AtomEntryEntityProducer.createETag(entityInfo, data);
+      if (eTag != null) {
+        jsonStreamWriter.separator()
+            .namedStringValue(FormatJson.ETAG, eTag);
+      }
+      if (type.hasStream()) {
+        jsonStreamWriter.separator()
+            .namedStringValueRaw(FormatJson.CONTENT_TYPE,
+                properties.getMediaResourceMimeType() == null ?
+                    type.getMapping() == null || type.getMapping().getMimeType() == null || data.get(type.getMapping().getMimeType()) == null ?
+                        HttpContentType.APPLICATION_OCTET_STREAM : data.get(type.getMapping().getMimeType()).toString() :
+                    properties.getMediaResourceMimeType())
+            .separator()
+            .namedStringValue(FormatJson.MEDIA_SRC, self + "/$value").separator()
+            .namedStringValue(FormatJson.EDIT_MEDIA, location + "/$value");
+      }
+      jsonStreamWriter.endObject();
+
+      for (final String propertyName : type.getPropertyNames()) {
+        if (entityInfo.getSelectedPropertyNames().contains(propertyName)) {
+          jsonStreamWriter.separator()
+              .name(propertyName);
+          JsonPropertyEntityProducer.appendPropertyValue(jsonStreamWriter, entityInfo.getPropertyInfo(propertyName), data.get(propertyName));
+        }
+      }
+
+      for (final String navigationPropertyName : type.getNavigationPropertyNames()) {
+        if (entityInfo.getSelectedNavigationPropertyNames().contains(navigationPropertyName)) {
+          jsonStreamWriter.separator()
+              .name(navigationPropertyName);
+          if (entityInfo.getExpandedNavigationPropertyNames().contains(navigationPropertyName)) {
+            if (properties.getCallbacks() != null && properties.getCallbacks().containsKey(navigationPropertyName)) {
+              final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) type.getProperty(navigationPropertyName);
+              final boolean isFeed = navigationProperty.getMultiplicity() == EdmMultiplicity.MANY;
+              final EdmEntitySet entitySet = entityInfo.getEntitySet();
+              final EdmEntitySet inlineEntitySet = entitySet.getRelatedEntitySet(navigationProperty);
+
+              WriteCallbackContext context = isFeed ? new WriteFeedCallbackContext() : new WriteEntryCallbackContext();
+              context.setSourceEntitySet(entitySet);
+              context.setNavigationProperty(navigationProperty);
+              context.setEntryData(data);
+              context.setCurrentExpandSelectTreeNode(properties.getExpandSelectTree().getLinks().get(navigationPropertyName));
+
+              ODataCallback callback = properties.getCallbacks().get(navigationPropertyName);
+              if (callback == null) {
+                throw new EntityProviderException(EntityProviderException.EXPANDNOTSUPPORTED);
+              }
+              try {
+                if (isFeed) {
+                  final WriteFeedCallbackResult result = ((OnWriteFeedContent) callback).retrieveFeedResult((WriteFeedCallbackContext) context);
+                  List<Map<String, Object>> inlineData = result.getFeedData();
+                  if (inlineData == null) {
+                    inlineData = new ArrayList<Map<String, Object>>();
+                  }
+                  final EntityProviderWriteProperties inlineProperties = result.getInlineProperties();
+                  final EntityInfoAggregator inlineEntityInfo = EntityInfoAggregator.create(inlineEntitySet, inlineProperties.getExpandSelectTree());
+                  new JsonFeedEntityProducer(inlineProperties).append(writer, inlineEntityInfo, inlineData, false);
+
+                } else {
+                  final WriteEntryCallbackResult result = ((OnWriteEntryContent) callback).retrieveEntryResult((WriteEntryCallbackContext) context);
+                  Map<String, Object> inlineData = result.getEntryData();
+                  if (inlineData != null && !inlineData.isEmpty()) {
+                    final EntityProviderWriteProperties inlineProperties = result.getInlineProperties();
+                    final EntityInfoAggregator inlineEntityInfo = EntityInfoAggregator.create(inlineEntitySet, inlineProperties.getExpandSelectTree());
+                    new JsonEntryEntityProducer(inlineProperties).append(writer, inlineEntityInfo, inlineData, false);
+                  } else {
+                    jsonStreamWriter.unquotedValue("null");
+                  }
+                }
+              } catch (final ODataApplicationException e) {
+                throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+              }
+            } else {
+              writeDeferredUri(navigationPropertyName);
+            }
+          } else {
+            writeDeferredUri(navigationPropertyName);
+          }
+        }
+      }
+
+      jsonStreamWriter.endObject();
+
+      if (isRootElement) {
+        jsonStreamWriter.endObject();
+      }
+
+      writer.flush();
+
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private void writeDeferredUri(final String navigationPropertyName) throws IOException {
+    jsonStreamWriter.beginObject()
+        .name(FormatJson.DEFERRED);
+    JsonLinkEntityProducer.appendUri(jsonStreamWriter, location + "/" + Encoder.encode(navigationPropertyName));
+    jsonStreamWriter.endObject();
+  }
+
+  public String getETag() {
+    return eTag;
+  }
+
+  public String getLocation() {
+    return location;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonErrorDocumentProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonErrorDocumentProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonErrorDocumentProducer.java
new file mode 100644
index 0000000..a65d997
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonErrorDocumentProducer.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Locale;
+
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class JsonErrorDocumentProducer {
+
+  public void writeErrorDocument(final Writer writer, final String errorCode, final String message, final Locale locale, final String innerError) throws IOException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    jsonStreamWriter.beginObject()
+        .name(FormatJson.ERROR)
+        .beginObject()
+        .namedStringValue(FormatJson.CODE, errorCode).separator()
+        .name(FormatJson.MESSAGE)
+        .beginObject()
+        .namedStringValueRaw(FormatJson.LANG,
+            locale == null || locale.getLanguage() == null ? null :
+                locale.getLanguage() + (locale.getCountry() == null || locale.getCountry().isEmpty() ? "" : ("-" + locale.getCountry())))
+        .separator()
+        .namedStringValue(FormatJson.VALUE, message)
+        .endObject();
+    if (innerError != null) {
+      jsonStreamWriter.separator()
+          .namedStringValue(FormatJson.INNER_ERROR, innerError);
+    }
+    jsonStreamWriter.endObject()
+        .endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
new file mode 100644
index 0000000..e406fe2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonFeedEntityProducer.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing an entity collection (a feed) in JSON.
+ * @author SAP AG
+ */
+public class JsonFeedEntityProducer {
+
+  private final EntityProviderWriteProperties properties;
+
+  public JsonFeedEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final Writer writer, final EntityInfoAggregator entityInfo, final List<Map<String, Object>> data, final boolean isRootElement) throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    try {
+      jsonStreamWriter.beginObject();
+
+      if (isRootElement) {
+        jsonStreamWriter.name(FormatJson.D)
+            .beginObject();
+      }
+
+      if (properties.getInlineCountType() == InlineCount.ALLPAGES) {
+        final int inlineCount = properties.getInlineCount() == null ? 0 : properties.getInlineCount();
+        jsonStreamWriter.namedStringValueRaw(FormatJson.COUNT, String.valueOf(inlineCount)).separator();
+      }
+
+      jsonStreamWriter.name(FormatJson.RESULTS)
+          .beginArray();
+      JsonEntryEntityProducer entryProducer = new JsonEntryEntityProducer(properties);
+      boolean first = true;
+      for (final Map<String, Object> entryData : data) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        entryProducer.append(writer, entityInfo, entryData, false);
+      }
+      jsonStreamWriter.endArray();
+
+      // Write "next" link.
+      // To be compatible with other implementations out there, the link is
+      // written directly after "__next" and not as "{"uri":"next link"}",
+      // deviating from the OData 2.0 specification.
+      if (properties.getNextLink() != null) {
+        jsonStreamWriter.separator()
+            .namedStringValue(FormatJson.NEXT, properties.getNextLink());
+      }
+
+      if (isRootElement) {
+        jsonStreamWriter.endObject();
+      }
+
+      jsonStreamWriter.endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinkEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinkEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinkEntityProducer.java
new file mode 100644
index 0000000..5edbe00
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinkEntityProducer.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing a link in JSON.
+ * @author SAP AG
+ */
+public class JsonLinkEntityProducer {
+
+  private final EntityProviderWriteProperties properties;
+
+  public JsonLinkEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final Writer writer, final EntityInfoAggregator entityInfo, final Map<String, Object> data) throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    final String uri = (properties.getServiceRoot() == null ? "" : properties.getServiceRoot().toASCIIString())
+        + AtomEntryEntityProducer.createSelfLink(entityInfo, data, null);
+    try {
+      jsonStreamWriter.beginObject()
+          .name(FormatJson.D);
+      appendUri(jsonStreamWriter, uri);
+      jsonStreamWriter.endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  protected static void appendUri(final JsonStreamWriter jsonStreamWriter, final String uri) throws IOException {
+    jsonStreamWriter.beginObject()
+        .namedStringValue(FormatJson.URI, uri)
+        .endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinksEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinksEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinksEntityProducer.java
new file mode 100644
index 0000000..1c2aa75
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonLinksEntityProducer.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing a link collection in JSON.
+ * @author SAP AG
+ */
+public class JsonLinksEntityProducer {
+
+  private final EntityProviderWriteProperties properties;
+
+  public JsonLinksEntityProducer(final EntityProviderWriteProperties properties) throws EntityProviderException {
+    this.properties = properties == null ? EntityProviderWriteProperties.serviceRoot(null).build() : properties;
+  }
+
+  public void append(final Writer writer, final EntityInfoAggregator entityInfo, final List<Map<String, Object>> data) throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    try {
+      jsonStreamWriter.beginObject()
+          .name(FormatJson.D);
+
+      if (properties.getInlineCountType() == InlineCount.ALLPAGES) {
+        final int inlineCount = properties.getInlineCount() == null ? 0 : properties.getInlineCount();
+        jsonStreamWriter.beginObject()
+            .namedStringValueRaw(FormatJson.COUNT, String.valueOf(inlineCount)).separator()
+            .name(FormatJson.RESULTS);
+      }
+
+      jsonStreamWriter.beginArray();
+      final String serviceRoot = properties.getServiceRoot().toASCIIString();
+      boolean first = true;
+      for (final Map<String, Object> entryData : data) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        JsonLinkEntityProducer.appendUri(jsonStreamWriter,
+            (serviceRoot == null ? "" : serviceRoot) + AtomEntryEntityProducer.createSelfLink(entityInfo, entryData, null));
+      }
+      jsonStreamWriter.endArray();
+
+      if (properties.getInlineCountType() == InlineCount.ALLPAGES) {
+        jsonStreamWriter.endObject();
+      }
+
+      jsonStreamWriter.endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonPropertyEntityProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonPropertyEntityProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonPropertyEntityProducer.java
new file mode 100644
index 0000000..81ec29f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonPropertyEntityProducer.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityComplexPropertyInfo;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Producer for writing a single simple or complex property in JSON, also usable
+ * for function imports returning a single instance of a simple or complex type.
+ * @author SAP AG
+ */
+public class JsonPropertyEntityProducer {
+
+  public void append(final Writer writer, final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+
+    try {
+      jsonStreamWriter.beginObject()
+          .name(FormatJson.D)
+          .beginObject();
+
+      jsonStreamWriter.name(propertyInfo.getName());
+      appendPropertyValue(jsonStreamWriter, propertyInfo.isComplex() ? (EntityComplexPropertyInfo) propertyInfo : propertyInfo, value);
+
+      jsonStreamWriter.endObject()
+          .endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  protected static void appendPropertyValue(final JsonStreamWriter jsonStreamWriter, final EntityPropertyInfo propertyInfo, final Object value) throws IOException, EdmException, EntityProviderException {
+    if (propertyInfo.isComplex()) {
+      if (value == null || value instanceof Map<?, ?>) {
+        jsonStreamWriter.beginObject();
+        appendPropertyMetadata(jsonStreamWriter, propertyInfo.getType());
+        for (final EntityPropertyInfo childPropertyInfo : ((EntityComplexPropertyInfo) propertyInfo).getPropertyInfos()) {
+          jsonStreamWriter.separator();
+          final String name = childPropertyInfo.getName();
+          jsonStreamWriter.name(name);
+          appendPropertyValue(jsonStreamWriter, childPropertyInfo, value == null ? null : ((Map<?, ?>) value).get(name));
+        }
+        jsonStreamWriter.endObject();
+      } else {
+        throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("A complex property must have a Map as data"));
+      }
+    } else {
+      final EdmSimpleType type = (EdmSimpleType) propertyInfo.getType();
+      final Object contentValue = value instanceof Map ? ((Map<?, ?>) value).get(propertyInfo.getName()) : value;
+      final String valueAsString = type.valueToString(contentValue, EdmLiteralKind.JSON, propertyInfo.getFacets());
+      switch (EdmSimpleTypeKind.valueOf(type.getName())) {
+      case String:
+        jsonStreamWriter.stringValue(valueAsString);
+        break;
+      case Boolean:
+      case Byte:
+      case SByte:
+      case Int16:
+      case Int32:
+        jsonStreamWriter.unquotedValue(valueAsString);
+        break;
+      case DateTime:
+      case DateTimeOffset:
+        // Although JSON escaping is (and should be) done in the JSON
+        // serializer, we backslash-escape the forward slash here explicitly
+        // because it is not required to escape it in JSON but in OData.
+        jsonStreamWriter.stringValueRaw(valueAsString == null ? null : valueAsString.replace("/", "\\/"));
+        break;
+      default:
+        jsonStreamWriter.stringValueRaw(valueAsString);
+        break;
+      }
+    }
+  }
+
+  protected static void appendPropertyMetadata(final JsonStreamWriter jsonStreamWriter, final EdmType type) throws IOException, EdmException {
+    jsonStreamWriter.name(FormatJson.METADATA)
+        .beginObject()
+        .namedStringValueRaw(FormatJson.TYPE, type.getNamespace() + Edm.DELIMITER + type.getName())
+        .endObject();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonServiceDocumentProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonServiceDocumentProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonServiceDocumentProducer.java
new file mode 100644
index 0000000..3dce13c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/JsonServiceDocumentProducer.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.ep.util.FormatJson;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * Writes the  OData service document in JSON.
+ * @author SAP AG
+ */
+public class JsonServiceDocumentProducer {
+
+  public static void writeServiceDocument(final Writer writer, final Edm edm) throws EntityProviderException {
+    final EdmServiceMetadata serviceMetadata = edm.getServiceMetadata();
+
+    JsonStreamWriter jsonStreamWriter = new JsonStreamWriter(writer);
+    try {
+      jsonStreamWriter.beginObject()
+          .name(FormatJson.D)
+          .beginObject()
+          .name(FormatJson.ENTITY_SETS)
+          .beginArray();
+
+      boolean first = true;
+      for (EdmEntitySetInfo info : serviceMetadata.getEntitySetInfos()) {
+        if (first) {
+          first = false;
+        } else {
+          jsonStreamWriter.separator();
+        }
+        jsonStreamWriter.stringValue(info.getEntitySetUri().toASCIIString());
+      }
+
+      jsonStreamWriter.endArray()
+          .endObject()
+          .endObject();
+    } catch (final IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (final ODataException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/TombstoneProducer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/TombstoneProducer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/TombstoneProducer.java
new file mode 100644
index 0000000..23f7ad7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/producer/TombstoneProducer.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.ep.producer;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+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.api.edm.EdmTargetPath;
+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.edm.EdmDateTimeOffset;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.util.FormatXml;
+
+/**
+ * @author SAP AG
+ */
+public class TombstoneProducer {
+
+  private String defaultDateString;
+
+  /**
+   * Appends tombstones to an already started feed.
+   * If the list is empty no elements will be appended.
+   * @param writer         same as in feed
+   * @param eia            same as in feed
+   * @param properties     same as in feed
+   * @param deletedEntries data to be appended
+   * @throws EntityProviderException
+   */
+  public void appendTombstones(final XMLStreamWriter writer, final EntityInfoAggregator eia, final EntityProviderWriteProperties properties, final List<Map<String, Object>> deletedEntries) throws EntityProviderException {
+    try {
+      for (Map<String, Object> deletedEntry : deletedEntries) {
+        writer.writeStartElement(TombstoneCallback.NAMESPACE_TOMBSTONE, FormatXml.ATOM_TOMBSTONE_DELETED_ENTRY);
+
+        appendRefAttribute(writer, eia, properties, deletedEntry);
+        appendWhenAttribute(writer, eia, deletedEntry);
+
+        writer.writeEndElement();
+      }
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    } catch (EdmSimpleTypeException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void appendWhenAttribute(final XMLStreamWriter writer, final EntityInfoAggregator eia, final Map<String, Object> deletedEntry) throws XMLStreamException, EdmSimpleTypeException {
+    Object updateDate = null;
+    EntityPropertyInfo updatedInfo = eia.getTargetPathInfo(EdmTargetPath.SYNDICATION_UPDATED);
+    if (updatedInfo != null) {
+      updateDate = deletedEntry.get(updatedInfo.getName());
+    }
+
+    if (updateDate == null) {
+      appendDefaultWhenAttribute(writer);
+    } else {
+      appendCustomWhenAttribute(writer, updateDate, updatedInfo);
+    }
+  }
+
+  private void appendCustomWhenAttribute(final XMLStreamWriter writer, final Object updateDate, final EntityPropertyInfo updatedInfo) throws XMLStreamException, EdmSimpleTypeException {
+    EdmFacets updateFacets = updatedInfo.getFacets();
+    writer.writeAttribute(FormatXml.ATOM_TOMBSTONE_WHEN, EdmDateTimeOffset.getInstance().valueToString(updateDate, EdmLiteralKind.DEFAULT, updateFacets));
+  }
+
+  private void appendRefAttribute(final XMLStreamWriter writer, final EntityInfoAggregator eia, final EntityProviderWriteProperties properties, final Map<String, Object> deletedEntry) throws XMLStreamException, EntityProviderException {
+    String ref = properties.getServiceRoot().toASCIIString() + AtomEntryEntityProducer.createSelfLink(eia, deletedEntry, null);
+    writer.writeAttribute(FormatXml.ATOM_TOMBSTONE_REF, ref);
+  }
+
+  private void appendDefaultWhenAttribute(final XMLStreamWriter writer) throws XMLStreamException, EdmSimpleTypeException {
+    if (defaultDateString == null) {
+      Object defaultDate = new Date();
+      defaultDateString = EdmDateTimeOffset.getInstance().valueToString(defaultDate, EdmLiteralKind.DEFAULT, null);
+    }
+    writer.writeAttribute(FormatXml.ATOM_TOMBSTONE_WHEN, defaultDateString);
+
+  }
+}


[32/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProvider.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProvider.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProvider.java
new file mode 100644
index 0000000..63d4c27
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProvider.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+
+/**
+ * Default EDM Provider which is to be extended by the application
+ * @author SAP AG
+ *
+ */
+public abstract class EdmProvider {
+
+  /**
+   * This method should return an {@link EntityContainerInfo} or <b>null</b> if nothing is found
+   * @param name (null for default container)
+   * @return {@link EntityContainerInfo} for the given name
+   * @throws ODataException
+   */
+  public EntityContainerInfo getEntityContainerInfo(final String name) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return an {@link EntityType} or <b>null</b> if nothing is found
+   * @param edmFQName
+   * @return {@link EntityType} for the given name
+   * @throws ODataException
+   */
+  public EntityType getEntityType(final FullQualifiedName edmFQName) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return a {@link ComplexType} or <b>null</b> if nothing is found
+   * @param edmFQName
+   * @return {@link ComplexType} for the given name
+   * @throws ODataException
+   */
+  public ComplexType getComplexType(final FullQualifiedName edmFQName) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return an {@link Association} or <b>null</b> if nothing is found
+   * @param edmFQName
+   * @return {@link Association} for the given name
+   * @throws ODataException
+   */
+  public Association getAssociation(final FullQualifiedName edmFQName) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return an {@link EntitySet} or <b>null</b> if nothing is found
+   * @param entityContainer
+   * @param name
+   * @return {@link EntitySet} for the given container name and entity set name
+   * @throws ODataException
+   */
+  public EntitySet getEntitySet(final String entityContainer, final String name) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return an {@link AssociationSet} or <b>null</b> if nothing is found
+   * @param entityContainer
+   * @param association
+   * @param sourceEntitySetName
+   * @param sourceEntitySetRole
+   * @return {@link AssociationSet} for the given container name, association name, source entity set name and source entity set role
+   * @throws ODataException
+   */
+  public AssociationSet getAssociationSet(final String entityContainer, final FullQualifiedName association, final String sourceEntitySetName, final String sourceEntitySetRole) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return a {@link FunctionImport} or <b>null</b> if nothing is found
+   * @param entityContainer
+   * @param name
+   * @return {@link FunctionImport} for the given container name and function import name
+   * @throws ODataException
+   */
+  public FunctionImport getFunctionImport(final String entityContainer, final String name) throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+
+  /**
+   * This method should return a collection of all {@link Schema} or <b>null</b> if nothing is found
+   * @return List<{@link Schema}>
+   * @throws ODataException
+   */
+  public List<Schema> getSchemas() throws ODataException {
+    throw new ODataNotImplementedException();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderAccessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderAccessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderAccessor.java
new file mode 100644
index 0000000..0ab6301
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderAccessor.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+/**
+ * This interface can be used to access the {@link EdmProvider} within an application. 
+ * @author SAP AG
+ *
+ */
+public interface EdmProviderAccessor {
+
+  /**
+   * @return {@link EdmProvider} of this service
+   */
+  public EdmProvider getEdmProvider();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderFactory.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderFactory.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderFactory.java
new file mode 100644
index 0000000..710f27b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EdmProviderFactory.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * EDM Provider Factory which can be used to create an edm provider (e.g. from a metadata document)
+ * @author SAP AG
+ *
+ */
+public class EdmProviderFactory {
+
+  /**
+   * Creates and returns an edm provider. 
+   * @param metadataXml a metadata xml input stream (means the metadata document)
+   * @param validate true if semantic checks for metadata document input stream shall be done
+   * @return an instance of EdmProvider
+   */
+  public static EdmProvider getEdmProvider(final InputStream metadataXml, final boolean validate) throws EntityProviderException {
+    return RuntimeDelegate.createEdmProvider(metadataXml, validate);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainer.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainer.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainer.java
new file mode 100644
index 0000000..fa18683
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainer.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent an entity container including its child elements
+ * @author SAP AG
+ */
+public class EntityContainer extends EntityContainerInfo {
+
+  private List<EntitySet> entitySets;
+  private List<AssociationSet> associationSets;
+  private List<FunctionImport> functionImports;
+  private Documentation documentation;
+
+  /**
+   * @return <b>List</b> of all entity sets of the entity container
+   */
+  public List<EntitySet> getEntitySets() {
+    return entitySets;
+  }
+
+  /**
+   * Sets the entity sets of this {@link EntityContainer}
+   * @param entitySets
+   * @return {@link EntityContainerInfo} for method chaining
+   */
+  public EntityContainer setEntitySets(final List<EntitySet> entitySets) {
+    this.entitySets = entitySets;
+    return this;
+  }
+
+  /**
+   * @return <b>List</b> of all association sets of the entity container
+   */
+  public List<AssociationSet> getAssociationSets() {
+    return associationSets;
+  }
+
+  /**
+   * Sets the association sets of this {@link EntityContainer}
+   * @param associationSets
+   * @return {@link EntityContainerInfo} for method chaining
+   */
+  public EntityContainer setAssociationSets(final List<AssociationSet> associationSets) {
+    this.associationSets = associationSets;
+    return this;
+  }
+
+  /**
+   * @return <b>List</b> of all function imports of the entity container
+   */
+  public List<FunctionImport> getFunctionImports() {
+    return functionImports;
+  }
+
+  /**
+   * Sets the function imports of this {@link EntityContainer}
+   * @param functionImports
+   * @return {@link EntityContainerInfo} for method chaining
+   */
+  public EntityContainer setFunctionImports(final List<FunctionImport> functionImports) {
+    this.functionImports = functionImports;
+    return this;
+  }
+
+  /**
+   * Sets the name of this {@link EntityContainer}
+   * @param name
+   * @return {@link EntityContainer} for method chaining
+   */
+  @Override
+  public EntityContainer setName(final String name) {
+    super.setName(name);
+    return this;
+  }
+
+  /**
+   * Sets the entity container which is the parent of this {@link EntityContainer}
+   * @param extendz
+   * @return {@link EntityContainer} for method chaining
+   */
+  @Override
+  public EntityContainer setExtendz(final String extendz) {
+    super.setExtendz(extendz);
+    return this;
+  }
+
+  /**
+   * Sets if this is the default {@link EntityContainer}
+   * @param isDefaultEntityContainer
+   * @return {@link EntityContainer} for method chaining
+   */
+  @Override
+  public EntityContainer setDefaultEntityContainer(final boolean isDefaultEntityContainer) {
+    super.setDefaultEntityContainer(isDefaultEntityContainer);
+    return this;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * Sets the {@link Documentation}
+   * @param documentation
+   * @return {@link EntityContainer} for method chaining
+   */
+  public EntityContainer setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainerInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainerInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainerInfo.java
new file mode 100644
index 0000000..593ba9d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityContainerInfo.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent an entity container
+ * @author SAP AG
+ */
+public class EntityContainerInfo {
+
+  private String name;
+  private String extendz;
+  private boolean isDefaultEntityContainer;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return <b>String</b> name of the container which is extended by this container
+   */
+  public String getExtendz() {
+    return extendz;
+  }
+
+  /**
+   * @return <b>boolean</b> if this container is the default container
+   */
+  public boolean isDefaultEntityContainer() {
+    return isDefaultEntityContainer;
+  }
+
+  /**
+   * Sets the name of this {@link EntityContainerInfo}
+   * @param name
+   * @return {@link EntityContainerInfo} for method chaining
+   */
+  public EntityContainerInfo setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the entity container which is the parent of this {@link EntityContainerInfo}
+   * @param extendz
+   * @return {@link EntityContainerInfo} for method chaining
+   */
+  public EntityContainerInfo setExtendz(final String extendz) {
+    this.extendz = extendz;
+    return this;
+  }
+
+  /**
+   * Sets if this is the default {@link EntityContainerInfo}
+   * @param isDefaultEntityContainer
+   * @return {@link EntityContainerInfo} for method chaining
+   */
+  public EntityContainerInfo setDefaultEntityContainer(final boolean isDefaultEntityContainer) {
+    this.isDefaultEntityContainer = isDefaultEntityContainer;
+    return this;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link EntityContainer}
+   * @param annotationAttributes
+   * @return {@link EntityContainer} for method chaining
+   */
+  public EntityContainerInfo setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link EntityContainer}
+   * @param annotationElements
+   * @return {@link EntityContainer} for method chaining
+   */
+  public EntityContainerInfo setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntitySet.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntitySet.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntitySet.java
new file mode 100644
index 0000000..fe100c9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntitySet.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent an entity set
+ * @author SAP AG
+ */
+public class EntitySet {
+
+  private String name;
+  private FullQualifiedName entityType;
+  private Mapping mapping;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String> name of this entity set
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link FullQualifiedName} of the entity type of this entity set
+   */
+  public FullQualifiedName getEntityType() {
+    return entityType;
+  }
+
+  /**
+   * @return {@link Mapping} for this type
+   */
+  public Mapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name of this {@link EntitySet}
+   * @param name
+   * @return {@link EntitySet} for method chaining
+   */
+  public EntitySet setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the {@link FullQualifiedName} of the {@link EntityType} of this {@link EntitySet}
+   * @param entityType
+   * @return {@link EntitySet} for method chaining
+   */
+  public EntitySet setEntityType(final FullQualifiedName entityType) {
+    this.entityType = entityType;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Mapping}
+   * @param mapping
+   * @return {@link EntitySet} for method chaining
+   */
+  public EntitySet setMapping(final Mapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation}
+   * @param documentation
+   * @return {@link EntitySet} for method chaining
+   */
+  public EntitySet setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link EntitySet}
+   * @param annotationAttributes
+   * @return {@link EntitySet} for method chaining
+   */
+  public EntitySet setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link EntitySet}
+   * @param annotationElements
+   * @return {@link EntitySet} for method chaining
+   */
+  public EntitySet setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityType.java
new file mode 100644
index 0000000..fecfe43
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/EntityType.java
@@ -0,0 +1,185 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this class represent an entity type
+ * @author SAP AG
+ */
+public class EntityType extends ComplexType {
+
+  private boolean hasStream;
+  private CustomizableFeedMappings customizableFeedMappings;
+  private Key key;
+  private List<NavigationProperty> navigationProperties;
+
+  /**
+   * @return <b>boolean</b> if this EntityType is a media resource
+   */
+  public boolean isHasStream() {
+    return hasStream;
+  }
+
+  /**
+   * @return {@link CustomizableFeedMappings} of this entity type
+   */
+  public CustomizableFeedMappings getCustomizableFeedMappings() {
+    return customizableFeedMappings;
+  }
+
+  /**
+   * @return {@link Key} of this entity type
+   */
+  public Key getKey() {
+    return key;
+  }
+
+  /**
+   * @return List<{@link NavigationProperty}> of this entity type
+   */
+  public List<NavigationProperty> getNavigationProperties() {
+    return navigationProperties;
+  }
+
+  /**
+   * Sets if this {@link EntityType} is a media resource
+   * @param hasStream
+   * @return {@link EntityType} for method chaining,
+   */
+  public EntityType setHasStream(final boolean hasStream) {
+    this.hasStream = hasStream;
+    return this;
+  }
+
+  /**
+   * Sets the {@link CustomizableFeedMappings} for this {@link EntityType}
+   * @param customizableFeedMappings
+   * @return {@link EntityType} for method chaining
+   */
+  public EntityType setCustomizableFeedMappings(final CustomizableFeedMappings customizableFeedMappings) {
+    this.customizableFeedMappings = customizableFeedMappings;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Key} for this {@link EntityType}
+   * @param key
+   * @return {@link EntityType} for method chaining
+   */
+  public EntityType setKey(final Key key) {
+    this.key = key;
+    return this;
+  }
+
+  /**
+   * Sets the {@link NavigationProperty}s for this {@link EntityType}
+   * @param navigationProperties
+   * @return {@link EntityType} for method chaining
+   */
+  public EntityType setNavigationProperties(final List<NavigationProperty> navigationProperties) {
+    this.navigationProperties = navigationProperties;
+    return this;
+  }
+
+  /**
+   * @param name
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setName(final String name) {
+    super.setName(name);
+    return this;
+  }
+
+  /**
+   * @param baseType
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setBaseType(final FullQualifiedName baseType) {
+    super.setBaseType(baseType);
+    return this;
+  }
+
+  /**
+   * @param isAbstract
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setAbstract(final boolean isAbstract) {
+    super.setAbstract(isAbstract);
+    return this;
+  }
+
+  /**
+   * @param properties
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setProperties(final List<Property> properties) {
+    super.setProperties(properties);
+    return this;
+  }
+
+  /**
+   * @param mapping
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setMapping(final Mapping mapping) {
+    super.setMapping(mapping);
+    return this;
+  }
+
+  /**
+   * @param documentation
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setDocumentation(final Documentation documentation) {
+    super.setDocumentation(documentation);
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link EntityType}
+   * @param annotationAttributes
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    super.setAnnotationAttributes(annotationAttributes);
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link EntityType}
+   * @param annotationElements
+   * @return {@link EntityType} for method chaining
+   */
+  @Override
+  public EntityType setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    super.setAnnotationElements(annotationElements);
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Facets.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Facets.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Facets.java
new file mode 100644
index 0000000..7dbfe2a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Facets.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+
+/**
+ * Objects of this class represent the facets an entity type, property or function import can have
+ * @author SAP AG
+ */
+public class Facets implements EdmFacets {
+
+  /** Specification default is TRUE but we won't set it here because 
+   * we want to know if it's set explicitly by an application. */
+  Boolean nullable;
+  String defaultValue;
+  Integer maxLength;
+  Boolean fixedLength;
+  Integer precision;
+  Integer scale;
+  Boolean unicode;
+  String collation;
+  EdmConcurrencyMode concurrencyMode;
+
+  @Override
+  public Boolean isNullable() {
+    return nullable;
+  }
+
+  @Override
+  public String getDefaultValue() {
+    return defaultValue;
+  }
+
+  @Override
+  public Integer getMaxLength() {
+    return maxLength;
+  }
+
+  @Override
+  public Boolean isFixedLength() {
+    return fixedLength;
+  }
+
+  @Override
+  public Integer getPrecision() {
+    return precision;
+  }
+
+  @Override
+  public Integer getScale() {
+    return scale;
+  }
+
+  @Override
+  public Boolean isUnicode() {
+    return unicode;
+  }
+
+  @Override
+  public String getCollation() {
+    return collation;
+  }
+
+  @Override
+  public EdmConcurrencyMode getConcurrencyMode() {
+    return concurrencyMode;
+  }
+
+  /**
+   * Sets if this {@link Facets} is nullable
+   * @param nullable
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setNullable(final Boolean nullable) {
+    this.nullable = nullable;
+    return this;
+  }
+
+  /**
+   * Sets the fixed length of this {@link Facets}
+   * @param fixedLength
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setFixedLength(final Boolean fixedLength) {
+    this.fixedLength = fixedLength;
+    return this;
+  }
+
+  /**
+   * Sets if this {@link Facets} is in Unicode
+   * @param unicode
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setUnicode(final Boolean unicode) {
+    this.unicode = unicode;
+    return this;
+  }
+
+  /**
+   * Sets the default value of this {@link Facets}
+   * @param defaultValue
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setDefaultValue(final String defaultValue) {
+    this.defaultValue = defaultValue;
+    return this;
+  }
+
+  /**
+   * Sets the maximum length of this {@link Facets}
+   * @param maxLength
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setMaxLength(final Integer maxLength) {
+    this.maxLength = maxLength;
+    return this;
+  }
+
+  /**
+   * Sets the precision of this {@link Facets}
+   * @param precision
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setPrecision(final Integer precision) {
+    this.precision = precision;
+    return this;
+  }
+
+  /**
+   * Sets the scale of this {@link Facets}
+   * @param scale
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setScale(final Integer scale) {
+    this.scale = scale;
+    return this;
+  }
+
+  /**
+   * Sets the collation of this {@link Facets}
+   * @param collation
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setCollation(final String collation) {
+    this.collation = collation;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmConcurrencyMode} of this {@link Facets}
+   * @param concurrencyMode
+   * @return {@link Facets} for method chaining
+   */
+  public Facets setConcurrencyMode(final EdmConcurrencyMode concurrencyMode) {
+    this.concurrencyMode = concurrencyMode;
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    final List<String> values = new ArrayList<String>();
+    if (nullable != null) {
+      values.add("Nullable=" + nullable);
+    }
+    if (defaultValue != null) {
+      values.add("DefaultValue=" + defaultValue);
+    }
+    if (maxLength != null) {
+      values.add("MaxLength=" + maxLength);
+    }
+    if (fixedLength != null) {
+      values.add("FixedLength=" + fixedLength);
+    }
+    if (precision != null) {
+      values.add("Precision=" + precision);
+    }
+    if (scale != null) {
+      values.add("Scale=" + scale);
+    }
+    if (unicode != null) {
+      values.add("Unicode=" + unicode);
+    }
+    if (collation != null) {
+      values.add("Collation=" + collation);
+    }
+    if (concurrencyMode != null) {
+      values.add("ConcurrencyMode=" + concurrencyMode);
+    }
+    return values.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImport.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImport.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImport.java
new file mode 100644
index 0000000..1cb5460
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImport.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent a function import
+ * @author SAP AG
+ */
+public class FunctionImport {
+
+  private String name;
+  private ReturnType returnType;
+  private String entitySet;
+  private String httpMethod;
+  private List<FunctionImportParameter> parameters;
+  private Mapping mapping;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name of this function import
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link ReturnType} of this function import
+   */
+  public ReturnType getReturnType() {
+    return returnType;
+  }
+
+  /**
+   * @return <b>String</b> name of the entity set
+   */
+  public String getEntitySet() {
+    return entitySet;
+  }
+
+  /**
+   * @return <b>String</b> name of  the used HTTP method
+   */
+  public String getHttpMethod() {
+    return httpMethod;
+  }
+
+  /**
+   * @return List<{@link FunctionImportParameter}>s of this function import
+   */
+  public List<FunctionImportParameter> getParameters() {
+    return parameters;
+  }
+
+  /**
+   * @return {@link Mapping} for this type
+   */
+  public Mapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name of this {@link FunctionImport}
+   * @param name
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the {@link ReturnType} of this {@link FunctionImport}
+   * @param returnType
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setReturnType(final ReturnType returnType) {
+    this.returnType = returnType;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EntitySet} of this {@link FunctionImport}
+   * @param entitySet
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setEntitySet(final String entitySet) {
+    this.entitySet = entitySet;
+    return this;
+  }
+
+  /**
+   * Sets the HTTP method of this {@link FunctionImport}
+   * @param httpMethod
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setHttpMethod(final String httpMethod) {
+    this.httpMethod = httpMethod;
+    return this;
+  }
+
+  /**
+   * Sets the {@link FunctionImportParameter}s of this {@link FunctionImport}
+   * @param parameters
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setParameters(final List<FunctionImportParameter> parameters) {
+    this.parameters = parameters;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Mapping}
+   * @param mapping
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setMapping(final Mapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation}
+   * @param documentation
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link FunctionImport}
+   * @param annotationAttributes
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link FunctionImport}
+   * @param annotationElements
+   * @return {@link FunctionImport} for method chaining
+   */
+  public FunctionImport setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImportParameter.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImportParameter.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImportParameter.java
new file mode 100644
index 0000000..eb97504
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/FunctionImportParameter.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+
+/**
+ * Objects of this class represent function import parameters
+ * @author SAP AG
+ */
+public class FunctionImportParameter {
+
+  private String name;
+  private String mode;
+  private EdmSimpleTypeKind type;
+  private EdmFacets facets;
+  private Mapping mapping;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name of the parameter
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return <b>String</b> mode of this parameter
+   */
+  public String getMode() {
+    return mode;
+  }
+
+  /**
+   * @return {@link EdmSimpleTypeKind} of this parameter
+   */
+  public EdmSimpleTypeKind getType() {
+    return type;
+  }
+
+  /**
+   * @return {@link EdmFacets} of this parameter
+   */
+  public EdmFacets getFacets() {
+    return facets;
+  }
+
+  /**
+   * @return {@link Mapping} of this parameter
+   */
+  public Mapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return collection of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return collection of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name of this {@link FunctionImportParameter}
+   * @param name
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the mode of this {@link FunctionImportParameter}
+   * @param mode
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setMode(final String mode) {
+    this.mode = mode;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmSimpleTypeKind} of this {@link FunctionImportParameter}
+   * @param type
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setType(final EdmSimpleTypeKind type) {
+    this.type = type;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmFacets} of this {@link FunctionImportParameter}
+   * @param facets
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setFacets(final EdmFacets facets) {
+    this.facets = facets;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Mapping} of this {@link FunctionImportParameter}
+   * @param mapping
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setMapping(final Mapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} of this {@link FunctionImportParameter}
+   * @param documentation
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationAttribute} for this {@link FunctionImportParameter}
+   * @param annotationAttributes
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the collection of {@link AnnotationElement} for this {@link FunctionImportParameter}
+   * @param annotationElements
+   * @return {@link FunctionImportParameter} for method chaining
+   */
+  public FunctionImportParameter setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Key.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Key.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Key.java
new file mode 100644
index 0000000..eeb6bb4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Key.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent a key for an entity type
+ * @author SAP AG
+ */
+public class Key {
+
+  private List<PropertyRef> keys;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return List<{@link PropertyRef}> references to the key properties
+   */
+  public List<PropertyRef> getKeys() {
+    return keys;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the {@link Property}s by their {@link PropertyRef} for this {@link Key}
+   * @param keys
+   * @return {@link Key} for method chaining
+   */
+  public Key setKeys(final List<PropertyRef> keys) {
+    this.keys = keys;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link Key}
+   * @param annotationAttributes
+   * @return {@link Key} for method chaining
+   */
+  public Key setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link Key}
+   * @param annotationElements
+   * @return {@link Key} for method chaining
+   */
+  public Key setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Mapping.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Mapping.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Mapping.java
new file mode 100644
index 0000000..a07944a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Mapping.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+
+/**
+ * Object of this class represent the mapping of a value to a MIME type.
+ * @author SAP AG
+ */
+public class Mapping implements EdmMapping {
+
+  private String value;
+  private String mimeType;
+  private Object object;
+
+  @Override
+  public String getInternalName() {
+    return value;
+  }
+
+  @Override
+  public String getMimeType() {
+    return mimeType;
+  }
+
+  @Override
+  public Object getObject() {
+    return object;
+  }
+
+  /**
+   * Sets the value for this {@link Mapping}.
+   * @param value
+   * @return {@link Mapping} for method chaining
+   */
+  public Mapping setInternalName(final String value) {
+    this.value = value;
+    return this;
+  }
+
+  /**
+   * Sets the mime type for this {@link Mapping}.
+   * @param mimeType
+   * @return {@link Mapping} for method chaining
+   */
+  public Mapping setMimeType(final String mimeType) {
+    this.mimeType = mimeType;
+    return this;
+  }
+
+  /**
+   * Sets an object. This method can be used by a provider to set whatever it wants to associate with this.
+   * @param object
+   * @return {@link Mapping} for method chaining
+   */
+  public Mapping setObject(final Object object) {
+    this.object = object;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/NavigationProperty.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/NavigationProperty.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/NavigationProperty.java
new file mode 100644
index 0000000..894a9c5
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/NavigationProperty.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this Class represent a navigation property
+ * @author SAP AG
+ */
+public class NavigationProperty {
+
+  private String name;
+  private FullQualifiedName relationship;
+  private String fromRole;
+  private String toRole;
+  private Documentation documentation;
+  private Mapping mapping;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name of this navigation property
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link FullQualifiedName} of the relationship
+   */
+  public FullQualifiedName getRelationship() {
+    return relationship;
+  }
+
+  /**
+   * @return <b>String</b> name of the role this navigation is comming from
+   */
+  public String getFromRole() {
+    return fromRole;
+  }
+
+  /**
+   * @return <b>String</b> name of the role this navigation is going to
+   */
+  public String getToRole() {
+    return toRole;
+  }
+
+  /**
+   * @return {@link Mapping} of this navigation property
+   */
+  public Mapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name of this {@link NavigationProperty}
+   * @param name
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the {@link FullQualifiedName} for the relationship of this {@link NavigationProperty}
+   * @param relationship
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setRelationship(final FullQualifiedName relationship) {
+    this.relationship = relationship;
+    return this;
+  }
+
+  /**
+   * Sets the role this {@link NavigationProperty} is comming from
+   * @param fromRole
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setFromRole(final String fromRole) {
+    this.fromRole = fromRole;
+    return this;
+  }
+
+  /**
+   * Sets the role this {@link NavigationProperty} is going to
+   * @param toRole
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setToRole(final String toRole) {
+    this.toRole = toRole;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Mapping} for this {@link NavigationProperty}
+   * @param mapping
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setMapping(final Mapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link NavigationProperty}
+   * @param documentation
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link NavigationProperty}
+   * @param annotationAttributes
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link NavigationProperty}
+   * @param annotationElements
+   * @return {@link NavigationProperty} for method chaining
+   */
+  public NavigationProperty setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/OnDelete.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/OnDelete.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/OnDelete.java
new file mode 100644
index 0000000..f21a559
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/OnDelete.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAction;
+
+/**
+ * Objects of this class represent an OnDelete Action
+ * @author SAP AG
+ */
+public class OnDelete {
+
+  private EdmAction action;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return {@link EdmAction} action
+   */
+  public EdmAction getAction() {
+    return action;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the {@link EdmAction} for this {@link OnDelete}
+   * @param action
+   * @return {@link OnDelete} for method chaining
+   */
+  public OnDelete setAction(final EdmAction action) {
+    this.action = action;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link OnDelete}
+   * @param documentation
+   * @return {@link OnDelete} for method chaining
+   */
+  public OnDelete setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link OnDelete}
+   * @param annotationAttributes
+   * @return {@link OnDelete} for method chaining
+   */
+  public OnDelete setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link OnDelete}
+   * @param annotationElements
+   * @return {@link OnDelete} for method chaining
+   */
+  public OnDelete setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Property.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Property.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Property.java
new file mode 100644
index 0000000..ee1dd27
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/Property.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+
+/**
+ * Objects of this class represent a property of an entity type
+ * @author SAP AG
+ */
+public abstract class Property {
+
+  private String name;
+  private EdmFacets facets;
+  private CustomizableFeedMappings customizableFeedMappings;
+  private String mimeType;
+  private Mapping mapping;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name of this property
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return {@link EdmFacets} of this property
+   */
+  public EdmFacets getFacets() {
+    return facets;
+  }
+
+  /**
+   * @return {@link CustomizableFeedMappings} of this property
+   */
+  public CustomizableFeedMappings getCustomizableFeedMappings() {
+    return customizableFeedMappings;
+  }
+
+  /**
+   * @return <b>String</b> mime type of this property
+   */
+  public String getMimeType() {
+    return mimeType;
+  }
+
+  /**
+   * @return {@link Mapping} of this property
+   */
+  public Mapping getMapping() {
+    return mapping;
+  }
+
+  /**
+   * @return {@link Documentation} of this property
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name for this {@link Property}
+   * @param name
+   * @return {@link Property} for method chaining
+   */
+  public Property setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Facets} for this {@link Property}
+   * @param facets
+   * @return {@link Property} for method chaining
+   */
+  public Property setFacets(final EdmFacets facets) {
+    this.facets = facets;
+    return this;
+  }
+
+  /**
+   * Sets the {@link CustomizableFeedMappings} for this {@link Property}
+   * @param customizableFeedMappings
+   * @return {@link Property} for method chaining
+   */
+  public Property setCustomizableFeedMappings(final CustomizableFeedMappings customizableFeedMappings) {
+    this.customizableFeedMappings = customizableFeedMappings;
+    return this;
+  }
+
+  /**
+   * Sets the mime type for this {@link Property}
+   * @param mimeType
+   * @return {@link Property} for method chaining
+   */
+  public Property setMimeType(final String mimeType) {
+    this.mimeType = mimeType;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Mapping} for this {@link Property}
+   * @param mapping
+   * @return {@link Property} for method chaining
+   */
+  public Property setMapping(final Mapping mapping) {
+    this.mapping = mapping;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} for this {@link Property}
+   * @param documentation
+   * @return {@link Property} for method chaining
+   */
+  public Property setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link Property}
+   * @param annotationAttributes
+   * @return {@link Property} for method chaining
+   */
+  public Property setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link Property}
+   * @param annotationElements
+   * @return {@link Property} for method chaining
+   */
+  public Property setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/PropertyRef.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/PropertyRef.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/PropertyRef.java
new file mode 100644
index 0000000..6227dd6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/PropertyRef.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this class represent a reference to a property via its name
+ * @author SAP AG
+ *
+ */
+public class PropertyRef {
+
+  private String name;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> name of the {@link Property} this {@link PropertyRef} is referencing to
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the name of the {@link Property} this {@link PropertyRef} is pointing to
+   * @param name
+   * @return {@link PropertyRef} for method chaining
+   */
+  public PropertyRef setName(final String name) {
+    this.name = name;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link PropertyRef}
+   * @param annotationAttributes
+   * @return {@link PropertyRef} for method chaining
+   */
+  public PropertyRef setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link PropertyRef}
+   * @param annotationElements
+   * @return {@link PropertyRef} for method chaining
+   */
+  public PropertyRef setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraint.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraint.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraint.java
new file mode 100644
index 0000000..7bd5baa
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraint.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this Class represent a referential constraint
+ * @author SAP AG
+ */
+public class ReferentialConstraint {
+
+  private ReferentialConstraintRole principal;
+  private ReferentialConstraintRole dependent;
+  private Documentation documentation;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return {@link ReferentialConstraintRole} the principal of this {@link ReferentialConstraint}
+   */
+  public ReferentialConstraintRole getPrincipal() {
+    return principal;
+  }
+
+  /**
+   * @return {@link ReferentialConstraintRole} the dependent of this {@link ReferentialConstraint}
+   */
+  public ReferentialConstraintRole getDependent() {
+    return dependent;
+  }
+
+  /**
+   * @return {@link Documentation} documentation
+   */
+  public Documentation getDocumentation() {
+    return documentation;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the principal {@link ReferentialConstraintRole} for this {@link ReferentialConstraint}
+   * @param principal
+   * @return {@link ReferentialConstraint} for method chaining
+   */
+  public ReferentialConstraint setPrincipal(final ReferentialConstraintRole principal) {
+    this.principal = principal;
+    return this;
+  }
+
+  /**
+   * Sets the dependent {@link ReferentialConstraintRole} for this {@link ReferentialConstraint}
+   * @param dependent
+   * @return {@link ReferentialConstraint} for method chaining
+   */
+  public ReferentialConstraint setDependent(final ReferentialConstraintRole dependent) {
+    this.dependent = dependent;
+    return this;
+  }
+
+  /**
+   * Sets the {@link Documentation} of this {@link ReferentialConstraint}
+   * @param documentation
+   * @return {@link ReferentialConstraint} for method chaining
+   */
+  public ReferentialConstraint setDocumentation(final Documentation documentation) {
+    this.documentation = documentation;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link ReferentialConstraint}
+   * @param annotationAttributes
+   * @return {@link ReferentialConstraint} for method chaining
+   */
+  public ReferentialConstraint setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link ReferentialConstraint}
+   * @param annotationElements
+   * @return {@link ReferentialConstraint} for method chaining
+   */
+  public ReferentialConstraint setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraintRole.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraintRole.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraintRole.java
new file mode 100644
index 0000000..cdd7397
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReferentialConstraintRole.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import java.util.List;
+
+/**
+ * Objects of this Class represent a referential constraint role
+ * @author SAP AG
+ */
+public class ReferentialConstraintRole {
+
+  private String role;
+  private List<PropertyRef> propertyRefs;
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<AnnotationElement> annotationElements;
+
+  /**
+   * @return <b>String</b> role of this {@link ReferentialConstraintRole}
+   */
+  public String getRole() {
+    return role;
+  }
+
+  /**
+   * @return List<{@link PropertyRef}> for this {@link ReferentialConstraintRole}
+   */
+  public List<PropertyRef> getPropertyRefs() {
+    return propertyRefs;
+  }
+
+  /**
+   * @return List of {@link AnnotationAttribute} annotation attributes
+   */
+  public List<AnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  /**
+   * @return List of {@link AnnotationElement} annotation elements
+   */
+  public List<AnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  /**
+   * Sets the role of this {@link ReferentialConstraintRole}
+   * @param role
+   * @return {@link ReferentialConstraintRole} for method chaining
+   */
+  public ReferentialConstraintRole setRole(final String role) {
+    this.role = role;
+    return this;
+  }
+
+  /**
+   * Sets the {@link PropertyRef}s of this {@link ReferentialConstraintRole}
+   * @param propertyRef
+   * @return {@link ReferentialConstraintRole} for method chaining
+   */
+  public ReferentialConstraintRole setPropertyRefs(final List<PropertyRef> propertyRef) {
+    propertyRefs = propertyRef;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationAttribute} for this {@link ReferentialConstraintRole}
+   * @param annotationAttributes
+   * @return {@link ReferentialConstraintRole} for method chaining
+   */
+  public ReferentialConstraintRole setAnnotationAttributes(final List<AnnotationAttribute> annotationAttributes) {
+    this.annotationAttributes = annotationAttributes;
+    return this;
+  }
+
+  /**
+   * Sets the List of {@link AnnotationElement} for this {@link ReferentialConstraintRole}
+   * @param annotationElements
+   * @return {@link ReferentialConstraintRole} for method chaining
+   */
+  public ReferentialConstraintRole setAnnotationElements(final List<AnnotationElement> annotationElements) {
+    this.annotationElements = annotationElements;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReturnType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReturnType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReturnType.java
new file mode 100644
index 0000000..2b4df05
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/provider/ReturnType.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.api.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+
+/**
+ * Objects of this Class represent a return type of a function import
+ * @author SAP AG
+ */
+public class ReturnType {
+
+  private FullQualifiedName typeName;
+  private EdmMultiplicity multiplicity;
+
+  /**
+   * @return {@link FullQualifiedName} type of this {@link ReturnType}
+   */
+  public FullQualifiedName getTypeName() {
+    return typeName;
+  }
+
+  /**
+   * @return {@link EdmMultiplicity} of this {@link ReturnType}
+   */
+  public EdmMultiplicity getMultiplicity() {
+    return multiplicity;
+  }
+
+  /**
+   * Sets the type  of this {@link ReturnType} via the types {@link FullQualifiedName}
+   * @param qualifiedName
+   * @return {@link ReturnType} for method chaining
+   */
+  public ReturnType setTypeName(final FullQualifiedName qualifiedName) {
+    typeName = qualifiedName;
+    return this;
+  }
+
+  /**
+   * Sets the {@link EdmMultiplicity} of this {@link ReturnType}
+   * @param multiplicity
+   * @return {@link ReturnType} for method chaining
+   */
+  public ReturnType setMultiplicity(final EdmMultiplicity multiplicity) {
+    this.multiplicity = multiplicity;
+    return this;
+  }
+
+  @Override
+  public String toString() {
+    if (EdmMultiplicity.MANY == multiplicity) {
+      return "Collection(" + typeName + ")";
+    } else {
+      return typeName.toString();
+    }
+  }
+
+}


[11/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
new file mode 100644
index 0000000..f437ace
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriParserImpl.java
@@ -0,0 +1,843 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriNotMatchingException;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.api.uri.UriSyntaxException;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.core.commons.Decoder;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+import org.apache.olingo.odata2.core.uri.expression.FilterParserImpl;
+import org.apache.olingo.odata2.core.uri.expression.OrderByParserImpl;
+
+/**
+ * Parser for the OData part of the URL.
+ * @author SAP AG
+ */
+public class UriParserImpl extends UriParser {
+
+  private static final Pattern INITIAL_SEGMENT_PATTERN = Pattern.compile("(?:([^.()]+)\\.)?([^.()]+)(?:\\((.+)\\)|(\\(\\)))?");
+  private static final Pattern NAVIGATION_SEGMENT_PATTERN = Pattern.compile("([^()]+)(?:\\((.+)\\)|(\\(\\)))?");
+  private static final Pattern NAMED_VALUE_PATTERN = Pattern.compile("(?:([^=]+)=)?([^=]+)");
+
+  private final Edm edm;
+  private final EdmSimpleTypeFacade simpleTypeFacade;
+  private List<String> pathSegments;
+  private String currentPathSegment;
+  private UriInfoImpl uriResult;
+  private Map<SystemQueryOption, String> systemQueryOptions;
+  private Map<String, String> otherQueryParameters;
+
+  public UriParserImpl(final Edm edm) {
+    this.edm = edm;
+    simpleTypeFacade = new EdmSimpleTypeFacadeImpl();
+  }
+
+  /**
+   * Parse the URI part after an OData service root,
+   * already splitted into path segments and query parameters.
+   * @param pathSegments    the {@link PathSegment}s of the resource path,
+   *                        potentially percent-encoded
+   * @param queryParameters the query parameters, already percent-decoded
+   * @return a {@link UriInfoImpl} instance containing the parsed information
+   */
+  @Override
+  public UriInfo parse(final List<PathSegment> pathSegments, final Map<String, String> queryParameters) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    this.pathSegments = copyPathSegmentList(pathSegments);
+    systemQueryOptions = new HashMap<SystemQueryOption, String>();
+    otherQueryParameters = new HashMap<String, String>();
+    uriResult = new UriInfoImpl();
+
+    preparePathSegments();
+
+    handleResourcePath();
+
+    distributeQueryParameters(queryParameters);
+    checkSystemQueryOptionsCompatibility();
+    handleSystemQueryOptions();
+    handleOtherQueryParameters();
+
+    return uriResult;
+  }
+
+  private void preparePathSegments() throws UriSyntaxException {
+    // Remove an empty path segment at the start of the OData part of the resource path.
+    if (!pathSegments.isEmpty() && pathSegments.get(0).equals("")) {
+      pathSegments.remove(0);
+    }
+
+    // Remove an empty path segment at the end of the resource path,
+    // although there is nothing in the OData specification that would allow that.
+    if (!pathSegments.isEmpty() && pathSegments.get(pathSegments.size() - 1).equals("")) {
+      pathSegments.remove(pathSegments.size() - 1);
+    }
+
+    // Intermediate empty path segments are an error, however.
+    for (String pathSegment : pathSegments) {
+      if (pathSegment.equals("")) {
+        throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+      }
+    }
+  }
+
+  private void handleResourcePath() throws UriSyntaxException, UriNotMatchingException, EdmException {
+    if (pathSegments.isEmpty()) {
+      uriResult.setUriType(UriType.URI0);
+    } else {
+
+      currentPathSegment = pathSegments.remove(0);
+
+      if ("$metadata".equals(currentPathSegment)) {
+        ensureLastSegment();
+        uriResult.setUriType(UriType.URI8);
+
+      } else if ("$batch".equals(currentPathSegment)) {
+        ensureLastSegment();
+        uriResult.setUriType(UriType.URI9);
+
+      } else {
+        handleNormalInitialSegment();
+      }
+    }
+  }
+
+  private void handleNormalInitialSegment() throws UriSyntaxException, UriNotMatchingException, EdmException {
+    final Matcher matcher = INITIAL_SEGMENT_PATTERN.matcher(currentPathSegment);
+    if (!matcher.matches()) {
+      throw new UriNotMatchingException(UriNotMatchingException.MATCHPROBLEM.addContent(currentPathSegment));
+    }
+
+    final String entityContainerName = percentDecode(matcher.group(1));
+    final String segmentName = percentDecode(matcher.group(2));
+    final String keyPredicate = matcher.group(3);
+    final String emptyParentheses = matcher.group(4);
+
+    final EdmEntityContainer entityContainer =
+        entityContainerName == null ? edm.getDefaultEntityContainer() : edm.getEntityContainer(entityContainerName);
+    if (entityContainer == null) {
+      throw new UriNotMatchingException(UriNotMatchingException.CONTAINERNOTFOUND.addContent(entityContainerName));
+    }
+    uriResult.setEntityContainer(entityContainer);
+
+    final EdmEntitySet entitySet = entityContainer.getEntitySet(segmentName);
+    if (entitySet != null) {
+      uriResult.setStartEntitySet(entitySet);
+      handleEntitySet(entitySet, keyPredicate);
+    } else {
+      final EdmFunctionImport functionImport = entityContainer.getFunctionImport(segmentName);
+      if (functionImport == null) {
+        throw new UriNotMatchingException(UriNotMatchingException.NOTFOUND.addContent(segmentName));
+      }
+      uriResult.setFunctionImport(functionImport);
+      handleFunctionImport(functionImport, emptyParentheses, keyPredicate);
+    }
+  }
+
+  private void handleEntitySet(final EdmEntitySet entitySet, final String keyPredicate) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    final EdmEntityType entityType = entitySet.getEntityType();
+
+    uriResult.setTargetType(entityType);
+    uriResult.setTargetEntitySet(entitySet);
+
+    if (keyPredicate == null) {
+      if (pathSegments.isEmpty()) {
+        uriResult.setUriType(UriType.URI1);
+      } else {
+        currentPathSegment = pathSegments.remove(0);
+        checkCount();
+        if (uriResult.isCount()) {
+          uriResult.setUriType(UriType.URI15);
+        } else {
+          throw new UriSyntaxException(UriSyntaxException.ENTITYSETINSTEADOFENTITY.addContent(entitySet.getName()));
+        }
+      }
+    } else {
+      uriResult.setKeyPredicates(parseKey(keyPredicate, entityType));
+      if (pathSegments.isEmpty()) {
+        uriResult.setUriType(UriType.URI2);
+      } else {
+        handleNavigationPathOptions();
+      }
+    }
+  }
+
+  private void handleNavigationPathOptions() throws UriSyntaxException, UriNotMatchingException, EdmException {
+    currentPathSegment = pathSegments.remove(0);
+
+    checkCount();
+    if (uriResult.isCount()) {
+      uriResult.setUriType(UriType.URI16); // Count of multiple entities is handled elsewhere
+
+    } else if ("$value".equals(currentPathSegment)) {
+      if (uriResult.getTargetEntitySet().getEntityType().hasStream()) {
+        ensureLastSegment();
+        uriResult.setUriType(UriType.URI17);
+        uriResult.setValue(true);
+      } else {
+        throw new UriSyntaxException(UriSyntaxException.NOMEDIARESOURCE);
+      }
+
+    } else if ("$links".equals(currentPathSegment)) {
+      uriResult.setLinks(true);
+      if (pathSegments.isEmpty()) {
+        throw new UriSyntaxException(UriSyntaxException.MUSTNOTBELASTSEGMENT.addContent(currentPathSegment));
+      }
+      currentPathSegment = pathSegments.remove(0);
+      handleNavigationProperties();
+
+    } else {
+      handleNavigationProperties();
+    }
+  }
+
+  private void handleNavigationProperties() throws UriSyntaxException, UriNotMatchingException, EdmException {
+
+    final Matcher matcher = NAVIGATION_SEGMENT_PATTERN.matcher(currentPathSegment);
+    if (!matcher.matches()) {
+      throw new UriNotMatchingException(UriNotMatchingException.MATCHPROBLEM.addContent(currentPathSegment));
+    }
+
+    final String navigationPropertyName = percentDecode(matcher.group(1));
+    final String keyPredicateName = matcher.group(2);
+    final String emptyParentheses = matcher.group(3);
+
+    final EdmTyped property = uriResult.getTargetEntitySet().getEntityType().getProperty(navigationPropertyName);
+    if (property == null) {
+      throw new UriNotMatchingException(UriNotMatchingException.PROPERTYNOTFOUND.addContent(navigationPropertyName));
+    }
+
+    switch (property.getType().getKind()) {
+    case SIMPLE:
+    case COMPLEX:
+      if (keyPredicateName != null || emptyParentheses != null) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(currentPathSegment));
+      }
+      if (uriResult.isLinks()) {
+        throw new UriSyntaxException(UriSyntaxException.NONAVIGATIONPROPERTY.addContent(property));
+      }
+
+      handlePropertyPath((EdmProperty) property);
+      break;
+
+    case ENTITY: // navigation properties point to entities
+      final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) property;
+      if (keyPredicateName != null || emptyParentheses != null) {
+        if (navigationProperty.getMultiplicity() != EdmMultiplicity.MANY) {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(currentPathSegment));
+        }
+      }
+
+      addNavigationSegment(keyPredicateName, navigationProperty);
+
+      boolean many = false;
+      if (navigationProperty.getMultiplicity() == EdmMultiplicity.MANY) {
+        many = keyPredicateName == null;
+      }
+
+      if (pathSegments.isEmpty()) {
+        if (many) {
+          if (uriResult.isLinks()) {
+            uriResult.setUriType(UriType.URI7B);
+          } else {
+            uriResult.setUriType(UriType.URI6B);
+          }
+        } else if (uriResult.isLinks()) {
+          uriResult.setUriType(UriType.URI7A);
+        } else {
+          uriResult.setUriType(UriType.URI6A);
+        }
+      } else if (many || uriResult.isLinks()) {
+        currentPathSegment = pathSegments.remove(0);
+        checkCount();
+        if (!uriResult.isCount()) {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(currentPathSegment));
+        }
+        if (many) {
+          if (uriResult.isLinks()) {
+            uriResult.setUriType(UriType.URI50B);
+          } else {
+            uriResult.setUriType(UriType.URI15);
+          }
+        } else {
+          uriResult.setUriType(UriType.URI50A);
+        }
+      } else {
+        handleNavigationPathOptions();
+      }
+      break;
+
+    default:
+      throw new UriSyntaxException(UriSyntaxException.INVALIDPROPERTYTYPE.addContent(property.getType().getKind()));
+    }
+  }
+
+  private void addNavigationSegment(final String keyPredicateName, final EdmNavigationProperty navigationProperty) throws UriSyntaxException, EdmException {
+    final EdmEntitySet targetEntitySet = uriResult.getTargetEntitySet().getRelatedEntitySet(navigationProperty);
+    final EdmEntityType targetEntityType = targetEntitySet.getEntityType();
+    uriResult.setTargetEntitySet(targetEntitySet);
+    uriResult.setTargetType(targetEntityType);
+
+    NavigationSegmentImpl navigationSegment = new NavigationSegmentImpl();
+    navigationSegment.setEntitySet(targetEntitySet);
+    navigationSegment.setNavigationProperty(navigationProperty);
+    if (keyPredicateName != null) {
+      navigationSegment.setKeyPredicates(parseKey(keyPredicateName, targetEntityType));
+    }
+    uriResult.addNavigationSegment(navigationSegment);
+  }
+
+  private void handlePropertyPath(final EdmProperty property) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    uriResult.addProperty(property);
+    final EdmType type = property.getType();
+
+    if (pathSegments.isEmpty()) {
+      if (type.getKind() == EdmTypeKind.SIMPLE) {
+        if (uriResult.getPropertyPath().size() == 1) {
+          uriResult.setUriType(UriType.URI5);
+        } else {
+          uriResult.setUriType(UriType.URI4);
+        }
+      } else if (type.getKind() == EdmTypeKind.COMPLEX) {
+        uriResult.setUriType(UriType.URI3);
+      } else {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDPROPERTYTYPE.addContent(type.getKind()));
+      }
+      uriResult.setTargetType(type);
+    } else {
+
+      currentPathSegment = percentDecode(pathSegments.remove(0));
+      switch (type.getKind()) {
+      case SIMPLE:
+        if ("$value".equals(currentPathSegment)) {
+          ensureLastSegment();
+          uriResult.setValue(true);
+          if (uriResult.getPropertyPath().size() == 1) {
+            uriResult.setUriType(UriType.URI5);
+          } else {
+            uriResult.setUriType(UriType.URI4);
+          }
+        } else {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(currentPathSegment));
+        }
+        uriResult.setTargetType(type);
+        break;
+
+      case COMPLEX:
+        final EdmProperty nextProperty = (EdmProperty) ((EdmComplexType) type).getProperty(currentPathSegment);
+        if (nextProperty == null) {
+          throw new UriNotMatchingException(UriNotMatchingException.PROPERTYNOTFOUND.addContent(currentPathSegment));
+        }
+
+        handlePropertyPath(nextProperty);
+        break;
+
+      default:
+        throw new UriSyntaxException(UriSyntaxException.INVALIDPROPERTYTYPE.addContent(type.getKind()));
+      }
+    }
+  }
+
+  private void ensureLastSegment() throws UriSyntaxException {
+    if (!pathSegments.isEmpty()) {
+      throw new UriSyntaxException(UriSyntaxException.MUSTBELASTSEGMENT.addContent(currentPathSegment));
+    }
+  }
+
+  private void checkCount() throws UriSyntaxException {
+    if ("$count".equals(currentPathSegment)) {
+      if (pathSegments.isEmpty()) {
+        uriResult.setCount(true);
+      } else {
+        throw new UriSyntaxException(UriSyntaxException.MUSTBELASTSEGMENT.addContent(currentPathSegment));
+      }
+    }
+  }
+
+  private ArrayList<KeyPredicate> parseKey(final String keyPredicate, final EdmEntityType entityType) throws UriSyntaxException, EdmException {
+    final List<EdmProperty> keyProperties = entityType.getKeyProperties();
+    ArrayList<EdmProperty> parsedKeyProperties = new ArrayList<EdmProperty>();
+    ArrayList<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+
+    for (final String key : keyPredicate.split(",", -1)) {
+
+      final Matcher matcher = NAMED_VALUE_PATTERN.matcher(key);
+      if (!matcher.matches()) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDKEYPREDICATE.addContent(keyPredicate));
+      }
+
+      String name = percentDecode(matcher.group(1));
+      final String value = percentDecode(matcher.group(2));
+
+      if (name == null) {
+        if (keyProperties.size() == 1) {
+          name = keyProperties.get(0).getName();
+        } else {
+          throw new UriSyntaxException(UriSyntaxException.MISSINGKEYPREDICATENAME.addContent(key));
+        }
+      }
+
+      EdmProperty keyProperty = null;
+      for (final EdmProperty testKeyProperty : keyProperties) {
+        if (testKeyProperty.getName().equals(name)) {
+          keyProperty = testKeyProperty;
+          break;
+        }
+      }
+      if (keyProperty == null) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDKEYPREDICATE.addContent(keyPredicate));
+      }
+      if (parsedKeyProperties.contains(keyProperty)) {
+        throw new UriSyntaxException(UriSyntaxException.DUPLICATEKEYNAMES.addContent(keyPredicate));
+      }
+      parsedKeyProperties.add(keyProperty);
+
+      final EdmLiteral uriLiteral = parseLiteral(value, (EdmSimpleType) keyProperty.getType());
+      keyPredicates.add(new KeyPredicateImpl(uriLiteral.getLiteral(), keyProperty));
+    }
+
+    if (parsedKeyProperties.size() != keyProperties.size()) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDKEYPREDICATE.addContent(keyPredicate));
+    }
+
+    return keyPredicates;
+  }
+
+  private void handleFunctionImport(final EdmFunctionImport functionImport, final String emptyParentheses, final String keyPredicate) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    final EdmTyped returnType = functionImport.getReturnType();
+    final EdmType type = returnType.getType();
+    final boolean isCollection = returnType.getMultiplicity() == EdmMultiplicity.MANY;
+
+    if (type.getKind() == EdmTypeKind.ENTITY && isCollection) {
+      handleEntitySet(functionImport.getEntitySet(), keyPredicate);
+      return;
+    }
+
+    if (emptyParentheses != null) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(emptyParentheses));
+    }
+
+    uriResult.setTargetType(type);
+    switch (type.getKind()) {
+    case SIMPLE:
+      uriResult.setUriType(isCollection ? UriType.URI13 : UriType.URI14);
+      break;
+    case COMPLEX:
+      uriResult.setUriType(isCollection ? UriType.URI11 : UriType.URI12);
+      break;
+    case ENTITY:
+      uriResult.setUriType(UriType.URI10);
+      break;
+    default:
+      throw new UriSyntaxException(UriSyntaxException.INVALIDRETURNTYPE.addContent(type.getKind()));
+    }
+
+    if (!pathSegments.isEmpty()) {
+      if (uriResult.getUriType() == UriType.URI14) {
+        currentPathSegment = pathSegments.remove(0);
+        if ("$value".equals(currentPathSegment)) {
+          uriResult.setValue(true);
+        } else {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(currentPathSegment));
+        }
+      }
+    }
+    ensureLastSegment();
+  }
+
+  private void distributeQueryParameters(final Map<String, String> queryParameters) throws UriSyntaxException {
+    for (final String queryOptionString : queryParameters.keySet()) {
+      final String value = queryParameters.get(queryOptionString);
+      if (queryOptionString.startsWith("$")) {
+        SystemQueryOption queryOption;
+        try {
+          queryOption = SystemQueryOption.valueOf(queryOptionString);
+        } catch (IllegalArgumentException e) {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDSYSTEMQUERYOPTION.addContent(queryOptionString), e);
+        }
+        if ("".equals(value)) {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDNULLVALUE.addContent(queryOptionString));
+        } else {
+          systemQueryOptions.put(queryOption, value);
+        }
+      } else {
+        otherQueryParameters.put(queryOptionString, value);
+      }
+    }
+  }
+
+  private void checkSystemQueryOptionsCompatibility() throws UriSyntaxException {
+    final UriType uriType = uriResult.getUriType();
+
+    for (SystemQueryOption queryOption : systemQueryOptions.keySet()) {
+
+      if (queryOption == SystemQueryOption.$format && (uriType == UriType.URI4 || uriType == UriType.URI5) && uriResult.isValue()) {
+        throw new UriSyntaxException(UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION.addContent(queryOption));
+      }
+
+      if (!uriType.isCompatible(queryOption)) {
+        throw new UriSyntaxException(UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION.addContent(queryOption));
+      }
+    }
+  }
+
+  private void handleSystemQueryOptions() throws UriSyntaxException, UriNotMatchingException, EdmException {
+
+    for (SystemQueryOption queryOption : systemQueryOptions.keySet()) {
+      switch (queryOption) {
+      case $format:
+        handleSystemQueryOptionFormat(systemQueryOptions.get(SystemQueryOption.$format));
+        break;
+      case $filter:
+        handleSystemQueryOptionFilter(systemQueryOptions.get(SystemQueryOption.$filter));
+        break;
+      case $inlinecount:
+        handleSystemQueryOptionInlineCount(systemQueryOptions.get(SystemQueryOption.$inlinecount));
+        break;
+      case $orderby:
+        handleSystemQueryOptionOrderBy(systemQueryOptions.get(SystemQueryOption.$orderby));
+        break;
+      case $skiptoken:
+        handleSystemQueryOptionSkipToken(systemQueryOptions.get(SystemQueryOption.$skiptoken));
+        break;
+      case $skip:
+        handleSystemQueryOptionSkip(systemQueryOptions.get(SystemQueryOption.$skip));
+        break;
+      case $top:
+        handleSystemQueryOptionTop(systemQueryOptions.get(SystemQueryOption.$top));
+        break;
+      case $expand:
+        handleSystemQueryOptionExpand(systemQueryOptions.get(SystemQueryOption.$expand));
+        break;
+      case $select:
+        handleSystemQueryOptionSelect(systemQueryOptions.get(SystemQueryOption.$select));
+        break;
+      default:
+        throw new ODataRuntimeException("Invalid System Query Option " + queryOption);
+      }
+    }
+  }
+
+  private void handleSystemQueryOptionFormat(final String format) throws UriSyntaxException {
+    uriResult.setFormat(format);
+  }
+
+  private void handleSystemQueryOptionFilter(final String filter) throws UriSyntaxException {
+    final EdmType targetType = uriResult.getTargetType();
+    if (targetType instanceof EdmEntityType) {
+      try {
+        uriResult.setFilter(new FilterParserImpl((EdmEntityType) targetType).parseFilterString(filter, true));
+      } catch (ExpressionParserException e) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDFILTEREXPRESSION.addContent(filter), e);
+      } catch (ODataMessageException e) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDFILTEREXPRESSION.addContent(filter), e);
+      }
+    }
+  }
+
+  private void handleSystemQueryOptionOrderBy(final String orderBy) throws UriSyntaxException {
+    final EdmType targetType = uriResult.getTargetType();
+    if (targetType instanceof EdmEntityType) {
+      try {
+        uriResult.setOrderBy(parseOrderByString((EdmEntityType) targetType, orderBy));
+      } catch (ExpressionParserException e) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDORDERBYEXPRESSION.addContent(orderBy), e);
+      } catch (ODataMessageException e) {
+        throw new UriSyntaxException(UriSyntaxException.INVALIDORDERBYEXPRESSION.addContent(orderBy), e);
+      }
+    }
+  }
+
+  private void handleSystemQueryOptionInlineCount(final String inlineCount) throws UriSyntaxException {
+    if ("allpages".equals(inlineCount)) {
+      uriResult.setInlineCount(InlineCount.ALLPAGES);
+    } else if ("none".equals(inlineCount)) {
+      uriResult.setInlineCount(InlineCount.NONE);
+    } else {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDVALUE.addContent(inlineCount));
+    }
+  }
+
+  private void handleSystemQueryOptionSkipToken(final String skiptoken) throws UriSyntaxException {
+    uriResult.setSkipToken(skiptoken);
+  }
+
+  private void handleSystemQueryOptionSkip(final String skip) throws UriSyntaxException {
+    try {
+      uriResult.setSkip(Integer.valueOf(skip));
+    } catch (NumberFormatException e) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDVALUE.addContent(skip), e);
+    }
+
+    if (skip.startsWith("-")) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDNEGATIVEVALUE.addContent(skip));
+    } else if (skip.startsWith("+")) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDVALUE.addContent(skip));
+    }
+  }
+
+  private void handleSystemQueryOptionTop(final String top) throws UriSyntaxException {
+    try {
+      uriResult.setTop(Integer.valueOf(top));
+    } catch (NumberFormatException e) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDVALUE.addContent(top), e);
+    }
+
+    if (top.startsWith("-")) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDNEGATIVEVALUE.addContent(top));
+    } else if (top.startsWith("+")) {
+      throw new UriSyntaxException(UriSyntaxException.INVALIDVALUE.addContent(top));
+    }
+  }
+
+  private void handleSystemQueryOptionExpand(final String expandStatement) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    ArrayList<ArrayList<NavigationPropertySegment>> expand = new ArrayList<ArrayList<NavigationPropertySegment>>();
+
+    if (expandStatement.startsWith(",") || expandStatement.endsWith(",")) {
+      throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+    }
+
+    for (String expandItemString : expandStatement.split(",")) {
+      expandItemString = expandItemString.trim();
+      if ("".equals(expandItemString)) {
+        throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+      }
+      if (expandItemString.startsWith("/") || expandItemString.endsWith("/")) {
+        throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+      }
+
+      ArrayList<NavigationPropertySegment> expandNavigationProperties = new ArrayList<NavigationPropertySegment>();
+      EdmEntitySet fromEntitySet = uriResult.getTargetEntitySet();
+
+      for (String expandPropertyName : expandItemString.split("/")) {
+        if ("".equals(expandPropertyName)) {
+          throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+        }
+
+        final EdmTyped property = fromEntitySet.getEntityType().getProperty(expandPropertyName);
+        if (property == null) {
+          throw new UriNotMatchingException(UriNotMatchingException.PROPERTYNOTFOUND.addContent(expandPropertyName));
+        }
+        if (property.getType().getKind() == EdmTypeKind.ENTITY) {
+          final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) property;
+          fromEntitySet = fromEntitySet.getRelatedEntitySet(navigationProperty);
+          NavigationPropertySegmentImpl propertySegment = new NavigationPropertySegmentImpl();
+          propertySegment.setNavigationProperty(navigationProperty);
+          propertySegment.setTargetEntitySet(fromEntitySet);
+          expandNavigationProperties.add(propertySegment);
+        } else {
+          throw new UriSyntaxException(UriSyntaxException.NONAVIGATIONPROPERTY.addContent(expandPropertyName));
+        }
+      }
+      expand.add(expandNavigationProperties);
+    }
+    uriResult.setExpand(expand);
+  }
+
+  private void handleSystemQueryOptionSelect(final String selectStatement) throws UriSyntaxException, UriNotMatchingException, EdmException {
+    ArrayList<SelectItem> select = new ArrayList<SelectItem>();
+
+    if (selectStatement.startsWith(",") || selectStatement.endsWith(",")) {
+      throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+    }
+
+    for (String selectItemString : selectStatement.split(",")) {
+      selectItemString = selectItemString.trim();
+      if ("".equals(selectItemString)) {
+        throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+      }
+      if (selectItemString.startsWith("/") || selectItemString.endsWith("/")) {
+        throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+      }
+
+      SelectItemImpl selectItem = new SelectItemImpl();
+      boolean exit = false;
+      EdmEntitySet fromEntitySet = uriResult.getTargetEntitySet();
+
+      for (String selectedPropertyName : selectItemString.split("/")) {
+        if ("".equals(selectedPropertyName)) {
+          throw new UriSyntaxException(UriSyntaxException.EMPTYSEGMENT);
+        }
+
+        if (exit) {
+          throw new UriSyntaxException(UriSyntaxException.INVALIDSEGMENT.addContent(selectItemString));
+        }
+
+        if ("*".equals(selectedPropertyName)) {
+          selectItem.setStar(true);
+          exit = true;
+          continue;
+        }
+
+        final EdmTyped property = fromEntitySet.getEntityType().getProperty(selectedPropertyName);
+        if (property == null) {
+          throw new UriNotMatchingException(UriNotMatchingException.PROPERTYNOTFOUND.addContent(selectedPropertyName));
+        }
+
+        switch (property.getType().getKind()) {
+        case SIMPLE:
+        case COMPLEX:
+          selectItem.setProperty((EdmProperty) property);
+          exit = true;
+          break;
+
+        case ENTITY: // navigation properties point to entities
+          final EdmNavigationProperty navigationProperty = (EdmNavigationProperty) property;
+          final EdmEntitySet targetEntitySet = fromEntitySet.getRelatedEntitySet(navigationProperty);
+
+          NavigationPropertySegmentImpl navigationPropertySegment = new NavigationPropertySegmentImpl();
+          navigationPropertySegment.setNavigationProperty(navigationProperty);
+          navigationPropertySegment.setTargetEntitySet(targetEntitySet);
+          selectItem.addNavigationPropertySegment(navigationPropertySegment);
+
+          fromEntitySet = targetEntitySet;
+          break;
+
+        default:
+          throw new UriSyntaxException(UriSyntaxException.INVALIDPROPERTYTYPE);
+        }
+      }
+      select.add(selectItem);
+    }
+    uriResult.setSelect(select);
+  }
+
+  private void handleOtherQueryParameters() throws UriSyntaxException, EdmException {
+    final EdmFunctionImport functionImport = uriResult.getFunctionImport();
+    if (functionImport != null) {
+      for (final String parameterName : functionImport.getParameterNames()) {
+        final EdmParameter parameter = functionImport.getParameter(parameterName);
+        final String value = otherQueryParameters.remove(parameterName);
+
+        if (value == null) {
+          if (parameter.getFacets() == null || parameter.getFacets().isNullable()) {
+            continue;
+          } else {
+            throw new UriSyntaxException(UriSyntaxException.MISSINGPARAMETER);
+          }
+        }
+
+        EdmLiteral uriLiteral = parseLiteral(value, (EdmSimpleType) parameter.getType());
+        uriResult.addFunctionImportParameter(parameterName, uriLiteral);
+      }
+    }
+
+    uriResult.setCustomQueryOptions(otherQueryParameters);
+  }
+
+  private EdmLiteral parseLiteral(final String value, final EdmSimpleType expectedType) throws UriSyntaxException {
+    EdmLiteral literal;
+    try {
+      literal = simpleTypeFacade.parseUriLiteral(value);
+    } catch (EdmLiteralException e) {
+      throw convertEdmLiteralException(e);
+    }
+
+    if (expectedType.isCompatible(literal.getType())) {
+      return literal;
+    } else {
+      throw new UriSyntaxException(UriSyntaxException.INCOMPATIBLELITERAL.addContent(value, expectedType));
+    }
+  }
+
+  private static UriSyntaxException convertEdmLiteralException(final EdmLiteralException e) {
+    final MessageReference messageReference = e.getMessageReference();
+
+    if (EdmLiteralException.LITERALFORMAT.equals(messageReference)) {
+      return new UriSyntaxException(UriSyntaxException.LITERALFORMAT.addContent(messageReference.getContent()), e);
+    } else if (EdmLiteralException.NOTEXT.equals(messageReference)) {
+      return new UriSyntaxException(UriSyntaxException.NOTEXT.addContent(messageReference.getContent()), e);
+    } else if (EdmLiteralException.UNKNOWNLITERAL.equals(messageReference)) {
+      return new UriSyntaxException(UriSyntaxException.UNKNOWNLITERAL.addContent(messageReference.getContent()), e);
+    } else {
+      return new UriSyntaxException(ODataBadRequestException.COMMON, e);
+    }
+  }
+
+  private static List<String> copyPathSegmentList(final List<PathSegment> source) {
+    List<String> copy = new ArrayList<String>();
+
+    for (final PathSegment segment : source) {
+      copy.add(segment.getPath());
+    }
+
+    return copy;
+  }
+
+  private static String percentDecode(final String value) throws UriSyntaxException {
+    try {
+      return Decoder.decode(value);
+    } catch (RuntimeException e) {
+      throw new UriSyntaxException(UriSyntaxException.URISYNTAX, e);
+    }
+  }
+
+  @Override
+  public FilterExpression parseFilterString(final EdmEntityType entityType, final String expression) throws ExpressionParserException, ODataMessageException {
+    return new FilterParserImpl(entityType).parseFilterString(expression);
+  }
+
+  @Override
+  public OrderByExpression parseOrderByString(final EdmEntityType entityType, final String expression) throws ExpressionParserException, ODataMessageException {
+    return new OrderByParserImpl(entityType).parseOrderByString(expression);
+  }
+
+  @Override
+  public ExpandSelectTreeNode buildExpandSelectTree(final List<SelectItem> select, final List<ArrayList<NavigationPropertySegment>> expand) throws EdmException {
+    return new ExpandSelectTreeCreator(select, expand).create();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriType.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriType.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriType.java
new file mode 100644
index 0000000..ffe4279
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/UriType.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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.uri;
+
+import java.util.ArrayList;
+
+/**
+ * @author SAP AG
+ */
+public enum UriType {
+  /**
+   * Service document
+   */
+  URI0(SystemQueryOption.$format),
+  /**
+   * Entity set
+   */
+  URI1(SystemQueryOption.$format, SystemQueryOption.$filter, SystemQueryOption.$inlinecount, SystemQueryOption.$orderby, SystemQueryOption.$skiptoken, SystemQueryOption.$skip, SystemQueryOption.$top, SystemQueryOption.$expand, SystemQueryOption.$select),
+  /**
+   * Entity set with key predicate
+   */
+  URI2(SystemQueryOption.$format, SystemQueryOption.$filter, SystemQueryOption.$expand, SystemQueryOption.$select),
+  /**
+   * Complex property of an entity
+   */
+  URI3(SystemQueryOption.$format),
+  /**
+   * Simple property of a complex property of an entity
+   */
+  URI4(SystemQueryOption.$format),
+  /**
+   * Simple property of an entity
+   */
+  URI5(SystemQueryOption.$format),
+  /**
+   * Navigation property of an entity with target multiplicity '1' or '0..1'
+   */
+  URI6A(SystemQueryOption.$format, SystemQueryOption.$filter, SystemQueryOption.$expand, SystemQueryOption.$select),
+  /**
+   * Navigation property of an entity with target multiplicity '*'
+   */
+  URI6B(SystemQueryOption.$format, SystemQueryOption.$filter, SystemQueryOption.$inlinecount, SystemQueryOption.$orderby, SystemQueryOption.$skiptoken, SystemQueryOption.$skip, SystemQueryOption.$top, SystemQueryOption.$expand, SystemQueryOption.$select),
+  /**
+   * Link to a single entity
+   */
+  URI7A(SystemQueryOption.$format, SystemQueryOption.$filter),
+  /**
+   * Link to multiple entities
+   */
+  URI7B(SystemQueryOption.$format, SystemQueryOption.$filter, SystemQueryOption.$inlinecount, SystemQueryOption.$orderby, SystemQueryOption.$skiptoken, SystemQueryOption.$skip, SystemQueryOption.$top),
+  /**
+   * Metadata document
+   */
+  URI8(),
+  /**
+   * Batch request
+   */
+  URI9(),
+  /**
+   * Function import returning a single instance of an entity type
+   */
+  URI10(SystemQueryOption.$format),
+  /**
+   * Function import returning a collection of complex-type instances
+   */
+  URI11(SystemQueryOption.$format),
+  /**
+   * Function import returning a single instance of a complex type
+   */
+  URI12(SystemQueryOption.$format),
+  /**
+   * Function import returning a collection of primitive-type instances
+   */
+  URI13(SystemQueryOption.$format),
+  /**
+   * Function import returning a single instance of a primitive type
+   */
+  URI14(SystemQueryOption.$format),
+  /**
+   * Count of an entity set
+   */
+  URI15(SystemQueryOption.$filter, SystemQueryOption.$orderby, SystemQueryOption.$skip, SystemQueryOption.$top),
+  /**
+   * Count of a single entity
+   */
+  URI16(SystemQueryOption.$filter),
+  /**
+   * Media resource of an entity
+   */
+  URI17(SystemQueryOption.$format, SystemQueryOption.$filter),
+  /**
+   * Count of link to a single entity
+   */
+  URI50A(SystemQueryOption.$filter),
+  /**
+   * Count of links to multiple entities
+   */
+  URI50B(SystemQueryOption.$filter, SystemQueryOption.$orderby, SystemQueryOption.$skip, SystemQueryOption.$top);
+
+  private ArrayList<SystemQueryOption> whiteList = new ArrayList<SystemQueryOption>();
+
+  private UriType(final SystemQueryOption... compatibleQueryOptions) {
+    for (SystemQueryOption queryOption : compatibleQueryOptions) {
+      whiteList.add(queryOption);
+    }
+  }
+
+  public boolean isCompatible(final SystemQueryOption queryOption) {
+    return whiteList.contains(queryOption);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ActualBinaryOperator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ActualBinaryOperator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ActualBinaryOperator.java
new file mode 100644
index 0000000..aa73a06
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ActualBinaryOperator.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+public class ActualBinaryOperator {
+  final protected InfoBinaryOperator operator;
+  final protected Token token;
+
+  public ActualBinaryOperator(final InfoBinaryOperator operatorInfo, final Token token) {
+    if (operatorInfo == null) {
+      throw new IllegalArgumentException("operatorInfo parameter must not be null");
+    }
+
+    operator = operatorInfo;
+    this.token = token;
+  }
+
+  public Token getToken() {
+    return token;
+  }
+
+  public InfoBinaryOperator getOP() {
+    return operator;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/BinaryExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/BinaryExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/BinaryExpressionImpl.java
new file mode 100644
index 0000000..f2e8af9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/BinaryExpressionImpl.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+
+/**
+ * @author SAP AG
+ */
+public class BinaryExpressionImpl implements BinaryExpression {
+  final protected InfoBinaryOperator operatorInfo;
+  final protected CommonExpression leftSide;
+  final protected CommonExpression rightSide;
+  final protected Token token;
+  protected EdmType edmType;
+
+  public BinaryExpressionImpl(final InfoBinaryOperator operatorInfo, final CommonExpression leftSide, final CommonExpression rightSide, final Token token) {
+    this.operatorInfo = operatorInfo;
+    this.leftSide = leftSide;
+    this.rightSide = rightSide;
+    this.token = token;
+    edmType = null;
+  }
+
+  @Override
+  public BinaryOperator getOperator() {
+    return operatorInfo.getOperator();
+  }
+
+  @Override
+  public CommonExpression getLeftOperand() {
+    return leftSide;
+  }
+
+  @Override
+  public CommonExpression getRightOperand() {
+    return rightSide;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return edmType;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    this.edmType = edmType;
+    return this;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.BINARY;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return operatorInfo.getSyntax();
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    Object retLeftSide = leftSide.accept(visitor);
+    Object retRightSide = rightSide.accept(visitor);
+
+    return visitor.visitBinary(this, operatorInfo.getOperator(), retLeftSide, retRightSide);
+  }
+
+  public Token getToken() {
+    return token;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ExpressionParserInternalError.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ExpressionParserInternalError.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ExpressionParserInternalError.java
new file mode 100644
index 0000000..76033f9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ExpressionParserInternalError.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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+
+/**
+ * Internal error in the expression parser.
+ * @author SAP AG
+ */
+public class ExpressionParserInternalError extends ODataMessageException {
+
+  static final long serialVersionUID = 77L;
+  public static final MessageReference ERROR_PARSING_METHOD = createMessageReference(ExpressionParserInternalError.class, "ERROR_PARSING_METHOD");
+  public static final MessageReference ERROR_PARSING_PARENTHESIS = createMessageReference(ExpressionParserInternalError.class, "ERROR_PARSING_PARENTHESIS");
+  public static final MessageReference ERROR_ACCESSING_EDM = createMessageReference(ExpressionParserInternalError.class, "ERROR_ACCESSING_EDM");
+  public static final MessageReference INVALID_TYPE_COUNT = createMessageReference(ExpressionParserInternalError.class, "INVALID_TYPE_COUNT");;
+  public static final MessageReference INVALID_TOKEN_AT = createMessageReference(ExpressionParserInternalError.class, "INVALID_TOKEN_AT");
+  public static final MessageReference INVALID_TOKENKIND_AT = createMessageReference(ExpressionParserInternalError.class, "INVALID_TOKENKIND_AT");
+
+  CommonExpression parenthesisExpression = null;
+
+  public ExpressionParserInternalError(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public ExpressionParserInternalError(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public ExpressionParserInternalError(final MessageReference messageReference, final TokenizerExpectError cause) {
+    super(messageReference, cause);
+  }
+
+  public ExpressionParserInternalError(final MessageReference messageReference, final EdmException cause) {
+    super(messageReference, cause);
+  }
+
+  public ExpressionParserInternalError setExpression(final CommonExpression parenthesisExpression) {
+    this.parenthesisExpression = parenthesisExpression;
+    return this;
+  }
+
+  public static ExpressionParserInternalError createERROR_PARSING_METHOD(final TokenizerExpectError cause) {
+    return new ExpressionParserInternalError(ERROR_PARSING_METHOD, cause);
+  }
+
+  public static ExpressionParserInternalError createERROR_PARSING_PARENTHESIS(final TokenizerExpectError cause) {
+    return new ExpressionParserInternalError(ERROR_PARSING_PARENTHESIS, cause);
+  }
+
+  public static ExpressionParserInternalError createERROR_PARSING_PARENTHESIS(final CommonExpression parenthesisExpression, final TokenizerExpectError cause) {
+    return new ExpressionParserInternalError(ERROR_PARSING_PARENTHESIS, cause).setExpression(parenthesisExpression);
+  }
+
+  public static ExpressionParserInternalError createERROR_ACCESSING_EDM(final EdmException cause) {
+    return new ExpressionParserInternalError(ERROR_ACCESSING_EDM, cause);
+  }
+
+  public static ExpressionParserInternalError createCOMMON() {
+    return new ExpressionParserInternalError(COMMON);
+  }
+
+  public static ExpressionParserInternalError createCOMMON(final Throwable e) {
+    return new ExpressionParserInternalError(COMMON, e);
+  }
+
+  public static ExpressionParserInternalError createINVALID_TYPE_COUNT() {
+    return new ExpressionParserInternalError(INVALID_TYPE_COUNT);
+  }
+
+  public static ExpressionParserInternalError createERROR_ACCESSING_EDM() {
+    return new ExpressionParserInternalError(ERROR_ACCESSING_EDM);
+  }
+
+  public static ExpressionParserInternalError createINVALID_TOKEN_AT(final String expectedToken, final Token actualToken) {
+    MessageReference msgRef = ExpressionParserInternalError.INVALID_TOKEN_AT.create();
+
+    msgRef.addContent(expectedToken);
+    msgRef.addContent(actualToken.getUriLiteral());
+    msgRef.addContent(actualToken.getPosition());
+
+    return new ExpressionParserInternalError(msgRef);
+  }
+
+  public static ExpressionParserInternalError createINVALID_TOKENKIND_AT(final TokenKind expectedTokenKind, final Token actualToken) {
+    MessageReference msgRef = ExpressionParserInternalError.INVALID_TOKEN_AT.create();
+
+    msgRef.addContent(expectedTokenKind.toString());
+    msgRef.addContent(actualToken.getKind().toString());
+    msgRef.addContent(actualToken.getUriLiteral());
+    msgRef.addContent(actualToken.getPosition());
+
+    return new ExpressionParserInternalError(msgRef);
+  }
+
+  public static ExpressionParserInternalError createNO_TOKEN_AVAILABLE(final String expectedToken) {
+    MessageReference msgRef = ExpressionParserInternalError.INVALID_TOKEN_AT.create();
+
+    msgRef.addContent(expectedToken);
+
+    return new ExpressionParserInternalError(msgRef);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterExpressionImpl.java
new file mode 100644
index 0000000..dcec62e
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterExpressionImpl.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * @author SAP AG
+ */
+public class FilterExpressionImpl implements FilterExpression {
+  private final String filterString;
+  private EdmType edmType;
+  private CommonExpression commonExpression;
+
+  public FilterExpressionImpl(final String filterExpression) {
+    filterString = filterExpression;
+  }
+
+  public FilterExpressionImpl(final String filterExpression, final CommonExpression childExpression) {
+    filterString = filterExpression;
+    commonExpression = childExpression;
+  }
+
+  @Override
+  public String getExpressionString() {
+    return filterString;
+  }
+
+  @Override
+  public CommonExpression getExpression() {
+    return commonExpression;
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    Object retCommonExpression = commonExpression.accept(visitor);
+
+    return visitor.visitFilterExpression(this, filterString, retCommonExpression);
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    this.edmType = edmType;
+    return this;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return edmType;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.FILTER;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return getExpressionString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParser.java
new file mode 100644
index 0000000..6697b6c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParser.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Interface which defines a method for parsing a $filter expression to allow different parser implementations
+ * <p>
+ * The current expression parser supports expressions as defined in the OData specification 2.0 with the following restrictions
+ *   - the methods "cast", "isof" and "replace" are not supported
+ *   
+ * The expression parser can be used with providing an Entity Data Model (EDM) an without providing it.
+ *  <p>When a EDM is provided the expression parser will be as strict as possible. That means:
+ *  <li>All properties used in the expression must be defined inside the EDM</li>
+ *  <li>The types of EDM properties will be checked against the lists of allowed type per method, binary- and unary operator</li>
+ *  </p>
+ *  <p>If no EDM is provided the expression parser performs a lax validation
+ *  <li>The properties used in the expression are not looked up inside the EDM and the type of the expression node representing the 
+ *      property will be "null"</li>
+ *  <li>Expression node with EDM-types which are "null" are not considered during the parameter type validation, to the return type of the parent expression node will
+ *  also become "null"</li>
+ *  
+ * @author SAP AG
+ */
+public interface FilterParser {
+  /**
+   * Parses a $filter expression string and creates an $orderby expression tree.
+   * @param expression
+   *   The $filter expression string ( for example "city eq 'Sydney'" ) to be parsed
+   * @return
+   *   Expression tree which can be traversed with help of the interfaces {@link org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor} and {@link org.apache.olingo.odata2.api.uri.expression.Visitable}
+   * @throws ExpressionParserException
+   *   Exception thrown due to errors while parsing the $filter expression string 
+   * @throws ODataMessageException
+   *   Used for extensibility   
+   **/
+  FilterExpression parseFilterString(String expression) throws ExpressionParserException, ODataMessageException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java
new file mode 100644
index 0000000..c3df6d7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/FilterParserExceptionImpl.java
@@ -0,0 +1,289 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
+
+/**
+ * This class is used to create exceptions of type FilterParserException.
+ * Because this class lies inside org.apache.olingo.odata2.core it is possible to define better/more detailed 
+ * input parameters for inserting into the exception text.<br>
+ * The exception {@link ExpressionParserException} does not know the org.apache.olingo.odata2.core content
+ * 
+ * @author SAP AG
+ */
+public class FilterParserExceptionImpl extends ExpressionParserException {
+  private static final long serialVersionUID = 77L;
+
+  static public ExpressionParserException createCOMMON() {
+    return new ExpressionParserException(ODataBadRequestException.COMMON);
+  }
+
+  static public ExpressionParserException createERROR_IN_TOKENIZER(final TokenizerException exceptionTokenizer, final String expression) {
+    Token token = exceptionTokenizer.getToken();
+    MessageReference msgRef = ExpressionParserException.ERROR_IN_TOKENIZER.create();
+
+    msgRef.addContent(token.getUriLiteral());
+    msgRef.addContent(Integer.toString(token.getPosition() + 1));
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef, exceptionTokenizer);
+  }
+
+  static public ExpressionParserException createINVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING(final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING.create();
+
+    msgRef.addContent(token.getUriLiteral());
+    msgRef.addContent(Integer.toString(token.getPosition() + 1));
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  static public ExpressionParserException createEXPRESSION_EXPECTED_AFTER_POS(final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.EXPRESSION_EXPECTED_AFTER_POS.create();
+
+    msgRef.addContent(Integer.toString(token.getPosition() + 1));
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  static public ExpressionParserException createEXPRESSION_EXPECTED_AFTER_POS(final int position, final String expression) {
+    MessageReference msgRef = ExpressionParserException.EXPRESSION_EXPECTED_AFTER_POS.create();
+
+    msgRef.addContent(position);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  static public ExpressionParserException createCOMMA_OR_END_EXPECTED_AT_POS(final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.COMMA_OR_END_EXPECTED_AT_POS.create();
+
+    msgRef.addContent(Integer.toString(token.getPosition() + 1));
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  static public ExpressionParserException createEXPRESSION_EXPECTED_AT_POS(final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.EXPRESSION_EXPECTED_AT_POS.create();
+
+    msgRef.addContent(Integer.toString(token.getPosition() + 1));
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  static public ExpressionParserException createCOMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS(final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS.create();
+
+    msgRef.addContent(Integer.toString(token.getPosition() + token.getUriLiteral().length()));
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createMETHOD_WRONG_ARG_COUNT(final MethodExpressionImpl methodExpression, final Token token, final String expression) {
+    MessageReference msgRef = null;
+    int minParam = methodExpression.getMethodInfo().getMinParameter();
+    int maxParam = methodExpression.getMethodInfo().getMaxParameter();
+
+    if ((minParam == -1) && (maxParam == -1)) {
+      //no exception thrown in this case
+    } else if ((minParam != -1) && (maxParam == -1)) {
+      //Tested with TestParserExceptions.TestPMreadParameters CASE 7-1
+      msgRef = ExpressionParserException.METHOD_WRONG_ARG_X_OR_MORE.create();
+      msgRef.addContent(methodExpression.getMethod().toUriLiteral());
+      msgRef.addContent(token.getPosition() + 1);
+      msgRef.addContent(expression);
+      msgRef.addContent(minParam);
+    } else if ((minParam == -1) && (maxParam != -1)) {
+      //Tested with TestParserExceptions.TestPMreadParameters CASE 8-2
+      msgRef = ExpressionParserException.METHOD_WRONG_ARG_X_OR_LESS.create();
+      msgRef.addContent(methodExpression.getMethod().toUriLiteral());
+      msgRef.addContent(token.getPosition() + 1);
+      msgRef.addContent(expression);
+      msgRef.addContent(maxParam);
+    } else if ((minParam != -1) && (maxParam != -1)) {
+      if (minParam == maxParam) {
+        //Tested with TestParserExceptions.TestPMreadParameters CASE 11-1
+        msgRef = ExpressionParserException.METHOD_WRONG_ARG_EXACT.create();
+        msgRef.addContent(methodExpression.getMethod().toUriLiteral());
+        msgRef.addContent(token.getPosition() + 1);
+        msgRef.addContent(expression);
+        msgRef.addContent(minParam);
+      } else {
+        //Tested with TestParserExceptions.TestPMreadParameters CASE 10-1
+        msgRef = ExpressionParserException.METHOD_WRONG_ARG_BETWEEN.create();
+        msgRef.addContent(methodExpression.getMethod().toUriLiteral());
+        msgRef.addContent(token.getPosition() + 1);
+        msgRef.addContent(expression);
+        msgRef.addContent(minParam);
+        msgRef.addContent(maxParam);
+      }
+    }
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createMETHOD_WRONG_INPUT_TYPE(final MethodExpressionImpl methodExpression, final Token token, final String expression) {
+    MessageReference msgRef = null;
+
+    //Tested with TestParserExceptions.TestPMreadParameters CASE 7-1
+    msgRef = ExpressionParserException.METHOD_WRONG_INPUT_TYPE.create();
+    msgRef.addContent(methodExpression.getMethod().toUriLiteral());
+    msgRef.addContent(token.getPosition() + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createLEFT_SIDE_NOT_A_PROPERTY(final Token token, final String expression) throws ExpressionParserInternalError {
+    MessageReference msgRef = ExpressionParserException.LEFT_SIDE_NOT_A_PROPERTY.create();
+
+    msgRef.addContent(token.getPosition() + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createLEFT_SIDE_NOT_STRUCTURAL_TYPE(final EdmType parentType, final PropertyExpressionImpl property, final Token token, final String expression) throws ExpressionParserInternalError {
+    MessageReference msgRef = ExpressionParserException.LEFT_SIDE_NOT_STRUCTURAL_TYPE.create();
+
+    try {
+      msgRef.addContent(property.getUriLiteral());
+      msgRef.addContent(parentType.getNamespace() + "." + parentType.getName());
+      msgRef.addContent(token.getPosition() + 1);
+      msgRef.addContent(expression);
+    } catch (EdmException e) {
+      throw ExpressionParserInternalError.createERROR_ACCESSING_EDM(e);
+    }
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createPROPERTY_NAME_NOT_FOUND_IN_TYPE(final EdmStructuralType parentType, final PropertyExpression property, final Token token, final String expression) throws ExpressionParserInternalError {
+    MessageReference msgRef = ExpressionParserException.PROPERTY_NAME_NOT_FOUND_IN_TYPE.create();
+
+    try {
+      msgRef.addContent(property.getUriLiteral());
+      msgRef.addContent(parentType.getNamespace() + "." + parentType.getName());
+      msgRef.addContent(token.getPosition() + 1);
+      msgRef.addContent(expression);
+    } catch (EdmException e) {
+      throw ExpressionParserInternalError.createERROR_ACCESSING_EDM(e);
+    }
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createTOKEN_UNDETERMINATED_STRING(final int position, final String expression) {
+    MessageReference msgRef = ExpressionParserException.TOKEN_UNDETERMINATED_STRING.create();
+
+    msgRef.addContent(position + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createINVALID_TYPES_FOR_BINARY_OPERATOR(final BinaryOperator op, final EdmType left, final EdmType right, final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR.create();
+
+    msgRef.addContent(op.toUriLiteral());
+
+    try {
+      msgRef.addContent(left.getNamespace() + "." + left.getName());
+    } catch (EdmException e) {
+      msgRef.addContent("");
+    }
+    try {
+      msgRef.addContent(right.getNamespace() + "." + right.getName());
+    } catch (EdmException e) {
+      msgRef.addContent("");
+    }
+    msgRef.addContent(token.getPosition() + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createMISSING_CLOSING_PHARENTHESIS(final int position, final String expression, final TokenizerExpectError e) {
+    MessageReference msgRef = ExpressionParserException.MISSING_CLOSING_PHARENTHESIS.create();
+
+    msgRef.addContent(position + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef, e);
+  }
+
+  public static ExpressionParserException createINVALID_SORT_ORDER(final Token token, final String expression) {
+    MessageReference msgRef = ExpressionParserException.INVALID_SORT_ORDER.create();
+    msgRef.addContent(token.getPosition() + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+  }
+
+  public static ExpressionParserException createINVALID_METHOD_CALL(final CommonExpression leftNode, final Token prevToken, final String expression) {
+    final MessageReference msgRef = ExpressionParserException.INVALID_METHOD_CALL.create();
+
+    msgRef.addContent(leftNode.getUriLiteral());
+    msgRef.addContent(prevToken.getPosition() + 1);
+    msgRef.addContent(expression);
+
+    return new ExpressionParserException(msgRef);
+
+  }
+
+  public static ExpressionParserException createTYPE_EXPECTED_AT(final EdmType expectedType, final EdmType actualType, final int position, final String expression) {
+    final MessageReference msgRef = ExpressionParserException.TYPE_EXPECTED_AT.create();
+
+    try {
+      msgRef.addContent(expectedType.getNamespace() + '.' + expectedType.getName());
+    } catch (EdmException e) {
+      msgRef.addContent("");
+    }
+
+    msgRef.addContent(position);
+    msgRef.addContent(expression);
+
+    if (actualType != null) {
+      try {
+        msgRef.addContent(actualType.getNamespace() + '.' + actualType.getName());
+      } catch (EdmException e) {
+        msgRef.addContent("");
+      }
+    } else {
+      msgRef.addContent("null");
+    }
+
+    return new ExpressionParserException(msgRef);
+
+  }
+}


[23/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
new file mode 100644
index 0000000..b24bbc1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchRequestParser.java
@@ -0,0 +1,563 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+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.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.regex.MatchResult;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
+import org.apache.olingo.odata2.core.PathInfoImpl;
+import org.apache.olingo.odata2.core.commons.Decoder;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class BatchRequestParser {
+  private static final String LF = "\n";
+  private static final String REG_EX_OPTIONAL_WHITESPACE = "\\s?";
+  private static final String REG_EX_ZERO_OR_MORE_WHITESPACES = "\\s*";
+  private static final String ANY_CHARACTERS = ".*";
+
+  private static final Pattern REG_EX_BLANK_LINE = Pattern.compile("(|" + REG_EX_ZERO_OR_MORE_WHITESPACES + ")");
+  private static final Pattern REG_EX_HEADER = Pattern.compile("([a-zA-Z\\-]+):" + REG_EX_OPTIONAL_WHITESPACE + "(.*)" + REG_EX_ZERO_OR_MORE_WHITESPACES);
+  private static final Pattern REG_EX_VERSION = Pattern.compile("(?:HTTP/[0-9]\\.[0-9])");
+  private static final Pattern REG_EX_ANY_BOUNDARY_STRING = Pattern.compile("--" + ANY_CHARACTERS + REG_EX_ZERO_OR_MORE_WHITESPACES);
+  private static final Pattern REG_EX_REQUEST_LINE = Pattern.compile("(GET|POST|PUT|DELETE|MERGE|PATCH)\\s(.*)\\s?" + REG_EX_VERSION + REG_EX_ZERO_OR_MORE_WHITESPACES);
+  private static final Pattern REG_EX_BOUNDARY_PARAMETER = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE + "boundary=(\".*\"|.*)" + REG_EX_ZERO_OR_MORE_WHITESPACES);
+  private static final Pattern REG_EX_CONTENT_TYPE = Pattern.compile(REG_EX_OPTIONAL_WHITESPACE + BatchConstants.MULTIPART_MIXED);
+  private static final Pattern REG_EX_QUERY_PARAMETER = Pattern.compile("((?:\\$|)[^=]+)=([^=]+)");
+
+  private static final String REG_EX_BOUNDARY = "([a-zA-Z0-9_\\-\\.'\\+]{1,70})|\"([a-zA-Z0-9_\\-\\.'\\+\\s\\(\\),/:=\\?]{1,69}[a-zA-Z0-9_\\-\\.'\\+\\(\\),/:=\\?])\""; // See RFC 2046
+  private String baseUri;
+  private PathInfo batchRequestPathInfo;
+  private String contentTypeMime;
+  private String boundary;
+  private String currentMimeHeaderContentId;
+  private int currentLineNumber = 0;
+  private static Set<String> HTTP_CHANGESET_METHODS;
+  private static Set<String> HTTP_BATCH_METHODS;
+
+  static {
+    HTTP_CHANGESET_METHODS = new HashSet<String>();
+    HTTP_CHANGESET_METHODS.add("POST");
+    HTTP_CHANGESET_METHODS.add("PUT");
+    HTTP_CHANGESET_METHODS.add("DELETE");
+    HTTP_CHANGESET_METHODS.add("MERGE");
+    HTTP_CHANGESET_METHODS.add("PATCH");
+
+    HTTP_BATCH_METHODS = new HashSet<String>();
+    HTTP_BATCH_METHODS.add("GET");
+  }
+
+  public BatchRequestParser(final String contentType, final EntityProviderBatchProperties properties) {
+    contentTypeMime = contentType;
+    batchRequestPathInfo = properties.getPathInfo();
+  }
+
+  public List<BatchPart> parse(final InputStream in) throws BatchException {
+    Scanner scanner = new Scanner(in, "UTF-8").useDelimiter(LF);
+    baseUri = getBaseUri();
+    List<BatchPart> requestList;
+    try {
+      requestList = parseBatchRequest(scanner);
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      scanner.close();
+      try {
+        in.close();
+      } catch (IOException e) {
+        throw new ODataRuntimeException(e);
+      }
+    }
+    return requestList;
+  }
+
+  private List<BatchPart> parseBatchRequest(final Scanner scanner) throws BatchException {
+    List<BatchPart> requests = new LinkedList<BatchPart>();
+    if (contentTypeMime != null) {
+      boundary = getBoundary(contentTypeMime);
+      parsePreamble(scanner);
+      String closeDelimiter = "--" + boundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES;
+      while (scanner.hasNext() && !scanner.hasNext(closeDelimiter)) {
+        requests.add(parseMultipart(scanner, boundary, false));
+        parseNewLine(scanner);
+      }
+      if (scanner.hasNext(closeDelimiter)) {
+        scanner.next(closeDelimiter);
+        currentLineNumber++;
+      } else {
+        throw new BatchException(BatchException.MISSING_CLOSE_DELIMITER.addContent(currentLineNumber));
+      }
+    } else {
+      throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
+    }
+    return requests;
+
+  }
+
+  //The method parses additional information prior to the first boundary delimiter line
+  private void parsePreamble(final Scanner scanner) {
+    while (scanner.hasNext() && !scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
+      scanner.next();
+      currentLineNumber++;
+    }
+  }
+
+  private BatchPart parseMultipart(final Scanner scanner, final String boundary, final boolean isChangeSet) throws BatchException {
+    Map<String, String> mimeHeaders = new HashMap<String, String>();
+    BatchPart multipart = null;
+    List<ODataRequest> requests = new ArrayList<ODataRequest>();
+    if (scanner.hasNext("--" + boundary + REG_EX_ZERO_OR_MORE_WHITESPACES)) {
+      scanner.next();
+      currentLineNumber++;
+      mimeHeaders = parseHeaders(scanner);
+      currentMimeHeaderContentId = mimeHeaders.get(BatchConstants.HTTP_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+
+      String contentType = mimeHeaders.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
+      if (contentType == null) {
+        throw new BatchException(BatchException.MISSING_CONTENT_TYPE);
+      }
+      if (isChangeSet) {
+        if (BatchConstants.HTTP_APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
+          validateEncoding(mimeHeaders.get(BatchConstants.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
+          parseNewLine(scanner);// mandatory
+
+          requests.add(parseRequest(scanner, isChangeSet));
+          multipart = new BatchPartImpl(false, requests);
+        } else {
+          throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(BatchConstants.HTTP_APPLICATION_HTTP));
+        }
+      } else {
+        if (BatchConstants.HTTP_APPLICATION_HTTP.equalsIgnoreCase(contentType)) {
+          validateEncoding(mimeHeaders.get(BatchConstants.HTTP_CONTENT_TRANSFER_ENCODING.toLowerCase(Locale.ENGLISH)));
+          parseNewLine(scanner);// mandatory
+          requests.add(parseRequest(scanner, isChangeSet));
+          multipart = new BatchPartImpl(false, requests);
+        } else if (contentType.matches(REG_EX_OPTIONAL_WHITESPACE + BatchConstants.MULTIPART_MIXED + ANY_CHARACTERS)) {
+          String changeSetBoundary = getBoundary(contentType);
+          if (boundary.equals(changeSetBoundary)) {
+            throw new BatchException(BatchException.INVALID_CHANGESET_BOUNDARY.addContent(currentLineNumber));
+          }
+          List<ODataRequest> changeSetRequests = new LinkedList<ODataRequest>();
+          parseNewLine(scanner);// mandatory
+          Pattern changeSetCloseDelimiter = Pattern.compile("--" + changeSetBoundary + "--" + REG_EX_ZERO_OR_MORE_WHITESPACES);
+          while (!scanner.hasNext(changeSetCloseDelimiter)) {
+            BatchPart part = parseMultipart(scanner, changeSetBoundary, true);
+            if (part.getRequests().size() == 1) {
+              changeSetRequests.add(part.getRequests().get(0));
+            }
+          }
+          scanner.next(changeSetCloseDelimiter);
+          currentLineNumber++;
+          multipart = new BatchPartImpl(true, changeSetRequests);
+        } else {
+          throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(BatchConstants.MULTIPART_MIXED + " or " + BatchConstants.HTTP_APPLICATION_HTTP));
+        }
+      }
+    } else if (scanner.hasNext(boundary + REG_EX_ZERO_OR_MORE_WHITESPACES)) {
+      currentLineNumber++;
+      throw new BatchException(BatchException.INVALID_BOUNDARY_DELIMITER.addContent(currentLineNumber));
+    } else if (scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
+      currentLineNumber++;
+      throw new BatchException(BatchException.NO_MATCH_WITH_BOUNDARY_STRING.addContent(boundary).addContent(currentLineNumber));
+    } else {
+      currentLineNumber++;
+      throw new BatchException(BatchException.MISSING_BOUNDARY_DELIMITER.addContent(currentLineNumber));
+    }
+    return multipart;
+
+  }
+
+  private ODataRequest parseRequest(final Scanner scanner, final boolean isChangeSet) throws BatchException {
+    try {
+    ODataRequest request;
+    if (scanner.hasNext(REG_EX_REQUEST_LINE)) {
+      scanner.next(REG_EX_REQUEST_LINE);
+      currentLineNumber++;
+      String method = null;
+      String uri = null;
+      MatchResult result = scanner.match();
+      if (result.groupCount() == 2) {
+        method = result.group(1);
+        uri = result.group(2).trim();
+      } else {
+        currentLineNumber++;
+        throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(scanner.next()).addContent(currentLineNumber));
+      }
+      PathInfo pathInfo = parseRequestUri(uri);
+      Map<String, String> queryParameters = parseQueryParameters(uri);
+      if (isChangeSet) {
+        if (!HTTP_CHANGESET_METHODS.contains(method)) {
+          throw new BatchException(BatchException.INVALID_CHANGESET_METHOD.addContent(currentLineNumber));
+        }
+      } else if (!HTTP_BATCH_METHODS.contains(method)) {
+        throw new BatchException(BatchException.INVALID_QUERY_OPERATION_METHOD.addContent(currentLineNumber));
+      }
+      ODataHttpMethod httpMethod = ODataHttpMethod.valueOf(method);
+      Map<String, List<String>> headers = parseRequestHeaders(scanner);
+      if (currentMimeHeaderContentId != null) {
+        List<String> headerList = new ArrayList<String>();
+        headerList.add(currentMimeHeaderContentId);
+        headers.put(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), headerList);
+      }
+
+      String contentType = getContentTypeHeader(headers);
+      List<String> acceptHeaders = getAcceptHeader(headers);
+      List<Locale> acceptLanguages = getAcceptLanguageHeader(headers);
+      parseNewLine(scanner);
+      InputStream body;
+        body = new ByteArrayInputStream("".getBytes("UTF-8"));
+      if (isChangeSet) {
+        body = parseBody(scanner);
+      }
+      if (contentType != null) {
+        request = ODataRequest.method(httpMethod)
+            .queryParameters(queryParameters)
+            .requestHeaders(headers)
+            .pathInfo(pathInfo)
+            .acceptableLanguages(acceptLanguages)
+            .contentType(contentType)
+            .body(body)
+            .acceptHeaders(acceptHeaders)
+            .build();
+      } else {
+        request = ODataRequest.method(httpMethod)
+            .queryParameters(queryParameters)
+            .requestHeaders(headers)
+            .pathInfo(pathInfo)
+            .acceptableLanguages(acceptLanguages)
+            .body(body)
+            .acceptHeaders(acceptHeaders)
+            .build();
+      }
+    } else {
+      currentLineNumber++;
+      throw new BatchException(BatchException.INVALID_REQUEST_LINE.addContent(scanner.next()).addContent(currentLineNumber));
+    }
+    return request;
+    } catch (UnsupportedEncodingException e) {
+      throw new ODataRuntimeException(e);
+    }
+  }
+
+  private Map<String, List<String>> parseRequestHeaders(final Scanner scanner) throws BatchException {
+    Map<String, List<String>> headers = new HashMap<String, List<String>>();
+    while (scanner.hasNext() && !scanner.hasNext(REG_EX_BLANK_LINE)) {
+      if (scanner.hasNext(REG_EX_HEADER)) {
+        scanner.next(REG_EX_HEADER);
+        currentLineNumber++;
+        MatchResult result = scanner.match();
+        if (result.groupCount() == 2) {
+          String headerName = result.group(1).trim().toLowerCase(Locale.ENGLISH);
+          String headerValue = result.group(2).trim();
+          if (HttpHeaders.ACCEPT.equalsIgnoreCase(headerName)) {
+            List<String> acceptHeaders = parseAcceptHeaders(headerValue);
+            headers.put(headerName, acceptHeaders);
+          } else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(headerName)) {
+            List<String> acceptLanguageHeaders = parseAcceptableLanguages(headerValue);
+            headers.put(headerName, acceptLanguageHeaders);
+          }
+          else if (!BatchConstants.HTTP_CONTENT_ID.equalsIgnoreCase(headerName)) {
+            if (headers.containsKey(headerName)) {
+              headers.get(headerName).add(headerValue);
+            } else {
+              List<String> headerList = new ArrayList<String>();
+              headerList.add(headerValue);
+              headers.put(headerName, headerList);
+            }
+          } else {
+            List<String> headerList = new ArrayList<String>();
+            headerList.add(headerValue);
+            headers.put(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH), headerList);
+          }
+        }
+      } else {
+        currentLineNumber++;
+        throw new BatchException(BatchException.INVALID_HEADER.addContent(scanner.next()).addContent(currentLineNumber));
+      }
+    }
+    return headers;
+  }
+
+  private PathInfo parseRequestUri(final String uri) throws BatchException {
+    PathInfoImpl pathInfo = new PathInfoImpl();
+    pathInfo.setServiceRoot(batchRequestPathInfo.getServiceRoot());
+    pathInfo.setPrecedingPathSegment(batchRequestPathInfo.getPrecedingSegments());
+    Scanner uriScanner = new Scanner(uri);
+    Pattern regexRequestUri = Pattern.compile("(?:" + baseUri + ")?/?([^?]+)(\\?.*)?");
+    if (uriScanner.hasNext(regexRequestUri)) {
+      uriScanner.next(regexRequestUri);
+      MatchResult result = uriScanner.match();
+      if (result.groupCount() == 2) {
+        String odataPathSegmentsAsString = result.group(1);
+        String queryParametersAsString = result.group(2) != null ? result.group(2) : "";
+        pathInfo.setODataPathSegment(parseODataPathSegments(odataPathSegmentsAsString));
+        try {
+          if (!odataPathSegmentsAsString.startsWith("$")) {
+            String requestUri = baseUri + "/" + odataPathSegmentsAsString + queryParametersAsString;
+            pathInfo.setRequestUri(new URI(requestUri));
+          }
+        } catch (URISyntaxException e) {
+          uriScanner.close();
+          throw new BatchException(BatchException.INVALID_URI, e);
+        }
+      } else {
+        uriScanner.close();
+        throw new BatchException(BatchException.INVALID_URI);
+      }
+    } else {
+      uriScanner.close();
+      throw new BatchException(BatchException.INVALID_URI);
+    }
+    uriScanner.close();
+    return pathInfo;
+  }
+
+  private Map<String, String> parseQueryParameters(final String uri) throws BatchException {
+    Scanner uriScanner = new Scanner(uri);
+    Map<String, String> queryParametersMap = new HashMap<String, String>();
+    Pattern regex = Pattern.compile("(?:" + baseUri + ")?/?" + "[^?]+" + "\\?(.*)");
+    if (uriScanner.hasNext(regex)) {
+      uriScanner.next(regex);
+      MatchResult uriResult = uriScanner.match();
+      if (uriResult.groupCount() == 1) {
+        String queryParams = uriResult.group(1);
+        Scanner queryParamsScanner = new Scanner(queryParams).useDelimiter("&");
+        while (queryParamsScanner.hasNext(REG_EX_QUERY_PARAMETER)) {
+          queryParamsScanner.next(REG_EX_QUERY_PARAMETER);
+          MatchResult result = queryParamsScanner.match();
+          if (result.groupCount() == 2) {
+            String systemQueryOption = result.group(1);
+            String value = result.group(2);
+            queryParametersMap.put(systemQueryOption, Decoder.decode(value));
+          } else {
+            queryParamsScanner.close();
+            throw new BatchException(BatchException.INVALID_QUERY_PARAMETER);
+          }
+        }
+        queryParamsScanner.close();
+
+      } else {
+        uriScanner.close();
+        throw new BatchException(BatchException.INVALID_URI);
+      }
+    }
+    uriScanner.close();
+    return queryParametersMap;
+  }
+
+  private List<PathSegment> parseODataPathSegments(final String odataPathSegmentsAsString) {
+    Scanner pathSegmentScanner = new Scanner(odataPathSegmentsAsString).useDelimiter("/");
+    List<PathSegment> odataPathSegments = new ArrayList<PathSegment>();
+    while (pathSegmentScanner.hasNext()) {
+      odataPathSegments.add(new ODataPathSegmentImpl(pathSegmentScanner.next(), null));
+    }
+    pathSegmentScanner.close();
+    return odataPathSegments;
+  }
+
+  private List<String> parseAcceptHeaders(final String headerValue) throws BatchException {
+    return AcceptParser.parseAcceptHeaders(headerValue);
+  }
+
+  private List<String> parseAcceptableLanguages(final String headerValue) throws BatchException {
+    return AcceptParser.parseAcceptableLanguages(headerValue);
+  }
+
+  private InputStream parseBody(final Scanner scanner) {
+    try {
+    String body = null;
+    InputStream requestBody;
+    while (scanner.hasNext() && !scanner.hasNext(REG_EX_ANY_BOUNDARY_STRING)) {
+      if (!scanner.hasNext(REG_EX_ZERO_OR_MORE_WHITESPACES)) {
+        if (body == null) {
+          body = scanner.next();
+        } else {
+          body = body + LF + scanner.next();
+        }
+      } else {
+        scanner.next();
+      }
+      currentLineNumber++;
+    }
+    if (body != null) {
+        requestBody = new ByteArrayInputStream(body.getBytes("UTF-8"));
+    } else {
+      requestBody = new ByteArrayInputStream("".getBytes("UTF-8"));
+    }
+    return requestBody;
+    } catch (UnsupportedEncodingException e) {
+      throw new ODataRuntimeException(e);
+    }
+  }
+
+  private String getBoundary(final String contentType) throws BatchException {
+    Scanner contentTypeScanner = new Scanner(contentType).useDelimiter(";\\s?");
+    if (contentTypeScanner.hasNext(REG_EX_CONTENT_TYPE)) {
+      contentTypeScanner.next(REG_EX_CONTENT_TYPE);
+    } else {
+      contentTypeScanner.close();
+      throw new BatchException(BatchException.INVALID_CONTENT_TYPE.addContent(BatchConstants.MULTIPART_MIXED));
+    }
+    if (contentTypeScanner.hasNext(REG_EX_BOUNDARY_PARAMETER)) {
+      contentTypeScanner.next(REG_EX_BOUNDARY_PARAMETER);
+      MatchResult result = contentTypeScanner.match();
+      contentTypeScanner.close();
+      if (result.groupCount() == 1 && result.group(1).trim().matches(REG_EX_BOUNDARY)) {
+        return trimQuota(result.group(1).trim());
+      } else {
+        throw new BatchException(BatchException.INVALID_BOUNDARY);
+      }
+    } else {
+      contentTypeScanner.close();
+      throw new BatchException(BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE);
+    }
+  }
+
+  private void validateEncoding(final String encoding) throws BatchException {
+    if (!BatchConstants.BINARY_ENCODING.equalsIgnoreCase(encoding)) {
+      throw new BatchException(BatchException.INVALID_CONTENT_TRANSFER_ENCODING);
+    }
+  }
+
+  private Map<String, String> parseHeaders(final Scanner scanner) throws BatchException {
+    Map<String, String> headers = new HashMap<String, String>();
+    while (scanner.hasNext() && !(scanner.hasNext(REG_EX_BLANK_LINE))) {
+      if (scanner.hasNext(REG_EX_HEADER)) {
+        scanner.next(REG_EX_HEADER);
+        currentLineNumber++;
+        MatchResult result = scanner.match();
+        if (result.groupCount() == 2) {
+          String headerName = result.group(1).trim().toLowerCase(Locale.ENGLISH);
+          String headerValue = result.group(2).trim();
+          headers.put(headerName, headerValue);
+        }
+      } else {
+        throw new BatchException(BatchException.INVALID_HEADER.addContent(scanner.next()));
+      }
+    }
+    return headers;
+  }
+
+  private void parseNewLine(final Scanner scanner) throws BatchException {
+    if (scanner.hasNext() && scanner.hasNext(REG_EX_BLANK_LINE)) {
+      scanner.next();
+      currentLineNumber++;
+    } else {
+      currentLineNumber++;
+      if (scanner.hasNext()) {
+        throw new BatchException(BatchException.MISSING_BLANK_LINE.addContent(scanner.next()).addContent(currentLineNumber));
+      } else {
+        throw new BatchException(BatchException.TRUNCATED_BODY.addContent(currentLineNumber));
+
+      }
+    }
+  }
+
+  private String getBaseUri() throws BatchException {
+    if (batchRequestPathInfo != null) {
+      if (batchRequestPathInfo.getServiceRoot() != null) {
+        String baseUri = batchRequestPathInfo.getServiceRoot().toASCIIString();
+        if (baseUri.lastIndexOf('/') == baseUri.length() - 1) {
+          baseUri = baseUri.substring(0, baseUri.length() - 1);
+        }
+        for (PathSegment precedingPS : batchRequestPathInfo.getPrecedingSegments()) {
+          baseUri = baseUri + "/" + precedingPS.getPath();
+        }
+        return baseUri;
+      }
+    } else {
+      throw new BatchException(BatchException.INVALID_PATHINFO);
+    }
+    return null;
+  }
+
+  private String trimQuota(String boundary) {
+    if (boundary.matches("\".*\"")) {
+      boundary = boundary.replace("\"", "");
+    }
+    boundary = boundary.replaceAll("\\)", "\\\\)");
+    boundary = boundary.replaceAll("\\(", "\\\\(");
+    boundary = boundary.replaceAll("\\?", "\\\\?");
+    boundary = boundary.replaceAll("\\+", "\\\\+");
+    return boundary;
+  }
+
+  private List<String> getAcceptHeader(final Map<String, List<String>> headers) {
+    List<String> acceptHeaders = new ArrayList<String>();
+    List<String> requestAcceptHeaderList = headers.get(HttpHeaders.ACCEPT.toLowerCase(Locale.ENGLISH));
+
+    if (requestAcceptHeaderList != null) {
+      acceptHeaders = requestAcceptHeaderList;
+    }
+    return acceptHeaders;
+  }
+
+  private List<Locale> getAcceptLanguageHeader(final Map<String, List<String>> headers) {
+    List<String> requestAcceptLanguageList = headers.get(HttpHeaders.ACCEPT_LANGUAGE.toLowerCase(Locale.ENGLISH));
+    List<Locale> acceptLanguages = new ArrayList<Locale>();
+    if (requestAcceptLanguageList != null) {
+      for (String acceptLanguage : requestAcceptLanguageList) {
+        String[] part = acceptLanguage.split("-");
+        String language = part[0];
+        String country = "";
+        if (part.length == 2) {
+          country = part[part.length - 1];
+        }
+        Locale locale = new Locale(language, country);
+        acceptLanguages.add(locale);
+      }
+    }
+    return acceptLanguages;
+  }
+
+  private String getContentTypeHeader(final Map<String, List<String>> headers) {
+    List<String> requestContentTypeList = headers.get(HttpHeaders.CONTENT_TYPE.toLowerCase(Locale.ENGLISH));
+    String contentType = null;
+    if (requestContentTypeList != null) {
+      for (String requestContentType : requestContentTypeList) {
+        contentType = contentType != null ? contentType + "," + requestContentType : requestContentType;
+      }
+    }
+    return contentType;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java
new file mode 100644
index 0000000..486bbdf
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponsePartImpl.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+public class BatchResponsePartImpl extends BatchResponsePart {
+  private List<ODataResponse> responses;
+  private boolean isChangeSet;
+
+  @Override
+  public List<ODataResponse> getResponses() {
+    return responses;
+  }
+
+  @Override
+  public boolean isChangeSet() {
+    return isChangeSet;
+  }
+
+  public class BatchResponsePartBuilderImpl extends BatchResponsePartBuilder {
+    private List<ODataResponse> responses;
+    private boolean isChangeSet;
+
+    @Override
+    public BatchResponsePart build() {
+      BatchResponsePartImpl.this.responses = responses;
+      BatchResponsePartImpl.this.isChangeSet = isChangeSet;
+      return BatchResponsePartImpl.this;
+    }
+
+    @Override
+    public BatchResponsePartBuilder responses(final List<ODataResponse> responses) {
+      this.responses = responses;
+      return this;
+    }
+
+    @Override
+    public BatchResponsePartBuilder changeSet(final boolean isChangeSet) {
+      this.isChangeSet = isChangeSet;
+      return this;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java
new file mode 100644
index 0000000..e705724
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchResponseWriter.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+public class BatchResponseWriter {
+  private static final String COLON = ":";
+  private static final String SP = " ";
+  private static final String LF = "\r\n";
+  private StringBuilder writer = new StringBuilder();
+
+  public ODataResponse writeResponse(final List<BatchResponsePart> batchResponseParts) throws BatchException {
+    String boundary = generateBoundary("batch");
+    appendResponseBody(batchResponseParts, boundary);
+    String batchResponseBody = writer.toString();
+    return ODataResponse.entity(batchResponseBody).status(HttpStatusCodes.ACCEPTED).
+        header(HttpHeaders.CONTENT_TYPE, BatchConstants.MULTIPART_MIXED + "; boundary=" + boundary)
+        .header(HttpHeaders.CONTENT_LENGTH, "" + batchResponseBody.length()).build();
+
+  }
+
+  private void appendChangeSet(final BatchResponsePart batchResponsePart) throws BatchException {
+    String boundary = generateBoundary("changeset");
+    writer.append(HttpHeaders.CONTENT_TYPE).append(COLON).append(SP).append("multipart/mixed; boundary=" + boundary).append(LF).append(LF);
+    for (ODataResponse response : batchResponsePart.getResponses()) {
+      writer.append("--").append(boundary).append(LF);
+      appendResponseBodyPart(response);
+    }
+    writer.append("--").append(boundary).append("--").append(LF).append(LF);
+  }
+
+  private void appendResponseBody(final List<BatchResponsePart> batchResponseParts, final String boundary) throws BatchException {
+
+    for (BatchResponsePart batchResponsePart : batchResponseParts) {
+      writer.append("--").append(boundary).append(LF);
+      if (batchResponsePart.isChangeSet()) {
+        appendChangeSet(batchResponsePart);
+      } else {
+        ODataResponse response = batchResponsePart.getResponses().get(0);
+        appendResponseBodyPart(response);
+      }
+    }
+    writer.append("--").append(boundary).append("--");
+  }
+
+  private void appendResponseBodyPart(final ODataResponse response) throws BatchException {
+    writer.append(HttpHeaders.CONTENT_TYPE).append(COLON).append(SP).append(BatchConstants.HTTP_APPLICATION_HTTP).append(LF);
+    writer.append(BatchConstants.HTTP_CONTENT_TRANSFER_ENCODING).append(COLON).append(SP).append("binary").append(LF);
+    if (response.getHeader(BatchConstants.MIME_HEADER_CONTENT_ID) != null) {
+      writer.append(BatchConstants.HTTP_CONTENT_ID).append(COLON).append(SP).append(response.getHeader(BatchConstants.MIME_HEADER_CONTENT_ID)).append(LF);
+    }
+    writer.append(LF);
+    writer.append("HTTP/1.1").append(SP).append(response.getStatus().getStatusCode()).append(SP).append(response.getStatus().getInfo()).append(LF);
+    appendHeader(response);
+    if (!HttpStatusCodes.NO_CONTENT.equals(response.getStatus())) {
+      String body;
+      if (response.getEntity() instanceof InputStream) {
+        InputStream in = (InputStream) response.getEntity();
+        body = readBody(in);
+      } else {
+        body = response.getEntity().toString();
+      }
+      writer.append(HttpHeaders.CONTENT_LENGTH).append(COLON).append(SP).append(body.length()).append(LF).append(LF);
+      writer.append(body);
+    }
+    writer.append(LF).append(LF);
+  }
+
+  private void appendHeader(final ODataResponse response) {
+    for (String name : response.getHeaderNames()) {
+      if (!BatchConstants.MIME_HEADER_CONTENT_ID.equalsIgnoreCase(name) && !BatchConstants.REQUEST_HEADER_CONTENT_ID.equalsIgnoreCase(name)) {
+        writer.append(name).append(COLON).append(SP).append(response.getHeader(name)).append(LF);
+      } else if (BatchConstants.REQUEST_HEADER_CONTENT_ID.equalsIgnoreCase(name)) {
+        writer.append(BatchConstants.HTTP_CONTENT_ID).append(COLON).append(SP).append(response.getHeader(name)).append(LF);
+      }
+    }
+  }
+
+  private String generateBoundary(final String value) {
+    return value + "_" + UUID.randomUUID().toString();
+  }
+
+  private String readBody(final InputStream in) throws BatchException {
+    byte[] tmp = new byte[2048];
+    int count;
+    BatchException cachedException = null;
+    StringBuffer b = new StringBuffer();
+    try {
+      count = in.read(tmp);
+      while (count >= 0) {
+        b.append(new String(tmp, 0, count));
+        count = in.read(tmp);
+      }
+    } catch (IOException e) {
+      cachedException = new BatchException(ODataMessageException.COMMON, e);
+      throw cachedException;
+    } finally {// NOPMD (suppress DoNotThrowExceptionInFinally)
+      try {
+        in.close();
+      } catch (IOException e) {
+        if (cachedException != null) {
+          throw cachedException;
+        }
+      }
+    }
+    return b.toString();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java
new file mode 100644
index 0000000..75e47f1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/ContentType.java
@@ -0,0 +1,734 @@
+/*******************************************************************************
+ * 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.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+/**
+ * Internally used {@link ContentType} for OData library.
+ * 
+ * For more details on format and content of a {@link ContentType} see    
+ * <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html)</code>.
+ * <pre>
+ * <code>
+ *   media-type     = type "/" subtype *( ";" parameter )
+ *   type           = token
+ *   subtype        = token
+ * </code>
+ * </pre>
+ * 
+ * Especially for <code>Accept</code> Header as defined in 
+ * <code>RFC 2616 chapter 14.1 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)</code>:
+ * <pre>
+ * <code>
+ * Accept = "Accept" ":"
+ *          #( media-range [ accept-params ] )
+ *  media-range = ( "* /*"
+ *                | ( type "/" "*" )
+ *                | ( type "/" subtype )
+ *                ) *( ";" parameter )
+ *  accept-params  = ";" "q" "=" qvalue *( accept-extension )
+ *  accept-extension = ";" token [ "=" ( token | quoted-string ) ]
+ * </code>
+ * </pre>
+ * 
+ * Especially for <code>Content-Type</code> Header as defined in 
+ * <code>RFC 2616 chapter 14.7 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html)</code>:
+ * <pre>
+ * <code>
+ * Content-Type   = "Content-Type" ":" media-type
+ * </code>
+ * </pre>
+ * 
+ * Once created a {@link ContentType} is <b>IMMUTABLE</b>.
+ * 
+ * @author SAP AG
+ */
+public class ContentType {
+
+  public enum ODataFormat {
+    ATOM, XML, JSON, MIME, CUSTOM
+  }
+
+  private static final Set<String> KNOWN_MIME_TYPES = new HashSet<String>();
+  static {
+    KNOWN_MIME_TYPES.add("audio");
+    KNOWN_MIME_TYPES.add("image");
+    KNOWN_MIME_TYPES.add("video");
+    KNOWN_MIME_TYPES.add("multipart");
+    KNOWN_MIME_TYPES.add("text");
+  }
+
+  private static final char WHITESPACE_CHAR = ' ';
+  private static final String PARAMETER_SEPARATOR = ";";
+  private static final String TYPE_SUBTYPE_SEPARATOR = "/";
+  private static final String MEDIA_TYPE_WILDCARD = "*";
+  private static final String VERBOSE = "verbose";
+
+  public static final String PARAMETER_CHARSET = "charset";
+  public static final String PARAMETER_ODATA = "odata";
+  public static final String PARAMETER_Q = "q";
+  public static final String CHARSET_UTF_8 = "utf-8";
+
+  public static final ContentType WILDCARD = new ContentType(MEDIA_TYPE_WILDCARD, MEDIA_TYPE_WILDCARD);
+
+  public static final ContentType APPLICATION_XML = new ContentType("application", "xml", ODataFormat.XML);
+  public static final ContentType APPLICATION_XML_CS_UTF_8 = ContentType.create(APPLICATION_XML, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType APPLICATION_ATOM_XML = new ContentType("application", "atom+xml", ODataFormat.ATOM);
+  public static final ContentType APPLICATION_ATOM_XML_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_XML, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType APPLICATION_ATOM_XML_ENTRY = new ContentType("application", "atom+xml", ODataFormat.ATOM, parameterMap("type", "entry"));
+  public static final ContentType APPLICATION_ATOM_XML_ENTRY_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_XML_ENTRY, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType APPLICATION_ATOM_XML_FEED = new ContentType("application", "atom+xml", ODataFormat.ATOM, parameterMap("type", "feed"));
+  public static final ContentType APPLICATION_ATOM_XML_FEED_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_XML_FEED, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType APPLICATION_ATOM_SVC = new ContentType("application", "atomsvc+xml", ODataFormat.ATOM);
+  public static final ContentType APPLICATION_ATOM_SVC_CS_UTF_8 = ContentType.create(APPLICATION_ATOM_SVC, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType APPLICATION_JSON = new ContentType("application", "json", ODataFormat.JSON);
+  public static final ContentType APPLICATION_JSON_ODATA_VERBOSE = ContentType.create(APPLICATION_JSON, PARAMETER_ODATA, VERBOSE);
+  public static final ContentType APPLICATION_JSON_CS_UTF_8 = ContentType.create(APPLICATION_JSON, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType APPLICATION_OCTET_STREAM = new ContentType("application", "octet-stream");
+  public static final ContentType TEXT_PLAIN = new ContentType("text", "plain");
+  public static final ContentType TEXT_PLAIN_CS_UTF_8 = ContentType.create(TEXT_PLAIN, PARAMETER_CHARSET, CHARSET_UTF_8);
+  public static final ContentType MULTIPART_MIXED = new ContentType("multipart", "mixed");
+
+  private String type;
+  private String subtype;
+  private Map<String, String> parameters;
+  private ODataFormat odataFormat;
+
+  private ContentType(final String type, final String subtype) {
+    this(type, subtype, ODataFormat.CUSTOM, null);
+  }
+
+  private ContentType(final String type, final String subtype, final ODataFormat odataFormat) {
+    this(type, subtype, odataFormat, null);
+  }
+
+  private ContentType(final String type, final String subtype, final ODataFormat odataFormat, final Map<String, String> parameters) {
+    if ((type == null || MEDIA_TYPE_WILDCARD.equals(type)) && !MEDIA_TYPE_WILDCARD.equals(subtype)) {
+      throw new IllegalArgumentException("Illegal combination of WILDCARD type with NONE WILDCARD subtype.");
+    }
+    this.odataFormat = odataFormat;
+    this.type = validateType(type);
+    this.subtype = validateType(subtype);
+
+    if (parameters == null) {
+      this.parameters = Collections.emptyMap();
+    } else {
+      this.parameters = new TreeMap<String, String>(new Comparator<String>() {
+        @Override
+        public int compare(final String o1, final String o2) {
+          return o1.compareToIgnoreCase(o2);
+        }
+      });
+      this.parameters.putAll(parameters);
+      this.parameters.remove(PARAMETER_Q);
+    }
+  }
+
+  private String validateType(final String type) {
+    if (type == null || type.isEmpty()) {
+      return MEDIA_TYPE_WILDCARD;
+    }
+    if (type.charAt(0) == WHITESPACE_CHAR || type.charAt(type.length() - 1) == WHITESPACE_CHAR) {
+      throw new IllegalArgumentException("Illegal leading/trailing whitespace found for type '" + type + "'.");
+    }
+    return type;
+  }
+
+  /**
+   * Validates if given <code>format</code> is parseable and can be used as input for
+   * {@link #create(String)} method.
+   * @param format to be validated string
+   * @return <code>true</code> if format is parseable otherwise <code>false</code>
+   */
+  public static boolean isParseable(final String format) {
+    try {
+      return ContentType.create(format) != null;
+    } catch (IllegalArgumentException e) {
+      return false;
+    }
+  }
+
+  /**
+   * Creates a content type from type and subtype
+   * @param type
+   * @param subtype
+   * @return a new <code>ContentType</code> object
+   */
+  public static ContentType create(final String type, final String subtype) {
+    return new ContentType(type, subtype, mapToODataFormat(type, subtype), null);
+  }
+
+  /**
+   * 
+   * @param type
+   * @param subtype
+   * @param parameters
+   * @return a new <code>ContentType</code> object
+   */
+  public static ContentType create(final String type, final String subtype, final Map<String, String> parameters) {
+    return new ContentType(type, subtype, mapToODataFormat(type, subtype), parameters);
+  }
+
+  /**
+   * 
+   * @param contentType
+   * @param parameterKey
+   * @param parameterValue
+   * @return a new <code>ContentType</code> object
+   */
+  public static ContentType create(final ContentType contentType, final String parameterKey, final String parameterValue) {
+    ContentType ct = new ContentType(contentType.type, contentType.subtype, contentType.odataFormat, contentType.parameters);
+    ct.parameters.put(parameterKey, parameterValue);
+    return ct;
+  }
+
+  /**
+   * Create a {@link ContentType} based on given input string (<code>format</code>).
+   * 
+   * Supported format is <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7</code>.
+   * This format is used as
+   * <code>HTTP Accept HEADER</code> format as defined in <code>RFC 2616 chapter 14.1</code>
+   * and 
+   * <code>HTTP Content-Type HEADER</code> format as defined in <code>RFC 2616 chapter 14.17</code>
+   * 
+   * @param format a string in format as defined in <code>RFC 2616 section 3.7</code>
+   * @return a new <code>ContentType</code> object
+   * @throws IllegalArgumentException if input string is not parseable
+   */
+  public static ContentType create(final String format) {
+    if (format == null) {
+      throw new IllegalArgumentException("Parameter format MUST NOT be NULL.");
+    }
+
+    // split 'types' and 'parameters'
+    String[] typesAndParameters = format.split(PARAMETER_SEPARATOR, 2);
+    String types = typesAndParameters[0];
+    String parameters = (typesAndParameters.length > 1 ? typesAndParameters[1] : null);
+    //
+    Map<String, String> parametersMap = parseParameters(parameters);
+    //
+    if (types.contains(TYPE_SUBTYPE_SEPARATOR)) {
+      String[] tokens = types.split(TYPE_SUBTYPE_SEPARATOR);
+      if (tokens.length == 2) {
+        return create(tokens[0], tokens[1], parametersMap);
+      } else {
+        throw new IllegalArgumentException("Too many '" + TYPE_SUBTYPE_SEPARATOR + "' in format '" + format + "'.");
+      }
+    } else {
+      return create(types, MEDIA_TYPE_WILDCARD, parametersMap);
+    }
+  }
+
+  /**
+   * Create a list of {@link ContentType} based on given input strings (<code>contentTypes</code>).
+   * 
+   * Supported format is <code>Media Type</code> format as defined in <code>RFC 2616 chapter 3.7</code>.
+   * This format is used as
+   * <code>HTTP Accept HEADER</code> format as defined in <code>RFC 2616 chapter 14.1</code>
+   * and 
+   * <code>HTTP Content-Type HEADER</code> format as defined in <code>RFC 2616 chapter 14.17</code>.
+   * <p>
+   * If one of the given strings can not be parsed an exception is thrown (hence no list is returned with the parseable strings).
+   * </p>
+   * 
+   * @param contentTypeStrings a list of strings in format as defined in <code>RFC 2616 section 3.7</code>
+   * @return a list of new <code>ContentType</code> object
+   * @throws IllegalArgumentException if one of the given input string is not parseable this exceptions is thrown
+   */
+  public static List<ContentType> create(final List<String> contentTypeStrings) {
+    List<ContentType> contentTypes = new ArrayList<ContentType>(contentTypeStrings.size());
+    for (String contentTypeString : contentTypeStrings) {
+      contentTypes.add(create(contentTypeString));
+    }
+    return contentTypes;
+  }
+
+  /**
+   * Parses the given input string (<code>format</code>) and returns created
+   * {@link ContentType} if input was valid or return <code>NULL</code> if
+   * input was not parseable.
+   * 
+   * For the definition of the supported format see {@link #create(String)}.
+   * 
+   * @param format a string in format as defined in <code>RFC 2616 section 3.7</code>
+   * @return a new <code>ContentType</code> object
+   */
+  public static ContentType parse(final String format) {
+    try {
+      return ContentType.create(format);
+    } catch (IllegalArgumentException e) {
+      return null;
+    }
+  }
+
+  /**
+   * 
+   * @param subtype
+   * @return
+   */
+  private static ODataFormat mapToODataFormat(final String type, final String subtype) {
+    ODataFormat odataFormat = ODataFormat.CUSTOM;
+    if (type.contains("application")) {
+      if (subtype.contains("atom")) {
+        odataFormat = ODataFormat.ATOM;
+      } else if (subtype.contains("xml")) {
+        odataFormat = ODataFormat.XML;
+      } else if (subtype.contains("json")) {
+        odataFormat = ODataFormat.JSON;
+      }
+    } else if (KNOWN_MIME_TYPES.contains(type)) {
+      odataFormat = ODataFormat.MIME;
+    }
+    return odataFormat;
+  }
+
+  /**
+   * 
+   * @param content
+   * @return a new <code>ContentType</code> object
+   */
+  private static Map<String, String> parameterMap(final String... content) {
+    Map<String, String> map = new HashMap<String, String>();
+    for (int i = 0; i < content.length - 1; i += 2) {
+      String key = content[i];
+      String value = content[i + 1];
+      map.put(key, value);
+    }
+    return map;
+  }
+
+  /**
+   * Valid input are <code>;</code> separated <code>key=value</code> pairs 
+   * without spaces between key and value.
+   * 
+   * <p>
+   * See RFC 2616:
+   * The type, subtype, and parameter attribute names are case-insensitive. 
+   * Parameter values might or might not be case-sensitive, depending on the 
+   * semantics of the parameter name. <b>Linear white space (LWS) MUST NOT be used 
+   * between the type and subtype, nor between an attribute and its value</b>. 
+   * </p>
+   * 
+   * @param parameters
+   * @return Map with keys mapped to values
+   */
+  private static Map<String, String> parseParameters(final String parameters) {
+    Map<String, String> parameterMap = new HashMap<String, String>();
+    if (parameters != null) {
+      String[] splittedParameters = parameters.split(PARAMETER_SEPARATOR);
+      for (String parameter : splittedParameters) {
+        String[] keyValue = parameter.split("=");
+        String key = keyValue[0].trim().toLowerCase(Locale.ENGLISH);
+        if (isParameterAllowed(key)) {
+          String value = keyValue.length > 1 ? keyValue[1] : null;
+          if (value != null && isLws(value.charAt(0))) {
+            throw new IllegalArgumentException("Value of parameter '" + key + "' starts with a LWS ('" + parameters + "').");
+          }
+          parameterMap.put(key, value);
+        }
+      }
+    }
+    return parameterMap;
+  }
+
+  /** 
+   * Validate if given character is a linear whitepace (includes <code>horizontal-tab, linefeed, carriage return and space</code>).
+   * 
+   * @param character to be checked
+   * @return <code>true</code> if character is a LWS, otherwise <code>false</code>.
+   */
+  private static boolean isLws(final char character) {
+    switch (character) {
+    case 9: // HT = <US-ASCII HT, horizontal-tab (9)>
+    case 10: // LF = <US-ASCII LF, linefeed (10)>
+    case 13: // CR = <US-ASCII CR, carriage return (13)>
+    case 32: // SP = <US-ASCII SP, space (32)>
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  private static boolean isParameterAllowed(final String key) {
+    return key != null && !PARAMETER_Q.equals(key.toLowerCase(Locale.US));
+  }
+
+  /**
+   * Ensure that charset parameter ({@link #PARAMETER_CHARSET}) is set on returned content type
+   * if this {@link ContentType} is a <code>odata text related</code> content type (@see {@link #isContentTypeODataTextRelated()}).
+   * If <code>this</code> {@link ContentType} has no charset parameter set a new {@link ContentType}
+   * with given <code>defaultCharset</code> is created.
+   * Otherwise if charset parameter is already set nothing is done.
+   * 
+   * @param defaultCharset
+   * @return ContentType
+   */
+  public ContentType receiveWithCharsetParameter(final String defaultCharset) {
+    if (isContentTypeODataTextRelated()) {
+      if (!parameters.containsKey(ContentType.PARAMETER_CHARSET)) {
+        return ContentType.create(this, ContentType.PARAMETER_CHARSET, defaultCharset);
+      }
+    }
+    return this;
+  }
+
+  /**
+   * 
+   * @return <code>true</code> if this {@link ContentType} is text related (in the view of OData)
+   */
+  public boolean isContentTypeODataTextRelated() {
+    return (ContentType.TEXT_PLAIN.equals(this)
+        || (getODataFormat() == ODataFormat.XML)
+        || (getODataFormat() == ODataFormat.ATOM)
+        || (getODataFormat() == ODataFormat.JSON));
+  }
+
+  public String getType() {
+    return type;
+  }
+
+  public String getSubtype() {
+    return subtype;
+  }
+
+  /**
+   * 
+   * @return parameters of this {@link ContentType} as unmodifiable map.
+   */
+  public Map<String, String> getParameters() {
+    return Collections.unmodifiableMap(parameters);
+  }
+
+  @Override
+  public int hashCode() {
+    return 1;
+  }
+
+  /**
+   * {@link ContentType}s are equal 
+   * <ul>
+   * <li>if <code>type</code>, <code>subtype</code> and all <code>parameters</code> have the same value.</li>
+   * <li>if <code>type</code> and/or <code>subtype</code> is set to "*" (in such a case the <code>parameters</code> are ignored).</li>
+   * </ul>
+   * 
+   * @return <code>true</code> if both instances are equal (see definition above), otherwise <code>false</code>.
+   */
+  @Override
+  public boolean equals(final Object obj) {
+    // NULL validation is done in method 'isEqualWithoutParameters(obj)'
+    Boolean compatible = isEqualWithoutParameters(obj);
+
+    if (compatible == null) {
+      ContentType other = (ContentType) obj;
+
+      // parameter checks
+      if (parameters == null) {
+        if (other.parameters != null) {
+          return false;
+        }
+      } else if (parameters.size() == other.parameters.size()) {
+        Iterator<Entry<String, String>> entries = parameters.entrySet().iterator();
+        Iterator<Entry<String, String>> otherEntries = other.parameters.entrySet().iterator();
+        while (entries.hasNext()) {
+          Entry<String, String> e = entries.next();
+          Entry<String, String> oe = otherEntries.next();
+
+          if (!areEqual(e.getKey(), oe.getKey())) {
+            return false;
+          }
+          if (!areEqual(e.getValue(), oe.getValue())) {
+            return false;
+          }
+        }
+      } else {
+        return false;
+      }
+      return true;
+    } else {
+      // all tests run
+      return compatible.booleanValue();
+    }
+  }
+
+  /**
+   * {@link ContentType}s are <b>compatible</b> 
+   * <ul>
+   * <li>if <code>type</code>, <code>subtype</code> have the same value.</li>
+   * <li>if <code>type</code> and/or <code>subtype</code> is set to "*"</li>
+   * </ul>
+   * The set <code>parameters</code> are <b>always</b> ignored (for compare with parameters see {@link #equals(Object)}).
+   * 
+   * @return <code>true</code> if both instances are equal (see definition above), otherwise <code>false</code>.
+   */
+  public boolean isCompatible(final ContentType obj) {
+    Boolean compatible = isEqualWithoutParameters(obj);
+    if (compatible == null) {
+      return true;
+    }
+    return compatible.booleanValue();
+  }
+
+  /**
+   * Check equal without parameters.
+   * It is possible that no decision about <code>equal/none equal</code> can be determined a <code>NULL</code> is returned.
+   * 
+   * @param obj to checked object
+   * @return <code>true</code> if both instances are equal (see definition above), otherwise <code>false</code> 
+   *          or <code>NULL</code> if no decision about <code>equal/none equal</code> could be determined.
+   */
+  private Boolean isEqualWithoutParameters(final Object obj) {
+    // basic checks
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+
+    ContentType other = (ContentType) obj;
+
+    // subtype checks
+    if (subtype == null) {
+      if (other.subtype != null) {
+        return false;
+      }
+    } else if (!subtype.equals(other.subtype)) {
+      if (!subtype.equals(MEDIA_TYPE_WILDCARD) && !other.subtype.equals(MEDIA_TYPE_WILDCARD)) {
+        return false;
+      }
+    }
+
+    // type checks
+    if (type == null) {
+      if (other.type != null) {
+        return false;
+      }
+    } else if (!type.equals(other.type)) {
+      if (!type.equals(MEDIA_TYPE_WILDCARD) && !other.type.equals(MEDIA_TYPE_WILDCARD)) {
+        return false;
+      }
+    }
+
+    // if wildcards are set, content types are defined as 'equal'
+    if (countWildcards() > 0 || other.countWildcards() > 0) {
+      return true;
+    }
+
+    return null;
+  }
+
+  /**
+   * Check whether both string are equal ignoring the case of the strings.
+   * 
+   * @param first
+   * @param second
+   * @return
+   */
+  private static boolean areEqual(final String first, final String second) {
+    if (first == null) {
+      if (second != null) {
+        return false;
+      }
+    } else if (!first.equalsIgnoreCase(second)) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * Get {@link ContentType} as string as defined in RFC 2616 (http://www.ietf.org/rfc/rfc2616.txt - chapter 14.17: Content-Type)
+   * 
+   * @return string representation of <code>ContentType</code> object
+   */
+  public String toContentTypeString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(type).append(TYPE_SUBTYPE_SEPARATOR).append(subtype);
+    for (String key : parameters.keySet()) {
+      if (isParameterAllowed(key)) {
+        String value = parameters.get(key);
+        sb.append(";").append(key).append("=").append(value);
+      }
+    }
+    return sb.toString();
+  }
+
+  @Override
+  public String toString() {
+    return toContentTypeString();
+  }
+
+  public ODataFormat getODataFormat() {
+    return odataFormat;
+  }
+
+  /**
+   * Find best match between this {@link ContentType} and the {@link ContentType} in the list.
+   * If a match (this {@link ContentType} is equal to a {@link ContentType} in list) is found either this or the {@link ContentType}
+   * from the list is returned based on which {@link ContentType} has less "**" characters set 
+   * (checked with {@link #compareWildcardCounts(ContentType)}.
+   * If no match (none {@link ContentType} in list is equal to this {@link ContentType}) is found <code>NULL</code> is returned.
+   * 
+   * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
+   * @return best matched content type in list or <code>NULL</code> if none content type match to this content type instance
+   */
+  public ContentType match(final List<ContentType> toMatchContentTypes) {
+    for (ContentType supportedContentType : toMatchContentTypes) {
+      if (equals(supportedContentType)) {
+        if (compareWildcardCounts(supportedContentType) < 0) {
+          return this;
+        } else {
+          return supportedContentType;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Find best match between this {@link ContentType} and the {@link ContentType} in the list ignoring all set parameters.
+   * If a match (this {@link ContentType} is equal to a {@link ContentType} in list) is found either this or the {@link ContentType}
+   * from the list is returned based on which {@link ContentType} has less "**" characters set 
+   * (checked with {@link #compareWildcardCounts(ContentType)}.
+   * If no match (none {@link ContentType} in list is equal to this {@link ContentType}) is found <code>NULL</code> is returned.
+   * 
+   * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
+   * @return best matched content type in list or <code>NULL</code> if none content type match to this content type instance
+   */
+  public ContentType matchCompatible(final List<ContentType> toMatchContentTypes) {
+    for (ContentType supportedContentType : toMatchContentTypes) {
+      if (isCompatible(supportedContentType)) {
+        if (compareWildcardCounts(supportedContentType) < 0) {
+          return this;
+        } else {
+          return supportedContentType;
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Check if a valid compatible match for this {@link ContentType} exists in given list.
+   * Compatible in this case means that <b>all set parameters are ignored</b>.
+   * For more detail what a valid match is see {@link #matchCompatible(List)}.
+   * 
+   * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
+   * @return <code>true</code> if a compatible content type was found in given list 
+   *          or <code>false</code> if none compatible content type match was found
+   */
+  public boolean hasCompatible(final List<ContentType> toMatchContentTypes) {
+    return matchCompatible(toMatchContentTypes) != null;
+  }
+
+  /**
+   * Check if a valid match for this {@link ContentType} exists in given list.
+   * For more detail what a valid match is see {@link #match(List)}.
+   * 
+   * @param toMatchContentTypes list of {@link ContentType}s which are matches against this {@link ContentType}
+   * @return <code>true</code> if a matching content type was found in given list 
+   *          or <code>false</code> if none matching content type match was found
+   */
+  public boolean hasMatch(final List<ContentType> toMatchContentTypes) {
+    return match(toMatchContentTypes) != null;
+  }
+
+  /**
+   * Compare wildcards counts/weights of both {@link ContentType}.
+   * 
+   * The smaller {@link ContentType} has lesser weighted wildcards then the bigger {@link ContentType}.
+   * As result this method returns this object weighted wildcards minus the given parameter object weighted wildcards.
+   * 
+   * A type wildcard is weighted with <code>2</code> and a subtype wildcard is weighted with <code>1</code>.
+   * 
+   * @param otherContentType {@link ContentType} to be compared to
+   * @return this object weighted wildcards minus the given parameter object weighted wildcards.
+   */
+  public int compareWildcardCounts(final ContentType otherContentType) {
+    return countWildcards() - otherContentType.countWildcards();
+  }
+
+  private int countWildcards() {
+    int count = 0;
+    if (MEDIA_TYPE_WILDCARD.equals(type)) {
+      count += 2;
+    }
+    if (MEDIA_TYPE_WILDCARD.equals(subtype)) {
+      count++;
+    }
+    return count;
+  }
+
+  /**
+   * 
+   * @return <code>true</code> if <code>type</code> or <code>subtype</code> of this instance is a "*".
+   */
+  public boolean hasWildcard() {
+    return (MEDIA_TYPE_WILDCARD.equals(type) || MEDIA_TYPE_WILDCARD.equals(subtype));
+  }
+
+  /**
+   * 
+   * @return <code>true</code> if both <code>type</code> and <code>subtype</code> of this instance are a "*".
+   */
+  public boolean isWildcard() {
+    return (MEDIA_TYPE_WILDCARD.equals(type) && MEDIA_TYPE_WILDCARD.equals(subtype));
+  }
+
+  public static List<ContentType> convert(final List<String> types) {
+    List<ContentType> results = new ArrayList<ContentType>();
+    for (String contentType : types) {
+      results.add(ContentType.create(contentType));
+    }
+    return results;
+  }
+
+  /**
+   * Check if a valid match for given content type formated string (<code>toMatch</code>) exists in given list.
+   * Therefore the given content type formated string (<code>toMatch</code>) is converted into a {@link ContentType}
+   * with a simple {@link #create(String)} call (during which an exception can occur).
+   * 
+   * For more detail in general see {@link #hasMatch(List)} and for what a valid match is see {@link #match(List)}.
+   * 
+   * @param toMatch content type formated string (<code>toMatch</code>) for which is checked if a match exists in given list
+   * @param matchExamples list of {@link ContentType}s which are matches against content type formated string (<code>toMatch</code>)
+   * @return <code>true</code> if a matching content type was found in given list 
+   *          or <code>false</code> if none matching content type match was found
+   */
+  public static boolean match(final String toMatch, final ContentType... matchExamples) {
+    ContentType toMatchContentType = ContentType.create(toMatch);
+
+    return toMatchContentType.hasMatch(Arrays.asList(matchExamples));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java
new file mode 100644
index 0000000..358faec
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Decoder.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Decodes a Java String containing a percent-encoded UTF-8 String value
+ * into a Java String (in its internal UTF-16 encoding).
+ * @author SAP AG
+ */
+public class Decoder {
+
+  /**
+   * Decodes a percent-encoded UTF-8 String value into a Java String
+   * (in its internal UTF-16 encoding).
+   * @param value the encoded String
+   * @return the Java String
+   * @throws IllegalArgumentException if value contains characters not representing UTF-8 bytes
+   *                                  or ends with an unfinished percent-encoded character
+   * @throws NumberFormatException    if the two characters after a percent character
+   *                                  are not hexadecimal digits
+   */
+  public static String decode(final String value) throws IllegalArgumentException, NumberFormatException {
+    if (value == null) {
+      return value;
+    }
+
+    // Use a tiny finite-state machine to handle decoding on byte level.
+    // There are only three states:
+    //   -2: normal bytes
+    //   -1: a byte representing the percent character has been read
+    // >= 0: a byte representing the first half-byte of a percent-encoded byte has been read
+    // The variable holding the state is also used to store the value of the first half-byte.
+    byte[] result = new byte[value.length()];
+    int position = 0;
+    byte encodedPart = -2;
+    for (final char c : value.toCharArray()) {
+      if (c <= Byte.MAX_VALUE) {
+        if (c == '%') {
+          if (encodedPart == -2) {
+            encodedPart = -1;
+          } else {
+            throw new IllegalArgumentException();
+          }
+        } else if (encodedPart == -1) {
+          encodedPart = (byte) c;
+        } else if (encodedPart >= 0) {
+          final int i = Integer.parseInt(String.valueOf(new char[] { (char) encodedPart, c }), 16);
+          if (i >= 0) {
+            result[position++] = (byte) i;
+          } else {
+            throw new NumberFormatException();
+          }
+          encodedPart = -2;
+        } else {
+          result[position++] = (byte) c;
+        }
+      } else {
+        throw new IllegalArgumentException();
+      }
+    }
+
+    if (encodedPart >= 0) {
+      throw new IllegalArgumentException();
+    }
+
+    try {
+      return new String(result, 0, position, "UTF-8");
+    } catch (UnsupportedEncodingException e) {
+      throw new IllegalArgumentException(e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java
new file mode 100644
index 0000000..1e28c8e
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/commons/Encoder.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Encodes a Java String (in its internal UTF-16 encoding) into its
+ * percent-encoded UTF-8 representation according to
+ * <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>
+ * (with consideration of its predecessor RFC 2396).
+ * @author SAP AG
+ */
+public class Encoder {
+
+  /**
+   * Encodes a Java String (in its internal UTF-16 encoding) into its
+   * percent-encoded UTF-8 representation according to
+   * <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>,
+   * suitable for parts of an OData path segment.
+   * @param value the Java String
+   * @return the encoded String
+   */
+  public static String encode(final String value) {
+    return encoder.encodeInternal(value);
+  }
+
+  // OData has special handling for "'", so we allow that to remain unencoded.
+  // Other sub-delims not used neither by JAX-RS nor by OData could be added
+  // if the encoding is considered to be too aggressive.
+  // RFC 3986 would also allow the gen-delims ":" and "@" to appear literally
+  // in path-segment parts.
+  private static final String ODATA_UNENCODED = "'";
+
+  // Character classes from RFC 3986
+  private final static String UNRESERVED = "-._~"; // + ALPHA + DIGIT
+  private final static String GEN_DELIMS = ":/?#[]@";
+  // RFC 3986 says: "For consistency, URI producers and normalizers should
+  // use uppercase hexadecimal digits for all percent-encodings."
+  private final static String[] hex = {
+      "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
+      "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F",
+      "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+      "%18", "%19", "%1A", "%1B", "%1C", "%1D", "%1E", "%1F",
+      "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
+      "%28", "%29", "%2A", "%2B", "%2C", "%2D", "%2E", "%2F",
+      "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
+      "%38", "%39", "%3A", "%3B", "%3C", "%3D", "%3E", "%3F",
+      "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
+      "%48", "%49", "%4A", "%4B", "%4C", "%4D", "%4E", "%4F",
+      "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
+      "%58", "%59", "%5A", "%5B", "%5C", "%5D", "%5E", "%5F",
+      "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
+      "%68", "%69", "%6A", "%6B", "%6C", "%6D", "%6E", "%6F",
+      "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
+      "%78", "%79", "%7A", "%7B", "%7C", "%7D", "%7E", "%7F",
+      "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
+      "%88", "%89", "%8A", "%8B", "%8C", "%8D", "%8E", "%8F",
+      "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
+      "%98", "%99", "%9A", "%9B", "%9C", "%9D", "%9E", "%9F",
+      "%A0", "%A1", "%A2", "%A3", "%A4", "%A5", "%A6", "%A7",
+      "%A8", "%A9", "%AA", "%AB", "%AC", "%AD", "%AE", "%AF",
+      "%B0", "%B1", "%B2", "%B3", "%B4", "%B5", "%B6", "%B7",
+      "%B8", "%B9", "%BA", "%BB", "%BC", "%BD", "%BE", "%BF",
+      "%C0", "%C1", "%C2", "%C3", "%C4", "%C5", "%C6", "%C7",
+      "%C8", "%C9", "%CA", "%CB", "%CC", "%CD", "%CE", "%CF",
+      "%D0", "%D1", "%D2", "%D3", "%D4", "%D5", "%D6", "%D7",
+      "%D8", "%D9", "%DA", "%DB", "%DC", "%DD", "%DE", "%DF",
+      "%E0", "%E1", "%E2", "%E3", "%E4", "%E5", "%E6", "%E7",
+      "%E8", "%E9", "%EA", "%EB", "%EC", "%ED", "%EE", "%EF",
+      "%F0", "%F1", "%F2", "%F3", "%F4", "%F5", "%F6", "%F7",
+      "%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
+  };
+
+  private static final Encoder encoder = new Encoder(ODATA_UNENCODED);
+
+  /** characters to remain unencoded in addition to {@link #UNRESERVED} */
+  private final String unencoded;
+
+  private Encoder(final String unencoded) {
+    this.unencoded = unencoded == null ? "" : unencoded;
+  }
+
+  /**
+   * <p>Returns the percent-encoded UTF-8 representation of a String.</p>
+   * <p>In order to avoid producing percent-encoded CESU-8 (as described in
+   * the Unicode Consortium's <a href="http://www.unicode.org/reports/tr26/">
+   * Technical Report #26</a>), this is done in two steps:
+   * <ol>
+   * <li>Re-encode the characters from their Java-internal UTF-16 representations
+   * into their UTF-8 representations.</li>
+   * <li>Percent-encode each of the bytes in the UTF-8 representation.
+   * This is possible on byte level because all characters that do not have
+   * a <code>%xx</code> representation are represented in one byte in UTF-8.</li>
+   * </ol></p>
+   * @param input input String
+   * @return encoded representation
+   */
+  private String encodeInternal(final String input) {
+    StringBuilder resultStr = new StringBuilder();
+
+    try {
+      for (byte utf8Byte : input.getBytes("UTF-8")) {
+        final char character = (char) utf8Byte;
+        if (isUnreserved(character)) {
+          resultStr.append(character);
+        } else if (isUnencoded(character)) {
+          resultStr.append(character);
+        } else if (utf8Byte >= 0) {
+          resultStr.append(hex[utf8Byte]);
+        }
+        else {
+          // case UTF-8 continuation byte
+          resultStr.append(hex[256 + utf8Byte]); // index adjusted for the usage of signed bytes
+        }
+      }
+    } catch (final UnsupportedEncodingException e) { // should never happen; UTF-8 is always there
+      return null;
+    }
+    return resultStr.toString();
+  }
+
+  private static boolean isUnreserved(final char character) {
+    return 'A' <= character && character <= 'Z' // case A..Z
+        || 'a' <= character && character <= 'z' // case a..z
+        || '0' <= character && character <= '9' // case 0..9
+        || UNRESERVED.indexOf(character) >= 0;
+  }
+
+  private boolean isUnencoded(final char character) {
+    return unencoded.indexOf(character) >= 0;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java
new file mode 100644
index 0000000..76ebe08
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfo.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public interface DebugInfo {
+
+  /**
+   * Gets the name of this debug information part, useful as title.
+   * @return the name
+   */
+  public String getName();
+
+  /**
+   * Appends the content of this debug information part
+   * to the given JSON stream writer.
+   * @param jsonStreamWriter a JSON stream writer
+   */
+  public void appendJson(JsonStreamWriter jsonStreamWriter) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
new file mode 100644
index 0000000..8ff1797
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoBody.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+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.ep.util.JsonStreamWriter;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoBody implements DebugInfo {
+
+  private final ODataResponse response;
+
+  public DebugInfoBody(final ODataResponse response) {
+    this.response = response;
+  }
+
+  @Override
+  public String getName() {
+    return "Body";
+  }
+
+  @Override
+  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+    final String contentType = response.getContentHeader();
+    if (contentType.startsWith("image/")) {
+      if (response.getEntity() instanceof InputStream) {
+        jsonStreamWriter.stringValueRaw(Base64.encodeBase64String(getBinaryFromInputStream((InputStream) response.getEntity())));
+      } else if (response.getEntity() instanceof String) {
+        jsonStreamWriter.stringValueRaw(getContentString());
+      } else {
+        throw new ClassCastException("Unsupported content entity class: " + response.getEntity().getClass().getName());
+      }
+    } else if (contentType.startsWith(HttpContentType.APPLICATION_JSON)) {
+      jsonStreamWriter.unquotedValue(getContentString());
+    } else {
+      jsonStreamWriter.stringValue(getContentString());
+    }
+  }
+
+  private String getContentString() {
+    String content;
+    if (response.getEntity() instanceof String) {
+      content = (String) response.getEntity();
+    } else if (response.getEntity() instanceof InputStream) {
+      content = getStringFromInputStream((InputStream) response.getEntity());
+    } else {
+      throw new ClassCastException("Unsupported content entity class: " + response.getEntity().getClass().getName());
+    }
+    return content;
+  }
+
+  private static byte[] getBinaryFromInputStream(final InputStream inputStream) {
+    try {
+      return new BasicEntityProvider().readBinary(inputStream);
+    } catch (final EntityProviderException e) {
+      return null;
+    }
+  }
+
+  private static String getStringFromInputStream(final InputStream inputStream) {
+    try {
+      return new BasicEntityProvider().readText(inputStream);
+    } catch (final EntityProviderException e) {
+      return null;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java
new file mode 100644
index 0000000..d94e1bf
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/debug/DebugInfoException.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * 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.debug;
+
+import java.io.IOException;
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.core.ep.util.JsonStreamWriter;
+import org.apache.olingo.odata2.core.exception.MessageService;
+
+/**
+ * @author SAP AG
+ */
+public class DebugInfoException implements DebugInfo {
+
+  private final Exception exception;
+  private final Locale locale;
+
+  public DebugInfoException(final Exception exception, final Locale locale) {
+    this.exception = exception;
+    this.locale = locale;
+  }
+
+  @Override
+  public String getName() {
+    return "Stacktrace";
+  }
+
+  @Override
+  public void appendJson(final JsonStreamWriter jsonStreamWriter) throws IOException {
+    jsonStreamWriter.beginObject()
+        .name("exceptions")
+        .beginArray();
+    Throwable throwable = exception;
+    while (throwable != null) {
+      jsonStreamWriter.beginObject()
+          .namedStringValueRaw("class", throwable.getClass().getCanonicalName()).separator()
+          .namedStringValue("message",
+              throwable instanceof ODataMessageException ?
+                  MessageService.getMessage(locale, ((ODataMessageException) throwable).getMessageReference()).getText() :
+                  throwable.getLocalizedMessage())
+          .separator();
+
+      jsonStreamWriter.name("invocation");
+      appendJsonStackTraceElement(jsonStreamWriter, throwable.getStackTrace()[0]);
+
+      jsonStreamWriter.endObject();
+      throwable = throwable.getCause();
+      if (throwable != null) {
+        jsonStreamWriter.separator();
+      }
+    }
+    jsonStreamWriter.endArray();
+    jsonStreamWriter.separator();
+
+    jsonStreamWriter.name("stacktrace")
+        .beginArray();
+    boolean first = true;
+    for (final StackTraceElement stackTraceElement : exception.getStackTrace()) {
+      if (!first) {
+        jsonStreamWriter.separator();
+      }
+      first = false;
+      appendJsonStackTraceElement(jsonStreamWriter, stackTraceElement);
+    }
+    jsonStreamWriter.endArray();
+    jsonStreamWriter.endObject();
+  }
+
+  private static void appendJsonStackTraceElement(final JsonStreamWriter jsonStreamWriter, final StackTraceElement stackTraceElement) throws IOException {
+    jsonStreamWriter.beginObject()
+        .namedStringValueRaw("class", stackTraceElement.getClassName()).separator()
+        .namedStringValueRaw("method", stackTraceElement.getMethodName()).separator()
+        .name("line").unquotedValue(Integer.toString(stackTraceElement.getLineNumber()))
+        .endObject();
+  }
+}


[48/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmFunctionImportView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmFunctionImportView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmFunctionImportView.java
new file mode 100644
index 0000000..a3f6e87
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmFunctionImportView.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+
+/**
+ * <p>
+ * A view on EDM Function Imports. EDM function imports are derived from Java
+ * class methods annotated with EDM Annotations.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM Function Import created
+ * from Java class methods. The implementation act as a container for list of
+ * function imports that are consistent.
+ * </p>
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * 
+ */
+public interface JPAEdmFunctionImportView extends JPAEdmBaseView {
+
+  /**
+   * The method returns a list of consistent Function Imports. A function
+   * import is said to be consistent only if it adheres to the rules defined
+   * in CSDL.
+   * 
+   * @return a list of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.FunctionImport}
+   */
+  List<FunctionImport> getConsistentFunctionImportList();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmKeyView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmKeyView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmKeyView.java
new file mode 100644
index 0000000..a40b122
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmKeyView.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.Key;
+
+/**
+ * A view on Java Persistence Entity Key Attributes and EDM Key properties. Java
+ * Persistence Key Attributes of type
+ * <ol>
+ * <li>embedded ID</li>
+ * <li>ID</li>
+ * </ol>
+ * are converted into EDM keys. Embedded IDs are expanded into simple EDM
+ * properties.
+ * <p>
+ * The implementation of the view provides access to EDM key properties for a
+ * given JPA EDM entity type. The view acts as a container for consistent EDM
+ * key property of an EDM entity type.
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView
+ * 
+ */
+public interface JPAEdmKeyView extends JPAEdmBaseView {
+  /**
+   * The method returns an instance of EDM key for the given JPA EDM Entity
+   * type.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.Key}
+   */
+  public Key getEdmKey();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmMapping.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmMapping.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmMapping.java
new file mode 100644
index 0000000..fc19827
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmMapping.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+/**
+ * The interface acts a container for storing Java persistence column name. The
+ * JPA EDM mapping instance can be associated with any EDM simple, EDM complex
+ * property to denote the properties Java persistence column name.
+ * 
+ * @author SAP AG
+ * 
+ */
+public interface JPAEdmMapping {
+  /**
+   * The method sets the Java persistence column name into the mapping
+   * container.
+   * 
+   * @param name
+   *            is the Java persistence column name
+   */
+  public void setJPAColumnName(String name);
+
+  /**
+   * The method gets the Java persistence column name from the mapping
+   * container.
+   * 
+   * @return a String representing the Java persistence column name set into
+   *         the container
+   */
+  public String getJPAColumnName();
+
+  /**
+   * The method sets the Java persistence entity/property type.
+   * 
+   * @param type
+   *            is an instance of type Class<?>
+   */
+  public void setJPAType(Class<?> type);
+
+  /**
+   * The method returns the Java persistence entity/property type.
+   * 
+   * @return type
+   */
+  public Class<?> getJPAType();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmModelView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmModelView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmModelView.java
new file mode 100644
index 0000000..c8bd871
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmModelView.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+/**
+ * A view on JPA meta model and EDM meta model. The view acts as the base for
+ * the construction of EDM meta model from a JPA meta model.
+ * <p>
+ * The implementation of the view acts as the container for JPA meta model and
+ * EDM meta model. The instance of JPA EDM meta model can be created using
+ * {@link org.apache.olingo.odata2.processor.api.jpa.factory.JPAAccessFactory}. The
+ * instance thus obtained can be used for constructing other elements of the
+ * meta model using
+ * {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder}.
+ * 
+ * @author SAP AG
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.JPAAccessFactory
+ */
+public interface JPAEdmModelView extends JPAEdmBaseView {
+  /**
+   * The method returns a consistent JPA EDM schema view created from the JPA
+   * meta model.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView}
+   */
+  public JPAEdmSchemaView getEdmSchemaView();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmNavigationPropertyView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmNavigationPropertyView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmNavigationPropertyView.java
new file mode 100644
index 0000000..0830032
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmNavigationPropertyView.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+
+/**
+ * A view on Java persistence entity relationship and EDM navigation property.
+ * Java persistence entity relationships annotated as
+ * <ol>
+ * <li>Many To Many</li>
+ * <li>One To Many</li>
+ * <li>One To One</li>
+ * <li>Many To One</li>
+ * </ol>
+ * are transformed into navigation properties.
+ * <p>
+ * The implementation of the view provides access to EDM navigation properties
+ * for a given JPA EDM entity type. The view acts as a container for consistent
+ * list of EDM navigation properties of an EDM entity type. EDM navigation
+ * property is consistent only if there exists a consistent EDM association.
+ * 
+ * @author SAP AG
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView
+ * 
+ */
+public interface JPAEdmNavigationPropertyView extends JPAEdmBaseView {
+  /**
+   * The method adds a navigation property view to its container.
+   * 
+   * @param view
+   *            is an instance of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView}
+   */
+  void addJPAEdmNavigationPropertyView(JPAEdmNavigationPropertyView view);
+
+  /**
+   * The method returns a consistent list of EDM navigation property. A
+   * navigation property is consistent only if all its mandatory properties
+   * can be built with no errors from Java persistence entity relationship.
+   * 
+   * @return a list of consistent EDM navigation property for the Entity
+   */
+  List<NavigationProperty> getConsistentEdmNavigationProperties();
+
+  /**
+   * The method returns the navigation property that is currently being
+   * processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.NavigationProperty}
+   */
+  NavigationProperty getEdmNavigationProperty();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmPropertyView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmPropertyView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmPropertyView.java
new file mode 100644
index 0000000..ba471bb
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmPropertyView.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import javax.persistence.metamodel.Attribute;
+
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+
+/**
+ * A view on Java Persistence Entity Attributes and EDM properties. Java
+ * Persistence Attributes of type
+ * <ol>
+ * <li>embedded ID - are converted into EDM keys</li>
+ * <li>ID - are converted into EDM keys</li>
+ * <li>attributes - are converted into EDM properties</li>
+ * <li>embeddable type - are converted into EDM complex properties</li>
+ * <li>relationships - are converted into Associations/Navigation properties</li>
+ * </ol>
+ * <p>
+ * The implementation of the view provides access to EDM properties for a given
+ * JPA EDM entity type. The view acts as a container for consistent list of EDM
+ * properties of an EDM entity type. EDM property is consistent only if there
+ * exists at least one property in the entity type and there is at least one key
+ * property.
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView
+ * 
+ */
+public interface JPAEdmPropertyView extends JPAEdmBaseView {
+  /**
+   * The method returns a simple EDM property.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.SimpleProperty}
+   */
+  SimpleProperty getEdmSimpleProperty();
+
+  /**
+   * The method returns a JPA EDM key view.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView}
+   */
+  JPAEdmKeyView getJPAEdmKeyView();
+
+  /**
+   * The method returns a list of Properties for the given Entity Type.
+   * 
+   * @return a list of {@link org.apache.olingo.odata2.api.edm.provider.Property}
+   */
+  List<Property> getEdmPropertyList();
+
+  /**
+   * The method returns a JPA Attribute for the given JPA entity type.
+   * 
+   * @return an instance of type {@link javax.persistence.metamodel.Attribute
+   *         <?, ?>}
+   */
+  Attribute<?, ?> getJPAAttribute();
+
+  /**
+   * The method returns a JPA EDM navigation property view.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView}
+   */
+  JPAEdmNavigationPropertyView getJPAEdmNavigationPropertyView();
+
+  /**
+   * The method returns a JPA EDM Entity Type view that holds the property
+   * view.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView}
+   */
+  JPAEdmEntityTypeView getJPAEdmEntityTypeView();
+
+  /**
+   * The method returns a JPA EDM Complex Type view that holds the property
+   * view.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView}
+   */
+  JPAEdmComplexTypeView getJPAEdmComplexTypeView();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintRoleView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintRoleView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintRoleView.java
new file mode 100644
index 0000000..abce3ba
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintRoleView.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraintRole;
+
+/**
+ * <p>
+ * A view on Java Persistence Entity Join Column's "name" and
+ * "referenced column name" attributes and Entity Data Model Referential
+ * Constraint's dependent and principal roles respectively. Each java
+ * persistence entity with properties annotated with Join Columns are
+ * transformed into Referential constraints and Referential constraint roles.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM referential constraint
+ * roles created from Java Persistence Entity Join Columns. The implementation
+ * acts as a container for EDM referential constraint roles. A referential
+ * constraint role is consistent only if the principal role and dependent roles
+ * can be created from JPA Entity relationships.
+ * </p>
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView
+ * 
+ */
+public interface JPAEdmReferentialConstraintRoleView extends JPAEdmBaseView {
+  /**
+   * Two types of EDM roles of a referential constraint.
+   */
+  public enum RoleType {
+    PRINCIPAL, DEPENDENT
+  }
+
+  /**
+   * The method returns the role type (PRINCIPAL or DEPENDENT)
+   * 
+   * @return a
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView.RoleType}
+   */
+  RoleType getRoleType();
+
+  /**
+   * The method returns the Referential constraint role that is currently
+   * being processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.ReferentialConstraintRole}
+   */
+  ReferentialConstraintRole getEdmReferentialConstraintRole();
+
+  /**
+   * The method returns the name of JPA attribute's column name (annotated
+   * with @Column). The returned Column Name acts as the PRINCIPAL entity
+   * type.
+   * 
+   * @return name of JPA Column name
+   */
+  String getJPAColumnName();
+
+  /**
+   * The method returns the EDM entity type name that holds the
+   * relationship/referential constraint. The entity type that acts as a
+   * DEPENDENT entity type.
+   * 
+   * @return name of EDM entity type
+   */
+  String getEdmEntityTypeName();
+
+  /**
+   * The method returns the EDM association name.
+   * 
+   * @return name of EDM association
+   */
+  String getEdmAssociationName();
+
+  /**
+   * The method tells if there exists a valid referential constraint for a
+   * given association.
+   * 
+   * @return true - if valid referential constraint exits else false
+   */
+  boolean isExists();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintView.java
new file mode 100644
index 0000000..4ccda56
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmReferentialConstraintView.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint;
+
+/**
+ * <p>
+ * A view on Java Persistence Entity Join Columns and Entity Data Model
+ * Referential Constraint. Each java persistence entity with properties
+ * annotated with Join Columns are transformed into Referential constraints.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM referential constraint
+ * created from Java Persistence Entity Join Columns. The implementation acts as
+ * a container for EDM referential constraint. A referential constraint is said
+ * to be consistent only if referential constraint role is consistent.
+ * </p>
+ * 
+ * @author SAP AG<br>
+ * @DoNotImplement
+ * <br>
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView
+ * 
+ */
+public interface JPAEdmReferentialConstraintView extends JPAEdmBaseView {
+
+  /**
+   * The method returns EDM referential constraint created from Java
+   * persistence Entity Join Columns.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint}
+   */
+  public ReferentialConstraint getEdmReferentialConstraint();
+
+  /**
+   * The method returns if a valid referential constraint exists for a given
+   * EDM association. If there exists a JPA entity relationship with join
+   * column having a valid "Name" and "ReferenceColumnName", that can be
+   * mapped to EDM properties in dependent and source EDM entities
+   * respectively then a valid EDM referential constraint exists.
+   * 
+   * @return true if there exists a valid referential constraint else false.
+   */
+  public boolean isExists();
+
+  /**
+   * The method returns the name of EDM Association.
+   * 
+   * @return name of an EDM association
+   */
+  public String getEdmRelationShipName();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmSchemaView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmSchemaView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmSchemaView.java
new file mode 100644
index 0000000..21d6b74
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmSchemaView.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+
+/**
+ * <p>
+ * A view on Java Persistence Model and Entity Data Model Schema. Each java
+ * persistence unit corresponds to a one EDM schema.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM schema created from
+ * Java Persistence unit. The implementation acts as a container for schema. The
+ * schema is consistent only if following elements are consistent
+ * <ol>
+ * <li>{@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}</li>
+ * <li>
+ * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView}</li>
+ * <li>{@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView}</li>
+ * </ol>
+ * </p>
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView
+ * 
+ */
+public interface JPAEdmSchemaView extends JPAEdmBaseView {
+  /**
+   * The method returns the EDM schema present in the container.
+   * 
+   * @return an instance EDM schema of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.Schema}
+   */
+  public Schema getEdmSchema();
+
+  /**
+   * The method returns JPA EDM container view. The JPA EDM container view can
+   * be used to access EDM Entity Container elements.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView}
+   */
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView();
+
+  /**
+   * The method returns JPA EDM complex view. The JPA EDM complex view can be
+   * used to access EDM complex types and JPA Embeddable Types.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView}
+   */
+  public JPAEdmComplexTypeView getJPAEdmComplexTypeView();
+
+  /**
+   * The method returns JPA EDM association view. The JPA EDM association view
+   * can be used to access EDM associations and JPA Relationships.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}
+   */
+  public JPAEdmAssociationView getJPAEdmAssociationView();
+
+  /**
+   * The method registers custom operations that shall be represented as Edm
+   * Function Imports. Custom operations are created using Edm Annotation
+   * {@link org.apache.olingo.odata2.api.annotation.edm.FunctionImport}.
+   * <p>
+   * Custom Operations can be part of JPA Entity or can be created in a class
+   * other than JPA Entity. Such custom operations can be registered using
+   * this method.
+   * <p>
+   * The method is a callback.
+   * 
+   * @param customClass
+   *            is the class that contains custom operations
+   * @param methodNames
+   *            is the name of the method that needs to be transformed into
+   *            Function Imports. It is an optional parameter. If null is
+   *            passed then all annotated methods are transformed into
+   *            Function Imports.
+   * 
+   */
+  public void registerOperations(Class<?> customClass, String methodNames[]);
+
+  /**
+   * The method returns an Hash Map containing the registered custom
+   * operations.
+   * 
+   * @return a HashMap of Class and the methods in the class
+   */
+  public HashMap<Class<?>, String[]> getRegisteredOperations();
+
+  public List<String> getNonKeyComplexTypeList();
+
+  public void addNonKeyComplexName(String complexTypeName);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAAttributeMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAAttributeMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAAttributeMapType.java
new file mode 100644
index 0000000..6a6a071
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAAttributeMapType.java
@@ -0,0 +1,213 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * 
+ * 				The default name for EDM
+ * 				property is derived from JPA attribute name. This can be overriden
+ * 				using
+ * 				JPAAttributeMapType.
+ * 			
+ * 
+ * <p>Java class for JPAAttributeMapType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPAAttributeMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="JPAAttribute" maxOccurs="unbounded" minOccurs="0">
+ *           &lt;complexType>
+ *             &lt;simpleContent>
+ *               &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+ *                 &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *                 &lt;attribute name="exclude" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *               &lt;/extension>
+ *             &lt;/simpleContent>
+ *           &lt;/complexType>
+ *         &lt;/element>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPAAttributeMapType", propOrder = {
+    "jpaAttribute"
+})
+public class JPAAttributeMapType {
+
+  @XmlElement(name = "JPAAttribute")
+  protected List<JPAAttributeMapType.JPAAttribute> jpaAttribute;
+
+  /**
+   * Gets the value of the jpaAttribute property.
+   * 
+   * <p>
+   * This accessor method returns a reference to the live list,
+   * not a snapshot. Therefore any modification you make to the
+   * returned list will be present inside the JAXB object.
+   * This is why there is not a <CODE>set</CODE> method for the jpaAttribute property.
+   * 
+   * <p>
+   * For example, to add a new item, do as follows:
+   * <pre>
+   *    getJPAAttribute().add(newItem);
+   * </pre>
+   * 
+   * 
+   * <p>
+   * Objects of the following type(s) are allowed in the list
+   * {@link JPAAttributeMapType.JPAAttribute }
+   * 
+   * 
+   */
+  public List<JPAAttributeMapType.JPAAttribute> getJPAAttribute() {
+    if (jpaAttribute == null) {
+      jpaAttribute = new ArrayList<JPAAttributeMapType.JPAAttribute>();
+    }
+    return jpaAttribute;
+  }
+
+  /**
+   * <p>Java class for anonymous complex type.
+   * 
+   * <p>The following schema fragment specifies the expected content contained within this class.
+   * 
+   * <pre>
+   * &lt;complexType>
+   *   &lt;simpleContent>
+   *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+   *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+   *       &lt;attribute name="exclude" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+   *     &lt;/extension>
+   *   &lt;/simpleContent>
+   * &lt;/complexType>
+   * </pre>
+   * 
+   * 
+   */
+  @XmlAccessorType(XmlAccessType.FIELD)
+  @XmlType(name = "", propOrder = {
+      "value"
+  })
+  public static class JPAAttribute {
+
+    @XmlValue
+    protected String value;
+    @XmlAttribute(name = "name", required = true)
+    protected String name;
+    @XmlAttribute(name = "exclude")
+    protected Boolean exclude;
+
+    /**
+     * Gets the value of the value property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getValue() {
+      return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setValue(final String value) {
+      this.value = value;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+      return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(final String value) {
+      name = value;
+    }
+
+    /**
+     * Gets the value of the exclude property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Boolean }
+     *     
+     */
+    public boolean isExclude() {
+      if (exclude == null) {
+        return false;
+      } else {
+        return exclude;
+      }
+    }
+
+    /**
+     * Sets the value of the exclude property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Boolean }
+     *     
+     */
+    public void setExclude(final Boolean value) {
+      exclude = value;
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModel.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModel.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModel.java
new file mode 100644
index 0000000..8d03da5
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModel.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>
+ * Java class for anonymous complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within
+ * this class.
+ * 
+ * <pre>
+ * &lt;complexType>
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="PersistenceUnit" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAPersistenceUnitMapType"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = { "persistenceUnit" })
+@XmlRootElement(name = "JPAEDMMappingModel")
+public class JPAEdmMappingModel {
+
+  @XmlElement(name = "PersistenceUnit", required = true)
+  protected JPAPersistenceUnitMapType persistenceUnit;
+
+  /**
+   * Gets the value of the persistenceUnit property.
+   * 
+   * @return possible object is {@link JPAPersistenceUnitMapType }
+   * 
+   */
+  public JPAPersistenceUnitMapType getPersistenceUnit() {
+    return persistenceUnit;
+  }
+
+  /**
+   * Sets the value of the persistenceUnit property.
+   * 
+   * @param value
+   *            allowed object is {@link JPAPersistenceUnitMapType }
+   * 
+   */
+  public void setPersistenceUnit(final JPAPersistenceUnitMapType value) {
+    persistenceUnit = value;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModelFactory.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModelFactory.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModelFactory.java
new file mode 100644
index 0000000..115ae1d
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEdmMappingModelFactory.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+/**
+ * This object contains factory methods for each Java content interface and Java
+ * element interface generated in the
+ * org.apache.olingo.odata2.processor.api.jpa.model.mapping package.
+ * <p>
+ * An ObjectFactory allows you to programatically construct new instances of the
+ * Java representation for XML content. The Java representation of XML content
+ * can consist of schema derived interfaces and classes representing the binding
+ * of schema type definitions, element declarations and model groups. Factory
+ * methods for each of these are provided in this class.
+ * 
+ */
+@XmlRegistry
+public class JPAEdmMappingModelFactory {
+
+  /**
+   * Create a new ObjectFactory that can be used to create new instances of
+   * schema derived classes for package:
+   * org.apache.olingo.odata2.processor.api.jpa.model.mapping
+   * 
+   */
+  public JPAEdmMappingModelFactory() {}
+
+  /**
+   * Create an instance of {@link JPARelationshipMapType }
+   * 
+   */
+  public JPARelationshipMapType createJPARelationshipMapType() {
+    return new JPARelationshipMapType();
+  }
+
+  /**
+   * Create an instance of {@link JPAAttributeMapType }
+   * 
+   */
+  public JPAAttributeMapType createJPAAttributeMapType() {
+    return new JPAAttributeMapType();
+  }
+
+  /**
+   * Create an instance of {@link JPAEDMMappingModel }
+   * 
+   */
+  public JPAEdmMappingModel createJPAEDMMappingModel() {
+    return new JPAEdmMappingModel();
+  }
+
+  /**
+   * Create an instance of {@link JPAPersistenceUnitMapType }
+   * 
+   */
+  public JPAPersistenceUnitMapType createJPAPersistenceUnitMapType() {
+    return new JPAPersistenceUnitMapType();
+  }
+
+  /**
+   * Create an instance of {@link JPAEmbeddableTypeMapType }
+   * 
+   */
+  public JPAEmbeddableTypeMapType createJPAEmbeddableTypeMapType() {
+    return new JPAEmbeddableTypeMapType();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypeMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypeMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypeMapType.java
new file mode 100644
index 0000000..d9fceb8
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypeMapType.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * 
+ * 				The default name for EDM
+ * 				complex type is derived from JPA Embeddable type name. This can be
+ * 				overriden using JPAEmbeddableTypeMapType.
+ * 			
+ * 
+ * <p>Java class for JPAEmbeddableTypeMapType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPAEmbeddableTypeMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="EDMComplexType" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         &lt;element name="JPAAttributes" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAAttributeMapType"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="exclude" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPAEmbeddableTypeMapType", propOrder = {
+    "edmComplexType",
+    "jpaAttributes"
+})
+public class JPAEmbeddableTypeMapType {
+
+  @XmlElement(name = "EDMComplexType")
+  protected String edmComplexType;
+  @XmlElement(name = "JPAAttributes", required = true)
+  protected JPAAttributeMapType jpaAttributes;
+  @XmlAttribute(name = "name", required = true)
+  protected String name;
+  @XmlAttribute(name = "exclude")
+  protected Boolean exclude;
+
+  /**
+   * Gets the value of the edmComplexType property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link String }
+   *     
+   */
+  public String getEDMComplexType() {
+    return edmComplexType;
+  }
+
+  /**
+   * Sets the value of the edmComplexType property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link String }
+   *     
+   */
+  public void setEDMComplexType(final String value) {
+    edmComplexType = value;
+  }
+
+  /**
+   * Gets the value of the jpaAttributes property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link JPAAttributeMapType }
+   *     
+   */
+  public JPAAttributeMapType getJPAAttributes() {
+    return jpaAttributes;
+  }
+
+  /**
+   * Sets the value of the jpaAttributes property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link JPAAttributeMapType }
+   *     
+   */
+  public void setJPAAttributes(final JPAAttributeMapType value) {
+    jpaAttributes = value;
+  }
+
+  /**
+   * Gets the value of the name property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link String }
+   *     
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Sets the value of the name property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link String }
+   *     
+   */
+  public void setName(final String value) {
+    name = value;
+  }
+
+  /**
+   * Gets the value of the exclude property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link Boolean }
+   *     
+   */
+  public boolean isExclude() {
+    if (exclude == null) {
+      return false;
+    } else {
+      return exclude;
+    }
+  }
+
+  /**
+   * Sets the value of the exclude property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link Boolean }
+   *     
+   */
+  public void setExclude(final Boolean value) {
+    exclude = value;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypesMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypesMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypesMapType.java
new file mode 100644
index 0000000..f7e5b8a
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEmbeddableTypesMapType.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>
+ * Java class for JPAEmbeddableTypesMapType complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within
+ * this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPAEmbeddableTypesMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="JPAEmbeddableType" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAEmbeddableTypeMapType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPAEmbeddableTypesMapType", propOrder = { "jpaEmbeddableType" })
+public class JPAEmbeddableTypesMapType {
+
+  @XmlElement(name = "JPAEmbeddableType")
+  protected List<JPAEmbeddableTypeMapType> jpaEmbeddableType;
+
+  /**
+   * Gets the value of the jpaEmbeddableType property.
+   * 
+   * <p>
+   * This accessor method returns a reference to the live list, not a
+   * snapshot. Therefore any modification you make to the returned list will
+   * be present inside the JAXB object. This is why there is not a
+   * <CODE>set</CODE> method for the jpaEmbeddableType property.
+   * 
+   * <p>
+   * For example, to add a new item, do as follows:
+   * 
+   * <pre>
+   * getJPAEmbeddableType().add(newItem);
+   * </pre>
+   * 
+   * 
+   * <p>
+   * Objects of the following type(s) are allowed in the list
+   * {@link JPAEmbeddableTypeMapType }
+   * 
+   * 
+   */
+  public List<JPAEmbeddableTypeMapType> getJPAEmbeddableType() {
+    if (jpaEmbeddableType == null) {
+      jpaEmbeddableType = new ArrayList<JPAEmbeddableTypeMapType>();
+    }
+    return jpaEmbeddableType;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypeMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypeMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypeMapType.java
new file mode 100644
index 0000000..10bccde
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypeMapType.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * 
+ * 				The default name for EDM
+ * 				entity type is derived from JPA entity type name. This can be
+ * 				overriden using JPAEntityTypeMapType.
+ * 			
+ * 
+ * <p>Java class for JPAEntityTypeMapType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPAEntityTypeMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="EDMEntityType" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         &lt;element name="EDMEntitySet" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         &lt;element name="JPAAttributes" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAAttributeMapType"/>
+ *         &lt;element name="JPARelationships" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPARelationshipMapType"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="exclude" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPAEntityTypeMapType", propOrder = {
+    "edmEntityType",
+    "edmEntitySet",
+    "jpaAttributes",
+    "jpaRelationships"
+})
+public class JPAEntityTypeMapType {
+
+  @XmlElement(name = "EDMEntityType")
+  protected String edmEntityType;
+  @XmlElement(name = "EDMEntitySet")
+  protected String edmEntitySet;
+  @XmlElement(name = "JPAAttributes", required = true)
+  protected JPAAttributeMapType jpaAttributes;
+  @XmlElement(name = "JPARelationships", required = true)
+  protected JPARelationshipMapType jpaRelationships;
+  @XmlAttribute(name = "name", required = true)
+  protected String name;
+  @XmlAttribute(name = "exclude")
+  protected Boolean exclude;
+
+  /**
+   * Gets the value of the edmEntityType property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link String }
+   *     
+   */
+  public String getEDMEntityType() {
+    return edmEntityType;
+  }
+
+  /**
+   * Sets the value of the edmEntityType property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link String }
+   *     
+   */
+  public void setEDMEntityType(final String value) {
+    edmEntityType = value;
+  }
+
+  /**
+   * Gets the value of the edmEntitySet property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link String }
+   *     
+   */
+  public String getEDMEntitySet() {
+    return edmEntitySet;
+  }
+
+  /**
+   * Sets the value of the edmEntitySet property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link String }
+   *     
+   */
+  public void setEDMEntitySet(final String value) {
+    edmEntitySet = value;
+  }
+
+  /**
+   * Gets the value of the jpaAttributes property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link JPAAttributeMapType }
+   *     
+   */
+  public JPAAttributeMapType getJPAAttributes() {
+    return jpaAttributes;
+  }
+
+  /**
+   * Sets the value of the jpaAttributes property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link JPAAttributeMapType }
+   *     
+   */
+  public void setJPAAttributes(final JPAAttributeMapType value) {
+    jpaAttributes = value;
+  }
+
+  /**
+   * Gets the value of the jpaRelationships property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link JPARelationshipMapType }
+   *     
+   */
+  public JPARelationshipMapType getJPARelationships() {
+    return jpaRelationships;
+  }
+
+  /**
+   * Sets the value of the jpaRelationships property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link JPARelationshipMapType }
+   *     
+   */
+  public void setJPARelationships(final JPARelationshipMapType value) {
+    jpaRelationships = value;
+  }
+
+  /**
+   * Gets the value of the name property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link String }
+   *     
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Sets the value of the name property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link String }
+   *     
+   */
+  public void setName(final String value) {
+    name = value;
+  }
+
+  /**
+   * Gets the value of the exclude property.
+   * 
+   * @return
+   *     possible object is
+   *     {@link Boolean }
+   *     
+   */
+  public boolean isExclude() {
+    if (exclude == null) {
+      return false;
+    } else {
+      return exclude;
+    }
+  }
+
+  /**
+   * Sets the value of the exclude property.
+   * 
+   * @param value
+   *     allowed object is
+   *     {@link Boolean }
+   *     
+   */
+  public void setExclude(final Boolean value) {
+    exclude = value;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypesMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypesMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypesMapType.java
new file mode 100644
index 0000000..f3e705e
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAEntityTypesMapType.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>
+ * Java class for JPAEntityTypesMapType complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within
+ * this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPAEntityTypesMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="JPAEntityType" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAEntityTypeMapType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPAEntityTypesMapType", propOrder = { "jpaEntityType" })
+public class JPAEntityTypesMapType {
+
+  @XmlElement(name = "JPAEntityType")
+  protected List<JPAEntityTypeMapType> jpaEntityType;
+
+  /**
+   * Gets the value of the jpaEntityType property.
+   * 
+   * <p>
+   * This accessor method returns a reference to the live list, not a
+   * snapshot. Therefore any modification you make to the returned list will
+   * be present inside the JAXB object. This is why there is not a
+   * <CODE>set</CODE> method for the jpaEntityType property.
+   * 
+   * <p>
+   * For example, to add a new item, do as follows:
+   * 
+   * <pre>
+   * getJPAEntityType().add(newItem);
+   * </pre>
+   * 
+   * 
+   * <p>
+   * Objects of the following type(s) are allowed in the list
+   * {@link JPAEntityTypeMapType }
+   * 
+   * 
+   */
+  public List<JPAEntityTypeMapType> getJPAEntityType() {
+    if (jpaEntityType == null) {
+      jpaEntityType = new ArrayList<JPAEntityTypeMapType>();
+    }
+    return jpaEntityType;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAPersistenceUnitMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAPersistenceUnitMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAPersistenceUnitMapType.java
new file mode 100644
index 0000000..9693307
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPAPersistenceUnitMapType.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.processor.api.jpa.model.mapping;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * 
+ * By default Java Persistence Unit name is taken as EDM schema name. This can
+ * be overriden using JPAPersistenceUnitMapType.
+ * 
+ * 
+ * <p>
+ * Java class for JPAPersistenceUnitMapType complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within
+ * this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPAPersistenceUnitMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="EDMSchemaNamespace" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         &lt;element name="JPAEntityTypes" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAEntityTypesMapType"/>
+ *         &lt;element name="JPAEmbeddableTypes" type="{http://www.sap.com/core/odata/processor/api/jpa/model/mapping}JPAEmbeddableTypesMapType"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPAPersistenceUnitMapType", propOrder = {
+    "edmSchemaNamespace", "jpaEntityTypes", "jpaEmbeddableTypes" })
+public class JPAPersistenceUnitMapType {
+
+  @XmlElement(name = "EDMSchemaNamespace")
+  protected String edmSchemaNamespace;
+  @XmlElement(name = "JPAEntityTypes", required = true)
+  protected JPAEntityTypesMapType jpaEntityTypes;
+  @XmlElement(name = "JPAEmbeddableTypes", required = true)
+  protected JPAEmbeddableTypesMapType jpaEmbeddableTypes;
+  @XmlAttribute(name = "name", required = true)
+  protected String name;
+
+  /**
+   * Gets the value of the edmSchemaNamespace property.
+   * 
+   * @return possible object is {@link String }
+   * 
+   */
+  public String getEDMSchemaNamespace() {
+    return edmSchemaNamespace;
+  }
+
+  /**
+   * Sets the value of the edmSchemaNamespace property.
+   * 
+   * @param value
+   *            allowed object is {@link String }
+   * 
+   */
+  public void setEDMSchemaNamespace(final String value) {
+    edmSchemaNamespace = value;
+  }
+
+  /**
+   * Gets the value of the jpaEntityTypes property.
+   * 
+   * @return possible object is {@link JPAEntityTypesMapType }
+   * 
+   */
+  public JPAEntityTypesMapType getJPAEntityTypes() {
+    return jpaEntityTypes;
+  }
+
+  /**
+   * Sets the value of the jpaEntityTypes property.
+   * 
+   * @param value
+   *            allowed object is {@link JPAEntityTypesMapType }
+   * 
+   */
+  public void setJPAEntityTypes(final JPAEntityTypesMapType value) {
+    jpaEntityTypes = value;
+  }
+
+  /**
+   * Gets the value of the jpaEmbeddableTypes property.
+   * 
+   * @return possible object is {@link JPAEmbeddableTypesMapType }
+   * 
+   */
+  public JPAEmbeddableTypesMapType getJPAEmbeddableTypes() {
+    return jpaEmbeddableTypes;
+  }
+
+  /**
+   * Sets the value of the jpaEmbeddableTypes property.
+   * 
+   * @param value
+   *            allowed object is {@link JPAEmbeddableTypesMapType }
+   * 
+   */
+  public void setJPAEmbeddableTypes(final JPAEmbeddableTypesMapType value) {
+    jpaEmbeddableTypes = value;
+  }
+
+  /**
+   * Gets the value of the name property.
+   * 
+   * @return possible object is {@link String }
+   * 
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Sets the value of the name property.
+   * 
+   * @param value
+   *            allowed object is {@link String }
+   * 
+   */
+  public void setName(final String value) {
+    name = value;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPARelationshipMapType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPARelationshipMapType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPARelationshipMapType.java
new file mode 100644
index 0000000..5c88792
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/JPARelationshipMapType.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model.mapping;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+/**
+ * 
+ * The default name for EDM navigation property is derived from JPA relationship
+ * name. This can be overriden using JPARelationshipMapType.
+ * 
+ * 
+ * <p>
+ * Java class for JPARelationshipMapType complex type.
+ * 
+ * <p>
+ * The following schema fragment specifies the expected content contained within
+ * this class.
+ * 
+ * <pre>
+ * &lt;complexType name="JPARelationshipMapType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="JPARelationship" maxOccurs="unbounded" minOccurs="0">
+ *           &lt;complexType>
+ *             &lt;simpleContent>
+ *               &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+ *                 &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *               &lt;/extension>
+ *             &lt;/simpleContent>
+ *           &lt;/complexType>
+ *         &lt;/element>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "JPARelationshipMapType", propOrder = { "jpaRelationship" })
+public class JPARelationshipMapType {
+
+  @XmlElement(name = "JPARelationship")
+  protected List<JPARelationshipMapType.JPARelationship> jpaRelationship;
+
+  /**
+   * Gets the value of the jpaRelationship property.
+   * 
+   * <p>
+   * This accessor method returns a reference to the live list, not a
+   * snapshot. Therefore any modification you make to the returned list will
+   * be present inside the JAXB object. This is why there is not a
+   * <CODE>set</CODE> method for the jpaRelationship property.
+   * 
+   * <p>
+   * For example, to add a new item, do as follows:
+   * 
+   * <pre>
+   * getJPARelationship().add(newItem);
+   * </pre>
+   * 
+   * 
+   * <p>
+   * Objects of the following type(s) are allowed in the list
+   * {@link JPARelationshipMapType.JPARelationship }
+   * 
+   * 
+   */
+  public List<JPARelationshipMapType.JPARelationship> getJPARelationship() {
+    if (jpaRelationship == null) {
+      jpaRelationship = new ArrayList<JPARelationshipMapType.JPARelationship>();
+    }
+    return jpaRelationship;
+  }
+
+  /**
+   * <p>
+   * Java class for anonymous complex type.
+   * 
+   * <p>
+   * The following schema fragment specifies the expected content contained
+   * within this class.
+   * 
+   * <pre>
+   * &lt;complexType>
+   *   &lt;simpleContent>
+   *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+   *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+   *     &lt;/extension>
+   *   &lt;/simpleContent>
+   * &lt;/complexType>
+   * </pre>
+   * 
+   * 
+   */
+  @XmlAccessorType(XmlAccessType.FIELD)
+  @XmlType(name = "", propOrder = { "value" })
+  public static class JPARelationship {
+
+    @XmlValue
+    protected String value;
+    @XmlAttribute(name = "name", required = true)
+    protected String name;
+
+    /**
+     * Gets the value of the value property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getValue() {
+      return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *            allowed object is {@link String }
+     * 
+     */
+    public void setValue(final String value) {
+      this.value = value;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return possible object is {@link String }
+     * 
+     */
+    public String getName() {
+      return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *            allowed object is {@link String }
+     * 
+     */
+    public void setName(final String value) {
+      name = value;
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/package-info.java
new file mode 100644
index 0000000..8d479b5
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/mapping/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library - Mapping Model</h3>
+ * The JPA EDM Mapping model (XML document) is represented as JAXB annotated Java Classes.
+ * 
+ * @author SAP AG
+ */
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.sap.com/core/odata/processor/api/jpa/model/mapping", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.olingo.odata2.processor.api.jpa.model.mapping;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/package-info.java
new file mode 100644
index 0000000..542f805
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library - JPA EDM Model</h3>
+ * The library provides a set of views over the JPA/EDM element containers. 
+ * The views can used to access the elements that form EDM.
+ * 
+ * @author SAP AG
+ */
+package org.apache.olingo.odata2.processor.api.jpa.model;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/package-info.java
new file mode 100644
index 0000000..9a62f1d
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/package-info.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library</h3>
+ * The library provides a way for the developers to create an OData Service from a Java Persistence Model.
+ * The library supports Java Persistence 2.0 and is dependent on OData library.
+ * 
+ * To create an OData service from JPA models
+ * <ol><li>extend the service factory class {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAServiceFactory}
+ * and implement the methods</li>
+ * <li>define a JAX-RS servlet in web.xml and configure the service factory as servlet init parameter. 
+ * <p><b>See Also:</b>{@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAServiceFactory}</li></ol>
+ * 
+ * @author SAP AG
+ */
+package org.apache.olingo.odata2.processor.api.jpa;
+


[40/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/ODataExpressionParserTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/ODataExpressionParserTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/ODataExpressionParserTest.java
new file mode 100644
index 0000000..b4d7fc3
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/ODataExpressionParserTest.java
@@ -0,0 +1,586 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+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.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
+import org.apache.olingo.odata2.api.uri.expression.MemberExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
+import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
+import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.UnaryOperator;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.ODataExpressionParser;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class ODataExpressionParserTest {
+
+  private static final String EXPECTED_STR_1 = "gwt1.SalesOrder = 1234";
+  private static final String EXPECTED_STR_2 = "gwt1.SalesOrder >= 1234 AND gwt1.SalesABC <> XYZ";
+  private static final String EXPECTED_STR_3 = "gwt1.SalesOrder >= 1234 OR gwt1.SalesABC <> XYZ";
+  private static final String EXPECTED_STR_4 = "gwt1.SalesOrder < 1234 AND gwt1.SalesABC <= XYZ";
+  private static final String EXPECTED_STR_5 = "gwt1.LineItems > 2345 AND gwt1.SalesOrder >= Amazon";
+  private static final String EXPECTED_STR_6 = "gwt1.Address.city = \'City_3\'";
+  private static final String EXPECTED_STR_7 = "gwt1.Address.city.area = \'BTM\'";
+  private static final String EXPECTED_STR_8 = "gwt1.field1 = 1 AND gwt1.field2 = 'abc'";
+  private static final String EXPECTED_STR_9 = "gwt1.BuyerAddress, gwt1.BuyerName, gwt1.BuyerId";
+  private static final String EXPECTED_STR_10 = "gwt1.SalesOrder";
+  private static final String EXPECTED_STR_11 = "NOT(gwt1.deliveryStatus)";
+  private static final String EXPECTED_STR_12 = "(CASE WHEN gwt1.currencyCode LIKE '%Ru%' THEN TRUE ELSE FALSE END) = true";
+  private static final String EXPECTED_STR_13 = "SUBSTRING(gwt1.currencyCode, 1 + 1 , 2) = 'NR'";
+  private static final String EXPECTED_STR_14 = "LOWER(gwt1.currencyCode) = 'inr rupees'";
+  private static final String EXPECTED_STR_15 = "(CASE WHEN LOWER(gwt1.currencyCode) LIKE '%nr rupees%' THEN TRUE ELSE FALSE END) = true";
+  private static final String EXPECTED_STR_16 = "(CASE WHEN gwt1.currencyCode LIKE '%INR%' THEN TRUE ELSE FALSE END) = true";
+  private static final String EXPECTED_STR_17 = "(CASE WHEN LOWER(gwt1.currencyCode) LIKE '%nr rupees%' THEN TRUE ELSE FALSE END) = true";
+
+  private static final String ADDRESS = "Address";
+  private static final String CITY = "city";
+  private static final String AREA = "area";
+  private static final String SALES_ORDER = "SalesOrder";
+  private static final String SALES_ABC = "SalesABC";
+  private static final String SAMPLE_DATA_1 = "1234";
+  private static final String SAMPLE_DATA_2 = "2345";
+  private static final String SAMPLE_DATA_XYZ = "XYZ";
+  private static final String SAMPLE_DATA_BTM = "\'BTM\'";
+  private static final String SAMPLE_DATA_CITY_3 = "\'City_3\'";
+  private static final String SAMPLE_DATA_LINE_ITEMS = "LineItems";
+  private static final String SAMPLE_DATA_AMAZON = "Amazon";
+  private static final String SAMPLE_DATA_FIELD1 = "field1";
+  private static final String SAMPLE_DATA_FIELD2 = "field2";
+
+  private static final String TABLE_ALIAS = "gwt1"; //$NON-NLS-1$
+
+  @Test
+  public void testParseWhereExpression() {
+    try {
+      String parsedStr = ODataJPATestConstants.EMPTY_STRING;
+      // Simple Binary query -
+      parsedStr = ODataExpressionParser.parseToJPAWhereExpression(
+          getBinaryExpressionMockedObj(BinaryOperator.EQ, ExpressionKind.PROPERTY,
+              SALES_ORDER, SAMPLE_DATA_1), TABLE_ALIAS);
+
+      assertEquals(EXPECTED_STR_1, parsedStr);
+      // complex query -
+      parsedStr = ODataJPATestConstants.EMPTY_STRING;
+
+      CommonExpression exp1 = getBinaryExpressionMockedObj(
+          BinaryOperator.GE, ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1);
+      CommonExpression exp2 = getBinaryExpressionMockedObj(
+          BinaryOperator.NE, ExpressionKind.PROPERTY, SALES_ABC, SAMPLE_DATA_XYZ);
+      parsedStr = ODataExpressionParser.parseToJPAWhereExpression(
+          getBinaryExpression(exp1, BinaryOperator.AND, exp2), TABLE_ALIAS);
+      assertEquals(EXPECTED_STR_2, parsedStr);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testMoreThanOneBinaryExpression() {
+    // complex query -
+    String parsedStr = ODataJPATestConstants.EMPTY_STRING;
+    CommonExpression exp1 = getBinaryExpressionMockedObj(BinaryOperator.GE,
+        ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1);
+    CommonExpression exp2 = getBinaryExpressionMockedObj(BinaryOperator.NE,
+        ExpressionKind.PROPERTY, SALES_ABC, SAMPLE_DATA_XYZ);
+    try {
+      parsedStr = ODataExpressionParser.parseToJPAWhereExpression(
+          getBinaryExpression(exp1, BinaryOperator.AND, exp2),
+          TABLE_ALIAS);
+      assertEquals(EXPECTED_STR_2, parsedStr);
+      parsedStr = ODataExpressionParser
+          .parseToJPAWhereExpression(
+              getBinaryExpression(exp1, BinaryOperator.OR, exp2),
+              TABLE_ALIAS);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals(EXPECTED_STR_3, parsedStr);
+  }
+
+  @Test
+  public void testParseFilterExpression() {
+    try {
+      assertEquals(EXPECTED_STR_10,
+          ODataExpressionParser.parseToJPAWhereExpression(
+              getFilterExpressionMockedObj(ExpressionKind.PROPERTY,
+                  SALES_ORDER), TABLE_ALIAS));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testAllBinaryOperators() { // Test for all Binary Operators
+    // complex query -
+    String parsedStr1 = ODataJPATestConstants.EMPTY_STRING;
+    String parsedStr2 = ODataJPATestConstants.EMPTY_STRING;
+
+    CommonExpression exp1 = getBinaryExpressionMockedObj(BinaryOperator.LT,
+        ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1);
+    CommonExpression exp2 = getBinaryExpressionMockedObj(BinaryOperator.LE,
+        ExpressionKind.PROPERTY, SALES_ABC, SAMPLE_DATA_XYZ);
+
+    try {
+      parsedStr1 = ODataExpressionParser.parseToJPAWhereExpression(
+          (BinaryExpression) getBinaryExpression(exp1,
+              BinaryOperator.AND, exp2), TABLE_ALIAS);
+      assertEquals(EXPECTED_STR_4, parsedStr1);
+
+      CommonExpression exp3 = getBinaryExpressionMockedObj(BinaryOperator.GT,
+          ExpressionKind.PROPERTY, SAMPLE_DATA_LINE_ITEMS, SAMPLE_DATA_2);
+      CommonExpression exp4 = getBinaryExpressionMockedObj(BinaryOperator.GE,
+          ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_AMAZON);
+
+      parsedStr2 = ODataExpressionParser.parseToJPAWhereExpression(
+          getBinaryExpression(exp3, BinaryOperator.AND, exp4),
+          TABLE_ALIAS);
+
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals(EXPECTED_STR_5, parsedStr2);
+  }
+
+  @Test
+  public void testParseMemberExpression() {
+    try {
+      assertEquals(EXPECTED_STR_6,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(
+                  getBinaryExpression(
+                      getMemberExpressionMockedObj(ADDRESS,
+                          CITY),
+                      BinaryOperator.EQ,
+                      getLiteralExpressionMockedObj(SAMPLE_DATA_CITY_3)),
+                  TABLE_ALIAS));
+      assertEquals(EXPECTED_STR_7,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(
+                  getBinaryExpression(
+                      getMultipleMemberExpressionMockedObj(ADDRESS, CITY, AREA),
+                      BinaryOperator.EQ,
+                      getLiteralExpressionMockedObj(SAMPLE_DATA_BTM)),
+                  TABLE_ALIAS));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testParseMethodExpression() {
+    try {
+      assertEquals(EXPECTED_STR_12,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(
+                  getBinaryExpression(
+                      getMethodExpressionMockedObj(MethodOperator.SUBSTRINGOF, "'Ru'", "currencyCode", null, 2),
+                      BinaryOperator.EQ,
+                      getLiteralExpressionMockedObj("true")),
+                  TABLE_ALIAS));
+      assertEquals(EXPECTED_STR_13,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(
+                  getBinaryExpression(
+                      getMethodExpressionMockedObj(MethodOperator.SUBSTRING, "currencyCode", "1", "2", 3),
+                      BinaryOperator.EQ,
+                      getLiteralExpressionMockedObj("'NR'")),
+                  TABLE_ALIAS));
+      assertEquals(EXPECTED_STR_14,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(
+                  getBinaryExpression(
+                      getMethodExpressionMockedObj(MethodOperator.TOLOWER, "currencyCode", null, null, 1),
+                      BinaryOperator.EQ,
+                      getLiteralExpressionMockedObj("'inr rupees'")),
+                  TABLE_ALIAS));
+      assertEquals(EXPECTED_STR_15,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(
+                  getBinaryExpression(
+                      getMultipleMethodExpressionMockedObj(MethodOperator.SUBSTRINGOF, "'nr rupees'", MethodOperator.TOLOWER, "currencyCode", 2, 1),
+                      BinaryOperator.EQ,
+                      getLiteralExpressionMockedObj("true")),
+                  TABLE_ALIAS));
+      assertEquals(EXPECTED_STR_16,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(getFilterExpressionForFunctionsMockedObj(MethodOperator.SUBSTRINGOF, "'INR'", null, "currencyCode", 2, null)
+                  /*getBinaryExpression(
+                  		getMemberExpressionMockedObj(ADDRESS,
+                  				CITY),
+                  		BinaryOperator.EQ,
+                  		getLiteralExpressionMockedObj(SAMPLE_DATA_CITY_3))*/,
+                  TABLE_ALIAS));
+      assertEquals(EXPECTED_STR_17,
+          ODataExpressionParser
+              .parseToJPAWhereExpression(getFilterExpressionForFunctionsMockedObj(MethodOperator.SUBSTRINGOF, "'nr rupees'", MethodOperator.TOLOWER, "currencyCode", 2, 1)
+                  /*getBinaryExpression(
+                  		getMemberExpressionMockedObj(ADDRESS,
+                  				CITY),
+                  		BinaryOperator.EQ,
+                  		getLiteralExpressionMockedObj(SAMPLE_DATA_CITY_3))*/,
+                  TABLE_ALIAS));
+
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  private CommonExpression getMethodExpressionMockedObj(final MethodOperator methodOperator, final String firstName, final String secondName, final String thirdName, final Integer parameterCount) {
+
+    List<CommonExpression> parameters = new ArrayList<CommonExpression>();
+
+    if (methodOperator == MethodOperator.SUBSTRINGOF) {
+      parameters.add(getLiteralExpressionMockedObj(firstName));
+      parameters.add(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, secondName));
+    }
+
+    else if (methodOperator == MethodOperator.SUBSTRING) {
+      parameters.add(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, firstName));
+      parameters.add(getLiteralExpressionMockedObj(secondName));
+      parameters.add(getLiteralExpressionMockedObj(thirdName));
+    }
+    else if (methodOperator == MethodOperator.TOLOWER) {
+      parameters.add(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, firstName));
+    }
+
+    MethodExpression methodExpression = EasyMock.createMock(MethodExpression.class);
+
+    EasyMock.expect(methodExpression.getKind()).andStubReturn(ExpressionKind.METHOD);
+    EasyMock.expect(methodExpression.getMethod()).andStubReturn(methodOperator);
+    EasyMock.expect(methodExpression.getParameterCount()).andStubReturn(parameterCount);
+    EasyMock.expect(methodExpression.getParameters()).andStubReturn(parameters);
+    EasyMock.replay(methodExpression);
+
+    return methodExpression;
+  }
+
+  private CommonExpression getMultipleMethodExpressionMockedObj(final MethodOperator methodOperator1, final String firstName, final MethodOperator methodOperator2, final String secondName, final Integer parameterCount1, final Integer parameterCount2) {
+
+    //complex query
+    List<CommonExpression> parameters = new ArrayList<CommonExpression>();
+
+    parameters.add(getLiteralExpressionMockedObj(firstName));
+    parameters.add(getMethodExpressionMockedObj(methodOperator2, secondName, null, null, 1));
+
+    MethodExpression methodExpression = EasyMock.createMock(MethodExpression.class);
+
+    EasyMock.expect(methodExpression.getKind()).andStubReturn(ExpressionKind.METHOD);
+    EasyMock.expect(methodExpression.getMethod()).andStubReturn(methodOperator1);
+    EasyMock.expect(methodExpression.getParameterCount()).andStubReturn(parameterCount1);
+    EasyMock.expect(methodExpression.getParameters()).andStubReturn(parameters);
+    EasyMock.replay(methodExpression);
+
+    return methodExpression;
+  }
+
+  private CommonExpression getMultipleMemberExpressionMockedObj(final String string1, final String string2, final String string3) {
+
+    MemberExpression memberExpression = EasyMock.createMock(MemberExpression.class);
+
+    EasyMock.expect(memberExpression.getPath()).andStubReturn(getMemberExpressionMockedObj(string1, string2));
+    EasyMock.expect(memberExpression.getProperty()).andStubReturn(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, string3));
+    EasyMock.expect(memberExpression.getKind()).andStubReturn(ExpressionKind.MEMBER);
+    EasyMock.replay(memberExpression);
+
+    return memberExpression;
+  }
+
+  @Test
+  public void testParseUnaryExpression() {
+
+    UnaryExpression unaryExpression = getUnaryExpressionMockedObj(
+        getPropertyExpressionMockedObj(ExpressionKind.PROPERTY,
+            "deliveryStatus"),
+        org.apache.olingo.odata2.api.uri.expression.UnaryOperator.NOT);
+    try {
+      assertEquals(EXPECTED_STR_11, ODataExpressionParser.parseToJPAWhereExpression(
+          unaryExpression, TABLE_ALIAS));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  private UnaryExpression getUnaryExpressionMockedObj(
+      final CommonExpression operand, final UnaryOperator unaryOperator) {
+    UnaryExpression unaryExpression = EasyMock
+        .createMock(UnaryExpression.class);
+    EasyMock.expect(unaryExpression.getKind())
+        .andStubReturn(ExpressionKind.UNARY);
+    EasyMock.expect(unaryExpression.getOperand()).andStubReturn(operand);
+    EasyMock.expect(unaryExpression.getOperator()).andStubReturn(unaryOperator);
+
+    EasyMock.replay(unaryExpression);
+    return unaryExpression;
+  }
+
+  private CommonExpression getMemberExpressionMockedObj(
+      final String pathUriLiteral, final String propertyUriLiteral) {
+    MemberExpression memberExpression = EasyMock
+        .createMock(MemberExpression.class);
+    EasyMock.expect(memberExpression.getPath())
+        .andStubReturn(
+            getPropertyExpressionMockedObj(ExpressionKind.PROPERTY,
+                pathUriLiteral));
+    EasyMock.expect(memberExpression.getProperty())
+        .andStubReturn(
+            getPropertyExpressionMockedObj(ExpressionKind.PROPERTY,
+                propertyUriLiteral));
+    EasyMock.expect(memberExpression.getKind())
+        .andStubReturn(ExpressionKind.MEMBER);
+
+    EasyMock.replay(memberExpression);
+    return memberExpression;
+  }
+
+  private LiteralExpression getLiteralExpressionMockedObj(final String uriLiteral) {
+    LiteralExpression rightOperandLiteralExpresion = EasyMock
+        .createMock(LiteralExpression.class);
+    EasyMock.expect(rightOperandLiteralExpresion.getKind())
+        .andStubReturn(ExpressionKind.LITERAL);
+    EasyMock.expect(rightOperandLiteralExpresion.getUriLiteral())
+        .andStubReturn(uriLiteral);// SAMPLE_DATA
+    EasyMock.expect(rightOperandLiteralExpresion.getEdmType())
+        .andStubReturn(getEdmSimpleTypeMockedObj(uriLiteral));
+    EasyMock.replay(rightOperandLiteralExpresion);
+    return rightOperandLiteralExpresion;
+
+  }
+
+  private EdmSimpleType getEdmSimpleTypeMockedObj(final String value) {
+    EdmSimpleType edmSimpleType = EasyMock.createMock(EdmSimpleType.class);
+    try {
+      EasyMock.expect(edmSimpleType.getName()).andReturn(value);
+      EasyMock.expect(edmSimpleType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmSimpleType.valueOfString(value, EdmLiteralKind.URI,
+          getEdmFacetsMockedObj(), null)).andStubReturn(value);
+      EasyMock.expect(edmSimpleType.valueOfString(value, EdmLiteralKind.URI, null, null)).andStubReturn(value);
+      EasyMock.expect(edmSimpleType.valueToString(value, EdmLiteralKind.DEFAULT,
+          getEdmFacetsMockedObj())).andStubReturn(value);
+      EasyMock.expect(edmSimpleType.valueToString(value, EdmLiteralKind.DEFAULT, null)).andStubReturn(value);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.expect(edmSimpleType.getDefaultType()).andStubReturn(null);
+    EasyMock.replay(edmSimpleType);
+    return edmSimpleType;
+  }
+
+  private EdmFacets getEdmFacetsMockedObj() {
+    EdmFacets facets = EasyMock.createMock(EdmFacets.class);
+
+    EasyMock.replay(facets);
+    return facets;
+  }
+
+  private PropertyExpression getPropertyExpressionMockedObj(
+      final ExpressionKind expKind, final String propertyName) {
+    PropertyExpression leftOperandPropertyExpresion = EasyMock.createMock(PropertyExpression.class);
+    EasyMock.expect(leftOperandPropertyExpresion.getKind()).andStubReturn(ExpressionKind.PROPERTY);
+    EasyMock.expect(leftOperandPropertyExpresion.getPropertyName()).andStubReturn(propertyName);
+    EasyMock.expect(leftOperandPropertyExpresion.getEdmProperty()).andStubReturn(getEdmTypedMockedObj(propertyName));
+    EasyMock.replay(leftOperandPropertyExpresion);
+    return leftOperandPropertyExpresion;
+  }
+
+  private EdmTyped getEdmTypedMockedObj(final String propertyName) {
+    EdmProperty mockedEdmProperty = EasyMock.createMock(EdmProperty.class);
+    try {
+      EasyMock.expect(mockedEdmProperty.getMapping()).andStubReturn(getEdmMappingMockedObj(propertyName));
+      EasyMock.replay(mockedEdmProperty);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return mockedEdmProperty;
+  }
+
+  private EdmMapping getEdmMappingMockedObj(final String propertyName) {
+    EdmMapping mockedEdmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mockedEdmMapping.getInternalName())
+        .andStubReturn(propertyName);
+    EasyMock.replay(mockedEdmMapping);
+    return mockedEdmMapping;
+  }
+
+  private BinaryExpression getBinaryExpressionMockedObj(
+      final BinaryOperator operator, final ExpressionKind leftOperandExpKind,
+      final String propertyName, final String literalStr) {
+    BinaryExpression binaryExpression = EasyMock
+        .createMock(BinaryExpression.class);
+    EasyMock.expect(binaryExpression.getKind())
+        .andStubReturn(ExpressionKind.BINARY);
+    EasyMock.expect(binaryExpression.getLeftOperand())
+        .andStubReturn(
+            getPropertyExpressionMockedObj(leftOperandExpKind,
+                propertyName));
+    EasyMock.expect(binaryExpression.getOperator()).andStubReturn(operator);
+    EasyMock.expect(binaryExpression.getRightOperand())
+        .andStubReturn(getLiteralExpressionMockedObj(literalStr));
+
+    EasyMock.replay(binaryExpression);
+    return binaryExpression;
+  }
+
+  private FilterExpression getFilterExpressionMockedObj(
+      final ExpressionKind leftOperandExpKind, final String propertyName) {
+    FilterExpression filterExpression = EasyMock
+        .createMock(FilterExpression.class);
+    EasyMock.expect(filterExpression.getKind())
+        .andStubReturn(ExpressionKind.FILTER);
+    EasyMock.expect(filterExpression.getExpression())
+        .andStubReturn(
+            getPropertyExpressionMockedObj(leftOperandExpKind,
+                propertyName));
+
+    EasyMock.replay(filterExpression);
+    return filterExpression;
+  }
+
+  private FilterExpression getFilterExpressionForFunctionsMockedObj(
+      final MethodOperator methodOperator1, final String firstName, final MethodOperator methodOperator2, final String secondName, final Integer parameterCount1, final Integer parameterCount2) {
+    //default value handling of SUBSTRINGOF
+    FilterExpression filterExpression = EasyMock
+        .createMock(FilterExpression.class);
+    EasyMock.expect(filterExpression.getKind())
+        .andStubReturn(ExpressionKind.FILTER);
+    if ((methodOperator2 != null) && (parameterCount2 != null)) {
+      EasyMock.expect(filterExpression.getExpression())
+          .andStubReturn(
+              getMultipleMethodExpressionMockedObj(methodOperator1, firstName, methodOperator2, secondName, parameterCount1, parameterCount2));
+    }
+    else {
+      EasyMock.expect(filterExpression.getExpression())
+          .andStubReturn(
+              getMethodExpressionMockedObj(methodOperator1, firstName, secondName, null, parameterCount1));
+    }
+
+    EasyMock.replay(filterExpression);
+    return filterExpression;
+  }
+
+  private CommonExpression getBinaryExpression(
+      final CommonExpression leftOperand, final BinaryOperator operator,
+      final CommonExpression rightOperand) {
+    BinaryExpression binaryExpression = EasyMock
+        .createMock(BinaryExpression.class);
+    EasyMock.expect(binaryExpression.getKind())
+        .andStubReturn(ExpressionKind.BINARY);
+    EasyMock.expect(binaryExpression.getLeftOperand())
+        .andStubReturn(leftOperand);
+    EasyMock.expect(binaryExpression.getRightOperand())
+        .andStubReturn(rightOperand);
+    EasyMock.expect(binaryExpression.getOperator()).andStubReturn(operator);
+
+    EasyMock.replay(binaryExpression);
+    return binaryExpression;
+  }
+
+  @Test
+  public void testParseKeyPredicates() {
+    // Setting up the expected value
+    KeyPredicate keyPredicate1 = EasyMock.createMock(KeyPredicate.class);
+    EdmProperty kpProperty1 = EasyMock.createMock(EdmProperty.class);
+    EasyMock.expect(keyPredicate1.getLiteral()).andStubReturn("1");
+    KeyPredicate keyPredicate2 = EasyMock.createMock(KeyPredicate.class);
+    EdmProperty kpProperty2 = EasyMock.createMock(EdmProperty.class);
+    EasyMock.expect(keyPredicate2.getLiteral()).andStubReturn("abc");
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    try {
+      EasyMock.expect(kpProperty1.getName()).andStubReturn(SAMPLE_DATA_FIELD1);
+      EasyMock.expect(kpProperty1.getType()).andStubReturn(
+          EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance());
+      EasyMock.expect(kpProperty2.getName()).andStubReturn(SAMPLE_DATA_FIELD2);
+      EasyMock.expect(kpProperty2.getType()).andStubReturn(
+          EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
+      EasyMock.expect(keyPredicate1.getProperty()).andStubReturn(kpProperty1);
+      EasyMock.expect(kpProperty1.getMapping()).andReturn(edmMapping);
+      EasyMock.expect(edmMapping.getInternalName()).andReturn(SAMPLE_DATA_FIELD1);
+      EasyMock.expect(keyPredicate2.getProperty()).andStubReturn(kpProperty2);
+      EasyMock.expect(kpProperty2.getMapping()).andReturn(edmMapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.expect(edmMapping.getInternalName()).andReturn(SAMPLE_DATA_FIELD2);
+    EasyMock.replay(edmMapping);
+    EasyMock.replay(kpProperty1, keyPredicate1, kpProperty2, keyPredicate2);
+
+    ArrayList<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    keyPredicates.add(keyPredicate1);
+    keyPredicates.add(keyPredicate2);
+    String str = null;
+
+    try {
+      str = ODataExpressionParser.parseKeyPredicates(keyPredicates,
+          TABLE_ALIAS);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    assertEquals(EXPECTED_STR_8, str);
+  }
+
+  @Test
+  public void testParseToJPASelectExpression() {
+
+    ArrayList<String> selectedFields = new ArrayList<String>();
+    selectedFields.add("BuyerAddress");
+    selectedFields.add("BuyerName");
+    selectedFields.add("BuyerId");
+
+    assertEquals(EXPECTED_STR_9,
+        ODataExpressionParser.parseToJPASelectExpression(TABLE_ALIAS,
+            selectedFields));
+    assertEquals(TABLE_ALIAS, ODataExpressionParser.parseToJPASelectExpression(
+        TABLE_ALIAS, null));
+
+    selectedFields.clear();
+    assertEquals(TABLE_ALIAS, ODataExpressionParser.parseToJPASelectExpression(
+        TABLE_ALIAS, selectedFields));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/TestUtil.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/TestUtil.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/TestUtil.java
new file mode 100644
index 0000000..f238a99
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/TestUtil.java
@@ -0,0 +1,391 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.EasyMock;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.cud.SalesOrderLineItem;
+
+public class TestUtil {
+
+  public static ExpandSelectTreeNode mockExpandSelectTreeNode() {
+    ExpandSelectTreeNode nextExpandNode = EasyMock
+        .createMock(ExpandSelectTreeNode.class);
+    Map<String, ExpandSelectTreeNode> nextLink = null;
+    EasyMock.expect(nextExpandNode.getLinks()).andStubReturn(nextLink);
+    EasyMock.replay(nextExpandNode);
+    ExpandSelectTreeNode expandNode = EasyMock
+        .createMock(ExpandSelectTreeNode.class);
+    Map<String, ExpandSelectTreeNode> links = new HashMap<String, ExpandSelectTreeNode>();
+    links.put("SalesOrderLineItemDetails", nextExpandNode);
+    EasyMock.expect(expandNode.getLinks()).andStubReturn(links);
+    EasyMock.replay(expandNode);
+    return expandNode;
+  }
+
+  public static ExpandSelectTreeNode mockCurrentExpandSelectTreeNode() {
+    ExpandSelectTreeNode expandNode = EasyMock
+        .createMock(ExpandSelectTreeNode.class);
+    Map<String, ExpandSelectTreeNode> links = new HashMap<String, ExpandSelectTreeNode>();
+    EasyMock.expect(expandNode.getLinks()).andStubReturn(links);
+    EasyMock.replay(expandNode);
+    return expandNode;
+  }
+
+  public static List<ArrayList<NavigationPropertySegment>> getExpandList() {
+    List<ArrayList<NavigationPropertySegment>> expandList = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    ArrayList<NavigationPropertySegment> expands = new ArrayList<NavigationPropertySegment>();
+    expands.add(mockNavigationPropertySegment());
+    expandList.add(expands);
+    return expandList;
+  }
+
+  public static WriteFeedCallbackContext getWriteFeedCallBackContext() {
+    URI selfLink = null;
+    WriteFeedCallbackContext writeContext = new WriteFeedCallbackContext();
+    try {
+      selfLink = new URI("SalesOrders(2L)/SalesOrderLineItemDetails");
+      writeContext.setSelfLink(selfLink);
+      writeContext
+          .setCurrentExpandSelectTreeNode(mockCurrentExpandSelectTreeNode());
+      writeContext.setNavigationProperty(mockNavigationProperty());
+      writeContext.setSourceEntitySet(mockSourceEntitySet());
+      writeContext.setEntryData(getFeedData());
+
+    } catch (URISyntaxException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    return writeContext;
+  }
+
+  public static WriteEntryCallbackContext getWriteEntryCallBackContext() {
+    WriteEntryCallbackContext writeContext = new WriteEntryCallbackContext();
+    writeContext
+        .setCurrentExpandSelectTreeNode(mockCurrentExpandSelectTreeNode());
+    writeContext.setNavigationProperty(mockNavigationProperty());
+    writeContext.setSourceEntitySet(mockSourceEntitySet());
+    writeContext.setEntryData(getEntryData());
+    return writeContext;
+  }
+
+  private static EdmEntitySet mockSourceEntitySet() {
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(entitySet.getEntityType()).andStubReturn(
+          mockSourceEdmEntityType());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entitySet);
+    return entitySet;
+  }
+
+  public static EdmEntityType mockSourceEdmEntityType() {
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    List<String> navigationPropertyNames = new ArrayList<String>();
+    List<String> propertyNames = new ArrayList<String>();
+    propertyNames.add("id");
+    propertyNames.add("description");
+    navigationPropertyNames.add("SalesOrderLineItemDetails");
+    try {
+      EasyMock.expect(mapping.getInternalName()).andStubReturn(
+          "SalesOrderHeader");
+      EasyMock.replay(mapping);
+      EasyMock.expect(entityType.getName()).andStubReturn(
+          "SalesOrderHeader");
+      EasyMock.expect(entityType.getMapping()).andStubReturn(mapping);
+      EasyMock.expect(entityType.getNavigationPropertyNames())
+          .andStubReturn(navigationPropertyNames);
+      EasyMock.expect(entityType.getProperty("SalesOrderLineItemDetails"))
+          .andStubReturn(mockNavigationProperty());
+      EdmProperty property1 = mockEdmPropertyOfSource1();
+      EasyMock.expect(entityType.getProperty("id")).andStubReturn(
+          property1);
+      EasyMock.expect(entityType.getProperty("description"))
+          .andStubReturn(mockEdmPropertyOfSource2());
+      EasyMock.expect(entityType.getPropertyNames()).andStubReturn(
+          propertyNames);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entityType);
+    return entityType;
+  }
+
+  private static EdmTyped mockEdmPropertyOfSource2() {
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType type = EasyMock.createMock(EdmType.class);
+    EasyMock.expect(type.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+    EasyMock.replay(type);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn("description");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("description");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(type);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(mapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    return edmProperty;
+  }
+
+  private static EdmProperty mockEdmPropertyOfSource1() {
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType type = EasyMock.createMock(EdmType.class);
+    EasyMock.expect(type.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+    EasyMock.replay(type);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn("id");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("id");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(type);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(mapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    return edmProperty;
+  }
+
+  private static Map<String, Object> getFeedData() {
+    Map<String, Object> entryData = new HashMap<String, Object>();
+    entryData.put("id", 1);
+    entryData.put("description", "laptop");
+    List<SalesOrderLineItem> salesOrderLineItems = new ArrayList<SalesOrderLineItem>();
+    salesOrderLineItems.add(new SalesOrderLineItem(23));
+    salesOrderLineItems.add(new SalesOrderLineItem(45));
+    entryData.put("SalesOrderLineItemDetails", salesOrderLineItems);
+    return entryData;
+  }
+
+  private static Map<String, Object> getEntryData() {
+    Map<String, Object> entryData = new HashMap<String, Object>();
+    entryData.put("id", 1);
+    entryData.put("description", "laptop");
+    entryData.put("SalesOrderLineItemDetails", new SalesOrderLineItem(23));
+    return entryData;
+  }
+
+  private static NavigationPropertySegment mockNavigationPropertySegment() {
+    NavigationPropertySegment navigationPropSegment = EasyMock
+        .createMock(NavigationPropertySegment.class);
+    EasyMock.expect(navigationPropSegment.getNavigationProperty())
+        .andStubReturn(mockNavigationProperty());
+    EasyMock.expect(navigationPropSegment.getTargetEntitySet())
+        .andStubReturn(mockTargetEntitySet());
+    EasyMock.replay(navigationPropSegment);
+    return navigationPropSegment;
+  }
+
+  public static NavigationPropertySegment mockThirdNavigationPropertySegment()
+  {
+    NavigationPropertySegment navigationPropSegment = EasyMock
+        .createMock(NavigationPropertySegment.class);
+    EasyMock.expect(navigationPropSegment.getNavigationProperty())
+        .andStubReturn(mockSecondNavigationProperty());
+    EasyMock.expect(navigationPropSegment.getTargetEntitySet())
+        .andStubReturn(mockThirdEntitySet());
+    EasyMock.replay(navigationPropSegment);
+    return navigationPropSegment;
+  }
+
+  public static EdmNavigationProperty mockSecondNavigationProperty() {
+    EdmNavigationProperty navigationProperty = EasyMock
+        .createMock(EdmNavigationProperty.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn(
+        "materials");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(navigationProperty.getMultiplicity())
+          .andStubReturn(EdmMultiplicity.ONE);
+      EasyMock.expect(navigationProperty.getMapping()).andStubReturn(
+          mapping);
+      EasyMock.expect(navigationProperty.getName()).andStubReturn(
+          "MaterialDetails");
+      EasyMock.expect(navigationProperty.getFromRole()).andStubReturn("SalesOrderLineItem");
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(navigationProperty);
+    return navigationProperty;
+  }
+
+  public static EdmEntitySet mockTargetEntitySet() {
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(entitySet.getEntityType()).andStubReturn(
+          mockTargetEdmEntityType());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entitySet);
+    return entitySet;
+  }
+
+  public static EdmEntitySet mockThirdEntitySet() {
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(entitySet.getEntityType()).andStubReturn(
+          mockThirdEdmEntityType());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entitySet);
+    return entitySet;
+
+  }
+
+  private static EdmEntityType mockThirdEdmEntityType() {
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+
+    List<String> propertyNames = new ArrayList<String>();
+    propertyNames.add("price");
+    try {
+      EasyMock.expect(mapping.getInternalName()).andStubReturn(
+          "Material");
+      EasyMock.replay(mapping);
+      EasyMock.expect(entityType.getName()).andStubReturn(
+          "Material");
+      EasyMock.expect(entityType.getMapping()).andStubReturn(mapping);
+      EdmProperty property = mockEdmPropertyOfTarget();
+      EasyMock.expect(entityType.getProperty("price")).andStubReturn(
+          property);
+      EasyMock.expect(entityType.getPropertyNames()).andStubReturn(
+          propertyNames);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entityType);
+    return entityType;
+  }
+
+  public static EdmEntityType mockTargetEdmEntityType() {
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+
+    List<String> propertyNames = new ArrayList<String>();
+    propertyNames.add("price");
+    try {
+      EasyMock.expect(mapping.getInternalName()).andStubReturn(
+          "SalesOrderLineItem");
+      EasyMock.replay(mapping);
+      EasyMock.expect(entityType.getName()).andStubReturn(
+          "SalesOrderLineItem");
+      EasyMock.expect(entityType.getMapping()).andStubReturn(mapping);
+      EdmProperty property = mockEdmPropertyOfTarget();
+      EasyMock.expect(entityType.getProperty("price")).andStubReturn(
+          property);
+      EasyMock.expect(entityType.getPropertyNames()).andStubReturn(
+          propertyNames);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entityType);
+    return entityType;
+  }
+
+  private static EdmProperty mockEdmPropertyOfTarget() {
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+
+    EdmType type = EasyMock.createMock(EdmType.class);
+    EasyMock.expect(type.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+    EasyMock.replay(type);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn("price");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("price");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(type);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(mapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    return edmProperty;
+  }
+
+  public static EdmNavigationProperty mockNavigationProperty() {
+    EdmNavigationProperty navigationProperty = EasyMock
+        .createMock(EdmNavigationProperty.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn(
+        "salesOrderLineItems");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(navigationProperty.getMultiplicity())
+          .andStubReturn(EdmMultiplicity.MANY);
+      EasyMock.expect(navigationProperty.getMapping()).andStubReturn(
+          mapping);
+      EasyMock.expect(navigationProperty.getName()).andStubReturn(
+          "SalesOrderLineItemDetails");
+      EasyMock.expect(navigationProperty.getFromRole()).andStubReturn("SalesOrderHeader");
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(navigationProperty);
+    return navigationProperty;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelServiceTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelServiceTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelServiceTest.java
new file mode 100644
index 0000000..e9b89dd
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelServiceTest.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStream;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.processor.core.jpa.mock.ODataJPAContextMock;
+
+public class JPAEdmMappingModelServiceTest extends JPAEdmMappingModelService {
+
+  private static JPAEdmMappingModelServiceTest objJPAEdmMappingModelServiceTest;
+
+  private static final String MAPPING_FILE_CORRECT = "SalesOrderProcessingMappingModels.xml";
+  private static final String MAPPING_FILE_INCORRECT = "TEST.xml";
+
+  private static int VARIANT_MAPPING_FILE; // 0 FOR INCORRECT, 1 FOR CORRECT
+
+  private static String PERSISTENCE_UNIT_NAME_JPA = "salesorderprocessing";
+  private static String PERSISTENCE_UNIT_NAME_EDM = "SalesOrderProcessing";
+
+  private static String ENTITY_TYPE_NAME_JPA = "SalesOrderHeader";
+  private static String ENTITY_TYPE_NAME_EDM = "SalesOrder";
+  private static String ENTITY_SET_NAME_EDM = "SalesOrders";
+  private static String RELATIONSHIP_NAME_JPA = "salesOrderItems";
+  private static String RELATIONSHIP_NAME_EDM = "SalesOrderItemDetails";
+  private static String ATTRIBUTE_NAME_JPA = "netAmount";
+  private static String ATTRIBUTE_NAME_EDM = "NetAmount";
+  private static String EMBEDDABLE_TYPE_NAME_JPA = "SalesOrderItemKey";
+  private static String EMBEDDABLE_ATTRIBUTE_NAME_JPA = "liId";
+  private static String EMBEDDABLE_ATTRIBUTE_NAME_EDM = "ID";
+  private static String EMBEDDABLE_TYPE_2_NAME_JPA = "SalesOrderItemKey";
+
+  private static String ENTITY_TYPE_NAME_JPA_WRONG = "SalesOrderHeaders";
+  private static String RELATIONSHIP_NAME_JPA_WRONG = "value";
+  private static String EMBEDDABLE_TYPE_NAME_JPA_WRONG = "SalesOrderItemKeys";
+
+  public JPAEdmMappingModelServiceTest() {
+    super(ODataJPAContextMock.mockODataJPAContext());
+  }
+
+  @BeforeClass
+  public static void setup() {
+    objJPAEdmMappingModelServiceTest = new JPAEdmMappingModelServiceTest();
+    VARIANT_MAPPING_FILE = 1;
+    objJPAEdmMappingModelServiceTest.loadMappingModel();
+  }
+
+  @Test
+  public void testLoadMappingModel() {
+    VARIANT_MAPPING_FILE = 1;
+    loadMappingModel();
+    assertTrue(isMappingModelExists());
+  }
+
+  @Test
+  public void testLoadMappingModelNegative() {
+    VARIANT_MAPPING_FILE = 0;
+    loadMappingModel();
+    assertFalse(isMappingModelExists());
+    // reset it for other JUnits
+    VARIANT_MAPPING_FILE = 1;
+    loadMappingModel();
+  }
+
+  @Test
+  public void testIsMappingModelExists() {
+    assertTrue(objJPAEdmMappingModelServiceTest.isMappingModelExists());
+  }
+
+  @Test
+  public void testGetJPAEdmMappingModel() {
+    assertNotNull(objJPAEdmMappingModelServiceTest.getJPAEdmMappingModel());
+  }
+
+  @Test
+  public void testMapJPAPersistenceUnit() {
+    assertEquals(PERSISTENCE_UNIT_NAME_EDM, objJPAEdmMappingModelServiceTest.mapJPAPersistenceUnit(PERSISTENCE_UNIT_NAME_JPA));
+  }
+
+  @Test
+  public void testMapJPAPersistenceUnitNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPAPersistenceUnit(PERSISTENCE_UNIT_NAME_EDM));// Wrong value to bring null
+  }
+
+  @Test
+  public void testMapJPAEntityType() {
+    assertEquals(ENTITY_TYPE_NAME_EDM, objJPAEdmMappingModelServiceTest.mapJPAEntityType(ENTITY_TYPE_NAME_JPA));
+  }
+
+  @Test
+  public void testMapJPAEntityTypeNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPAEntityType(ENTITY_TYPE_NAME_JPA_WRONG));// Wrong value to bring null
+  }
+
+  @Test
+  public void testMapJPAEntitySet() {
+    assertEquals(ENTITY_SET_NAME_EDM, objJPAEdmMappingModelServiceTest.mapJPAEntitySet(ENTITY_TYPE_NAME_JPA));
+  }
+
+  @Test
+  public void testMapJPAEntitySetNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPAEntitySet(ENTITY_TYPE_NAME_JPA_WRONG));// Wrong value to bring null
+  }
+
+  @Test
+  public void testMapJPAAttribute() {
+    assertEquals(ATTRIBUTE_NAME_EDM, objJPAEdmMappingModelServiceTest.mapJPAAttribute(ENTITY_TYPE_NAME_JPA, ATTRIBUTE_NAME_JPA));
+  }
+
+  @Test
+  public void testMapJPAAttributeNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPAAttribute(ENTITY_TYPE_NAME_JPA, ATTRIBUTE_NAME_JPA + "AA"));// Wrong value to bring null
+  }
+
+  @Test
+  public void testMapJPARelationship() {
+    assertEquals(RELATIONSHIP_NAME_EDM, objJPAEdmMappingModelServiceTest.mapJPARelationship(ENTITY_TYPE_NAME_JPA, RELATIONSHIP_NAME_JPA));
+  }
+
+  @Test
+  public void testMapJPARelationshipNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPARelationship(ENTITY_TYPE_NAME_JPA, RELATIONSHIP_NAME_JPA_WRONG));// Wrong value to bring null
+  }
+
+  @Test
+  public void testMapJPAEmbeddableType() {
+    assertEquals("SalesOrderLineItemKey", objJPAEdmMappingModelServiceTest.mapJPAEmbeddableType("SalesOrderItemKey"));
+  }
+
+  @Test
+  public void testMapJPAEmbeddableTypeNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPAEmbeddableType(EMBEDDABLE_TYPE_NAME_JPA_WRONG));// Wrong value to bring null
+  }
+
+  @Test
+  public void testMapJPAEmbeddableTypeAttribute() {
+    assertEquals(EMBEDDABLE_ATTRIBUTE_NAME_EDM, objJPAEdmMappingModelServiceTest.mapJPAEmbeddableTypeAttribute(EMBEDDABLE_TYPE_NAME_JPA, EMBEDDABLE_ATTRIBUTE_NAME_JPA));
+  }
+
+  @Test
+  public void testMapJPAEmbeddableTypeAttributeNegative() {
+    assertNull(objJPAEdmMappingModelServiceTest.mapJPAEmbeddableTypeAttribute(EMBEDDABLE_TYPE_NAME_JPA_WRONG, EMBEDDABLE_ATTRIBUTE_NAME_JPA));
+  }
+
+  @Test
+  public void testCheckExclusionOfJPAEntityType() {
+    assertTrue(!objJPAEdmMappingModelServiceTest.checkExclusionOfJPAEntityType(ENTITY_TYPE_NAME_JPA));
+  }
+
+  @Test
+  public void testCheckExclusionOfJPAAttributeType() {
+    assertTrue(!objJPAEdmMappingModelServiceTest.checkExclusionOfJPAAttributeType(ENTITY_TYPE_NAME_JPA, ATTRIBUTE_NAME_JPA));
+  }
+
+  @Test
+  public void testCheckExclusionOfJPAEmbeddableType() {
+    assertTrue(!objJPAEdmMappingModelServiceTest.checkExclusionOfJPAEmbeddableType(EMBEDDABLE_TYPE_2_NAME_JPA));
+  }
+
+  @Test
+  public void testCheckExclusionOfJPAEmbeddableAttributeType() {
+    assertTrue(!objJPAEdmMappingModelServiceTest.checkExclusionOfJPAEmbeddableAttributeType(EMBEDDABLE_TYPE_NAME_JPA, EMBEDDABLE_ATTRIBUTE_NAME_JPA));
+  }
+
+  /**
+   * This method is for loading the xml file for testing.
+   */
+  @Override
+  protected InputStream loadMappingModelInputStream() {
+    if (VARIANT_MAPPING_FILE == 1) {
+      return ClassLoader.getSystemResourceAsStream(MAPPING_FILE_CORRECT);
+    } else {
+      return ClassLoader.getSystemResourceAsStream(MAPPING_FILE_INCORRECT);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilderTest.java
new file mode 100644
index 0000000..d94a192
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmNameBuilderTest.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.core.jpa.ODataJPAContextImpl;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAEntityTypeMock;
+
+public class JPAEdmNameBuilderTest {
+
+  @SuppressWarnings("rawtypes")
+  @Test
+  public void testBuildJPAEdmComplexPropertyViewJPAEdmPropertyView() {
+    JPAEdmComplexPropertyView complexPropertyView = EasyMock.createMock(JPAEdmComplexPropertyView.class);
+    ComplexProperty complexProperty = new ComplexProperty();
+    EasyMock.expect(complexPropertyView.getEdmComplexProperty()).andStubReturn(complexProperty);
+    ODataJPAContextImpl oDataJPAContext = new ODataJPAContextImpl();
+    JPAEdmMappingModelService mappingModelService = new JPAEdmMappingModelService(oDataJPAContext);
+    EasyMock.expect(complexPropertyView.getJPAEdmMappingModelAccess()).andStubReturn(mappingModelService);
+
+    // Mocking EDMProperty
+    JPAEdmPropertyView propertyView = EasyMock.createMock(JPAEdmPropertyView.class);
+    JPAEdmEntityTypeView entityTypeView = EasyMock.createMock(JPAEdmEntityTypeView.class);
+    EasyMock.expect(entityTypeView.getJPAEntityType()).andStubReturn(new JEntityType());
+    EasyMock.replay(entityTypeView);
+    EasyMock.expect(propertyView.getJPAAttribute()).andStubReturn(new JAttribute());
+    EasyMock.expect(propertyView.getJPAEdmEntityTypeView()).andStubReturn(entityTypeView);
+    EasyMock.replay(complexPropertyView);
+    EasyMock.replay(propertyView);
+
+    JPAEdmNameBuilder.build(complexPropertyView, propertyView);
+    assertEquals("Id", complexPropertyView.getEdmComplexProperty().getName());
+
+  }
+
+  @SuppressWarnings("hiding")
+  class JAttribute<Object, String> extends JPAAttributeMock<Object, java.lang.String>
+  {
+
+    @Override
+    public java.lang.String getName() {
+      return "id";
+    }
+
+    @Override
+    public Class<java.lang.String> getJavaType() {
+      return java.lang.String.class;
+    }
+
+  }
+
+  class JEntityType<Object> extends JPAEntityTypeMock<Object>
+  {
+
+    @Override
+    public java.lang.String getName() {
+      return "SalesOrderHeader";
+    }
+
+  }
+
+  @Test
+  public void testBuildJPAEdmComplexPropertyViewString() {
+    assertTrue(true);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertorTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertorTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertorTest.java
new file mode 100644
index 0000000..7d0e9b1
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPATypeConvertorTest.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPATypeConvertorTest {
+
+  private EdmSimpleTypeKind edmSimpleKindTypeString;
+  private EdmSimpleTypeKind edmSimpleKindTypeByteArr;
+  private EdmSimpleTypeKind edmSimpleKindTypeLong;
+  private EdmSimpleTypeKind edmSimpleKindTypeShort;
+  private EdmSimpleTypeKind edmSimpleKindTypeInteger;
+  private EdmSimpleTypeKind edmSimpleKindTypeDouble;
+  private EdmSimpleTypeKind edmSimpleKindTypeFloat;
+  private EdmSimpleTypeKind edmSimpleKindTypeBigDecimal;
+  private EdmSimpleTypeKind edmSimpleKindTypeByte;
+  private EdmSimpleTypeKind edmSimpleKindTypeBoolean;
+  private EdmSimpleTypeKind edmSimpleKindTypeUUID;
+
+  @Test
+  public void testConvertToEdmSimpleType() {
+    String str = "entity";
+    byte[] byteArr = new byte[3];
+    Long longObj = new Long(0);
+    Short shortObj = new Short((short) 0);
+    Integer integerObj = new Integer(0);
+    Double doubleObj = new Double(0);
+    Float floatObj = new Float(0);
+    BigDecimal bigDecimalObj = new BigDecimal(0);
+    Byte byteObj = new Byte((byte) 0);
+    Boolean booleanObj = Boolean.TRUE;
+    UUID uUID = new UUID(0, 0);
+
+    try {
+      edmSimpleKindTypeString = JPATypeConvertor
+          .convertToEdmSimpleType(str.getClass(), null);
+      edmSimpleKindTypeByteArr = JPATypeConvertor
+          .convertToEdmSimpleType(byteArr.getClass(), null);
+      edmSimpleKindTypeLong = JPATypeConvertor
+          .convertToEdmSimpleType(longObj.getClass(), null);
+      edmSimpleKindTypeShort = JPATypeConvertor
+          .convertToEdmSimpleType(shortObj.getClass(), null);
+      edmSimpleKindTypeInteger = JPATypeConvertor
+          .convertToEdmSimpleType(integerObj.getClass(), null);
+      edmSimpleKindTypeDouble = JPATypeConvertor
+          .convertToEdmSimpleType(doubleObj.getClass(), null);
+      edmSimpleKindTypeFloat = JPATypeConvertor
+          .convertToEdmSimpleType(floatObj.getClass(), null);
+      edmSimpleKindTypeBigDecimal = JPATypeConvertor
+          .convertToEdmSimpleType(bigDecimalObj.getClass(), null);
+      edmSimpleKindTypeByte = JPATypeConvertor
+          .convertToEdmSimpleType(byteObj.getClass(), null);
+      edmSimpleKindTypeBoolean = JPATypeConvertor
+          .convertToEdmSimpleType(booleanObj.getClass(), null);
+      /*edmSimpleKindTypeDate = JPATypeConvertor
+      		.convertToEdmSimpleType(dateObj.getClass(),null);*/
+      edmSimpleKindTypeUUID = JPATypeConvertor
+          .convertToEdmSimpleType(uUID.getClass(), null);
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    assertEquals(EdmSimpleTypeKind.String, edmSimpleKindTypeString);
+    assertEquals(EdmSimpleTypeKind.Binary, edmSimpleKindTypeByteArr);
+    assertEquals(EdmSimpleTypeKind.Int64, edmSimpleKindTypeLong);
+    assertEquals(EdmSimpleTypeKind.Int16, edmSimpleKindTypeShort);
+    assertEquals(EdmSimpleTypeKind.Int32, edmSimpleKindTypeInteger);
+    assertEquals(EdmSimpleTypeKind.Double, edmSimpleKindTypeDouble);
+    assertEquals(EdmSimpleTypeKind.Single, edmSimpleKindTypeFloat);
+    assertEquals(EdmSimpleTypeKind.Decimal, edmSimpleKindTypeBigDecimal);
+    assertEquals(EdmSimpleTypeKind.Byte, edmSimpleKindTypeByte);
+    assertEquals(EdmSimpleTypeKind.Boolean, edmSimpleKindTypeBoolean);
+    //assertEquals(EdmSimpleTypeKind.DateTime, edmSimpleKindTypeDate);
+    assertEquals(EdmSimpleTypeKind.Guid, edmSimpleKindTypeUUID);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/common/ODataJPATestConstants.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/common/ODataJPATestConstants.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/common/ODataJPATestConstants.java
new file mode 100644
index 0000000..066cc26
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/common/ODataJPATestConstants.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.common;
+
+public final class ODataJPATestConstants {
+
+  public static final String EXCEPTION_MSG_PART_1 = "Exception [ ";
+  public static final String EXCEPTION_MSG_PART_2 = " ] not expected";
+  public static final String EMPTY_STRING = "gwt1";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequestTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequestTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequestTest.java
new file mode 100644
index 0000000..8e75313
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPACreateRequestTest.java
@@ -0,0 +1,375 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.core.ep.entry.EntryMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.MediaMetadataImpl;
+import org.apache.olingo.odata2.core.ep.entry.ODataEntryImpl;
+import org.apache.olingo.odata2.core.ep.feed.FeedMetadataImpl;
+import org.apache.olingo.odata2.core.ep.feed.ODataFeedImpl;
+import org.apache.olingo.odata2.core.uri.ExpandSelectTreeNodeImpl;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPACreateRequestTest {
+
+  @Test
+  public void testProcess() {
+
+    JPACreateRequest createRequest = new JPACreateRequest(JPATestUtil.mockMetaModel());
+    PostUriInfo postUriInfo = JPATestUtil.getPostUriInfo();
+    try {
+      createRequest.process(postUriInfo, null, "application/xml");
+    } catch (ODataJPARuntimeException e) {
+      if (e.isCausedByMessageException()) {
+        assertTrue(true);
+      } else {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+
+  }
+
+  @Test
+  public void testGetSetterName()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    Method method = getMethodForTesting("getSetterName", createRequest);
+    if (method != null)
+    {
+      method.setAccessible(true);
+      Object[] actualParams = { "salesOrderItems" };
+      try {
+        String result = (String) method.invoke(createRequest, actualParams);
+        assertEquals("setSalesOrderItems", result);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+
+  }
+
+  @Test
+  public void testParse2JPAEntityValueMap() {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    EdmStructuralType edmEntityType = JPATestUtil.getEdmStructuralType();
+    Object result = null;
+    try {
+      result = createRequest.parse2JPAEntityValueMap(JPATestUtil.getJPAEntity(), edmEntityType, JPATestUtil.getPropertyValueMap(), "SalesOrderHeader");
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(result);
+    assertEquals(((SalesOrderHeader) result).getId(), 1);
+
+  }
+
+  @Test
+  public void testCreateInlinedEntities()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest(JPATestUtil.mockMetaModel());
+    Method method = getMethodForTesting("createInlinedEntities", createRequest);
+    if (method != null)
+    {
+      method.setAccessible(true);
+      EdmEntitySet edmEntitySet = JPATestUtil.mockSourceEdmEntitySet();
+      ODataEntryImpl odataEntry = createODataEntry();
+      Object[] actualParams = { JPATestUtil.getJPAEntity(), edmEntitySet, odataEntry, "SalesOrderHeader" };
+      try {
+
+        method.invoke(createRequest, actualParams);
+
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+
+    }
+
+  }
+
+  @Test
+  public void testGetSettersForNavigationProperties()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    Method method = getMethodForTesting("getSettersForNavigationProperties", createRequest);
+    if (method != null)
+    {
+      method.setAccessible(true);
+      Map<String, Class<?>> relatedClassMap = new HashMap<String, Class<?>>();
+      relatedClassMap.put("salesOrderLineItems", SalesOrderLineItem.class);
+      Object[] actualParams = { JPATestUtil.getJPAEntity(), JPATestUtil.mockSourceEdmEntitySet(), relatedClassMap };
+      try {
+        @SuppressWarnings("unchecked")
+        List<HashMap<?, ?>> result = (List<HashMap<?, ?>>) method.invoke(createRequest, actualParams);
+        assertEquals(2, result.size());
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+
+    }
+  }
+
+  @Test
+  public void testSetNavigationProperties()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    Method method = getMethodForTesting("setNavigationProperties", createRequest);
+
+    if (method != null)
+    {
+      method.setAccessible(true);
+      Map<String, Class<?>> relatedClassMap = new HashMap<String, Class<?>>();
+      relatedClassMap.put("salesOrderLineItems", SalesOrderLineItem.class);
+      Map<String, Object> propertyValueMap = new HashMap<String, Object>();
+      propertyValueMap.put("id", 1);
+      List<Object> objectList = new ArrayList<Object>();
+      objectList.add(new SalesOrderLineItem(23));
+      propertyValueMap.put("salesOrderLineItems", objectList);
+      Object[] actualParams = { JPATestUtil.getJPAEntity(), JPATestUtil.mockSourceEdmEntitySet(), propertyValueMap, "SalesOrderHeader", relatedClassMap };
+      try {
+        method.invoke(createRequest, actualParams);
+        //This method returns nothing. It only sets value in an object.
+        // If no exception is thrown then we assert true
+        assertTrue(true);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+  }
+
+  @Test
+  public void testPopulateEmbeddableKey()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    Method method = getMethodForTesting("populateEmbeddableKey", createRequest);
+    if (method != null) {
+      method.setAccessible(true);
+      SalesOrderLineItemKey embeddableKeyObject = new SalesOrderLineItemKey();
+      String key = "soId";
+      String setterName = "setSoId";
+      Map<String, Object> propertyValueMap = new HashMap<String, Object>();
+      propertyValueMap.put("soId", 23);
+      propertyValueMap.put("liId", 45);
+      Field field = null;
+      Map<String, Class<?>> jpaEmbeddableObjectKeyMap = new HashMap<String, Class<?>>();
+      jpaEmbeddableObjectKeyMap.put("soId", int.class);
+      jpaEmbeddableObjectKeyMap.put("liId", int.class);
+      Object[] actualParams = { embeddableKeyObject, key, setterName, propertyValueMap };
+      try {
+        for (Field f : createRequest.getClass().getSuperclass().getDeclaredFields()) {
+          if (f.getName().equalsIgnoreCase("jpaEmbeddableKeyObjectMap")) {
+            field = f;
+            break;
+          }
+        }
+        field.setAccessible(true);
+        field.set(createRequest, jpaEmbeddableObjectKeyMap);
+        method.invoke(createRequest, actualParams);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (SecurityException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+  }
+
+  @Test
+  public void testPopulateEmbeddableKeyInvocationIssue()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    Method method = getMethodForTesting("populateEmbeddableKey", createRequest);
+    if (method != null) {
+      method.setAccessible(true);
+      SalesOrderLineItemKey embeddableKeyObject = new SalesOrderLineItemKey();
+      String key = "soId";
+      String setterName = "setSoId";
+      Map<String, Object> propertyValueMap = new HashMap<String, Object>();
+      propertyValueMap.put("soId", "23");
+      propertyValueMap.put("liId", "45");
+      Field field = null;
+      Map<String, Class<?>> jpaEmbeddableObjectKeyMap = new HashMap<String, Class<?>>();
+      jpaEmbeddableObjectKeyMap.put("soId", int.class);
+      jpaEmbeddableObjectKeyMap.put("liId", int.class);
+      Object[] actualParams = { embeddableKeyObject, key, setterName, propertyValueMap };
+      //			Object[] incorrectParams = {embeddableKeyObject,key,setterName,propertyValueMap};
+      try {
+        for (Field f : createRequest.getClass().getSuperclass().getDeclaredFields()) {
+          if (f.getName().equalsIgnoreCase("jpaEmbeddableKeyObjectMap")) {
+            field = f;
+            break;
+          }
+        }
+        field.setAccessible(true);
+        field.set(createRequest, jpaEmbeddableObjectKeyMap);
+        method.invoke(createRequest, actualParams);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        assertTrue(true);
+      } catch (SecurityException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+  }
+
+  @Test
+  public void testPopulateEmbeddableKeyNoSuchMethod()
+  {
+    JPACreateRequest createRequest = new JPACreateRequest();
+    Method method = getMethodForTesting("populateEmbeddableKey", createRequest);
+    if (method != null) {
+      method.setAccessible(true);
+      SalesOrderLineItemKey embeddableKeyObject = new SalesOrderLineItemKey();
+      String key = "soId";
+      String setterName = "setPoId";
+      Map<String, Object> propertyValueMap = new HashMap<String, Object>();
+      propertyValueMap.put("soId", 23);
+      propertyValueMap.put("liId", 45);
+      Field field = null;
+      Map<String, Class<?>> jpaEmbeddableObjectKeyMap = new HashMap<String, Class<?>>();
+      jpaEmbeddableObjectKeyMap.put("soId", int.class);
+      jpaEmbeddableObjectKeyMap.put("liId", int.class);
+      Object[] actualParams = { embeddableKeyObject, key, setterName, propertyValueMap };
+      try {
+        for (Field f : createRequest.getClass().getSuperclass().getDeclaredFields()) {
+          if (f.getName().equalsIgnoreCase("jpaEmbeddableKeyObjectMap")) {
+            field = f;
+            break;
+          }
+        }
+        field.setAccessible(true);
+        field.set(createRequest, jpaEmbeddableObjectKeyMap);
+        method.invoke(createRequest, actualParams);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (InvocationTargetException e) {
+        assertTrue(true);
+      } catch (SecurityException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+  }
+
+  private ODataEntryImpl createODataEntry() {
+    HashMap<String, Object> data = new HashMap<String, Object>();
+    HashMap<String, Object> data1 = new HashMap<String, Object>();
+    List<ODataEntry> oDataEntryList = new ArrayList<ODataEntry>();
+
+    MediaMetadataImpl mediaMetadata = new MediaMetadataImpl();
+    mediaMetadata.setContentType("application/xml");
+    EntryMetadataImpl entryMetadata = new EntryMetadataImpl();
+    entryMetadata.setId("http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/SalesOrderProcessing.svc/SalesOrders(5L)");
+    ExpandSelectTreeNodeImpl expandSelectTree = new ExpandSelectTreeNodeImpl();
+    expandSelectTree.putLink("SalesOrderLineItemDetails", new ExpandSelectTreeNodeImpl());
+    expandSelectTree.setExpanded();
+    expandSelectTree.setAllExplicitly();
+    data1.put("id", 1);
+    data1.put("SalesOrderLineItemDetails", new SalesOrderLineItem(23));
+    ODataEntry lineItemOdataEntry = new ODataEntryImpl(data1, mediaMetadata, entryMetadata, expandSelectTree);
+    oDataEntryList.add(lineItemOdataEntry);
+    FeedMetadataImpl feedMetadata = new FeedMetadataImpl();
+    ODataFeedImpl odataFeedImpl = new ODataFeedImpl(oDataEntryList, feedMetadata);
+    data.put("id", 1);
+    data.put("SalesOrderLineItemDetails", odataFeedImpl);
+    ODataEntryImpl odataEntry = new ODataEntryImpl(data, mediaMetadata, entryMetadata, expandSelectTree);
+    odataEntry.setContainsInlineEntry(true);
+    return odataEntry;
+  }
+
+  private Method getMethodForTesting(final String methodName, final Object object)
+  {
+    Method method = null;
+    for (Method m : object.getClass().getDeclaredMethods()) {
+      if (m.getName().equals(methodName))
+      {
+        method = m;
+        break;
+      }
+    }
+    return method;
+  }
+
+}


[04/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
new file mode 100644
index 0000000..4ef463d
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmParserTest.java
@@ -0,0 +1,1491 @@
+/*******************************************************************************
+ * 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.edm.parser;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.io.StringReader;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+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.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.EdmTestProvider;
+
+public class EdmParserTest {
+
+  private static final String DEFAULT_VALUE = "Photo";
+  private static final String FC_TARGET_PATH = "Содержание";
+  private static final String FC_NS_URI = "http://localhost";
+  private static final String FC_NS_PREFIX = "ру";
+  private static final Boolean FC_KEEP_IN_CONTENT = Boolean.FALSE;
+  private static final String NAMESPACE = "RefScenario";
+  private static final String NAMESPACE2 = "RefScenario2";
+  private static final String MIME_TYPE = "image/jpeg";
+  private static final String ASSOCIATION = "ManagerEmployees";
+  private static final int MAX_LENGTH = 4;
+
+  private final String[] propertyNames = { "EmployeeId", "EmployeeName",
+      "Location" };
+
+  private final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+      + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+      + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+      + Edm.NAMESPACE_M_2007_08 + "\">" + "<Schema Namespace=\""
+      + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+      + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+      + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\"" + propertyNames[0]
+      + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+      + "<Property Name=\"" + propertyNames[1]
+      + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+      + "<Property Name=\"" + propertyNames[2]
+      + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+      + "</EntityType>" + "<ComplexType Name=\"c_Location\">"
+      + "<Property Name=\"Country\" Type=\"Edm.String\"/>"
+      + "</ComplexType>" + "</Schema>" + "</edmx:DataServices>"
+      + "</edmx:Edmx>";
+
+  private final String xmlWithBaseType = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+      + Edm.NAMESPACE_EDMX_2007_06
+      + "\">"
+      + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+      + Edm.NAMESPACE_M_2007_08
+      + "\">"
+      + "<Schema Namespace=\""
+      + NAMESPACE
+      + "\" xmlns=\""
+      + Edm.NAMESPACE_EDM_2008_09
+      + "\">"
+      + "<EntityType Name= \"Employee\">"
+      + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\""
+      + propertyNames[0]
+      + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+      + "<Property Name=\""
+      + propertyNames[1]
+      + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+      + "<Property Name=\""
+      + propertyNames[2]
+      + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+      + "</EntityType>"
+      + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+      + "</EntityType>"
+      + "<ComplexType Name=\"c_Location\">"
+      + "<Property Name=\"Country\" Type=\"Edm.String\"/>"
+      + "</ComplexType>"
+      + "</Schema>"
+      + "</edmx:DataServices>"
+      + "</edmx:Edmx>";
+
+  private final String xmlWithAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+      + Edm.NAMESPACE_EDMX_2007_06
+      + "\">"
+      + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+      + Edm.NAMESPACE_M_2007_08
+      + "\">"
+      + "<Schema Namespace=\""
+      + NAMESPACE
+      + "\" xmlns=\""
+      + Edm.NAMESPACE_EDM_2008_09
+      + "\">"
+      + "<EntityType Name= \"Employee\">"
+      + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\""
+      + propertyNames[0]
+      + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+      + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+      + "</EntityType>"
+      + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+      + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+      + "</EntityType>"
+      + "<Association Name=\""
+      + ASSOCIATION
+      + "\">"
+      + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+      + "<OnDelete Action=\"Cascade\"/>"
+      + "</End>"
+      + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+      + "</Association>"
+      + "</Schema>"
+      + "<Schema Namespace=\""
+      + NAMESPACE2
+      + "\" xmlns=\""
+      + Edm.NAMESPACE_EDM_2008_09
+      + "\">"
+      + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+      + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+      + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>"
+      + "<AssociationSet Name=\""
+      + ASSOCIATION
+      + "\" Association=\"RefScenario."
+      + ASSOCIATION
+      + "\">"
+      + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>"
+      + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+      + "</AssociationSet>"
+      + "</EntityContainer>"
+      + "</Schema>"
+      + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  private final String xmlWithTwoSchemas = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+      + Edm.NAMESPACE_EDMX_2007_06
+      + "\">"
+      + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+      + Edm.NAMESPACE_M_2007_08
+      + "\">"
+      + "<Schema Namespace=\""
+      + NAMESPACE
+      + "\" xmlns=\""
+      + Edm.NAMESPACE_EDM_2008_09
+      + "\">"
+      + "<EntityType Name= \"Employee\">"
+      + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+      + "<Property Name=\""
+      + propertyNames[0]
+      + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+      + "<Property Name=\""
+      + propertyNames[1]
+      + "\" Type=\"Edm.String\"/>"
+      + "</EntityType>"
+      + "</Schema>"
+      + "<Schema Namespace=\""
+      + NAMESPACE2
+      + "\" xmlns=\""
+      + Edm.NAMESPACE_EDM_2008_09
+      + "\">"
+      + "<EntityType Name= \"Photo\">"
+      + "<Key><PropertyRef Name=\"Id\"/></Key>"
+      + "<Property Name=\"Id\" Type=\"Edm.Int32\" Nullable=\"false\" ConcurrencyMode=\"Fixed\" MaxLength=\""
+      + MAX_LENGTH
+      + "\"/>"
+      + "<Property Name=\"Name\" Type=\"Edm.String\" Unicode=\"true\" DefaultValue=\""
+      + DEFAULT_VALUE
+      + "\" FixedLength=\"false\"/>"
+      + "<Property Name=\"BinaryData\" Type=\"Edm.Binary\" m:MimeType=\""
+      + MIME_TYPE
+      + "\"/>"
+      + "<Property Name=\"Содержание\" Type=\"Edm.String\" m:FC_TargetPath=\""
+      + FC_TARGET_PATH
+      + "\" m:FC_NsUri=\""
+      + FC_NS_URI
+      + "\""
+      + " m:FC_NsPrefix=\""
+      + FC_NS_PREFIX
+      + "\" m:FC_KeepInContent=\""
+      + FC_KEEP_IN_CONTENT
+      + "\" m:FC_ContentKind=\"text\" >"
+      + "</Property>"
+      + "</EntityType>"
+      + "</Schema>"
+      + "</edmx:DataServices>" + "</edmx:Edmx>";
+
+  @Test
+  public void test() throws XMLStreamException, EntityProviderException {
+    int i = 0;
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (Schema schema : result.getSchemas()) {
+      assertEquals(NAMESPACE, schema.getNamespace());
+      assertEquals(1, schema.getEntityTypes().size());
+      assertEquals("Employee", schema.getEntityTypes().get(0).getName());
+      assertEquals(Boolean.TRUE, schema.getEntityTypes().get(0).isHasStream());
+      for (PropertyRef propertyRef : schema.getEntityTypes().get(0)
+          .getKey().getKeys()) {
+        assertEquals("EmployeeId", propertyRef.getName());
+      }
+      for (Property property : schema.getEntityTypes().get(0)
+          .getProperties()) {
+        assertEquals(propertyNames[i], property.getName());
+        if ("Location".equals(property.getName())) {
+          ComplexProperty cProperty = (ComplexProperty) property;
+          assertEquals(NAMESPACE, cProperty.getType().getNamespace());
+          assertEquals("c_Location", cProperty.getType().getName());
+        } else if ("EmployeeName".equals(property.getName())) {
+          assertNotNull(property.getCustomizableFeedMappings());
+          assertEquals("SyndicationTitle", property.getCustomizableFeedMappings().getFcTargetPath());
+          assertNull(property.getCustomizableFeedMappings().getFcContentKind());
+        }
+        i++;
+      }
+      assertEquals(1, schema.getComplexTypes().size());
+      assertEquals("c_Location", schema.getComplexTypes().get(0)
+          .getName());
+    }
+  }
+
+  @Test
+  public void testBaseType() throws XMLStreamException,
+      EntityProviderException {
+    int i = 0;
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithBaseType);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (Schema schema : result.getSchemas()) {
+      assertEquals(NAMESPACE, schema.getNamespace());
+      assertEquals(2, schema.getEntityTypes().size());
+      assertEquals("Employee", schema.getEntityTypes().get(0).getName());
+      for (PropertyRef propertyRef : schema.getEntityTypes().get(0)
+          .getKey().getKeys()) {
+        assertEquals("EmployeeId", propertyRef.getName());
+      }
+      for (Property property : schema.getEntityTypes().get(0)
+          .getProperties()) {
+        assertEquals(propertyNames[i], property.getName());
+        i++;
+      }
+
+    }
+  }
+
+  @Test
+  public void testComplexTypeWithBaseType() throws XMLStreamException,
+      EntityProviderException {
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" Alias=\"RS\"  xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\"" + propertyNames[2]
+        + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "<ComplexType Name=\"c_BaseType_for_Location\" Abstract=\"true\">"
+        + "<Property Name=\"Country\" Type=\"Edm.String\"/>"
+        + "</ComplexType>"
+        + "<ComplexType Name=\"c_Location\" BaseType=\"RefScenario.c_BaseType_for_Location\">"
+        + "</ComplexType>"
+        + "<ComplexType Name=\"c_Other_Location\" BaseType=\"RS.c_BaseType_for_Location\">"
+        + "</ComplexType>"
+        + "</Schema>" + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (Schema schema : result.getSchemas()) {
+      for (ComplexType complexType : schema.getComplexTypes()) {
+        if ("c_Location".equals(complexType.getName())) {
+          assertNotNull(complexType.getBaseType());
+          assertTrue(!complexType.isAbstract());
+          assertEquals("c_BaseType_for_Location", complexType.getBaseType().getName());
+          assertEquals("RefScenario", complexType.getBaseType().getNamespace());
+        }
+        else if ("c_Other_Location".equals(complexType.getName())) {
+          assertNotNull(complexType.getBaseType());
+          assertTrue(!complexType.isAbstract());
+          assertEquals("c_BaseType_for_Location", complexType.getBaseType().getName());
+          assertEquals("RS", complexType.getBaseType().getNamespace());
+        }
+        else if ("c_BaseType_for_Location".equals(complexType.getName())) {
+          assertNotNull(complexType.isAbstract());
+          assertTrue(complexType.isAbstract());
+        } else {
+          assertTrue(false);
+        }
+      }
+
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testComplexTypeWithInvalidBaseType() throws XMLStreamException,
+      EntityProviderException {
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08 + "\">" + "<Schema Namespace=\""
+        + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\"" + propertyNames[2]
+        + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "<ComplexType Name=\"c_BaseType_for_Location\" Abstract=\"true\">"
+        + "<Property Name=\"Country\" Type=\"Edm.String\"/>"
+        + "</ComplexType>"
+        + "<ComplexType Name=\"c_Location\" BaseType=\"RefScenario.Employee\">"
+        + "</ComplexType>"
+        + "</Schema>" + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testComplexTypeWithInvalidBaseType2() throws XMLStreamException,
+      EntityProviderException {
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08 + "\">" + "<Schema Namespace=\""
+        + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\"" + propertyNames[2]
+        + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "<ComplexType Name=\"c_BaseType_for_Location\" Abstract=\"true\">"
+        + "<Property Name=\"Country\" Type=\"Edm.String\"/>"
+        + "</ComplexType>"
+        + "<ComplexType Name=\"c_Location\" BaseType=\"c_BaseType_for_Location\">"
+        + "</ComplexType>"
+        + "</Schema>" + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test
+  public void testAssociation() throws XMLStreamException,
+      EntityProviderException {
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithAssociation);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (Schema schema : result.getSchemas()) {
+      for (EntityType entityType : schema.getEntityTypes()) {
+        if ("Manager".equals(entityType.getName())) {
+          assertEquals("RefScenario", entityType.getBaseType()
+              .getNamespace());
+          assertEquals("Employee", entityType.getBaseType().getName());
+          for (NavigationProperty navProperty : entityType
+              .getNavigationProperties()) {
+            assertEquals("r_Manager", navProperty.getFromRole());
+            assertEquals("r_Employees", navProperty.getToRole());
+            assertEquals("RefScenario", navProperty
+                .getRelationship().getNamespace());
+            assertEquals(ASSOCIATION, navProperty.getRelationship()
+                .getName());
+          }
+        }
+        if ("Employee".equals(entityType.getName())) {
+          for (NavigationProperty navProperty : entityType
+              .getNavigationProperties()) {
+            assertEquals("r_Employees", navProperty.getFromRole());
+            assertEquals("RefScenario", navProperty
+                .getRelationship().getNamespace());
+            assertEquals(ASSOCIATION, navProperty.getRelationship()
+                .getName());
+          }
+        }
+      }
+      for (Association association : schema.getAssociations()) {
+        AssociationEnd end;
+        assertEquals(ASSOCIATION, association.getName());
+        if ("Employee"
+            .equals(association.getEnd1().getType().getName())) {
+          end = association.getEnd1();
+        } else {
+          end = association.getEnd2();
+        }
+        assertEquals(EdmMultiplicity.MANY, end.getMultiplicity());
+        assertEquals("r_Employees", end.getRole());
+        assertEquals(EdmAction.Cascade, end.getOnDelete().getAction());
+      }
+    }
+  }
+
+  @Test
+  public void testTwoSchemas() throws XMLStreamException,
+      EntityProviderException {
+    int i = 0;
+    String schemasNs[] = { NAMESPACE, NAMESPACE2 };
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithTwoSchemas);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    assertEquals(2, result.getSchemas().size());
+    for (Schema schema : result.getSchemas()) {
+      assertEquals(schemasNs[i], schema.getNamespace());
+      assertEquals(1, schema.getEntityTypes().size());
+      i++;
+
+    }
+  }
+
+  @Test
+  public void testProperties() throws EntityProviderException,
+      XMLStreamException {
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithTwoSchemas);
+    DataServices result = parser.readMetadata(reader, true);
+    for (Schema schema : result.getSchemas()) {
+      for (EntityType entityType : schema.getEntityTypes()) {
+        if ("Employee".equals(entityType.getName())) {
+          for (Property property : entityType.getProperties()) {
+            if (propertyNames[0].equals(property.getName())) {
+              assertNotNull(property.getFacets());
+              assertEquals(Boolean.FALSE, property.getFacets().isNullable());
+            } else if (propertyNames[1].equals(property.getName())) {
+              assertNull(property.getFacets());
+            }
+          }
+        } else if ("Photo".equals(entityType.getName())) {
+          for (Property property : entityType.getProperties()) {
+            SimpleProperty sProperty = (SimpleProperty) property;
+            if ("Id".equals(property.getName())) {
+              assertEquals(Boolean.FALSE, property.getFacets()
+                  .isNullable());
+              assertEquals(EdmConcurrencyMode.Fixed, property
+                  .getFacets().getConcurrencyMode());
+              assertEquals(new Integer(MAX_LENGTH), property
+                  .getFacets().getMaxLength());
+
+              assertEquals(EdmSimpleTypeKind.Int32,
+                  sProperty.getType());
+              assertNull(property.getCustomizableFeedMappings());
+            }
+            if ("Name".equals(property.getName())) {
+              assertEquals(Boolean.TRUE, property.getFacets()
+                  .isUnicode());
+              assertEquals(DEFAULT_VALUE, property.getFacets()
+                  .getDefaultValue());
+              assertEquals(Boolean.FALSE, property.getFacets()
+                  .isFixedLength());
+              assertEquals(EdmSimpleTypeKind.String,
+                  sProperty.getType());
+              assertNull(property.getCustomizableFeedMappings());
+            }
+            if ("Содержание".equals(property.getName())) {
+              assertEquals(FC_TARGET_PATH, property
+                  .getCustomizableFeedMappings()
+                  .getFcTargetPath());
+              assertEquals(FC_NS_URI, property
+                  .getCustomizableFeedMappings().getFcNsUri());
+              assertEquals(FC_NS_PREFIX, property
+                  .getCustomizableFeedMappings()
+                  .getFcNsPrefix());
+              assertEquals(FC_KEEP_IN_CONTENT, property
+                  .getCustomizableFeedMappings()
+                  .isFcKeepInContent());
+              assertEquals(EdmContentKind.text, property
+                  .getCustomizableFeedMappings()
+                  .getFcContentKind());
+            }
+            if ("BinaryData".equals(property.getName())) {
+              assertEquals(MIME_TYPE, property.getMimeType());
+            }
+          }
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testEntitySet() throws XMLStreamException,
+      EntityProviderException {
+    final String xmWithEntityContainer = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\""
+        + propertyNames[1]
+        + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmWithEntityContainer);
+    DataServices result = parser.readMetadata(reader, true);
+    for (Schema schema : result.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+        for (EntitySet entitySet : container.getEntitySets()) {
+          assertEquals("Employees", entitySet.getName());
+          assertEquals("Employee", entitySet.getEntityType()
+              .getName());
+          assertEquals(NAMESPACE, entitySet.getEntityType()
+              .getNamespace());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testAssociationSet() throws XMLStreamException,
+      EntityProviderException {
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithAssociation);
+    DataServices result = parser.readMetadata(reader, true);
+    for (Schema schema : result.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        assertEquals(NAMESPACE2, schema.getNamespace());
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+        for (AssociationSet assocSet : container.getAssociationSets()) {
+          assertEquals(ASSOCIATION, assocSet.getName());
+          assertEquals(ASSOCIATION, assocSet.getAssociation().getName());
+          assertEquals(NAMESPACE, assocSet.getAssociation().getNamespace());
+          AssociationSetEnd end;
+          if ("Employees".equals(assocSet.getEnd1().getEntitySet())) {
+            end = assocSet.getEnd1();
+          } else {
+            end = assocSet.getEnd2();
+          }
+          assertEquals("r_Employees", end.getRole());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testFunctionImport() throws XMLStreamException,
+      EntityProviderException {
+    final String xmWithEntityContainer = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\""
+        + propertyNames[1]
+        + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+        + "<Parameter Name=\"q\" Type=\"Edm.String\" Nullable=\"true\" />"
+        + "</FunctionImport>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices>" + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmWithEntityContainer);
+    DataServices result = parser.readMetadata(reader, true);
+    for (Schema schema : result.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        assertEquals(Boolean.TRUE, container.isDefaultEntityContainer());
+        for (FunctionImport functionImport : container.getFunctionImports()) {
+          assertEquals("EmployeeSearch", functionImport.getName());
+          assertEquals("Employees", functionImport.getEntitySet());
+          assertEquals(NAMESPACE, functionImport.getReturnType().getTypeName().getNamespace());
+          assertEquals("Employee", functionImport.getReturnType().getTypeName().getName());
+          assertEquals(EdmMultiplicity.MANY, functionImport.getReturnType().getMultiplicity());
+          assertEquals("GET", functionImport.getHttpMethod());
+          for (FunctionImportParameter parameter : functionImport.getParameters()) {
+            assertEquals("q", parameter.getName());
+            assertEquals(EdmSimpleTypeKind.String, parameter.getType());
+            assertEquals(Boolean.TRUE, parameter.getFacets().isNullable());
+          }
+        }
+      }
+    }
+
+  }
+
+  @Test()
+  public void testAlias() throws XMLStreamException, EntityProviderException {
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" Alias=\"RS\"  xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RS.Employee\" m:HasStream=\"true\">"
+        + "</EntityType>" + "</Schema>" + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    DataServices result = parser.readMetadata(reader, true);
+    for (Schema schema : result.getSchemas()) {
+      assertEquals("RS", schema.getAlias());
+      for (EntityType entityType : schema.getEntityTypes()) {
+        if ("Manager".equals(entityType.getName())) {
+          assertEquals("Employee", entityType.getBaseType().getName());
+          assertEquals("RS", entityType.getBaseType().getNamespace());
+        }
+      }
+
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testEntityTypeWithoutKeys() throws XMLStreamException, EntityProviderException {
+    final String xmlWithoutKeys = "<Schema Namespace=\"" + NAMESPACE
+        + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\">" + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "</EntityType>" + "</Schema>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithoutKeys);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidBaseType() throws XMLStreamException,
+      EntityProviderException {
+    final String xmlWithInvalidBaseType = "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Manager\" BaseType=\"Employee\" m:HasStream=\"true\">"
+        + "</EntityType>" + "</Schema>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidBaseType);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidRole() throws XMLStreamException,
+      EntityProviderException {
+    final String xmlWithInvalidAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"Manager\" ToRole=\"Employees\" />"
+        + "</EntityType>"
+        + "<Association Name=\"ManagerEmployees\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association>"
+        + "</Schema>"
+        + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociation);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidRelationship() throws XMLStreamException,
+      EntityProviderException {
+    final String xmlWithInvalidAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployee\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "</EntityType>"
+        + "<Association Name=\"ManagerEmployees\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association>"
+        + "</Schema>"
+        + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociation);
+    parser.readMetadata(reader, true);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingRelationship() throws Exception {
+    final String xmlWithInvalidAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "</EntityType>"
+        + "<Association Name=\"ManagerEmployees\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Relationship", e.getMessageReference().getContent().get(0));
+      assertEquals("NavigationProperty", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingEntityType() throws Exception {
+    final String xmlWithInvalidAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" />"
+        + "</EntityContainer>"
+        + "<Association Name=\"ManagerEmployees\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("EntityType", e.getMessageReference().getContent().get(0));
+      assertEquals("EntitySet", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingType() throws Exception {
+    final String xmlWithInvalidAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "</EntityType>"
+        + "<Association Name=\"ManagerEmployees\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("Property", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingTypeAtAssociation() throws Exception {
+    final String xmlWithInvalidAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "</EntityType>"
+        + "<Association Name=\"ManagerEmployees\">"
+        + "<End Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association></Schema></edmx:DataServices></edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("End", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingTypeAtFunctionImport() throws Exception {
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08 + "\">" + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\"" + propertyNames[1] + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "<FunctionImport Name=\"EmployeeSearch\" ReturnType=\"Collection(RefScenario.Employee)\" EntitySet=\"Employees\" m:HttpMethod=\"GET\">"
+        + "<Parameter Name=\"q\" Nullable=\"true\" />"
+        + "</FunctionImport>"
+        + "</EntityContainer></Schema></edmx:DataServices></edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Type", e.getMessageReference().getContent().get(0));
+      assertEquals("Parameter", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testMissingAssociation() throws Exception {
+    final String xmlWithAssociation = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"" + propertyNames[0] + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "<AssociationSet Name=\"" + ASSOCIATION
+        //        + "\" Association=\"RefScenario." + ASSOCIATION 
+        + "\">"
+        + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+        + "</AssociationSet>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices></edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithAssociation);
+    try {
+      parser.readMetadata(reader, true);
+    } catch (EntityProviderException e) {
+      assertEquals(EntityProviderException.MISSING_ATTRIBUTE.getKey(), e.getMessageReference().getKey());
+      assertEquals(2, e.getMessageReference().getContent().size());
+      assertEquals("Association", e.getMessageReference().getContent().get(0));
+      assertEquals("AssociationSet", e.getMessageReference().getContent().get(1));
+      throw e;
+    }
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidAssociation() throws XMLStreamException,
+      EntityProviderException {
+    final String xmlWithInvalidAssociationSet = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+        + "</EntityType>"
+        + "<Association Name=\""
+        + ASSOCIATION
+        + "\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+        + "<OnDelete Action=\"Cascade\"/>"
+        + "</End>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>"
+        + "<AssociationSet Name=\""
+        + ASSOCIATION
+        + "\" Association=\"RefScenario2."
+        + ASSOCIATION
+        + "\">"
+        + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>"
+        + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+        + "</AssociationSet>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices>" + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociationSet);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidAssociationEnd() throws XMLStreamException,
+      EntityProviderException {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+        + employees
+        + "\" ToRole=\""
+        + manager
+        + "\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+        + manager
+        + "\" ToRole=\""
+        + employees
+        + "\" />"
+        + "</EntityType>"
+        + "<Association Name=\""
+        + ASSOCIATION
+        + "\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\""
+        + employees
+        + "1"
+        + "\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\""
+        + manager
+        + "\"/>"
+        + "</Association>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>"
+        + "<AssociationSet Name=\""
+        + ASSOCIATION
+        + "\" Association=\"RefScenario2."
+        + ASSOCIATION
+        + "\">"
+        + "<End EntitySet=\"Managers\" Role=\""
+        + manager
+        + "\"/>"
+        + "<End EntitySet=\"Employees\" Role=\""
+        + employees
+        + "\"/>"
+        + "</AssociationSet>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices>" + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidAssociationEnd2() throws XMLStreamException,
+      EntityProviderException {
+    final String employees = "r_Employees";
+    final String manager = "r_Manager";
+    final String xmlWithInvalidAssociationSetEnd = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+        + employees
+        + "\" ToRole=\""
+        + manager
+        + "\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\""
+        + manager
+        + "\" ToRole=\""
+        + employees
+        + "\" />"
+        + "</EntityType>"
+        + "<Association Name=\""
+        + ASSOCIATION
+        + "\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\""
+        + employees
+        + "\"/>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\""
+        + manager
+        + "\"/>"
+        + "</Association>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Employee\"/>"
+        + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>"
+        + "<AssociationSet Name=\""
+        + ASSOCIATION
+        + "\" Association=\"RefScenario2."
+        + ASSOCIATION
+        + "\">"
+        + "<End EntitySet=\"Managers\" Role=\""
+        + manager
+        + "\"/>"
+        + "<End EntitySet=\"Managers\" Role=\""
+        + manager
+        + "\"/>"
+        + "</AssociationSet>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices>" + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithInvalidAssociationSetEnd);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void testInvalidEntitySet() throws XMLStreamException,
+      EntityProviderException {
+    final String xmWithEntityContainer = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\""
+        + propertyNames[1]
+        + "\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\"/>"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RefScenario.Mitarbeiter\"/>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmWithEntityContainer);
+    parser.readMetadata(reader, true);
+
+  }
+
+  @Test
+  public void testEntityTypeInOtherSchema() throws XMLStreamException, EntityProviderException {
+    final String xmWithEntityContainer = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\" m:HasStream=\"true\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Photos\" EntityType=\"" + NAMESPACE2 + ".Photo\"/>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "<Schema Namespace=\"" + NAMESPACE2 + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Photo\">"
+        + "<Key><PropertyRef Name=\"Id\"/></Key>"
+        + "<Property Name=\"Id\" Type=\"Edm.Int32\" Nullable=\"false\"/>"
+        + "</EntityType>"
+        + "</Schema>"
+        + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmWithEntityContainer);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals("2.0", result.getDataServiceVersion());
+    for (Schema schema : result.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        assertEquals("Container1", container.getName());
+        for (EntitySet entitySet : container.getEntitySets()) {
+          assertEquals(NAMESPACE2, entitySet.getEntityType().getNamespace());
+          assertEquals("Photo", entitySet.getEntityType().getName());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void scenarioTest() throws XMLStreamException,
+      EntityProviderException {
+    final String ASSOCIATION2 = "TeamEmployees";
+    final String xml = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\""
+        + Edm.NAMESPACE_EDMX_2007_06
+        + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\""
+        + Edm.NAMESPACE_M_2007_08
+        + "\">"
+        + "<Schema Namespace=\""
+        + NAMESPACE
+        + "\" Alias=\"RS\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Employee\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\""
+        + propertyNames[0]
+        + "\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\""
+        + propertyNames[2]
+        + "\" Type=\"RefScenario.c_Location\" Nullable=\"false\"/>"
+        + "<NavigationProperty Name=\"ne_Manager\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Manager\" />"
+        + "<NavigationProperty Name=\"ne_Team\" Relationship=\"RefScenario.TeamEmployees\" FromRole=\"r_Employees\" ToRole=\"r_Team\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Manager\" BaseType=\"RefScenario.Employee\" m:HasStream=\"true\">"
+        + "<NavigationProperty Name=\"nm_Employees\" Relationship=\"RefScenario.ManagerEmployees\" FromRole=\"r_Manager\" ToRole=\"r_Employees\" />"
+        + "</EntityType>"
+        + "<EntityType Name=\"Team\">"
+        + "<Key>"
+        + "<PropertyRef Name=\"Id\"/>"
+        + "</Key>"
+        + "<NavigationProperty Name=\"nt_Employees\" Relationship=\"RefScenario.TeamEmployees\" FromRole=\"r_Team\" ToRole=\"r_Employees\" />"
+        + "</EntityType>"
+        + "<ComplexType Name=\"c_Location\">"
+        + "<Property Name=\"Country\" Type=\"Edm.String\"/>"
+        + "</ComplexType>"
+        + "<Association Name=\""
+        + ASSOCIATION
+        + "\">"
+        + "<End Type=\"RS.Employee\" Multiplicity=\"*\" Role=\"r_Employees\">"
+        + "<OnDelete Action=\"Cascade\"/>"
+        + "</End>"
+        + "<End Type=\"RefScenario.Manager\" Multiplicity=\"1\" Role=\"r_Manager\"/>"
+        + "</Association>"
+        + "<Association Name=\""
+        + ASSOCIATION2
+        + "\">"
+        + "<End Type=\"RefScenario.Employee\" Multiplicity=\"*\" Role=\"r_Employees\"/>"
+        + "<End Type=\"RefScenario.Team\" Multiplicity=\"1\" Role=\"r_Team\"/>"
+        + "</Association>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Employees\" EntityType=\"RS.Employee\"/>"
+        + "<EntitySet Name=\"Managers\" EntityType=\"RefScenario.Manager\"/>"
+        + "<EntitySet Name=\"Teams\" EntityType=\"RefScenario.Team\"/>"
+        + "<AssociationSet Name=\""
+        + ASSOCIATION
+        + "\" Association=\"RefScenario."
+        + ASSOCIATION
+        + "\">"
+        + "<End EntitySet=\"Managers\" Role=\"r_Manager\"/>"
+        + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+        + "</AssociationSet>"
+        + "<AssociationSet Name=\""
+        + ASSOCIATION2
+        + "\" Association=\"RefScenario."
+        + ASSOCIATION2
+        + "\">"
+        + "<End EntitySet=\"Teams\" Role=\"r_Team\"/>"
+        + "<End EntitySet=\"Employees\" Role=\"r_Employees\"/>"
+        + "</AssociationSet>"
+        + "</EntityContainer>"
+        + "</Schema>"
+        + "<Schema Namespace=\""
+        + NAMESPACE2
+        + "\" xmlns=\""
+        + Edm.NAMESPACE_EDM_2008_09
+        + "\">"
+        + "<EntityType Name= \"Photo\">"
+        + "<Key>"
+        + "<PropertyRef Name=\"Id\"/>"
+        + "<PropertyRef Name=\"Name\"/>"
+        + "</Key>"
+        + "<Property Name=\"Id\" Type=\"Edm.Int32\" Nullable=\"false\" ConcurrencyMode=\"Fixed\" MaxLength=\""
+        + MAX_LENGTH
+        + "\"/>"
+        + "<Property Name=\"Name\" Type=\"Edm.String\" Unicode=\"true\" DefaultValue=\""
+        + DEFAULT_VALUE
+        + "\" FixedLength=\"false\"/>"
+        + "<Property Name=\"BinaryData\" Type=\"Edm.Binary\" m:MimeType=\""
+        + MIME_TYPE
+        + "\"/>"
+        + "<Property Name=\"Содержание\" Type=\"Edm.String\" m:FC_TargetPath=\""
+        + FC_TARGET_PATH
+        + "\" m:FC_NsUri=\""
+        + FC_NS_URI
+        + "\""
+        + " m:FC_NsPrefix=\""
+        + FC_NS_PREFIX
+        + "\" m:FC_KeepInContent=\""
+        + FC_KEEP_IN_CONTENT
+        + "\" m:FC_ContentKind=\"text\" >"
+        + "</Property>"
+        + "</EntityType>"
+        + "<EntityContainer Name=\"Container1\" m:IsDefaultEntityContainer=\"true\">"
+        + "<EntitySet Name=\"Photos\" EntityType=\"RefScenario2.Photo\"/>"
+        + "</EntityContainer>" + "</Schema>" + "</edmx:DataServices>"
+        + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xml);
+    DataServices result = parser.readMetadata(reader, true);
+    assertEquals(2, result.getSchemas().size());
+    for (Schema schema : result.getSchemas()) {
+      if (NAMESPACE.equals(schema.getNamespace())) {
+        assertEquals(3, schema.getEntityTypes().size());
+        assertEquals(1, schema.getComplexTypes().size());
+        assertEquals(2, schema.getAssociations().size());
+        assertEquals(1, schema.getEntityContainers().size());
+      } else if (NAMESPACE2.equals(schema.getNamespace())) {
+        assertEquals(1, schema.getEntityTypes().size());
+        assertEquals(0, schema.getComplexTypes().size());
+        assertEquals(0, schema.getAssociations().size());
+        assertEquals(1, schema.getEntityContainers().size());
+        for (EntityType entityType : schema.getEntityTypes()) {
+          assertEquals(2, entityType.getKey().getKeys().size());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testRefScenario() throws Exception {
+    EdmProvider testProvider = new EdmTestProvider();
+    ODataResponse response = EntityProvider.writeMetadata(testProvider.getSchemas(), null);
+
+    String stream = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    EdmParser parser = new EdmParser();
+    DataServices result = parser.readMetadata(createStreamReader(stream), true);
+
+    ODataResponse response2 = EntityProvider.writeMetadata(result.getSchemas(), null);
+    String streamAfterParse = StringHelper.inputStreamToString((InputStream) response2.getEntity());
+    assertEquals(stream, streamAfterParse);
+  }
+
+  @Test
+  public void testAnnotations() throws XMLStreamException, EntityProviderException {
+    final String xmlWithAnnotations = "<edmx:Edmx Version=\"1.0\" xmlns:edmx=\"" + Edm.NAMESPACE_EDMX_2007_06 + "\">"
+        + "<edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\">"
+        + "<Schema Namespace=\"" + NAMESPACE + "\" xmlns=\"" + Edm.NAMESPACE_EDM_2008_09 + "\">"
+        + "<EntityType Name= \"Employee\" prefix1:href=\"http://google.de\" xmlns:prefix1=\"namespaceForAnno\">"
+        + "<Key><PropertyRef Name=\"EmployeeId\"/></Key>"
+        + "<Property Name=\"EmployeeId\" Type=\"Edm.String\" Nullable=\"false\"/>"
+        + "<Property Name=\"EmployeeName\" Type=\"Edm.String\" m:FC_TargetPath=\"SyndicationTitle\" annoPrefix:annoName=\"annoText\" xmlns:annoPrefix=\"http://annoNamespace\">"
+        + "<propertyAnnoElement>text</propertyAnnoElement>"
+        + "<propertyAnnoElement2 />"
+        + "</Property>"
+        + "</EntityType>"
+        + "<schemaElementTest1>"
+        + "<prefix:schemaElementTest2 xmlns:prefix=\"namespace\">text3"
+        + "</prefix:schemaElementTest2>"
+        + "<schemaElementTest3 rel=\"self\" pre:href=\"http://google.com\" xmlns:pre=\"namespaceForAnno\">text4</schemaElementTest3>"
+        + " </schemaElementTest1>"
+        + "</Schema>"
+
+        + "</edmx:DataServices>" + "</edmx:Edmx>";
+    EdmParser parser = new EdmParser();
+    XMLStreamReader reader = createStreamReader(xmlWithAnnotations);
+    DataServices result = parser.readMetadata(reader, false);
+    for (Schema schema : result.getSchemas()) {
+      assertEquals(1, schema.getAnnotationElements().size());
+      for (AnnotationElement annoElement : schema.getAnnotationElements()) {
+        for (AnnotationElement childAnnoElement : annoElement.getChildElements()) {
+          if ("schemaElementTest2".equals(childAnnoElement.getName())) {
+            assertEquals("prefix", childAnnoElement.getPrefix());
+            assertEquals("namespace", childAnnoElement.getNamespace());
+            assertEquals("text3", childAnnoElement.getText());
+          } else if ("schemaElementTest3".equals(childAnnoElement.getName())) {
+            assertEquals("text4", childAnnoElement.getText());
+            assertEquals("rel", childAnnoElement.getAttributes().get(0).getName());
+            assertEquals("self", childAnnoElement.getAttributes().get(0).getText());
+            assertEquals("", childAnnoElement.getAttributes().get(0).getPrefix());
+            assertNull(childAnnoElement.getAttributes().get(0).getNamespace());
+            assertEquals("href", childAnnoElement.getAttributes().get(1).getName());
+            assertEquals("pre", childAnnoElement.getAttributes().get(1).getPrefix());
+            assertEquals("namespaceForAnno", childAnnoElement.getAttributes().get(1).getNamespace());
+            assertEquals("http://google.com", childAnnoElement.getAttributes().get(1).getText());
+          } else {
+            throw new EntityProviderException(null, "xmlWithAnnotations");
+          }
+        }
+      }
+      for (EntityType entityType : schema.getEntityTypes()) {
+        AnnotationAttribute attr = entityType.getAnnotationAttributes().get(0);
+        assertEquals("href", attr.getName());
+        assertEquals("prefix1", attr.getPrefix());
+        assertEquals("namespaceForAnno", attr.getNamespace());
+        assertEquals("http://google.de", attr.getText());
+        for (Property property : entityType.getProperties()) {
+          if ("EmployeeName".equals(property.getName())) {
+            assertEquals(2, property.getAnnotationElements().size());
+            for (AnnotationElement anElement : property.getAnnotationElements()) {
+              if ("propertyAnnoElement".equals(anElement.getName())) {
+                assertEquals("text", anElement.getText());
+              }
+            }
+            for (AnnotationAttribute anAttribute : property.getAnnotationAttributes()) {
+              assertEquals("annoName", anAttribute.getName());
+              assertEquals("annoPrefix", anAttribute.getPrefix());
+              assertEquals("annoText", anAttribute.getText());
+              assertEquals("http://annoNamespace", anAttribute.getNamespace());
+            }
+          }
+        }
+      }
+    }
+  }
+
+  private XMLStreamReader createStreamReader(final String xml)
+      throws XMLStreamException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+    XMLStreamReader streamReader = factory
+        .createXMLStreamReader(new StringReader(xml));
+
+    return streamReader;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmxProviderTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmxProviderTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmxProviderTest.java
new file mode 100644
index 0000000..5307f6e
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/parser/EdmxProviderTest.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * 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.edm.parser;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.InputStream;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamException;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.edm.provider.EdmImplProv;
+import org.apache.olingo.odata2.testutil.mock.EdmTestProvider;
+
+public class EdmxProviderTest {
+
+  @Test
+  public void testEntityType() throws EntityProviderException, ODataException, XMLStreamException {
+    Edm edm = createEdm();
+
+    assertNotNull(edm);
+    FullQualifiedName fqNameEmployee = new FullQualifiedName("RefScenario", "Employee");
+    EdmProvider testProvider = new EdmTestProvider();
+    EdmImplProv edmImpl = (EdmImplProv) edm;
+    EntityType employee = edmImpl.getEdmProvider().getEntityType(fqNameEmployee);
+    EntityType testEmployee = testProvider.getEntityType(fqNameEmployee);
+    assertEquals(testEmployee.getName(), employee.getName());
+    assertEquals(testEmployee.isHasStream(), employee.isHasStream());
+    assertEquals(testEmployee.getProperties().size(), employee.getProperties().size());
+    assertEquals(testEmployee.getNavigationProperties().size(), employee.getNavigationProperties().size());
+
+  }
+
+  @Test
+  public void testAssociation() throws EntityProviderException, ODataException, XMLStreamException {
+    Edm edm = createEdm();
+    assertNotNull(edm);
+
+    FullQualifiedName fqNameAssociation = new FullQualifiedName("RefScenario", "BuildingRooms");
+    EdmProvider testProvider = new EdmTestProvider();
+    EdmImplProv edmImpl = (EdmImplProv) edm;
+    Association association = edmImpl.getEdmProvider().getAssociation(fqNameAssociation);
+    Association testAssociation = testProvider.getAssociation(fqNameAssociation);
+    assertEquals(testAssociation.getName(), association.getName());
+    assertEquals(testAssociation.getEnd1().getMultiplicity(), association.getEnd1().getMultiplicity());
+    assertEquals(testAssociation.getEnd2().getRole(), association.getEnd2().getRole());
+    assertEquals(testAssociation.getEnd1().getType(), association.getEnd1().getType());
+
+  }
+
+  @Test
+  public void testAssociationSet() throws EntityProviderException, ODataException, XMLStreamException {
+    EdmProvider testProvider = new EdmTestProvider();
+    Edm edm = createEdm();
+    assertNotNull(edm);
+
+    FullQualifiedName fqNameAssociation = new FullQualifiedName("RefScenario", "ManagerEmployees");
+    EdmImplProv edmImpl = (EdmImplProv) edm;
+    AssociationSet associationSet = edmImpl.getEdmProvider().getAssociationSet("Container1", fqNameAssociation, "Managers", "r_Manager");
+    AssociationSet testAssociationSet = testProvider.getAssociationSet("Container1", fqNameAssociation, "Managers", "r_Manager");
+    assertEquals(testAssociationSet.getName(), associationSet.getName());
+    assertEquals(testAssociationSet.getEnd1().getEntitySet(), associationSet.getEnd1().getEntitySet());
+    assertEquals(testAssociationSet.getEnd2().getEntitySet(), associationSet.getEnd2().getEntitySet());
+    assertEquals(testAssociationSet.getEnd2().getRole(), associationSet.getEnd2().getRole());
+
+  }
+
+  @Test
+  public void testSchema() throws EntityProviderException, ODataException, XMLStreamException {
+    EdmProvider testProvider = new EdmTestProvider();
+    Edm edm = createEdm();
+    assertNotNull(edm);
+
+    EdmImplProv edmImpl = (EdmImplProv) edm;
+    List<Schema> schemas = edmImpl.getEdmProvider().getSchemas();
+    List<Schema> testSchemas = testProvider.getSchemas();
+    assertEquals(testSchemas.size(), schemas.size());
+
+    if (!schemas.isEmpty() && !testSchemas.isEmpty()) {
+      Schema schema = schemas.get(0);
+      Schema testSchema = testSchemas.get(0);
+      assertEquals(testSchema.getEntityContainers().size(), schema.getEntityContainers().size());
+      assertEquals(testSchema.getEntityTypes().size(), schema.getEntityTypes().size());
+      assertEquals(testSchema.getComplexTypes().size(), schema.getComplexTypes().size());
+    }
+  }
+
+  @Test
+  public void testContainer() throws EntityProviderException, ODataException, XMLStreamException {
+    EdmProvider testProvider = new EdmTestProvider();
+    Edm edm = createEdm();
+    assertNotNull(edm);
+
+    EdmImplProv edmImpl = (EdmImplProv) edm;
+    EntityContainerInfo container = edmImpl.getEdmProvider().getEntityContainerInfo("Container2");
+    EntityContainerInfo testContainer = testProvider.getEntityContainerInfo("Container2");
+    assertEquals(testContainer.getName(), container.getName());
+    assertEquals(testContainer.isDefaultEntityContainer(), container.isDefaultEntityContainer());
+
+    container = edmImpl.getEdmProvider().getEntityContainerInfo(null);
+    testContainer = testProvider.getEntityContainerInfo(null);
+    assertNotNull(container);
+    assertEquals(testContainer.getName(), container.getName());
+    assertEquals(testContainer.isDefaultEntityContainer(), container.isDefaultEntityContainer());
+  }
+
+  private Edm createEdm() throws EntityProviderException, ODataException {
+    EdmProvider testProvider = new EdmTestProvider();
+    ODataResponse response = EntityProvider.writeMetadata(testProvider.getSchemas(), null);
+    InputStream in = (InputStream) response.getEntity();
+    return EntityProvider.readMetadata(in, true);
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProvTest.java
new file mode 100644
index 0000000..ccca92f
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProvTest.java
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmAnnotationsImplProvTest extends BaseTest {
+
+  private static EdmAnnotationsImplProv annotationsProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    List<AnnotationAttribute> annotationAttributes = new ArrayList<AnnotationAttribute>();
+    AnnotationAttribute attribute = new AnnotationAttribute().setName("attributeName").setNamespace("namespace").setPrefix("prefix").setText("Text");
+    annotationAttributes.add(attribute);
+
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    AnnotationElement element = new AnnotationElement().setName("elementName").setNamespace("namespace").setPrefix("prefix").setText("xmlData");
+    annotationElements.add(element);
+
+    annotationsProvider = new EdmAnnotationsImplProv(annotationAttributes, annotationElements);
+
+  }
+
+  @Test
+  public void testAttributes() {
+    List<? extends EdmAnnotationAttribute> annotations = annotationsProvider.getAnnotationAttributes();
+    assertEquals(1, annotations.size());
+
+    Iterator<? extends EdmAnnotationAttribute> iterator = annotations.iterator();
+    while (iterator.hasNext()) {
+      EdmAnnotationAttribute attribute = iterator.next();
+      assertEquals("attributeName", attribute.getName());
+      assertEquals("namespace", attribute.getNamespace());
+      assertEquals("prefix", attribute.getPrefix());
+      assertEquals("Text", attribute.getText());
+    }
+  }
+
+  @Test
+  public void testAttribute() {
+    EdmAnnotationAttribute attribute = annotationsProvider.getAnnotationAttribute("attributeName", "namespace");
+    assertEquals("attributeName", attribute.getName());
+    assertEquals("namespace", attribute.getNamespace());
+    assertEquals("prefix", attribute.getPrefix());
+    assertEquals("Text", attribute.getText());
+  }
+
+  @Test
+  public void testAttributeNull() {
+    EdmAnnotationAttribute attribute = annotationsProvider.getAnnotationAttribute("attributeNameWrong", "namespaceWrong");
+    assertNull(attribute);
+  }
+
+  @Test
+  public void testElements() {
+    List<? extends EdmAnnotationElement> annotations = annotationsProvider.getAnnotationElements();
+    assertEquals(1, annotations.size());
+
+    Iterator<? extends EdmAnnotationElement> iterator = annotations.iterator();
+    while (iterator.hasNext()) {
+      EdmAnnotationElement element = iterator.next();
+      assertEquals("elementName", element.getName());
+      assertEquals("namespace", element.getNamespace());
+      assertEquals("prefix", element.getPrefix());
+      assertEquals("xmlData", element.getText());
+    }
+  }
+
+  @Test
+  public void testElement() {
+    EdmAnnotationElement element = annotationsProvider.getAnnotationElement("elementName", "namespace");
+    assertEquals("elementName", element.getName());
+    assertEquals("namespace", element.getNamespace());
+    assertEquals("prefix", element.getPrefix());
+    assertEquals("xmlData", element.getText());
+  }
+
+  @Test
+  public void testElementNull() {
+    EdmAnnotationElement element = annotationsProvider.getAnnotationElement("elementNameWrong", "namespaceWrong");
+    assertNull(element);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProvTest.java
new file mode 100644
index 0000000..683a77c
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProvTest.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmAssociationEndImplProvTest extends BaseTest {
+  private static EdmAssociationEndImplProv associationEndProv;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    AssociationEnd end1 = new AssociationEnd().setRole("end1Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+
+    associationEndProv = new EdmAssociationEndImplProv(edmImplProv, end1);
+  }
+
+  @Test
+  public void testAssociationEnd() throws Exception {
+    EdmAssociationEnd associationEnd = associationEndProv;
+
+    assertEquals("end1Role", associationEnd.getRole());
+    assertEquals(EdmMultiplicity.ONE, associationEnd.getMultiplicity());
+  }
+
+  @Test(expected = EdmException.class)
+  public void testAssociationEntityType() throws Exception {
+    EdmAssociationEnd associationEnd = associationEndProv;
+    associationEnd.getEntityType();
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = associationEndProv;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}


[39/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPATestUtil.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPATestUtil.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPATestUtil.java
new file mode 100644
index 0000000..586363b
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPATestUtil.java
@@ -0,0 +1,554 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.CollectionAttribute;
+import javax.persistence.metamodel.EntityType;
+import javax.persistence.metamodel.IdentifiableType;
+import javax.persistence.metamodel.ListAttribute;
+import javax.persistence.metamodel.MapAttribute;
+import javax.persistence.metamodel.Metamodel;
+import javax.persistence.metamodel.PluralAttribute;
+import javax.persistence.metamodel.SetAttribute;
+import javax.persistence.metamodel.SingularAttribute;
+import javax.persistence.metamodel.Type;
+
+import org.easymock.EasyMock;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmMappingImpl;
+
+public class JPATestUtil {
+
+  public static EdmStructuralType getEdmStructuralType()
+  {
+    EdmStructuralType edmType = EasyMock.createMock(EdmStructuralType.class);
+    try {
+      List<String> propertyNames = new ArrayList<String>();
+      propertyNames.add("id");
+      propertyNames.add("description");
+      EdmProperty edmProperty1 = mockEdmProperty1();
+      EdmProperty edmProperty2 = mockEdmProperty2();
+      EdmMapping edmMapping = mockEdmMappingForEntityType();
+      EasyMock.expect(edmType.getName()).andStubReturn("SalesOrderHeader");
+      EasyMock.expect(edmType.getPropertyNames()).andStubReturn(propertyNames);
+      EasyMock.expect(edmType.getProperty("id")).andStubReturn(edmProperty1);
+      EasyMock.expect(edmType.getProperty("description")).andStubReturn(edmProperty2);
+      EasyMock.expect(edmType.getMapping()).andStubReturn(edmMapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmType);
+    return edmType;
+  }
+
+  public static Map<String, Object> getPropertyValueMap()
+  {
+    Map<String, Object> propertyValueMap = new HashMap<String, Object>();
+    propertyValueMap.put("id", 1);
+    return propertyValueMap;
+  }
+
+  public static PostUriInfo getPostUriInfo() {
+    PostUriInfo postUriInfo = EasyMock.createMock(PostUriInfo.class);
+    EdmEntitySet targetEntitySet = mockSourceEdmEntitySet();
+    EasyMock.expect(postUriInfo.getTargetEntitySet()).andStubReturn(targetEntitySet);
+    EasyMock.replay(postUriInfo);
+    return postUriInfo;
+  }
+
+  public static PutMergePatchUriInfo getPutMergePatchUriInfo() {
+    PutMergePatchUriInfo putUriInfo = EasyMock.createMock(PutMergePatchUriInfo.class);
+    EdmEntitySet targetEntitySet = mockSourceEdmEntitySet();
+    EasyMock.expect(putUriInfo.getTargetEntitySet()).andStubReturn(targetEntitySet);
+    EasyMock.replay(putUriInfo);
+    return putUriInfo;
+  }
+
+  public static EdmEntitySet mockSourceEdmEntitySet() {
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      final EdmNavigationProperty navigationProperty = mockNavigationProperty();
+      EasyMock.expect(entitySet.getEntityType()).andStubReturn(mockEdmEntityType(navigationProperty));
+      EasyMock.expect(entitySet.getRelatedEntitySet(navigationProperty)).andStubReturn(getSIEntitySet());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entitySet);
+    return entitySet;
+  }
+
+  public static Object getJPAEntity()
+  {
+    SalesOrderHeader sHead = new SalesOrderHeader(1, "laptop");
+    SalesOrderLineItem sItem = new SalesOrderLineItem(23);
+    List<SalesOrderLineItem> sItems = new ArrayList<SalesOrderLineItem>();
+    sItems.add(sItem);
+    sHead.setSalesOrderLineItems(sItems);
+    return sHead;
+
+  }
+
+  public static EdmEntityType mockEdmEntityType(final EdmNavigationProperty navigationProperty) {
+
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    List<String> navigationPropertyNames = new ArrayList<String>();
+    List<String> propertyNames = new ArrayList<String>();
+    List<EdmProperty> keyProperties = new ArrayList<EdmProperty>();
+    propertyNames.add("id");
+    propertyNames.add("description");
+    navigationPropertyNames.add("SalesOrderLineItemDetails");
+    try {
+      EasyMock.expect(mapping.getInternalName()).andStubReturn("SalesOrderHeader");
+      EasyMock.replay(mapping);
+      EasyMock.expect(entityType.getName()).andStubReturn("SalesOrderHeader");
+      EasyMock.expect(entityType.getMapping()).andStubReturn(mapping);
+      EasyMock.expect(entityType.getNavigationPropertyNames()).andStubReturn(navigationPropertyNames);
+      EasyMock.expect(entityType.getProperty("SalesOrderLineItemDetails")).andStubReturn(/*mockNavigationProperty()*/navigationProperty);
+      EdmProperty property1 = mockEdmProperty1();
+      keyProperties.add(property1);
+      EasyMock.expect(entityType.getProperty("id")).andStubReturn(property1);
+      EasyMock.expect(entityType.getProperty("description")).andStubReturn(mockEdmProperty2());
+      EasyMock.expect(entityType.getKeyProperties()).andReturn(keyProperties);
+      EasyMock.expect(entityType.getPropertyNames()).andStubReturn(propertyNames);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entityType);
+    return entityType;
+  }
+
+  private static EdmEntitySet getSIEntitySet() {
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(entitySet.getEntityType()).andStubReturn(
+          mockTargetEdmEntityType());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entitySet);
+    return entitySet;
+
+  }
+
+  public static EdmEntityType mockTargetEdmEntityType() {
+    EdmEntityType entityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+
+    List<String> propertyNames = new ArrayList<String>();
+    propertyNames.add("price");
+    try {
+      EasyMock.expect(mapping.getInternalName()).andStubReturn(
+          "SalesOrderLineItem");
+      EasyMock.replay(mapping);
+      EasyMock.expect(entityType.getName()).andStubReturn(
+          "SalesOrderLineItem");
+      EasyMock.expect(entityType.getMapping()).andStubReturn(mapping);
+      EdmProperty property = mockEdmPropertyOfTarget();
+      EasyMock.expect(entityType.getProperty("price")).andStubReturn(
+          property);
+      EasyMock.expect(entityType.getPropertyNames()).andStubReturn(
+          propertyNames);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entityType);
+    return entityType;
+  }
+
+  private static EdmProperty mockEdmPropertyOfTarget() {
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+
+    EdmType type = EasyMock.createMock(EdmType.class);
+    EasyMock.expect(type.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+    EasyMock.replay(type);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn("price");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("price");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(type);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(mapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    return edmProperty;
+  }
+
+  public static EdmNavigationProperty mockNavigationProperty() {
+    EdmNavigationProperty navigationProperty = EasyMock.createMock(EdmNavigationProperty.class);
+    EdmMapping mapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(mapping.getInternalName()).andStubReturn("salesOrderLineItems");
+    EasyMock.replay(mapping);
+    try {
+      EasyMock.expect(navigationProperty.getMultiplicity()).andStubReturn(EdmMultiplicity.MANY);
+      EasyMock.expect(navigationProperty.getMapping()).andStubReturn(mapping);
+
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(navigationProperty);
+    return navigationProperty;
+
+    //EdmNavigationPropertyImplProv navigationPropertyImplProv = new EdmNavigationPropertyImplProv(edm, property)
+  }
+
+  public static Metamodel mockMetaModel()
+  {
+    Set<EntityType<?>> jpaEntities = new HashSet<EntityType<?>>();
+    jpaEntities.add(new JPATestUtil.DemoEntityType());
+    Metamodel metaModel = EasyMock.createMock(Metamodel.class);
+    EasyMock.expect(metaModel.getEntities()).andStubReturn(jpaEntities);
+    EasyMock.replay(metaModel);
+    return metaModel;
+  }
+
+  private static EdmMapping mockEdmMappingForEntityType() {
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("SalesOrderHeader");
+    EasyMock.replay(edmMapping);
+    return edmMapping;
+  }
+
+  private static EdmProperty mockEdmProperty1() {
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType = mockEdmType1();
+    EdmMapping edmMapping = mockEdmMappingForProperty1();
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("id");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    return edmProperty;
+
+  }
+
+  private static EdmProperty mockEdmProperty2() {
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmType edmType = mockEdmType2();
+    EdmMapping edmMapping = mockEdmMappingForProperty2();
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("description");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmProperty);
+    return edmProperty;
+
+  }
+
+  private static EdmMapping mockEdmMappingForProperty1() {
+    JPAEdmMappingImpl mapping = new JPAEdmMappingImpl();
+    mapping.setJPAType(null);
+    mapping.setInternalName("id");
+    return (EdmMapping) mapping;
+  }
+
+  private static EdmMapping mockEdmMappingForProperty2() {
+    JPAEdmMappingImpl mapping = new JPAEdmMappingImpl();
+    mapping.setJPAType(null);
+    mapping.setInternalName("description");
+    return (EdmMapping) mapping;
+  }
+
+  private static EdmType mockEdmType1() {
+    return EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance();
+
+  }
+
+  private static EdmType mockEdmType2() {
+    return EdmSimpleTypeKind.String.getEdmSimpleTypeInstance();
+
+  }
+
+  static class DemoEntityType implements EntityType<SalesOrderHeader>
+  {
+
+    @Override
+    public <Y> SingularAttribute<? super org.apache.olingo.odata2.processor.core.jpa.cud.SalesOrderHeader, Y> getId(
+        final Class<Y> type) {
+      return null;
+    }
+
+    @Override
+    public <Y> SingularAttribute<org.apache.olingo.odata2.processor.core.jpa.cud.SalesOrderHeader, Y> getDeclaredId(
+        final Class<Y> type) {
+      return null;
+    }
+
+    @Override
+    public <Y> SingularAttribute<? super SalesOrderHeader, Y> getVersion(
+        final Class<Y> type) {
+      return null;
+    }
+
+    @Override
+    public <Y> SingularAttribute<SalesOrderHeader, Y> getDeclaredVersion(
+        final Class<Y> type) {
+      return null;
+    }
+
+    @Override
+    public IdentifiableType<? super SalesOrderHeader> getSupertype() {
+      return null;
+    }
+
+    @Override
+    public boolean hasSingleIdAttribute() {
+      return false;
+    }
+
+    @Override
+    public boolean hasVersionAttribute() {
+      return false;
+    }
+
+    @Override
+    public Set<SingularAttribute<? super SalesOrderHeader, ?>> getIdClassAttributes() {
+      return null;
+    }
+
+    @Override
+    public Type<?> getIdType() {
+      return null;
+    }
+
+    @Override
+    public Set<Attribute<? super SalesOrderHeader, ?>> getAttributes() {
+      return null;
+    }
+
+    @Override
+    public Set<Attribute<SalesOrderHeader, ?>> getDeclaredAttributes() {
+      return null;
+    }
+
+    @Override
+    public <Y> SingularAttribute<? super SalesOrderHeader, Y> getSingularAttribute(
+        final String name, final Class<Y> type) {
+      return null;
+    }
+
+    @Override
+    public <Y> SingularAttribute<SalesOrderHeader, Y> getDeclaredSingularAttribute(
+        final String name, final Class<Y> type) {
+      return null;
+    }
+
+    @Override
+    public Set<SingularAttribute<? super SalesOrderHeader, ?>> getSingularAttributes() {
+      return null;
+    }
+
+    @Override
+    public Set<SingularAttribute<SalesOrderHeader, ?>> getDeclaredSingularAttributes() {
+      return null;
+    }
+
+    @Override
+    public <E> CollectionAttribute<? super SalesOrderHeader, E> getCollection(
+        final String name, final Class<E> elementType) {
+      return null;
+    }
+
+    @Override
+    public <E> CollectionAttribute<SalesOrderHeader, E> getDeclaredCollection(
+        final String name, final Class<E> elementType) {
+      return null;
+    }
+
+    @Override
+    public <E> SetAttribute<? super SalesOrderHeader, E> getSet(
+        final String name, final Class<E> elementType) {
+      return null;
+    }
+
+    @Override
+    public <E> SetAttribute<SalesOrderHeader, E> getDeclaredSet(
+        final String name, final Class<E> elementType) {
+      return null;
+    }
+
+    @Override
+    public <E> ListAttribute<? super SalesOrderHeader, E> getList(
+        final String name, final Class<E> elementType) {
+      return null;
+    }
+
+    @Override
+    public <E> ListAttribute<SalesOrderHeader, E> getDeclaredList(
+        final String name, final Class<E> elementType) {
+      return null;
+    }
+
+    @Override
+    public <K, V> MapAttribute<? super SalesOrderHeader, K, V> getMap(
+        final String name, final Class<K> keyType, final Class<V> valueType) {
+      return null;
+    }
+
+    @Override
+    public <K, V> MapAttribute<SalesOrderHeader, K, V> getDeclaredMap(
+        final String name, final Class<K> keyType, final Class<V> valueType) {
+      return null;
+    }
+
+    @Override
+    public Set<PluralAttribute<? super SalesOrderHeader, ?, ?>> getPluralAttributes() {
+      return null;
+    }
+
+    @Override
+    public Set<PluralAttribute<SalesOrderHeader, ?, ?>> getDeclaredPluralAttributes() {
+      return null;
+    }
+
+    @Override
+    public Attribute<? super SalesOrderHeader, ?> getAttribute(final String name) {
+      return null;
+    }
+
+    @Override
+    public Attribute<SalesOrderHeader, ?> getDeclaredAttribute(final String name) {
+      return null;
+    }
+
+    @Override
+    public SingularAttribute<? super SalesOrderHeader, ?> getSingularAttribute(
+        final String name) {
+      return null;
+    }
+
+    @Override
+    public SingularAttribute<SalesOrderHeader, ?> getDeclaredSingularAttribute(
+        final String name) {
+      return null;
+    }
+
+    @Override
+    public CollectionAttribute<? super SalesOrderHeader, ?> getCollection(
+        final String name) {
+      return null;
+    }
+
+    @Override
+    public CollectionAttribute<SalesOrderHeader, ?> getDeclaredCollection(
+        final String name) {
+      return null;
+    }
+
+    @Override
+    public SetAttribute<? super SalesOrderHeader, ?> getSet(final String name) {
+      return null;
+    }
+
+    @Override
+    public SetAttribute<SalesOrderHeader, ?> getDeclaredSet(final String name) {
+      return null;
+    }
+
+    @Override
+    public ListAttribute<? super SalesOrderHeader, ?> getList(final String name) {
+      return null;
+    }
+
+    @Override
+    public ListAttribute<SalesOrderHeader, ?> getDeclaredList(final String name) {
+      return null;
+    }
+
+    @Override
+    public MapAttribute<? super SalesOrderHeader, ?, ?> getMap(final String name) {
+      return null;
+    }
+
+    @Override
+    public MapAttribute<SalesOrderHeader, ?, ?> getDeclaredMap(final String name) {
+      return null;
+    }
+
+    @Override
+    public javax.persistence.metamodel.Type.PersistenceType getPersistenceType() {
+      return null;
+    }
+
+    @Override
+    public Class<SalesOrderHeader> getJavaType() {
+      return org.apache.olingo.odata2.processor.core.jpa.cud.SalesOrderHeader.class;
+    }
+
+    @Override
+    public javax.persistence.metamodel.Bindable.BindableType getBindableType() {
+      return null;
+    }
+
+    @Override
+    public Class<SalesOrderHeader> getBindableJavaType() {
+      return null;
+    }
+
+    @Override
+    public String getName() {
+      return "SalesOrderHeader";
+    }
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequestTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequestTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequestTest.java
new file mode 100644
index 0000000..0238664
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/JPAUpdateRequestTest.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPAUpdateRequestTest {
+
+  @Test
+  public void testProcess() {
+
+    JPAUpdateRequest updateRequest = new JPAUpdateRequest();
+    PutMergePatchUriInfo putUriInfo = JPATestUtil.getPutMergePatchUriInfo();
+    try {
+      updateRequest.process(JPATestUtil.getJPAEntity(), putUriInfo, null, "application/xml");
+    } catch (ODataJPARuntimeException e) {
+      if (e.isCausedByMessageException()) {
+        assertTrue(true);
+      } else {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+    }
+
+  }
+
+  @Test
+  public void testParse2JPAEntityValueMap() {
+    JPAUpdateRequest updateRequest = new JPAUpdateRequest();
+    final EdmNavigationProperty navigationProperty = JPATestUtil.mockNavigationProperty();
+    EdmEntityType edmEntityType = JPATestUtil.mockEdmEntityType(navigationProperty);
+    Map<String, Object> propertyValueMap = JPATestUtil.getPropertyValueMap();
+    propertyValueMap.put("description", "desktop");
+    Object result = null;
+    try {
+      result = updateRequest.parse2JPAEntityValueMap(JPATestUtil.getJPAEntity(), edmEntityType, propertyValueMap);
+      assertEquals("desktop", ((SalesOrderHeader) result).getDescription());
+      assertEquals(1, ((SalesOrderHeader) result).getId());
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(result);
+    assertEquals(((SalesOrderHeader) result).getId(), 1);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderHeader.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderHeader.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderHeader.java
new file mode 100644
index 0000000..858db9e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderHeader.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SalesOrderHeader {
+
+  private int id;
+  private String description;
+
+  public SalesOrderHeader()
+  {}
+
+  public SalesOrderHeader(final int id, final String description) {
+    super();
+    this.id = id;
+    this.description = description;
+  }
+
+  private List<SalesOrderLineItem> salesOrderLineItems = new ArrayList<SalesOrderLineItem>();
+
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDescription(final String description) {
+    this.description = description;
+  }
+
+  public int getId() {
+    return id;
+  }
+
+  public void setId(final int id) {
+    this.id = id;
+  }
+
+  public List<SalesOrderLineItem> getSalesOrderLineItems() {
+    return salesOrderLineItems;
+  }
+
+  public void setSalesOrderLineItems(final List<SalesOrderLineItem> salesOrderLineItems) {
+    this.salesOrderLineItems = salesOrderLineItems;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItem.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItem.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItem.java
new file mode 100644
index 0000000..0c2b6c2
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItem.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+public class SalesOrderLineItem {
+
+  private int price;
+
+  public SalesOrderLineItem(final int price) {
+    super();
+    this.price = price;
+  }
+
+  public int getPrice() {
+    return price;
+  }
+
+  public void setPrice(final int price) {
+    this.price = price;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItemKey.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItemKey.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItemKey.java
new file mode 100644
index 0000000..8dd0f32
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/cud/SalesOrderLineItemKey.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.cud;
+
+public class SalesOrderLineItemKey {
+
+  private int soId;
+  private int liId;
+
+  public SalesOrderLineItemKey() {
+
+  }
+
+  public SalesOrderLineItemKey(final int soId, final int liId) {
+    super();
+    this.soId = soId;
+    this.liId = liId;
+  }
+
+  public int getSoId() {
+    return soId;
+  }
+
+  public void setSoId(final int soId) {
+    this.soId = soId;
+  }
+
+  public int getLiId() {
+    return liId;
+  }
+
+  public void setLiId(final int liId) {
+    this.liId = liId;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderNegativeTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderNegativeTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderNegativeTest.java
new file mode 100644
index 0000000..7bfe54e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderNegativeTest.java
@@ -0,0 +1,220 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.edm;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.ODataJPAContextMock;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmModel;
+
+public class ODataJPAEdmProviderNegativeTest {
+
+  private static ODataJPAEdmProvider edmProvider;
+
+  @BeforeClass
+  public static void setup() {
+
+    edmProvider = new ODataJPAEdmProvider();
+    try {
+      Class<? extends ODataJPAEdmProvider> clazz = edmProvider.getClass();
+      Field field = clazz.getDeclaredField("schemas");
+      field.setAccessible(true);
+      List<Schema> schemas = new ArrayList<Schema>();
+      schemas.add(new Schema().setNamespace("salesorderprocessing")); //Empty Schema
+      field.set(edmProvider, schemas);
+      field = clazz.getDeclaredField("oDataJPAContext");
+      field.setAccessible(true);
+      field.set(edmProvider, ODataJPAContextMock.mockODataJPAContext());
+      field = clazz.getDeclaredField("jpaEdmModel");
+      field.setAccessible(true);
+      field.set(edmProvider, new JPAEdmModel(null, null));
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testNullGetEntityContainerInfo() {
+    EntityContainerInfo entityContainer = null;
+    try {
+      entityContainer = edmProvider
+          .getEntityContainerInfo("salesorderprocessingContainer");
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNull(entityContainer);
+  }
+
+  @Test
+  public void testNullGetEntityType() {
+    FullQualifiedName entityTypeName = new FullQualifiedName(
+        "salesorderprocessing", "SalesOrderHeader");
+    try {
+      assertNull(edmProvider.getEntityType(entityTypeName));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testNullGetComplexType() {
+    FullQualifiedName complexTypeName = new FullQualifiedName(
+        "salesorderprocessing", "Address");
+    try {
+      assertNull(edmProvider.getComplexType(complexTypeName));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetAssociationFullQualifiedName() {
+    Association association = null;
+    try {
+      association = edmProvider.getAssociation(new FullQualifiedName(
+          "salesorderprocessing", "SalesOrderHeader_SalesOrderItem"));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNull(association);
+  }
+
+  @Test
+  public void testGetEntitySet() {
+    try {
+      assertNull(edmProvider.getEntitySet(
+          "salesorderprocessingContainer", "SalesOrderHeaders"));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetAssociationSet() {
+    try {
+      assertNull(edmProvider.getAssociationSet(
+          "salesorderprocessingContainer", new FullQualifiedName(
+              "salesorderprocessing",
+              "SalesOrderHeader_SalesOrderItem"),
+          "SalesOrderHeaders", "SalesOrderHeader"));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testNullGetFunctionImport() {
+
+    try {
+      assertNull(edmProvider.getFunctionImport(
+          "salesorderprocessingContainer",
+          "SalesOrder_FunctionImport1"));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+  
+  @Test
+  public void testNullGetFunctionImport2() {
+
+    try {
+      ODataJPAEdmProvider provider = new ODataJPAEdmProvider();
+      try {
+        Class<? extends ODataJPAEdmProvider> clazz = provider.getClass();
+        Field field = clazz.getDeclaredField("schemas");
+        field.setAccessible(true);
+        List<Schema> schemas = new ArrayList<Schema>();
+        Schema schema = new Schema().setNamespace("salesorderprocessing");
+        EntityContainer container = new EntityContainer().setName("salesorderprocessingContainer");
+        List<EntityContainer> containerList = new ArrayList<EntityContainer>();
+        containerList.add(container); // Empty Container
+        schema.setEntityContainers(containerList);
+        schemas.add(schema); //Empty Schema
+        field.set(provider, schemas);
+      } catch (IllegalArgumentException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (IllegalAccessException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (NoSuchFieldException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      } catch (SecurityException e) {
+        fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+            + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+      }
+
+      assertNull(provider.getFunctionImport(
+          "salesorderprocessingContainer",
+          "SalesOrder_FunctionImport1"));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testGetSchemas() {
+    try {
+      assertNotNull(edmProvider.getSchemas());
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderTest.java
new file mode 100644
index 0000000..63a771f
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/edm/ODataJPAEdmProviderTest.java
@@ -0,0 +1,456 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.edm;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.ODataJPAContextMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.EdmSchemaMock;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmModel;
+
+public class ODataJPAEdmProviderTest {
+
+  private static ODataJPAEdmProvider edmProvider;
+
+  @BeforeClass
+  public static void setup() {
+
+    edmProvider = new ODataJPAEdmProvider();
+    try {
+      Class<? extends ODataJPAEdmProvider> clazz = edmProvider.getClass();
+      Field field = clazz.getDeclaredField("schemas");
+      field.setAccessible(true);
+      List<Schema> schemas = new ArrayList<Schema>();
+      schemas.add(EdmSchemaMock.createMockEdmSchema());
+      field.set(edmProvider, schemas);
+      field = clazz.getDeclaredField("oDataJPAContext");
+      field.setAccessible(true);
+      field.set(edmProvider, ODataJPAContextMock.mockODataJPAContext());
+      field = clazz.getDeclaredField("jpaEdmModel");
+      field.setAccessible(true);
+      field.set(edmProvider, new JPAEdmModel(null, null));
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testConstructor() {
+    try {
+      ODataJPAEdmProvider edmProv = new ODataJPAEdmProvider(
+          ODataJPAContextMock.mockODataJPAContext());
+      edmProv.getClass();
+    } catch (Exception e) {
+      e.printStackTrace();
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testGetODataJPAContext() {
+    String pUnitName = edmProvider.getODataJPAContext()
+        .getPersistenceUnitName();
+    assertEquals("salesorderprocessing", pUnitName);
+  }
+
+  @Test
+  public void testGetEntityContainerInfo() {
+    String entityContainerName = null;
+    EntityContainerInfo entityContainer = null;
+    try {
+      entityContainer = edmProvider
+          .getEntityContainerInfo("salesorderprocessingContainer");
+      entityContainerName = entityContainer.getName();
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    assertEquals("salesorderprocessingContainer", entityContainerName);
+    assertNotNull(entityContainer);
+  }
+  
+  @Test
+  public void testDefaultGetEntityContainerInfo() {
+    String entityContainerName = null;
+    EntityContainerInfo entityContainer = null;
+    try {
+      entityContainer = edmProvider
+          .getEntityContainerInfo(null);
+      entityContainerName = entityContainer.getName();
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    assertEquals("salesorderprocessingContainer", entityContainerName);
+    assertNotNull(entityContainer);
+  }
+
+  @Test
+  public void testGetEntityType() {
+    FullQualifiedName entityTypeName = new FullQualifiedName(
+        "salesorderprocessing", "SalesOrderHeader");
+    String entityName = null;
+    try {
+      entityName = edmProvider.getEntityType(entityTypeName).getName();
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals("SalesOrderHeader", entityName);
+    try {
+      edmProvider
+          .getEntityType(new FullQualifiedName("salesorder", "abc"));
+    } catch (ODataException e) {
+      assertTrue(true);
+    }
+
+  }
+
+  @Test
+  public void testGetComplexType() {
+    FullQualifiedName complexTypeName = new FullQualifiedName(
+        "salesorderprocessing", "Address");
+    String nameStr = null;
+    try {
+      nameStr = edmProvider.getComplexType(complexTypeName).getName();
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals("Address", nameStr);
+  }
+
+  @Test
+  public void testGetAssociationFullQualifiedName() {
+    Association association = null;
+    try {
+      association = edmProvider.getAssociation(new FullQualifiedName(
+          "salesorderprocessing", "SalesOrderHeader_SalesOrderItem"));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(association);
+    assertEquals("SalesOrderHeader_SalesOrderItem", association.getName());
+  }
+
+  @Test
+  public void testGetEntitySet() {
+    String entitySetName = null;
+    try {
+      entitySetName = edmProvider.getEntitySet(
+          "salesorderprocessingContainer", "SalesOrderHeaders")
+          .getName();
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals("SalesOrderHeaders", entitySetName);
+    try {
+      assertNull(edmProvider.getEntitySet("salesorderprocessing",
+          "SalesOrderHeaders"));
+    } catch (ODataException e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testGetAssociationSet() {
+    AssociationSet associationSet = null;
+
+    try {
+      associationSet = edmProvider.getAssociationSet(
+          "salesorderprocessingContainer", new FullQualifiedName(
+              "salesorderprocessing",
+              "SalesOrderHeader_SalesOrderItem"),
+          "SalesOrderHeaders", "SalesOrderHeader");
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(associationSet);
+    assertEquals("SalesOrderHeader_SalesOrderItemSet",
+        associationSet.getName());
+    try {
+      associationSet = edmProvider.getAssociationSet(
+          "salesorderprocessingContainer", new FullQualifiedName(
+              "salesorderprocessing",
+              "SalesOrderHeader_SalesOrderItem"),
+          "SalesOrderItems", "SalesOrderItem");
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(associationSet);
+    try {
+      associationSet = edmProvider.getAssociationSet(
+          "salesorderproceContainer", new FullQualifiedName(
+              "salesorderprocessing",
+              "SalesOrderHeader_SalesOrderItem"),
+          "SalesOrderItems", "SalesOrderItem");
+    } catch (ODataException e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testGetFunctionImport() {
+    String functionImportName = null;
+    try {
+      functionImportName = edmProvider.getFunctionImport(
+          "salesorderprocessingContainer",
+          "SalesOrder_FunctionImport1").getName();
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals("SalesOrder_FunctionImport1", functionImportName);
+    try {
+      functionImportName = edmProvider.getFunctionImport(
+          "salesorderprocessingContainer",
+          "SalesOrder_FunctionImport1").getName();
+    } catch (ODataException e) {
+      assertTrue(true);
+    }
+    try {
+      assertNotNull(edmProvider.getFunctionImport(
+          "salesorderprocessingContainer",
+          "SalesOrder_FunctionImport1"));
+    } catch (ODataException e) {
+      e.printStackTrace();
+    }
+  }
+
+  @Test
+  public void testGetSchemas() {
+    try {
+      assertNotNull(edmProvider.getSchemas());
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testgetComplexTypeWithBuffer() {
+    HashMap<String, ComplexType> compTypes = new HashMap<String, ComplexType>();
+    ComplexType comp = new ComplexType();
+    comp.setName("Address");
+    compTypes.put("salesorderprocessing" + "." + "Address", comp);
+    ODataJPAEdmProvider jpaEdmProv = new ODataJPAEdmProvider();
+    Class<?> claz = jpaEdmProv.getClass();
+    Field f;
+    try {
+      f = claz.getDeclaredField("complexTypes");
+      f.setAccessible(true);
+      f.set(jpaEdmProv, compTypes);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    try {
+      assertEquals(comp, jpaEdmProv.getComplexType(new FullQualifiedName(
+          "salesorderprocessing", "Address")));
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    try {
+      jpaEdmProv.getComplexType(new FullQualifiedName("salesorderessing",
+          "abc"));
+    } catch (ODataJPAModelException e) {
+      assertTrue(true);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetEntityContainerInfoWithBuffer() {
+    HashMap<String, EntityContainerInfo> entityContainerInfos = new HashMap<String, EntityContainerInfo>();
+    EntityContainerInfo entityContainer = new EntityContainerInfo();
+    entityContainer.setName("salesorderprocessingContainer");
+    entityContainerInfos.put("salesorderprocessingContainer",
+        entityContainer);
+    ODataJPAEdmProvider jpaEdmProv = new ODataJPAEdmProvider();
+    Class<?> claz = jpaEdmProv.getClass();
+    try {
+      Field f = claz.getDeclaredField("entityContainerInfos");
+      f.setAccessible(true);
+      f.set(jpaEdmProv, entityContainerInfos);
+      assertEquals(
+          entityContainer,
+          jpaEdmProv
+              .getEntityContainerInfo("salesorderprocessingContainer"));
+      jpaEdmProv.getEntityContainerInfo("abc");
+    } catch (ODataJPAModelException e) {
+      assertTrue(true);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetEntityTypeWithBuffer() {
+    HashMap<String, org.apache.olingo.odata2.api.edm.provider.EntityType> entityTypes = new HashMap<String, org.apache.olingo.odata2.api.edm.provider.EntityType>();
+    org.apache.olingo.odata2.api.edm.provider.EntityType entity = new org.apache.olingo.odata2.api.edm.provider.EntityType();
+    entity.setName("SalesOrderHeader");
+    entityTypes.put("salesorderprocessing" + "." + "SalesorderHeader",
+        entity);
+    ODataJPAEdmProvider jpaEdmProv = new ODataJPAEdmProvider();
+    Class<?> claz = jpaEdmProv.getClass();
+    Field f;
+    try {
+      f = claz.getDeclaredField("entityTypes");
+      f.setAccessible(true);
+      f.set(jpaEdmProv, entityTypes);
+      assertEquals(entity,
+          jpaEdmProv.getEntityType(new FullQualifiedName(
+              "salesorderprocessing", "SalesorderHeader")));
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    try {
+      jpaEdmProv.getEntityType(new FullQualifiedName("salesoprocessing",
+          "abc"));
+    } catch (ODataJPAModelException e) {
+      assertTrue(true);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetAssociationWithBuffer() {
+    HashMap<String, Association> associations = new HashMap<String, Association>();
+    Association association = new Association();
+    association.setName("SalesOrderHeader_SalesOrderItem");
+    associations.put("salesorderprocessing" + "."
+        + "SalesOrderHeader_SalesOrderItem", association);
+    ODataJPAEdmProvider jpaEdmProv = new ODataJPAEdmProvider();
+    Class<?> claz = jpaEdmProv.getClass();
+    Field f;
+    try {
+      f = claz.getDeclaredField("associations");
+      f.setAccessible(true);
+      f.set(jpaEdmProv, associations);
+      assertEquals(association,
+          jpaEdmProv.getAssociation(new FullQualifiedName(
+              "salesorderprocessing",
+              "SalesOrderHeader_SalesOrderItem")));
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    try {
+      jpaEdmProv.getAssociation(new FullQualifiedName(
+          "salesorderprocessing", "abc"));
+    } catch (ODataJPAModelException e) {
+      assertTrue(true);
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLBuilderFactoryTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLBuilderFactoryTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLBuilderFactoryTest.java
new file mode 100644
index 0000000..5129092
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLBuilderFactoryTest.java
@@ -0,0 +1,414 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.persistence.Cache;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceUnitUtil;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.metamodel.Metamodel;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.factory.JPAAccessFactory;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAAccessFactory;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.ODataJPAContextImpl;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAProcessorImplTest;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.factory.ODataJPAFactoryImpl;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectContext.JPQLSelectContextBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLSelectSingleContext.JPQLSelectSingleContextBuilder;
+
+public class JPQLBuilderFactoryTest {
+
+  @Test
+  public void testGetStatementBuilderFactoryforSelect() throws ODataException {
+
+    GetEntitySetUriInfo getEntitySetView = getUriInfo();
+
+    // Build JPQL Context
+    JPQLContext selectContext = JPQLContext.createBuilder(
+        JPQLContextType.SELECT, getEntitySetView).build();
+    JPQLStatementBuilder statementBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getStatementBuilder(selectContext);
+
+    assertTrue(statementBuilder instanceof JPQLSelectStatementBuilder);
+
+  }
+
+  @Test
+  public void testGetStatementBuilderFactoryforSelectSingle()
+      throws ODataException {
+
+    GetEntityUriInfo getEntityView = getEntityUriInfo();
+
+    // Build JPQL Context
+    JPQLContext selectContext = JPQLContext.createBuilder(
+        JPQLContextType.SELECT_SINGLE, getEntityView).build();
+    JPQLStatementBuilder statementBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getStatementBuilder(selectContext);
+
+    assertTrue(statementBuilder instanceof JPQLSelectSingleStatementBuilder);
+
+  }
+
+  @Test
+  public void testGetStatementBuilderFactoryforJoinSelect()
+      throws ODataException {
+
+    GetEntitySetUriInfo getEntitySetView = getUriInfo();
+
+    // Build JPQL Context
+    JPQLContext selectContext = JPQLContext.createBuilder(
+        JPQLContextType.JOIN, getEntitySetView).build();
+    JPQLStatementBuilder statementBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getStatementBuilder(selectContext);
+
+    assertTrue(statementBuilder instanceof JPQLJoinStatementBuilder);
+
+  }
+
+  @Test
+  public void testGetStatementBuilderFactoryforJoinSelectSingle()
+      throws ODataException {
+
+    GetEntityUriInfo getEntityView = getEntityUriInfo();
+
+    // Build JPQL Context
+    JPQLContext selectContext = JPQLContext.createBuilder(
+        JPQLContextType.JOIN_SINGLE, getEntityView).build();
+    JPQLStatementBuilder statementBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getStatementBuilder(selectContext);
+
+    assertTrue(statementBuilder instanceof JPQLJoinSelectSingleStatementBuilder);
+
+  }
+
+  @Test
+  public void testGetContextBuilderforDelete() throws ODataException {
+
+    // Build JPQL ContextBuilder
+    JPQLContextBuilder contextBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getContextBuilder(
+            JPQLContextType.DELETE);
+
+    assertNull(contextBuilder);
+
+  }
+
+  @Test
+  public void testGetContextBuilderforSelect() throws ODataException {
+
+    // Build JPQL ContextBuilder
+    JPQLContextBuilder contextBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getContextBuilder(
+            JPQLContextType.SELECT);
+
+    assertNotNull(contextBuilder);
+    assertTrue(contextBuilder instanceof JPQLSelectContextBuilder);
+
+  }
+
+  @Test
+  public void testGetContextBuilderforSelectSingle() throws ODataException {
+
+    // Build JPQL ContextBuilder
+    JPQLContextBuilder contextBuilder = new ODataJPAFactoryImpl()
+        .getJPQLBuilderFactory().getContextBuilder(
+            JPQLContextType.SELECT_SINGLE);
+
+    assertNotNull(contextBuilder);
+    assertTrue(contextBuilder instanceof JPQLSelectSingleContextBuilder);
+
+  }
+
+  private GetEntitySetUriInfo getUriInfo() throws EdmException {
+    GetEntitySetUriInfo getEntitySetView = EasyMock
+        .createMock(GetEntitySetUriInfo.class);
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("SOItem");
+    EasyMock.replay(edmEntityType);
+    OrderByExpression orderByExpression = EasyMock
+        .createMock(OrderByExpression.class);
+    EasyMock.expect(getEntitySetView.getTargetEntitySet()).andStubReturn(
+        edmEntitySet);
+    EdmEntitySet startEdmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType startEdmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(startEdmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(startEdmEntityType.getName()).andStubReturn("SOHeader");
+    EasyMock.expect(startEdmEntitySet.getEntityType()).andStubReturn(startEdmEntityType);
+    EasyMock.expect(getEntitySetView.getStartEntitySet()).andStubReturn(
+        startEdmEntitySet);
+    EasyMock.replay(startEdmEntityType, startEdmEntitySet);
+    EasyMock.expect(getEntitySetView.getOrderBy()).andStubReturn(
+        orderByExpression);
+    EasyMock.expect(getEntitySetView.getSelect()).andStubReturn(null);
+    EasyMock.expect(getEntitySetView.getFilter()).andStubReturn(null);
+    List<NavigationSegment> navigationSegments = new ArrayList<NavigationSegment>();
+    EasyMock.expect(getEntitySetView.getNavigationSegments())
+        .andStubReturn(navigationSegments);
+    KeyPredicate keyPredicate = EasyMock
+        .createMock(KeyPredicate.class);
+    EdmProperty kpProperty = EasyMock
+        .createMock(EdmProperty.class);
+    EdmSimpleType edmType = EasyMock
+        .createMock(EdmSimpleType.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("Field1");
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    try {
+      EasyMock.expect(kpProperty.getName()).andStubReturn("Field1");
+      EasyMock.expect(kpProperty.getType()).andStubReturn(edmType);
+
+      EasyMock.expect(kpProperty.getMapping()).andStubReturn(edmMapping);
+
+    } catch (EdmException e2) {
+      fail("this should not happen");
+    }
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(kpProperty);
+    EasyMock.replay(edmMapping, edmType, kpProperty, keyPredicate);
+    List<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    keyPredicates.add(keyPredicate);
+    EasyMock.expect(getEntitySetView.getKeyPredicates()).andStubReturn(keyPredicates);
+    EasyMock.replay(getEntitySetView);
+    EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(
+        edmEntityType);
+    EasyMock.replay(edmEntitySet);
+    return getEntitySetView;
+  }
+
+  private GetEntityUriInfo getEntityUriInfo() throws EdmException {
+    GetEntityUriInfo getEntityView = EasyMock
+        .createMock(GetEntityUriInfo.class);
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(edmEntityType.getKeyProperties()).andStubReturn(
+        new ArrayList<EdmProperty>());
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("");
+    EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(
+        edmEntityType);
+    EasyMock.expect(getEntityView.getSelect()).andStubReturn(null);
+    EasyMock.expect(getEntityView.getTargetEntitySet()).andStubReturn(
+        edmEntitySet);
+    EdmEntitySet startEdmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType startEdmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(startEdmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(startEdmEntityType.getName()).andStubReturn("SOHeader");
+    EasyMock.expect(startEdmEntitySet.getEntityType()).andStubReturn(startEdmEntityType);
+    EasyMock.expect(getEntityView.getStartEntitySet()).andStubReturn(
+        startEdmEntitySet);
+    EasyMock.replay(startEdmEntityType, startEdmEntitySet);
+    EasyMock.replay(edmEntityType, edmEntitySet);
+    EasyMock.expect(getEntityView.getKeyPredicates()).andStubReturn(
+        new ArrayList<KeyPredicate>());
+    List<NavigationSegment> navigationSegments = new ArrayList<NavigationSegment>();
+    EasyMock.expect(getEntityView.getNavigationSegments()).andStubReturn(
+        navigationSegments);
+    EasyMock.replay(getEntityView);
+    return getEntityView;
+  }
+
+  @Test
+  public void testJPAAccessFactory() {
+    ODataJPAFactoryImpl oDataJPAFactoryImpl = new ODataJPAFactoryImpl();
+    JPAAccessFactory jpaAccessFactory = oDataJPAFactoryImpl
+        .getJPAAccessFactory();
+    ODataJPAContextImpl oDataJPAContextImpl = new ODataJPAContextImpl();
+    Class<?> clazz = oDataJPAContextImpl.getClass();
+    try {
+      Field field = clazz.getDeclaredField("em");
+      field.setAccessible(true);
+      field.set(oDataJPAContextImpl, new JPAProcessorImplTest().getLocalEntityManager());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EntityManagerFactory emf = new EntityManagerFactory() {
+
+      @Override
+      public boolean isOpen() {
+        return false;
+      }
+
+      @Override
+      public Map<String, Object> getProperties() {
+        return null;
+      }
+
+      @Override
+      public PersistenceUnitUtil getPersistenceUnitUtil() {
+        return null;
+      }
+
+      @Override
+      public Metamodel getMetamodel() {
+        return null;
+      }
+
+      @Override
+      public CriteriaBuilder getCriteriaBuilder() {
+        return null;
+      }
+
+      @Override
+      public Cache getCache() {
+        return null;
+      }
+
+      @SuppressWarnings("rawtypes")
+      @Override
+      public EntityManager createEntityManager(final Map arg0) {
+        return null;
+      }
+
+      @Override
+      public EntityManager createEntityManager() {
+        return null;
+      }
+
+      @Override
+      public void close() {}
+    };
+    oDataJPAContextImpl.setEntityManagerFactory(emf);
+    oDataJPAContextImpl.setPersistenceUnitName("pUnit");
+
+    assertNotNull(jpaAccessFactory.getJPAProcessor(oDataJPAContextImpl));
+    assertNotNull(jpaAccessFactory.getJPAEdmModelView(oDataJPAContextImpl));
+
+  }
+
+  @Test
+  public void testOdataJpaAccessFactory() {
+
+    ODataJPAFactoryImpl oDataJPAFactoryImpl = new ODataJPAFactoryImpl();
+    ODataJPAAccessFactory jpaAccessFactory = oDataJPAFactoryImpl
+        .getODataJPAAccessFactory();
+    ODataJPAContextImpl oDataJPAContextImpl = new ODataJPAContextImpl();
+
+    EntityManagerFactory emf = new EntityManagerFactory() {
+
+      @Override
+      public boolean isOpen() {
+        // TODO Auto-generated method stub
+        return false;
+      }
+
+      @Override
+      public Map<String, Object> getProperties() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @Override
+      public PersistenceUnitUtil getPersistenceUnitUtil() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @Override
+      public Metamodel getMetamodel() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @Override
+      public CriteriaBuilder getCriteriaBuilder() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @Override
+      public Cache getCache() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @SuppressWarnings("rawtypes")
+      @Override
+      public EntityManager createEntityManager(final Map arg0) {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @Override
+      public EntityManager createEntityManager() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+
+      @Override
+      public void close() {
+        // TODO Auto-generated method stub
+
+      }
+    };
+    oDataJPAContextImpl.setEntityManagerFactory(emf);
+    oDataJPAContextImpl.setPersistenceUnitName("pUnit");
+
+    assertNotNull(jpaAccessFactory.getODataJPAMessageService(new Locale(
+        "en")));
+    assertNotNull(jpaAccessFactory.createODataJPAContext());
+    assertNotNull(jpaAccessFactory
+        .createJPAEdmProvider(oDataJPAContextImpl));
+    assertNotNull(jpaAccessFactory
+        .createODataProcessor(oDataJPAContextImpl));
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinContextTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinContextTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinContextTest.java
new file mode 100644
index 0000000..6ad377d
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/jpql/JPQLJoinContextTest.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.jpql;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.jpql.JPQLJoinSelectContext.JPQLJoinContextBuilder;
+
+public class JPQLJoinContextTest {
+
+  GetEntitySetUriInfo entitySetUriInfo;
+
+  @BeforeClass
+  public static void setUpBeforeClass() throws Exception {}
+
+  @AfterClass
+  public static void tearDownAfterClass() throws Exception {}
+
+  @Before
+  public void setUp() throws Exception {
+    entitySetUriInfo = EasyMock.createMock(GetEntitySetUriInfo.class);
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    List<NavigationSegment> navigationSegments = new ArrayList<NavigationSegment>();
+    final EdmNavigationProperty navigationProperty = createNavigationProperty("a");
+    final EdmNavigationProperty navigationProperty1 = createNavigationProperty("b");
+    final List<KeyPredicate> keyPredicates = createKeyPredicates();
+    NavigationSegment navigationSegment = new NavigationSegment() {
+
+      @Override
+      public EdmNavigationProperty getNavigationProperty() {
+        return navigationProperty;
+      }
+
+      @Override
+      public List<KeyPredicate> getKeyPredicates() {
+        return keyPredicates;
+      }
+
+      @Override
+      public EdmEntitySet getEntitySet() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+    NavigationSegment navigationSegment1 = new NavigationSegment() {
+
+      @Override
+      public EdmNavigationProperty getNavigationProperty() {
+        return navigationProperty1;
+      }
+
+      @Override
+      public List<KeyPredicate> getKeyPredicates() {
+        return keyPredicates;
+      }
+
+      @Override
+      public EdmEntitySet getEntitySet() {
+        // TODO Auto-generated method stub
+        return null;
+      }
+    };
+    navigationSegments.add(navigationSegment);
+    navigationSegments.add(navigationSegment1);
+    EasyMock.expect(entitySetUriInfo.getNavigationSegments()).andStubReturn(navigationSegments);
+    EasyMock.expect(entitySetUriInfo.getOrderBy()).andStubReturn(null);
+    EasyMock.expect(entitySetUriInfo.getTop()).andStubReturn(null);
+    EasyMock.expect(entitySetUriInfo.getSkip()).andStubReturn(null);
+    EasyMock.expect(entitySetUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(entitySetUriInfo.getFilter()).andStubReturn(null);
+    EasyMock.expect(entitySetUriInfo.getKeyPredicates()).andStubReturn(keyPredicates);
+    EasyMock.expect(entitySetUriInfo
+        .getTargetEntitySet()).andStubReturn(edmEntitySet);
+    EdmEntitySet startEdmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    EdmEntityType startEdmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EasyMock.expect(startEdmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(startEdmEntityType.getName()).andStubReturn("SOHeader");
+    EasyMock.expect(startEdmEntitySet.getEntityType()).andStubReturn(startEdmEntityType);
+    EasyMock.expect(entitySetUriInfo.getStartEntitySet()).andStubReturn(
+        startEdmEntitySet);
+    EasyMock.replay(startEdmEntityType, startEdmEntitySet);
+    EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(edmEntityType);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(null);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("SOHeader");
+    EasyMock.replay(edmEntityType, edmEntitySet, entitySetUriInfo);
+
+  }
+
+  @After
+  public void tearDown() throws Exception {}
+
+  @Test
+  public void testGetJPAOuterJoinClauses() {
+    JPQLJoinSelectContext joinContext = new JPQLJoinSelectContext(false);
+    JPQLJoinContextBuilder joinContextBuilder = joinContext.new JPQLJoinContextBuilder();
+    try {
+      joinContextBuilder.entitySetView = entitySetUriInfo;
+      joinContextBuilder.build();
+    } catch (ODataJPAModelException e) {
+      fail("Should not come here");
+    } catch (ODataJPARuntimeException e) {
+      fail("Should not come here");
+    }
+    List<JPAJoinClause> joinClauses = joinContext.getJPAJoinClauses();
+    assertNotNull(joinClauses);
+    assertTrue(joinClauses.size() > 0);
+    assertEquals("E1", joinClauses.get(0).getEntityAlias());
+    assertEquals("SOHeader", joinClauses.get(0).getEntityName());
+    assertEquals("s_Itema", joinClauses.get(1).getEntityRelationShip());
+    assertEquals("R1", joinClauses.get(1).getEntityRelationShipAlias());
+  }
+
+  private EdmNavigationProperty createNavigationProperty(final String z) throws EdmException {
+    EdmNavigationProperty navigationProperty = EasyMock.createMock(EdmNavigationProperty.class);
+    EdmAssociation association = EasyMock.createMock(EdmAssociation.class);
+    EdmAssociationEnd associationEnd = EasyMock.createMock(EdmAssociationEnd.class);
+    EasyMock.expect(navigationProperty.getFromRole()).andStubReturn("roleA" + z);
+    EasyMock.expect(navigationProperty.getToRole()).andStubReturn("roleB" + z);
+    EasyMock.expect(navigationProperty.getName()).andStubReturn("navP" + z);
+    EasyMock.expect(navigationProperty.getName()).andStubReturn("navP" + z);
+    EasyMock.expect(navigationProperty.getMultiplicity()).andStubReturn(EdmMultiplicity.ONE);
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("sItem" + z);
+    EasyMock.expect(edmEntityType.getMapping()).andStubReturn(edmMapping);
+    EasyMock.expect(edmEntityType.getName()).andStubReturn("soItem" + z);
+    EasyMock.expect(associationEnd.getEntityType()).andStubReturn(edmEntityType);
+    EasyMock.expect(association.getEnd("roleA" + z)).andStubReturn(associationEnd);
+    EasyMock.expect(navigationProperty.getRelationship()).andStubReturn(association);
+    EdmMapping edmMapping1 = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping1.getInternalName()).andStubReturn("s_Item" + z);
+    EasyMock.expect(navigationProperty.getMapping()).andStubReturn(edmMapping1);
+    EasyMock.replay(edmMapping, edmMapping1, edmEntityType, associationEnd, association, navigationProperty);
+    return navigationProperty;
+  }
+
+  private List<KeyPredicate> createKeyPredicates() throws EdmException {
+    KeyPredicate keyPredicate = EasyMock.createMock(KeyPredicate.class);
+    EasyMock.expect(keyPredicate.getLiteral()).andStubReturn("1");
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("soid");
+    EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+    EasyMock.expect(edmProperty.getName()).andStubReturn("soid");
+    EdmSimpleType edmType = EasyMock.createMock(EdmSimpleType.class);
+    EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+    EasyMock.expect(keyPredicate.getProperty()).andStubReturn(edmProperty);
+
+    EasyMock.replay(edmType, edmMapping, edmProperty, keyPredicate);
+    List<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    keyPredicates.add(keyPredicate);
+    return keyPredicates;
+  }
+
+}


[34/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/InlineCount.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/InlineCount.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/InlineCount.java
new file mode 100644
index 0000000..92d858e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/InlineCount.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.api.commons;
+
+/**
+ * Inlinecount constants as described in the OData protocol
+ * @author SAP AG
+ */
+public enum InlineCount {
+  ALLPAGES, NONE;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpHeaders.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpHeaders.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpHeaders.java
new file mode 100644
index 0000000..65ea4e2
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpHeaders.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.api.commons;
+
+/**
+ * HTTP header constants as used in the OData protocol
+ * @author SAP AG
+ */
+public class ODataHttpHeaders {
+
+  public static final String DATASERVICEVERSION = "DataServiceVersion";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpMethod.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpMethod.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpMethod.java
new file mode 100644
index 0000000..cc283b9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/ODataHttpMethod.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.api.commons;
+
+/**
+ * The supported HTTP methods.
+ * @author SAP AG
+ */
+public enum ODataHttpMethod {
+  GET, PUT, POST, DELETE, PATCH, MERGE;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/package-info.java
new file mode 100644
index 0000000..c51b5b4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/package-info.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * The commons package contains constants used in the HTTP and OData protocol.
+ */
+package org.apache.olingo.odata2.api.commons;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/Edm.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/Edm.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/Edm.java
new file mode 100644
index 0000000..65e1e68
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/Edm.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * Entity Data Model (EDM)
+ * <p>Interface representing a Entity Data Model as described in the Conceptual Schema Definition.
+ * @author SAP AG
+ */
+public interface Edm {
+
+  public static final String NAMESPACE_EDM_2008_09 = "http://schemas.microsoft.com/ado/2008/09/edm";
+  public static final String NAMESPACE_APP_2007 = "http://www.w3.org/2007/app";
+  public static final String NAMESPACE_ATOM_2005 = "http://www.w3.org/2005/Atom";
+  public static final String NAMESPACE_D_2007_08 = "http://schemas.microsoft.com/ado/2007/08/dataservices";
+  public static final String NAMESPACE_M_2007_08 = "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata";
+  public static final String NAMESPACE_EDMX_2007_06 = "http://schemas.microsoft.com/ado/2007/06/edmx";
+  public static final String NAMESPACE_REL_2007_08 = "http://schemas.microsoft.com/ado/2007/08/dataservices/related/";
+  public static final String NAMESPACE_REL_ASSOC_2007_08 = "http://schemas.microsoft.com/ado/2007/08/dataservices/relatedlinks/";
+  public static final String NAMESPACE_SCHEME_2007_08 = "http://schemas.microsoft.com/ado/2007/08/dataservices/scheme";
+  public static final String NAMESPACE_XML_1998 = "http://www.w3.org/XML/1998/namespace";
+  public static final String PREFIX_EDM = "edm";
+  public static final String PREFIX_APP = "app";
+  public static final String PREFIX_ATOM = "atom";
+  public static final String PREFIX_D = "d";
+  public static final String PREFIX_M = "m";
+  public static final String PREFIX_XML = "xml";
+  public static final String PREFIX_EDMX = "edmx";
+  public static final String LINK_REL_SELF = "self";
+  public static final String LINK_REL_EDIT_MEDIA = "edit-media";
+  public static final String LINK_REL_EDIT = "edit";
+  public static final String LINK_REL_NEXT = "next";
+  public static final String DELIMITER = ".";
+
+  /**
+   * Get entity container by name
+   * <p>See {@link EdmEntityContainer} for more information.
+   * @param name
+   * @return {@link EdmEntityContainer}
+   * @throws EdmException
+   */
+  EdmEntityContainer getEntityContainer(String name) throws EdmException;
+
+  /**
+   * Get entity type by full qualified name
+   * <p>See {@link EdmEntityType} for more information.
+   * @param namespace
+   * @param name
+   * @return {@link EdmEntityType}
+   * @throws EdmException
+   */
+  EdmEntityType getEntityType(String namespace, String name) throws EdmException;
+
+  /**
+   * Get complex type by full qualified name
+   * <p>See {@link EdmComplexType} for more information.
+   * @param namespace
+   * @param name
+   * @return {@link EdmComplexType}
+   * @throws EdmException
+   */
+  EdmComplexType getComplexType(String namespace, String name) throws EdmException;
+
+  /**
+   * Get association by full qualified name
+   * <p>See {@link EdmAssociation} for more information.
+   * @param namespace
+   * @param name
+   * @return {@link EdmAssociation}
+   * @throws EdmException
+   */
+  EdmAssociation getAssociation(String namespace, String name) throws EdmException;
+
+  /**
+   * Get service metadata
+   * <p>See {@link EdmServiceMetadata} for more information.
+   * @return {@link EdmServiceMetadata}
+   */
+  EdmServiceMetadata getServiceMetadata();
+
+  /**
+   * Get default entity container
+   * <p>See {@link EdmEntityContainer} for more information.
+   * @return {@link EdmEntityContainer}
+   * @throws EdmException
+   */
+  EdmEntityContainer getDefaultEntityContainer() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAction.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAction.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAction.java
new file mode 100644
index 0000000..6bbefda
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAction.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL Action Element
+ * <p>EdmAction can either be Cascade or None. Cascade implies that a delete operation on an entity also should delete the relationship instances.
+ * @author SAP AG
+ */
+public enum EdmAction {
+
+  Cascade, None;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotatable.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotatable.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotatable.java
new file mode 100644
index 0000000..f51289f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotatable.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmAnnotatable can be applied to CSDL elements as described in the Conceptual Schema Definition Language.
+ * @author SAP AG
+ */
+public interface EdmAnnotatable {
+
+  /**
+   * Get all annotations applied to an EDM element
+   * 
+   * @return {@link EdmAnnotations}
+   * @throws EdmException
+   */
+  EdmAnnotations getAnnotations() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationAttribute.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationAttribute.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationAttribute.java
new file mode 100644
index 0000000..8e62e2f
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationAttribute.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL AnnotationAttribute element. 
+ * <p>EdmAnnotationAttribute is a custom XML attribute which can be applied to a CSDL element.
+ * @author SAP AG
+ */
+public interface EdmAnnotationAttribute {
+
+  /**
+   * Get the namespace of the custom attribute
+   * 
+   * @return String
+   */
+  String getNamespace();
+
+  /**
+   * Get the prefix of the custom attribute
+   * 
+   * @return String
+   */
+  String getPrefix();
+
+  /**
+   * Get the name of the custom attribute
+   * 
+   * @return String
+   */
+  String getName();
+
+  /**
+   * Get the text of the custom attribute
+   * 
+   * @return String
+   */
+  String getText();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationElement.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationElement.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationElement.java
new file mode 100644
index 0000000..4cb68c0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotationElement.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL AnnotationElement element
+ * <p>EdmAnnotationElement is a custom XML element which can be applied to a CSDL element. 
+ * @author SAP AG
+ */
+public interface EdmAnnotationElement {
+
+  /**
+   * Get the namespace of the custom element
+   * 
+   * @return String
+   */
+  String getNamespace();
+
+  /**
+   * Get the prefix of the custom element
+   * 
+   * @return String
+   */
+  String getPrefix();
+
+  /**
+   * Get the name of the custom element
+   * 
+   * @return String
+   */
+  String getName();
+
+  /**
+   * Get the XML data of the custom element
+   * 
+   * @return String
+   */
+  String getText();
+
+  /**
+   * Get the child elements of the custom element
+   * 
+   * @return child elements of this {@link EdmAnnotationElement}
+   */
+  List<AnnotationElement> getChildElements();
+
+  /**
+   * Get the attributes of this custom element
+   * 
+   * @return the attributes of this {@link EdmAnnotationElement}
+   */
+  List<AnnotationAttribute> getAttributes();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotations.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotations.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotations.java
new file mode 100644
index 0000000..a2c3807
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAnnotations.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.util.List;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmAnnotations holds all annotation attributes and elements for a specific CSDL element.
+ * @author SAP AG
+ */
+public interface EdmAnnotations {
+
+  /**
+   * Get all annotation elements for the CSDL element
+   * 
+   * @return List of {@link EdmAnnotationElement}
+   */
+  List<? extends EdmAnnotationElement> getAnnotationElements();
+
+  /**
+   * Get annotation element by full qualified name
+   * 
+   * @param name
+   * @param namespace
+   * @return String
+   */
+
+  EdmAnnotationElement getAnnotationElement(String name, String namespace);
+
+  /**
+   * Get all annotation attributes for the CSDL element
+   * 
+   * @return List of {@link EdmAnnotationAttribute}
+   */
+  List<? extends EdmAnnotationAttribute> getAnnotationAttributes();
+
+  /**
+   * Get annotation attribute by full qualified name
+   * 
+   * @param name
+   * @param namespace
+   * @return String
+   */
+  EdmAnnotationAttribute getAnnotationAttribute(String name, String namespace);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociation.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociation.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociation.java
new file mode 100644
index 0000000..628feb6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociation.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL Association element
+ * 
+ * <p>EdmAssociation defines the relationship of two entity types. 
+ * @author SAP AG
+ */
+public interface EdmAssociation extends EdmType {
+
+  /**
+   * Get the {@link EdmAssociationEnd} by role
+   * @param role
+   * @return {@link EdmAssociationEnd}
+   * @throws EdmException
+   */
+  EdmAssociationEnd getEnd(String role) throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationEnd.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationEnd.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationEnd.java
new file mode 100644
index 0000000..f5b4a78
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationEnd.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL AssociationEnd element
+ * 
+ * <p>EdmAssociationEnd defines one side of the relationship of two entity types.
+ * @author SAP AG
+ */
+public interface EdmAssociationEnd {
+
+  /**
+   * @return the role of this {@link EdmAssociationEnd} as a String.
+   */
+  String getRole();
+
+  /**
+   * @return {@link EdmEntityType} this association end points to.
+   * @throws EdmException
+   */
+  EdmEntityType getEntityType() throws EdmException;
+
+  /**
+   * See {@link EdmMultiplicity} for more information about possible multiplicities.
+   * @return {@link EdmMultiplicity}
+   */
+  EdmMultiplicity getMultiplicity();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSet.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSet.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSet.java
new file mode 100644
index 0000000..81e739c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSet.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL AssociationSet element
+ * 
+ * <p>EdmAssociationSet defines the relationship of two entity sets.
+ * @author SAP AG
+ */
+public interface EdmAssociationSet extends EdmNamed {
+
+  /**
+   * Get the association
+   * 
+   * @return {@link EdmAssociation}
+   * @throws EdmException
+   */
+  EdmAssociation getAssociation() throws EdmException;
+
+  /**
+   * Get the association set end
+   * 
+   * @param role
+   * @return {@link EdmAssociationSetEnd}
+   * @throws EdmException
+   */
+  EdmAssociationSetEnd getEnd(String role) throws EdmException;
+
+  /**
+   * Get the entity container the association set is located in
+   * 
+   * @return {@link EdmEntityContainer}
+   * @throws EdmException
+   */
+  EdmEntityContainer getEntityContainer() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSetEnd.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSetEnd.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSetEnd.java
new file mode 100644
index 0000000..40d88cb
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmAssociationSetEnd.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL AssociationSetEnd element
+ * 
+ * <p>EdmAssociationSetEnd defines one side of the relationship of two entity sets.
+ * @author SAP AG
+ */
+public interface EdmAssociationSetEnd {
+
+  /**
+   * Get the role name
+   * 
+   * @return String
+   */
+  String getRole();
+
+  /**
+   * Get the entity set
+   * 
+   * @return {@link EdmEntitySet}
+   * @throws EdmException
+   */
+  EdmEntitySet getEntitySet() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmComplexType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmComplexType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmComplexType.java
new file mode 100644
index 0000000..d51771b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmComplexType.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * <p>A CSDL ComplexType element.</p>
+ * <p>EdmComplexType holds a set of related information like {@link EdmSimpleType}
+ * properties and EdmComplexType properties.
+ * @author SAP AG
+ * @org.apache.olingo.odata2.DoNotImplement
+ */
+public interface EdmComplexType extends EdmStructuralType {
+
+  @Override
+  EdmComplexType getBaseType() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmConcurrencyMode.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmConcurrencyMode.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmConcurrencyMode.java
new file mode 100644
index 0000000..779ab26
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmConcurrencyMode.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmConcurrencyMode can be applied to any primitive Entity Data Model (EDM) type.
+ * <p>Possible values are "None", which is the default, and "Fixed". Fixed implies that the property should be used for optimistic concurrency checks.
+ * @author SAP AG
+ */
+public enum EdmConcurrencyMode {
+
+  None, Fixed;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmContentKind.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmContentKind.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmContentKind.java
new file mode 100644
index 0000000..b62b6b7
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmContentKind.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmContentType is used for Feed Customization.
+ * <p>It specifies the content type of the value of the property being mapped via a customizable feed mapping.
+ * This value can be "text", "html" or "xhtml". 
+ * @author SAP AG
+ */
+public enum EdmContentKind {
+
+  text, html, xhtml;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmCustomizableFeedMappings.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmCustomizableFeedMappings.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmCustomizableFeedMappings.java
new file mode 100644
index 0000000..62133ef
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmCustomizableFeedMappings.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * Customizable Feed property mappings for the AtomPub Format as defined in the OData specification.
+ * @author SAP AG
+ */
+public interface EdmCustomizableFeedMappings {
+
+  /**
+   * Get the information if the property should be kept in the content
+   * 
+   * @return <code>true</code> if the property must be kept in the content
+   */
+  public Boolean isFcKeepInContent();
+
+  /**
+   * Get the content kind
+   * 
+   * @return {@link EdmContentKind}
+   */
+  public EdmContentKind getFcContentKind();
+
+  /**
+   * Get the XML namespace prefix
+   * 
+   * @return String
+   */
+  public String getFcNsPrefix();
+
+  /**
+   * Get the XML namespace URI
+   * 
+   * @return String
+   */
+  public String getFcNsUri();
+
+  /**
+   * Get the source path
+   * 
+   * @return String
+   */
+  public String getFcSourcePath();
+
+  /**
+   * Get the target path
+   * 
+   * @return String
+   */
+  public String getFcTargetPath();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmElement.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmElement.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmElement.java
new file mode 100644
index 0000000..f6a7c37
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmElement.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmElement is the base interface for {@link EdmParameter} and {@link EdmProperty} and provides
+ * the information by which facets further specialize the usage of the type.
+ * @author SAP AG
+ */
+public interface EdmElement extends EdmMappable, EdmTyped {
+
+  /**
+   * Get the facet information for an element
+   * 
+   * @return {@link EdmFacets}
+   * @throws EdmException
+   */
+  EdmFacets getFacets() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityContainer.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityContainer.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityContainer.java
new file mode 100644
index 0000000..f2a9a63
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityContainer.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL EntityContainer element
+ * 
+ * <p>EdmEntityContainer hold the information of EntitySets, FunctionImports and AssociationSets contained
+ * @author SAP AG
+ */
+public interface EdmEntityContainer extends EdmNamed {
+
+  /**
+   * @return <b>boolean</b> true if this is the default container
+   */
+  boolean isDefaultEntityContainer();
+
+  /**
+   * Get contained EntitySet by name
+   * 
+   * @param name
+   * @return {@link EdmEntitySet}
+   * @throws EdmException
+   */
+  EdmEntitySet getEntitySet(String name) throws EdmException;
+
+  /**
+   * Get contained FunctionImport by name
+   * 
+   * @param name
+   * @return {@link EdmFunctionImport}
+   * @throws EdmException
+   */
+  EdmFunctionImport getFunctionImport(String name) throws EdmException;
+
+  /**
+   * Get contained AssociationSet by providing the source entity set and the navigation property
+   * 
+   * @param sourceEntitySet of type {@link EdmEntitySet}
+   * @param navigationProperty of type {@link EdmNavigationProperty}
+   * @return {@link EdmAssociationSet}
+   * @throws EdmException
+   */
+  EdmAssociationSet getAssociationSet(EdmEntitySet sourceEntitySet, EdmNavigationProperty navigationProperty) throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySet.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySet.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySet.java
new file mode 100644
index 0000000..6cfdc07
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySet.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL EntitySet element
+ * <p>EdmEntitySet is the container for entity type instances as described in the OData protocol. 
+ * @author SAP AG
+ */
+public interface EdmEntitySet extends EdmMappable, EdmNamed {
+
+  /**
+   * Get the entity type
+   * 
+   * @return {@link EdmEntityType}
+   * @throws EdmException
+   */
+  EdmEntityType getEntityType() throws EdmException;
+
+  /**
+   * Get the related entity set by providing the navigation property
+   * 
+   * @param navigationProperty of type {@link EdmNavigationProperty}
+   * @return {@link EdmEntitySet}
+   * @throws EdmException
+   */
+  EdmEntitySet getRelatedEntitySet(EdmNavigationProperty navigationProperty) throws EdmException;
+
+  /**
+   * Get the entity container the entity set is contained in
+   * 
+   * @return {@link EdmEntityContainer}
+   * @throws EdmException
+   */
+  EdmEntityContainer getEntityContainer() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySetInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySetInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySetInfo.java
new file mode 100644
index 0000000..8994357
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntitySetInfo.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.net.URI;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * Objects of this class contain information about one entity set inside the EntityDataModel.
+ * @author SAP AG
+ *
+ */
+public interface EdmEntitySetInfo {
+
+  /**
+   * @return the entity container name which contains this entity set.
+   */
+  public String getEntityContainerName();
+
+  /**
+   * @return the entity set name
+   */
+  public String getEntitySetName();
+
+  /**
+   * @return true if this entity set is contained inside the default container
+   */
+  public boolean isDefaultEntityContainer();
+
+  /**
+   * We use a {@link URI} object here to ensure the right encoding. If a string representation is needed the toASCIIString() method can be used.
+   * @return the uri to this entity set e.g. "Employees"
+   */
+  public URI getEntitySetUri();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityType.java
new file mode 100644
index 0000000..d0a0c92
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmEntityType.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.util.List;
+
+/**
+ * <p>A CSDL EntityType element.</p>
+ * <p>EdmEntityType holds a set of related information like {@link EdmSimpleType}
+ * properties and {@link EdmComplexType} properties and in addition to a
+ * {@link EdmComplexType complex type} it provides information about key properties,
+ * customizable feed mappings and {@link EdmNavigationProperty navigation properties}. 
+ * @author SAP AG
+ * @org.apache.olingo.odata2.DoNotImplement
+ */
+public interface EdmEntityType extends EdmStructuralType {
+
+  /**
+   * Gets all key property names.
+   * @return collection of key property names of type List<String>
+   * @throws EdmException
+   */
+  List<String> getKeyPropertyNames() throws EdmException;
+
+  /**
+   * Get all key properties as list of {@link EdmProperty}.
+   * @return collection of key properties of type List<EdmProperty>
+   * @throws EdmException
+   */
+  List<EdmProperty> getKeyProperties() throws EdmException;
+
+  /**
+   * Indicates if the entity type is treated as Media Link Entry
+   * with associated Media Resource.
+   * @return <code>true</code> if the entity type is a Media Link Entry  
+   * @throws EdmException
+   */
+  boolean hasStream() throws EdmException;
+
+  @Override
+  EdmEntityType getBaseType() throws EdmException;
+
+  /**
+   * Gets the Customizable Feed Mappings of the entity type.
+   * @return {@link EdmCustomizableFeedMappings}
+   * @throws EdmException
+   */
+  EdmCustomizableFeedMappings getCustomizableFeedMappings() throws EdmException;
+
+  /**
+   * Gets all navigation property names.
+   * @return collection of navigation properties of type List<String>
+   * @throws EdmException
+   */
+  List<String> getNavigationPropertyNames() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
new file mode 100644
index 0000000..62dceb9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmException.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * An exception for problems regarding the Entity Data Model.
+ * @author SAP AG
+ */
+public class EdmException extends ODataMessageException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(EdmException.class, "COMMON");
+  public static final MessageReference PROVIDERPROBLEM = createMessageReference(EdmException.class, "PROVIDERPROBLEM");
+
+  public EdmException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public EdmException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public EdmException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, errorCode);
+  }
+
+  public EdmException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFacets.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFacets.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFacets.java
new file mode 100644
index 0000000..3421f0c
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFacets.java
@@ -0,0 +1,91 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * <p>A Facet is an element defined in CSDL that provides information
+ * that specializes the usage of a type.</p>
+ * @author SAP AG
+ */
+public interface EdmFacets {
+
+  /**
+   * Get the information if the type in use is nullable
+   * 
+   * @return <code>true</code> if the type in use is nullable
+   */
+  Boolean isNullable();
+
+  /**
+   * Get the default value of the type in use
+   * 
+   * @return a default value of the type in use as String
+   */
+  String getDefaultValue();
+
+  /**
+   * Get the maximum length of the type in use
+   *
+   * @return the maximum length of the type in use as Integer
+   */
+  Integer getMaxLength();
+
+  /**
+   * Get the information if the type in has a fixed length
+   * 
+   * @return <code>true</code> if the type in use has a fixed length
+   */
+  Boolean isFixedLength();
+
+  /**
+   * Get the precision of the type in use
+   * 
+   * @return the precision of the type in use as Integer
+   */
+  Integer getPrecision();
+
+  /**
+   * Get the scale of the type in use
+   * 
+   * @return the scale of the type in use as Integer
+   */
+  Integer getScale();
+
+  /**
+   * Get the information if UNICODE or ASCII characters are used. Default is UNICODE.
+   * 
+   * @return <code>true</code> if UNICODE characters are used
+   */
+  Boolean isUnicode();
+
+  /**
+   * Get the sorting sequence to be used.
+   * 
+   * @return the sorting sequence as String
+   */
+  String getCollation();
+
+  /**
+   * Get the information if the value of the type in use should be used for optimistic concurrency checks.
+   * 
+   * @return {@link EdmConcurrencyMode}
+   */
+  EdmConcurrencyMode getConcurrencyMode();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFunctionImport.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFunctionImport.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFunctionImport.java
new file mode 100644
index 0000000..e016822
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmFunctionImport.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import java.util.Collection;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL FunctionImport element
+ * 
+ * EdmFunctionImport can be used model functions which have input parameters, an associated HTTP Method
+ * and a return type which can be of different kinds:
+ * 
+ * <li>{@link EdmSimpleType} or a collection of simple types
+ * <li>{@link EdmEntityType} or a collection of entity types
+ * <li>{@link EdmEntitySet}
+ * @author SAP AG
+ */
+public interface EdmFunctionImport extends EdmMappable, EdmNamed {
+
+  /**
+   * Get the parameter by name
+   * @param name
+   * @return {@link EdmParameter}
+   * @throws EdmException
+   */
+  EdmParameter getParameter(String name) throws EdmException;
+
+  /**
+   * Get all parameter names
+   * @return collection of parameter names of type Collection<String>
+   * @throws EdmException
+   */
+  Collection<String> getParameterNames() throws EdmException;
+
+  /**
+   * Get the edm entity set
+   * @return {@link EdmEntitySet}
+   * @throws EdmException
+   */
+  EdmEntitySet getEntitySet() throws EdmException;
+
+  /**
+   * Get the HTTP Method
+   * @return HTTP Method as String
+   * @throws EdmException
+   */
+  String getHttpMethod() throws EdmException;
+
+  /**
+   * @return {@link EdmTyped}
+   * @throws EdmException
+   */
+  EdmTyped getReturnType() throws EdmException;
+
+  /**
+   * Get the entity container the function import is contained in
+   * @return {@link EdmEntityContainer}
+   * @throws EdmException
+   */
+  EdmEntityContainer getEntityContainer() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteral.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteral.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteral.java
new file mode 100644
index 0000000..e7b47d2
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteral.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * <p>Representation of a simple-typed literal</p>
+ * <p>The literal is in default representation. The URI representation differs
+ * from the default representation mainly in the additional presence of type
+ * indicators (prefixes or suffixes, respectively); since the type information
+ * is stored here separately, the default representation is more appropriate.
+ * Should the URI representation be needed, it can be re-created by calling
+ * {@link EdmSimpleType#toUriLiteral}.</p>
+ * @author SAP AG
+ * @see EdmLiteralKind
+ */
+public final class EdmLiteral {
+  private final EdmSimpleType type;
+  private final String literal;
+
+  /**
+   * Creates an {@link EdmLiteral} object out of the simple type and the literal string.
+   * @param type {@link EdmSimpleType} simple type
+   * @param literal String literal in default (<em>not</em> URI) representation
+   */
+  public EdmLiteral(final EdmSimpleType type, final String literal) {
+    this.type = type;
+    this.literal = literal;
+  }
+
+  /**
+   * Gets the simple type of the literal.
+   * @return {@link EdmSimpleType} object
+   */
+  public EdmSimpleType getType() {
+    return type;
+  }
+
+  /**
+   * Gets the literal String.
+   * @return {@link String} literal in default (<em>not</em> URI) representation
+   */
+  public String getLiteral() {
+    return literal;
+  }
+
+  @Override
+  public String toString() {
+    return "type=" + type + ", literal=" + literal;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralException.java
new file mode 100644
index 0000000..02c4a4e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralException.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * Exception for violation of the OData URI construction rules, resulting in a 400 Bad Request response
+ * @author SAP AG
+ */
+public class EdmLiteralException extends EdmException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference NOTEXT = createMessageReference(EdmLiteralException.class, "NOTEXT");
+  public static final MessageReference LITERALFORMAT = createMessageReference(EdmLiteralException.class, "LITERALFORMAT");
+  public static final MessageReference UNKNOWNLITERAL = createMessageReference(EdmLiteralException.class, "UNKNOWNLITERAL");
+
+  public EdmLiteralException(final MessageReference MessageReference) {
+    super(MessageReference);
+  }
+
+  public EdmLiteralException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public EdmLiteralException(final MessageReference MessageReference, final String errorCode) {
+    super(MessageReference, errorCode);
+  }
+
+  public EdmLiteralException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralKind.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralKind.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralKind.java
new file mode 100644
index 0000000..5002487
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmLiteralKind.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmLiteralKind indicates the format of an EDM literal.
+ * @author SAP AG
+ */
+public enum EdmLiteralKind {
+
+  DEFAULT, URI, JSON;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMappable.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMappable.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMappable.java
new file mode 100644
index 0000000..9755054
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMappable.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmMappable can be applied to CSDL elements to associate additional information.
+ * @author SAP AG
+ */
+public interface EdmMappable {
+
+  /**
+   * Get mapping information applied to an EDM element
+   * 
+   * @return {@link EdmMapping}
+   * @throws EdmException
+   */
+  EdmMapping getMapping() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMapping.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMapping.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMapping.java
new file mode 100644
index 0000000..b6eb600
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMapping.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmMapping holds custom mapping information which can be applied to a CSDL element.
+ * @author SAP AG
+ */
+public interface EdmMapping {
+
+  /**
+   * Get the mapping value
+   * 
+   * @return mapping name as String
+   */
+  String getInternalName();
+
+  /**
+   * Get the mapping name for mime type lookup
+   * 
+   * @return mapping name as String
+   */
+  String getMimeType();
+
+  /**
+   * Get the set object for this mapping
+   * 
+   * @return {@link Object} object
+   */
+  Object getObject();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMultiplicity.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMultiplicity.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMultiplicity.java
new file mode 100644
index 0000000..c8ed71a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmMultiplicity.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * <p>EdmMultiplicity indicates the number of entity type instances
+ * an association end can relate to:
+ * <dl>
+ * <dt>0..1</dt><dd>one or none</dd>
+ * <dt>   1</dt><dd>exactly one</dd>
+ * <dt>   *</dt><dd>many</dd>
+ * </dl></p> 
+ * @author SAP AG
+ */
+public enum EdmMultiplicity {
+
+  ZERO_TO_ONE("0..1"), MANY("*"), ONE("1");
+
+  private final String literal;
+
+  private EdmMultiplicity(final String literal) {
+    this.literal = literal;
+  }
+
+  /**
+   * Gets the multiplicity for a given name.
+   * @param literal
+   * @return {@link EdmMultiplicity}
+   */
+  public static EdmMultiplicity fromLiteral(final String literal) {
+    for (final EdmMultiplicity edmMultiplicity : EdmMultiplicity.values()) {
+      if (edmMultiplicity.toString().equals(literal)) {
+        return edmMultiplicity;
+      }
+    }
+    throw new IllegalArgumentException("Invalid literal " + literal);
+  }
+
+  /**
+   * Returns the OData literal form of this multiplicity.
+   * @return the OData literal form of this multiplicity
+   */
+  @Override
+  public String toString() {
+    return literal;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNamed.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNamed.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNamed.java
new file mode 100644
index 0000000..0b40b42
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNamed.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * EdmName is the base interface for nearly all CSDL constructs.
+ * @author SAP AG
+ */
+public interface EdmNamed {
+
+  /** 
+   * @return name as String
+   * @throws EdmException
+   */
+  String getName() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNavigationProperty.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNavigationProperty.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNavigationProperty.java
new file mode 100644
index 0000000..0d757ff
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmNavigationProperty.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL NavigationProperty element
+ * 
+ * <p>EdmNavigationProperty allows navigation from one entity type to another via a relationship.
+ * @author SAP AG
+ */
+public interface EdmNavigationProperty extends EdmTyped, EdmMappable {
+
+  /**
+   * Get the relationship of the navigation property
+   * 
+   * @return {@link EdmAssociation}
+   * @throws EdmException
+   */
+  EdmAssociation getRelationship() throws EdmException;
+
+  /**
+   * Get the from role of the navigation property
+   * 
+   * @return from role as String
+   * @throws EdmException
+   */
+  String getFromRole() throws EdmException;
+
+  /**
+   * Get the to role of the navigation property
+   * 
+   * @return to role as String
+   * @throws EdmException
+   */
+  String getToRole() throws EdmException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmParameter.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmParameter.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmParameter.java
new file mode 100644
index 0000000..ba5bca6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmParameter.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * @org.apache.olingo.odata2.DoNotImplement
+ * A CSDL FunctionImportParameter element
+ * <p>EdmParameter defines a function import parameter (which is used as input parameter). FunctionImports are described in {@link org.apache.olingo.odata2.api.edm.provider.FunctionImport} or in the OData protocol.
+ * @author SAP AG
+ */
+public interface EdmParameter extends EdmElement {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmProperty.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmProperty.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmProperty.java
new file mode 100644
index 0000000..1cef8a0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/edm/EdmProperty.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.api.edm;
+
+/**
+ * A CSDL Property element
+ * <p>EdmProperty defines a simple type or a complex type.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface EdmProperty extends EdmElement {
+
+  /**
+   * Get customizable feed mappings for this property
+   * 
+   * @return {@link EdmCustomizableFeedMappings}
+   * @throws EdmException
+   */
+  EdmCustomizableFeedMappings getCustomizableFeedMappings() throws EdmException;
+
+  /**
+   * Get the related mime type for the property
+   * 
+   * @return mime type as String
+   * @throws EdmException
+   */
+  String getMimeType() throws EdmException;
+
+  /**
+   * Get the info if the property is a simple property
+   * 
+   * @return true, if it is a simple property
+   */
+  boolean isSimple();
+}


[18/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/AtomEntityProvider.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/AtomEntityProvider.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/AtomEntityProvider.java
new file mode 100644
index 0000000..1e99e72
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/AtomEntityProvider.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * 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.ep;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.olingo.odata2.api.ODataServiceVersion;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpHeaders;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.consumer.AtomServiceDocumentConsumer;
+import org.apache.olingo.odata2.core.ep.consumer.XmlEntityConsumer;
+import org.apache.olingo.odata2.core.ep.producer.AtomEntryEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.AtomFeedProducer;
+import org.apache.olingo.odata2.core.ep.producer.AtomServiceDocumentProducer;
+import org.apache.olingo.odata2.core.ep.producer.XmlCollectionEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.XmlErrorDocumentProducer;
+import org.apache.olingo.odata2.core.ep.producer.XmlLinkEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.XmlLinksEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.XmlPropertyEntityProducer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class AtomEntityProvider implements ContentTypeBasedEntityProvider {
+
+  /** Default used charset for writer and response content header */
+  private static final String DEFAULT_CHARSET = ContentType.CHARSET_UTF_8;
+  private static final String XML_VERSION = "1.0";
+  private final ODataFormat odataFormat;
+
+  public AtomEntityProvider() throws EntityProviderException {
+    this(ODataFormat.ATOM);
+  }
+
+  public AtomEntityProvider(final ContentType contentType) throws EntityProviderException {
+    this(contentType.getODataFormat());
+  }
+
+  public AtomEntityProvider(final ODataFormat odataFormat) throws EntityProviderException {
+    switch (odataFormat) {
+    case ATOM:
+    case XML:
+      this.odataFormat = odataFormat;
+      break;
+    default:
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Got unsupported ODataFormat '" + odataFormat + "'."));
+    }
+  }
+
+  /**
+   * <p>Serializes an error message according to the OData standard.</p>
+   * <p>In case an error occurs, it is logged.
+   * An exception is not thrown because this method is used in exception handling.</p>
+   * @param status      the {@link HttpStatusCodes} associated with this error  
+   * @param errorCode   a String that serves as a substatus to the HTTP response code
+   * @param message     a human-readable message describing the error
+   * @param locale      the {@link Locale} that should be used to format the error message
+   * @param innerError  the inner error for this message. If it is null or an empty String no inner error tag is shown inside the response xml
+   * @return            an {@link ODataResponse} containing the serialized error message
+   */
+  @Override
+  public ODataResponse writeErrorDocument(final HttpStatusCodes status, final String errorCode, final String message, final Locale locale, final String innerError) {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+
+      XmlErrorDocumentProducer producer = new XmlErrorDocumentProducer();
+      producer.writeErrorDocument(writer, errorCode, message, locale, innerError);
+
+      writer.flush();
+      csb.closeWrite();
+
+      ODataResponseBuilder response = ODataResponse.entity(csb.getInputStream())
+          .contentHeader(ContentType.APPLICATION_XML.toContentTypeString())
+          .header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10)
+          .status(status);
+      return response.build();
+    } catch (Exception e) {
+      csb.close();
+      throw new ODataRuntimeException(e);
+    }
+  }
+
+  /**
+   * Write service document based on given {@link Edm} and <code>service root</code> as
+   * content type "<code>application/atomsvc+xml; charset=utf-8</code>".
+   * 
+   * @param edm the Entity Data Model
+   * @param serviceRoot the root URI of the service
+   * @return resulting {@link ODataResponse} with written service document
+   * @throws EntityProviderException
+   */
+  @Override
+  public ODataResponse writeServiceDocument(final Edm edm, final String serviceRoot) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStreamWriter writer = new OutputStreamWriter(csb.getOutputStream(), DEFAULT_CHARSET);
+      AtomServiceDocumentProducer as = new AtomServiceDocumentProducer(edm, serviceRoot);
+      as.writeServiceDocument(writer);
+      csb.closeWrite();
+
+      ODataResponse response = ODataResponse.entity(csb.getInputStream())
+          .contentHeader(ContentType.APPLICATION_ATOM_SVC_CS_UTF_8.toContentTypeString())
+          .build();
+
+      return response;
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeEntry(final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      AtomEntryEntityProducer as = new AtomEntryEntityProducer(properties);
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+      as.append(writer, eia, data, true, false);
+
+      writer.flush();
+      csb.closeWrite();
+
+      ODataResponseBuilder response = ODataResponse.entity(csb.getInputStream())
+          .contentHeader(getContentHeader(ContentType.APPLICATION_ATOM_XML_ENTRY))
+          .eTag(as.getETag())
+          .idLiteral(as.getLocation());
+      return response.build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeProperty(final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    EntityPropertyInfo propertyInfo = EntityInfoAggregator.create(edmProperty);
+    return writeSingleTypedElement(propertyInfo, value);
+  }
+
+  private ODataResponse writeSingleTypedElement(final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      XmlPropertyEntityProducer ps = new XmlPropertyEntityProducer();
+      ps.append(writer, propertyInfo, value);
+
+      writer.flush();
+      csb.closeWrite();
+
+      return ODataResponse.entity(csb.getInputStream()).contentHeader(getContentHeader(ContentType.APPLICATION_XML)).build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeFeed(final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      AtomFeedProducer atomFeedProvider = new AtomFeedProducer(properties);
+      EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+      atomFeedProvider.append(writer, eia, data, false);
+
+      writer.flush();
+      csb.closeWrite();
+
+      ODataResponse response = ODataResponse.entity(csb.getInputStream()).contentHeader(getContentHeader(ContentType.APPLICATION_ATOM_XML_FEED)).build();
+      return response;
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (XMLStreamException e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private String getContentHeader(final ContentType mediaType) {
+    if (odataFormat == ODataFormat.XML) {
+      return ContentType.APPLICATION_XML_CS_UTF_8.toContentTypeString();
+    }
+    return ContentType.create(mediaType, ContentType.PARAMETER_CHARSET, DEFAULT_CHARSET).toContentTypeString();
+  }
+
+  @Override
+  public ODataResponse writeLink(final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      XmlLinkEntityProducer entity = new XmlLinkEntityProducer(properties);
+      final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+      entity.append(writer, entityInfo, data, true);
+
+      writer.flush();
+      csb.closeWrite();
+
+      return ODataResponse.entity(csb.getInputStream()).contentHeader(getContentHeader(ContentType.APPLICATION_XML)).build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+  }
+
+  @Override
+  public ODataResponse writeLinks(final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      XmlLinksEntityProducer entity = new XmlLinksEntityProducer(properties);
+      final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+      entity.append(writer, entityInfo, data);
+
+      writer.flush();
+      csb.closeWrite();
+
+      return ODataResponse.entity(csb.getInputStream()).contentHeader(getContentHeader(ContentType.APPLICATION_XML)).build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private ODataResponse writeCollection(final EntityPropertyInfo propertyInfo, final List<?> data) throws EntityProviderException {
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = csb.getOutputStream();
+      XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, DEFAULT_CHARSET);
+      writer.writeStartDocument(DEFAULT_CHARSET, XML_VERSION);
+
+      XmlCollectionEntityProducer.append(writer, propertyInfo, data);
+
+      writer.flush();
+      csb.closeWrite();
+
+      return ODataResponse.entity(csb.getInputStream()).contentHeader(getContentHeader(ContentType.APPLICATION_XML)).build();
+    } catch (EntityProviderException e) {
+      csb.close();
+      throw e;
+    } catch (Exception e) {
+      csb.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeFunctionImport(final EdmFunctionImport functionImport, final Object data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    try {
+      final EdmType type = functionImport.getReturnType().getType();
+      final boolean isCollection = functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY;
+
+      if (type.getKind() == EdmTypeKind.ENTITY) {
+        @SuppressWarnings("unchecked")
+        Map<String, Object> map = (Map<String, Object>) data;
+        return writeEntry(functionImport.getEntitySet(), map, properties);
+      }
+
+      final EntityPropertyInfo info = EntityInfoAggregator.create(functionImport);
+      if (isCollection) {
+        return writeCollection(info, (List<?>) data);
+      } else {
+        return writeSingleTypedElement(info, data);
+      }
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    return xec.readFeed(entitySet, content, properties);
+  }
+
+  @Override
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    return xec.readEntry(entitySet, content, properties);
+  }
+
+  @Override
+  public Map<String, Object> readProperty(final EdmProperty edmProperty, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    return xec.readProperty(edmProperty, content, properties);
+  }
+
+  @Override
+  public String readLink(final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    return xec.readLink(entitySet, content);
+  }
+
+  @Override
+  public List<String> readLinks(final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    XmlEntityConsumer xec = new XmlEntityConsumer();
+    return xec.readLinks(entitySet, content);
+  }
+
+  @Override
+  public ServiceDocument readServiceDocument(final InputStream serviceDocument) throws EntityProviderException {
+    AtomServiceDocumentConsumer serviceDocConsumer = new AtomServiceDocumentConsumer();
+    return serviceDocConsumer.parseXml(serviceDocument);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
new file mode 100644
index 0000000..55b7a20
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/BasicEntityProvider.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * 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.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 javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+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.provider.DataServices;
+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.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.producer.XmlMetadataProducer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+
+/**
+ * Provider for all basic (content type independent) entity provider methods.
+ * 
+ * @author SAP AG
+ */
+public class BasicEntityProvider {
+
+  /** Default used charset for writer and response content header */
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  /**
+   * Reads binary data from an input stream.
+   * @param content the content input stream
+   * @return the binary data
+   * @throws EntityProviderException
+   */
+  public byte[] readBinary(final InputStream content) throws EntityProviderException {
+    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+    byte[] value = new byte[Short.MAX_VALUE];
+    int count;
+    try {
+      while ((count = content.read(value)) > 0) {
+        buffer.write(value, 0, count);
+      }
+      content.close();
+      buffer.flush();
+      return buffer.toByteArray();
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  /**
+   * Reads text from an input stream.
+   * @param content the content input stream
+   * @return text as string from <code>InputStream</code>
+   * @throws EntityProviderException
+   */
+  public String readText(final InputStream content) throws EntityProviderException {
+    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(content, Charset.forName(DEFAULT_CHARSET)));
+    StringBuilder stringBuilder = new StringBuilder();
+    try {
+      String line = null;
+      while ((line = bufferedReader.readLine()) != null) {
+        stringBuilder.append(line);
+      }
+      bufferedReader.close();
+    } catch (IOException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    return stringBuilder.toString();
+  }
+
+  /**
+   * Reads an unformatted value of an EDM property as binary or as content type <code>text/plain</code>.
+   * @param edmProperty the EDM property
+   * @param content the content input stream
+   * @param typeMapping 
+   * @return the value as the proper system data type
+   * @throws EntityProviderException
+   */
+  public Object readPropertyValue(final EdmProperty edmProperty, final InputStream content, final Class<?> typeMapping) throws EntityProviderException {
+    EdmSimpleType type;
+    try {
+      type = (EdmSimpleType) edmProperty.getType();
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+    if (type == EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance()) {
+      return readBinary(content);
+    } else {
+      try {
+        if (typeMapping == null) {
+          return type.valueOfString(readText(content), EdmLiteralKind.DEFAULT, edmProperty.getFacets(), type.getDefaultType());
+        } else {
+          return type.valueOfString(readText(content), EdmLiteralKind.DEFAULT, edmProperty.getFacets(), typeMapping);
+        }
+      } catch (EdmException e) {
+        throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      }
+    }
+  }
+
+  /**
+   * Write property as binary or as content type <code>text/plain</code>.
+   * @param edmProperty the EDM property
+   * @param value its value
+   * @return resulting {@link ODataResponse} with written content
+   * @throws EntityProviderException
+   */
+  public ODataResponse writePropertyValue(final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    try {
+      final EdmSimpleType type = (EdmSimpleType) edmProperty.getType();
+
+      if (type == EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance()) {
+        String contentType = HttpContentType.APPLICATION_OCTET_STREAM;
+        Object binary = value;
+        if (edmProperty.getMimeType() != null) {
+          contentType = edmProperty.getMimeType();
+        } else {
+          if (edmProperty.getMapping() != null && edmProperty.getMapping().getMimeType() != null) {
+            String mimeTypeMapping = edmProperty.getMapping().getMimeType();
+            if (value instanceof Map) {
+              final Map<?, ?> mappedData = (Map<?, ?>) value;
+              binary = mappedData.get(edmProperty.getName());
+              contentType = (String) mappedData.get(mimeTypeMapping);
+            } else {
+              throw new EntityProviderException(EntityProviderException.COMMON);
+            }
+          }
+        }
+        return writeBinary(contentType, (byte[]) binary);
+
+      } else {
+        return writeText(type.valueToString(value, EdmLiteralKind.DEFAULT, edmProperty.getFacets()));
+      }
+
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  /**
+   * Write text value as content type <code>text/plain</code>.
+   * @param value the string that is written to {@link ODataResponse}
+   * @return resulting {@link ODataResponse} with written text content
+   * @throws EntityProviderException
+   */
+  public ODataResponse writeText(final String value) throws EntityProviderException {
+    ODataResponseBuilder builder = ODataResponse.newBuilder();
+    if (value != null) {
+      ByteArrayInputStream stream;
+      try {
+        stream = new ByteArrayInputStream(value.getBytes(DEFAULT_CHARSET));
+      } catch (UnsupportedEncodingException e) {
+        throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+      }
+      builder.entity(stream);
+    }
+    builder.contentHeader(ContentType.TEXT_PLAIN_CS_UTF_8.toContentTypeString());
+    return builder.build();
+  }
+
+  /**
+   * Write binary content with content type header set to given <code>mime type</code> parameter.
+   * @param mimeType MIME type which is written and used as content type header information
+   * @param data data is written to {@link ODataResponse}
+   * @return resulting {@link ODataResponse} with written binary content
+   * @throws EntityProviderException
+   */
+  public ODataResponse writeBinary(final String mimeType, final byte[] data) throws EntityProviderException {
+    ODataResponseBuilder builder = ODataResponse.newBuilder();
+    if (data != null) {
+      ByteArrayInputStream bais = new ByteArrayInputStream(data);
+      builder.contentHeader(mimeType);
+      builder.entity(bais);
+    } else {
+      builder.status(HttpStatusCodes.NO_CONTENT);
+    }
+    return builder.build();
+  }
+
+  /**
+   * Writes the metadata in XML format. Predefined namespaces is of type Map{@literal <}prefix,namespace{@literal >} and may be null or an empty Map.
+   * @param schemas
+   * @param predefinedNamespaces
+   * @return resulting {@link ODataResponse} with written metadata content
+   * @throws EntityProviderException
+   */
+  public ODataResponse writeMetadata(final List<Schema> schemas, final Map<String, String> predefinedNamespaces) throws EntityProviderException {
+    ODataResponseBuilder builder = ODataResponse.newBuilder();
+    String dataServiceVersion = ODataServiceVersion.V10;
+    if (schemas != null) {
+      dataServiceVersion = calculateDataServiceVersion(schemas);
+    }
+    DataServices metadata = new DataServices().setSchemas(schemas).setDataServiceVersion(dataServiceVersion);
+    OutputStreamWriter writer = null;
+    CircleStreamBuffer csb = new CircleStreamBuffer();
+    try {
+      writer = new OutputStreamWriter(csb.getOutputStream(), "UTF-8");
+      XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(writer);
+      XmlMetadataProducer.writeMetadata(metadata, xmlStreamWriter, predefinedNamespaces);
+    } catch (UnsupportedEncodingException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    } catch (FactoryConfigurationError e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+    builder.entity(csb.getInputStream());
+    builder.contentHeader(ContentType.APPLICATION_XML_CS_UTF_8.toContentTypeString());
+    builder.header(ODataHttpHeaders.DATASERVICEVERSION, dataServiceVersion);
+    return builder.build();
+  }
+
+  /**
+   * Calculates the necessary data service version for the metadata serialization
+   * @param schemas
+   * @return DataServiceversion as String
+   */
+  private String calculateDataServiceVersion(final List<Schema> schemas) {
+
+    String dataServiceVersion = ODataServiceVersion.V10;
+
+    if (schemas != null) {
+      for (Schema schema : schemas) {
+        List<EntityType> entityTypes = schema.getEntityTypes();
+        if (entityTypes != null) {
+          for (EntityType entityType : entityTypes) {
+            List<Property> properties = entityType.getProperties();
+            if (properties != null) {
+              for (Property property : properties) {
+                if (property.getCustomizableFeedMappings() != null) {
+                  if (property.getCustomizableFeedMappings().getFcKeepInContent() != null) {
+                    if (!property.getCustomizableFeedMappings().getFcKeepInContent()) {
+                      dataServiceVersion = ODataServiceVersion.V20;
+                      return dataServiceVersion;
+                    }
+                  }
+                }
+              }
+              if (entityType.getCustomizableFeedMappings() != null) {
+                if (entityType.getCustomizableFeedMappings().getFcKeepInContent() != null) {
+                  if (entityType.getCustomizableFeedMappings().getFcKeepInContent()) {
+                    dataServiceVersion = ODataServiceVersion.V20;
+                    return dataServiceVersion;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return dataServiceVersion;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ContentTypeBasedEntityProvider.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ContentTypeBasedEntityProvider.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ContentTypeBasedEntityProvider.java
new file mode 100644
index 0000000..9e6df27
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ContentTypeBasedEntityProvider.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.ep;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+
+/**
+ * Interface for all none basic (content type <b>dependent</b>) provider methods.
+ * 
+ * @author SAP AG
+ */
+public interface ContentTypeBasedEntityProvider {
+
+  ODataFeed readFeed(EdmEntitySet entitySet, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
+
+  ODataEntry readEntry(EdmEntitySet entitySet, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
+
+  Map<String, Object> readProperty(EdmProperty edmProperty, InputStream content, EntityProviderReadProperties properties) throws EntityProviderException;
+
+  String readLink(EdmEntitySet entitySet, InputStream content) throws EntityProviderException;
+
+  List<String> readLinks(EdmEntitySet entitySet, InputStream content) throws EntityProviderException;
+
+  ODataResponse writeServiceDocument(Edm edm, String serviceRoot) throws EntityProviderException;
+
+  ODataResponse writeFeed(EdmEntitySet entitySet, List<Map<String, Object>> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+  ODataResponse writeEntry(EdmEntitySet entitySet, Map<String, Object> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+  ODataResponse writeProperty(EdmProperty edmProperty, Object value) throws EntityProviderException;
+
+  ODataResponse writeLink(EdmEntitySet entitySet, Map<String, Object> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+  ODataResponse writeLinks(EdmEntitySet entitySet, List<Map<String, Object>> data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+  ODataResponse writeFunctionImport(EdmFunctionImport functionImport, Object data, EntityProviderWriteProperties properties) throws EntityProviderException;
+
+  ODataResponse writeErrorDocument(HttpStatusCodes status, String errorCode, String message, Locale locale, String innerError);
+
+  ServiceDocument readServiceDocument(InputStream serviceDocument) throws EntityProviderException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/JsonEntityProvider.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/JsonEntityProvider.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/JsonEntityProvider.java
new file mode 100644
index 0000000..a38b7e9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/JsonEntityProvider.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * 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.ep;
+
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+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.InlineCount;
+import org.apache.olingo.odata2.api.commons.ODataHttpHeaders;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityPropertyInfo;
+import org.apache.olingo.odata2.core.ep.consumer.JsonEntityConsumer;
+import org.apache.olingo.odata2.core.ep.consumer.JsonServiceDocumentConsumer;
+import org.apache.olingo.odata2.core.ep.producer.JsonCollectionEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonEntryEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonErrorDocumentProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonFeedEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonLinkEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonLinksEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonPropertyEntityProducer;
+import org.apache.olingo.odata2.core.ep.producer.JsonServiceDocumentProducer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class JsonEntityProvider implements ContentTypeBasedEntityProvider {
+
+  private static final String DEFAULT_CHARSET = "UTF-8";
+
+  /**
+   * <p>Serializes an error message according to the OData standard.</p>
+   * <p>In case an error occurs, it is logged.
+   * An exception is not thrown because this method is used in exception handling.</p>
+   * @param status      the {@link HttpStatusCodes status code} associated with this error  
+   * @param errorCode   a String that serves as a substatus to the HTTP response code
+   * @param message     a human-readable message describing the error
+   * @param locale      the {@link Locale} that should be used to format the error message
+   * @param innerError  the inner error for this message; if it is null or an empty String
+   *                    no inner error tag is shown inside the response structure
+   * @return            an {@link ODataResponse} containing the serialized error message
+   */
+  @Override
+  public ODataResponse writeErrorDocument(final HttpStatusCodes status, final String errorCode, final String message, final Locale locale, final String innerError) {
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonErrorDocumentProducer().writeErrorDocument(writer, errorCode, message, locale, innerError);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.status(status)
+          .entity(buffer.getInputStream())
+          .contentHeader(HttpContentType.APPLICATION_JSON)
+          .header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10)
+          .build();
+    } catch (Exception e) {
+      buffer.close();
+      throw new ODataRuntimeException(e);
+    }
+  }
+
+  /**
+   * Writes service document based on given {@link Edm} and <code>service root</code>.
+   * @param edm the Entity Data Model
+   * @param serviceRoot the root URI of the service
+   * @return resulting {@link ODataResponse} with written service document
+   * @throws EntityProviderException
+   */
+  @Override
+  public ODataResponse writeServiceDocument(final Edm edm, final String serviceRoot) throws EntityProviderException {
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      JsonServiceDocumentProducer.writeServiceDocument(writer, edm);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream())
+          .contentHeader(HttpContentType.APPLICATION_JSON)
+          .header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10)
+          .build();
+    } catch (Exception e) {
+      buffer.close();
+      throw new ODataRuntimeException(e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeEntry(final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      JsonEntryEntityProducer producer = new JsonEntryEntityProducer(properties);
+      producer.append(writer, entityInfo, data, true);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream())
+          .contentHeader(HttpContentType.APPLICATION_JSON)
+          .eTag(producer.getETag())
+          .idLiteral(producer.getLocation())
+          .build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeProperty(final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    return writeSingleTypedElement(EntityInfoAggregator.create(edmProperty), value);
+  }
+
+  private ODataResponse writeSingleTypedElement(final EntityPropertyInfo propertyInfo, final Object value) throws EntityProviderException {
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      OutputStream outStream = buffer.getOutputStream();
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream, DEFAULT_CHARSET));
+      new JsonPropertyEntityProducer().append(writer, propertyInfo, value);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream())
+          .contentHeader(HttpContentType.APPLICATION_JSON)
+          .header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10)
+          .build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeFeed(final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonFeedEntityProducer(properties).append(writer, entityInfo, data, true);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream()).contentHeader(HttpContentType.APPLICATION_JSON).build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeLink(final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonLinkEntityProducer(properties).append(writer, entityInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream())
+          .contentHeader(HttpContentType.APPLICATION_JSON)
+          .header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10)
+          .build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeLinks(final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    final EntityInfoAggregator entityInfo = EntityInfoAggregator.create(entitySet, properties.getExpandSelectTree());
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonLinksEntityProducer(properties).append(writer, entityInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      ODataResponseBuilder response = ODataResponse.entity(buffer.getInputStream()).contentHeader(HttpContentType.APPLICATION_JSON);
+      if (properties.getInlineCountType() != InlineCount.ALLPAGES) {
+        response = response.header(ODataHttpHeaders.DATASERVICEVERSION, ODataServiceVersion.V10);
+      }
+      return response.build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  private ODataResponse writeCollection(final EntityPropertyInfo propertyInfo, final List<?> data) throws EntityProviderException {
+    CircleStreamBuffer buffer = new CircleStreamBuffer();
+
+    try {
+      BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(buffer.getOutputStream(), DEFAULT_CHARSET));
+      new JsonCollectionEntityProducer().append(writer, propertyInfo, data);
+      writer.flush();
+      buffer.closeWrite();
+
+      return ODataResponse.entity(buffer.getInputStream()).contentHeader(HttpContentType.APPLICATION_JSON).build();
+    } catch (EntityProviderException e) {
+      buffer.close();
+      throw e;
+    } catch (Exception e) {
+      buffer.close();
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeFunctionImport(final EdmFunctionImport functionImport, final Object data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    try {
+      if (functionImport.getReturnType().getType().getKind() == EdmTypeKind.ENTITY) {
+        @SuppressWarnings("unchecked")
+        Map<String, Object> map = (Map<String, Object>) data;
+        return writeEntry(functionImport.getEntitySet(), map, properties);
+      }
+
+      final EntityPropertyInfo info = EntityInfoAggregator.create(functionImport);
+      if (functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY) {
+        return writeCollection(info, (List<?>) data);
+      } else {
+        return writeSingleTypedElement(info, data);
+      }
+    } catch (final EdmException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+  }
+
+  @Override
+  public ODataFeed readFeed(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    JsonEntityConsumer jec = new JsonEntityConsumer();
+    return jec.readFeed(entitySet, content, properties);
+  }
+
+  @Override
+  public ODataEntry readEntry(final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    JsonEntityConsumer jec = new JsonEntityConsumer();
+    return jec.readEntry(entitySet, content, properties);
+  }
+
+  @Override
+  public Map<String, Object> readProperty(final EdmProperty edmProperty, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return new JsonEntityConsumer().readProperty(edmProperty, content, properties);
+  }
+
+  @Override
+  public String readLink(final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    return new JsonEntityConsumer().readLink(entitySet, content);
+  }
+
+  @Override
+  public List<String> readLinks(final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    return new JsonEntityConsumer().readLinks(entitySet, content);
+  }
+
+  @Override
+  public ServiceDocument readServiceDocument(final InputStream serviceDocument) throws EntityProviderException {
+    JsonServiceDocumentConsumer serviceDocConsumer = new JsonServiceDocumentConsumer();
+    return serviceDocConsumer.parseJson(serviceDocument);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImpl.java
new file mode 100644
index 0000000..38da4cc
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImpl.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * 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.ep;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.ep.EntityProvider.EntityProviderInterface;
+import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.servicedocument.ServiceDocument;
+import org.apache.olingo.odata2.core.batch.BatchRequestParser;
+import org.apache.olingo.odata2.core.batch.BatchResponseWriter;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.edm.parser.EdmxProvider;
+import org.apache.olingo.odata2.core.edm.provider.EdmImplProv;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class ProviderFacadeImpl implements EntityProviderInterface {
+
+  private static BasicEntityProvider create() throws EntityProviderException {
+    return new BasicEntityProvider();
+  }
+
+  private static ContentTypeBasedEntityProvider create(final String contentType) throws EntityProviderException {
+    return create(ContentType.create(contentType));
+  }
+
+  private static ContentTypeBasedEntityProvider create(final ContentType contentType) throws EntityProviderException {
+    try {
+      switch (contentType.getODataFormat()) {
+      case ATOM:
+      case XML:
+        return new AtomEntityProvider(contentType.getODataFormat());
+      case JSON:
+        return new JsonEntityProvider();
+      default:
+        throw new ODataNotAcceptableException(ODataNotAcceptableException.NOT_SUPPORTED_CONTENT_TYPE.addContent(contentType));
+      }
+    } catch (final ODataNotAcceptableException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeErrorDocument(final ODataErrorContext context) {
+    try {
+      return create(context.getContentType()).writeErrorDocument(context.getHttpStatus(), context.getErrorCode(), context.getMessage(), context.getLocale(), context.getInnerError());
+    } catch (EntityProviderException e) {
+      throw new ODataRuntimeException(e);
+    }
+  }
+
+  @Override
+  public ODataResponse writeServiceDocument(final String contentType, final Edm edm, final String serviceRoot) throws EntityProviderException {
+    return create(contentType).writeServiceDocument(edm, serviceRoot);
+  }
+
+  @Override
+  public ODataResponse writePropertyValue(final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    return create().writePropertyValue(edmProperty, value);
+  }
+
+  @Override
+  public ODataResponse writeText(final String value) throws EntityProviderException {
+    return create().writeText(value);
+  }
+
+  @Override
+  public ODataResponse writeBinary(final String mimeType, final byte[] data) throws EntityProviderException {
+    return create().writeBinary(mimeType, data);
+  }
+
+  @Override
+  public ODataResponse writeFeed(final String contentType, final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return create(contentType).writeFeed(entitySet, data, properties);
+  }
+
+  @Override
+  public ODataResponse writeEntry(final String contentType, final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return create(contentType).writeEntry(entitySet, data, properties);
+  }
+
+  @Override
+  public ODataResponse writeProperty(final String contentType, final EdmProperty edmProperty, final Object value) throws EntityProviderException {
+    return create(contentType).writeProperty(edmProperty, value);
+  }
+
+  @Override
+  public ODataResponse writeLink(final String contentType, final EdmEntitySet entitySet, final Map<String, Object> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return create(contentType).writeLink(entitySet, data, properties);
+  }
+
+  @Override
+  public ODataResponse writeLinks(final String contentType, final EdmEntitySet entitySet, final List<Map<String, Object>> data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return create(contentType).writeLinks(entitySet, data, properties);
+  }
+
+  @Override
+  public ODataResponse writeFunctionImport(final String contentType, final EdmFunctionImport functionImport, final Object data, final EntityProviderWriteProperties properties) throws EntityProviderException {
+    return create(contentType).writeFunctionImport(functionImport, data, properties);
+  }
+
+  @Override
+  public ODataFeed readFeed(final String contentType, final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return create(contentType).readFeed(entitySet, content, properties);
+  }
+
+  @Override
+  public ODataEntry readEntry(final String contentType, final EdmEntitySet entitySet, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return create(contentType).readEntry(entitySet, content, properties);
+  }
+
+  @Override
+  public Map<String, Object> readProperty(final String contentType, final EdmProperty edmProperty, final InputStream content, final EntityProviderReadProperties properties) throws EntityProviderException {
+    return create(contentType).readProperty(edmProperty, content, properties);
+  }
+
+  @Override
+  public Object readPropertyValue(final EdmProperty edmProperty, final InputStream content, final Class<?> typeMapping) throws EntityProviderException {
+    return create().readPropertyValue(edmProperty, content, typeMapping);
+  }
+
+  @Override
+  public List<String> readLinks(final String contentType, final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    return create(contentType).readLinks(entitySet, content);
+  }
+
+  @Override
+  public String readLink(final String contentType, final EdmEntitySet entitySet, final InputStream content) throws EntityProviderException {
+    return create(contentType).readLink(entitySet, content);
+  }
+
+  @Override
+  public byte[] readBinary(final InputStream content) throws EntityProviderException {
+    return create().readBinary(content);
+  }
+
+  @Override
+  public ODataResponse writeMetadata(final List<Schema> schemas, final Map<String, String> predefinedNamespaces) throws EntityProviderException {
+    return create().writeMetadata(schemas, predefinedNamespaces);
+  }
+
+  @Override
+  public Edm readMetadata(final InputStream inputStream, final boolean validate) throws EntityProviderException {
+    EdmProvider provider = new EdmxProvider().parse(inputStream, validate);
+    return new EdmImplProv(provider);
+  }
+
+  @Override
+  public ServiceDocument readServiceDocument(final InputStream serviceDocument, final String contentType) throws EntityProviderException {
+    return create(contentType).readServiceDocument(serviceDocument);
+  }
+
+  @Override
+  public List<BatchPart> parseBatchRequest(final String contentType, final InputStream content, final EntityProviderBatchProperties properties) throws BatchException {
+    List<BatchPart> batchParts = new BatchRequestParser(contentType, properties).parse(content);
+    return batchParts;
+  }
+
+  @Override
+  public ODataResponse writeBatchResponse(final List<BatchResponsePart> batchResponseParts) throws BatchException {
+    BatchResponseWriter batchWriter = new BatchResponseWriter();
+    return batchWriter.writeResponse(batchResponseParts);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityComplexPropertyInfo.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityComplexPropertyInfo.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityComplexPropertyInfo.java
new file mode 100644
index 0000000..dfd96e0
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityComplexPropertyInfo.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.ep.aggregator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+/**
+ * author SAP AG
+ */
+public class EntityComplexPropertyInfo extends EntityPropertyInfo {
+
+  protected List<EntityPropertyInfo> entityPropertyInfo;
+
+  EntityComplexPropertyInfo(final String name, final EdmType type, final EdmFacets facets, final EdmCustomizableFeedMappings customizableFeedMapping, final List<EntityPropertyInfo> childEntityInfos) {
+    super(name, type, facets, customizableFeedMapping, null, null);
+    entityPropertyInfo = childEntityInfos;
+  }
+
+  static EntityComplexPropertyInfo create(final EdmProperty property, final List<String> propertyNames, final Map<String, EntityPropertyInfo> childEntityInfos) throws EdmException {
+    List<EntityPropertyInfo> childEntityInfoList = new ArrayList<EntityPropertyInfo>(childEntityInfos.size());
+    for (String name : propertyNames) {
+      childEntityInfoList.add(childEntityInfos.get(name));
+    }
+
+    EntityComplexPropertyInfo info = new EntityComplexPropertyInfo(
+        property.getName(),
+        property.getType(),
+        property.getFacets(),
+        property.getCustomizableFeedMappings(),
+        childEntityInfoList);
+    return info;
+  }
+
+  @Override
+  public boolean isComplex() {
+    return true;
+  }
+
+  public List<EntityPropertyInfo> getPropertyInfos() {
+    return Collections.unmodifiableList(entityPropertyInfo);
+  }
+
+  public EntityPropertyInfo getPropertyInfo(final String name) {
+    for (EntityPropertyInfo info : entityPropertyInfo) {
+      if (info.getName().equals(name)) {
+        return info;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    for (EntityPropertyInfo info : entityPropertyInfo) {
+      if (sb.length() == 0) {
+        sb.append(super.toString()).append("=>[").append(info.toString());
+      } else {
+        sb.append(", ").append(info.toString());
+      }
+    }
+    sb.append("]");
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregator.java
new file mode 100644
index 0000000..7d964c2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregator.java
@@ -0,0 +1,451 @@
+/*******************************************************************************
+ * 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.ep.aggregator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmCustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTargetPath;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+
+/**
+ * Aggregator to get easy and fast access to all for serialization and de-serialization necessary {@link EdmEntitySet} informations.
+ * 
+ * @author SAP AG
+ */
+public class EntityInfoAggregator {
+
+  private static final Set<String> SYN_TARGET_PATHS = new HashSet<String>(Arrays.asList(
+      EdmTargetPath.SYNDICATION_AUTHORNAME,
+      EdmTargetPath.SYNDICATION_AUTHOREMAIL,
+      EdmTargetPath.SYNDICATION_AUTHORURI,
+      EdmTargetPath.SYNDICATION_PUBLISHED,
+      EdmTargetPath.SYNDICATION_RIGHTS,
+      EdmTargetPath.SYNDICATION_TITLE,
+      EdmTargetPath.SYNDICATION_UPDATED,
+      EdmTargetPath.SYNDICATION_CONTRIBUTORNAME,
+      EdmTargetPath.SYNDICATION_CONTRIBUTOREMAIL,
+      EdmTargetPath.SYNDICATION_CONTRIBUTORURI,
+      EdmTargetPath.SYNDICATION_SOURCE,
+      EdmTargetPath.SYNDICATION_SUMMARY));
+
+  private Map<String, EntityPropertyInfo> propertyInfo = new HashMap<String, EntityPropertyInfo>();
+  private Map<String, NavigationPropertyInfo> navigationPropertyInfos = new HashMap<String, NavigationPropertyInfo>();
+  private List<EntityPropertyInfo> keyPropertyInfos;
+
+  /*
+   * list with all property names in the order based on order in {@link EdmProperty} (normally [key, entity,
+   * navigation])
+   */
+  private List<String> etagPropertyNames = new ArrayList<String>();
+  private List<String> propertyNames;
+  private List<String> navigationPropertyNames;
+  private List<String> selectedPropertyNames;
+  private List<String> selectedNavigationPropertyNames;
+  private List<String> expandedNavigationPropertyNames;
+
+  private Map<String, EntityPropertyInfo> targetPath2EntityPropertyInfo = new HashMap<String, EntityPropertyInfo>();
+  private List<String> noneSyndicationTargetPaths = new ArrayList<String>();
+
+  private boolean isDefaultEntityContainer;
+  private String entitySetName;
+  private String entityContainerName;
+
+  private EdmEntityType entityType;
+  private EdmEntitySet entitySet;
+
+  /**
+   * Constructor is private to force creation over {@link #create(EdmEntitySet)} method.
+   */
+  private EntityInfoAggregator() {}
+
+  /**
+   * Create an {@link EntityInfoAggregator} based on given {@link EdmEntitySet}
+   * 
+   * @param entitySet
+   *          with which the {@link EntityInfoAggregator} is initialized.
+   * @param expandSelectTree 
+   * @return created and initialized {@link EntityInfoAggregator}
+   * @throws EntityProviderException
+   *           if during initialization of {@link EntityInfoAggregator} something goes wrong (e.g. exceptions during
+   *           access
+   *           of {@link EdmEntitySet}).
+   */
+  public static EntityInfoAggregator create(final EdmEntitySet entitySet, final ExpandSelectTreeNode expandSelectTree) throws EntityProviderException {
+    EntityInfoAggregator eia = new EntityInfoAggregator();
+    eia.initialize(entitySet, expandSelectTree);
+    return eia;
+  }
+
+  /**
+   * Create an {@link EntityInfoAggregator} based on given {@link EdmEntitySet}
+   * 
+   * @param entitySet
+   *          with which the {@link EntityInfoAggregator} is initialized.
+   * @return created and initialized {@link EntityInfoAggregator}
+   * @throws EntityProviderException
+   *           if during initialization of {@link EntityInfoAggregator} something goes wrong (e.g. exceptions during
+   *           access
+   *           of {@link EdmEntitySet}).
+   */
+  public static EntityInfoAggregator create(final EdmEntitySet entitySet) throws EntityProviderException {
+    EntityInfoAggregator eia = new EntityInfoAggregator();
+    eia.initialize(entitySet, null);
+    return eia;
+  }
+
+  /**
+   * Create an {@link EntityPropertyInfo} based on given {@link EdmProperty}
+   * 
+   * @param property
+   *          for which the {@link EntityPropertyInfo} is created.
+   * @return created {@link EntityPropertyInfo}
+   * @throws EntityProviderException
+   *           if create of {@link EntityPropertyInfo} something goes wrong (e.g. exceptions during
+   *           access of {@link EdmProperty}).
+   */
+  public static EntityPropertyInfo create(final EdmProperty property) throws EntityProviderException {
+    try {
+      EntityInfoAggregator eia = new EntityInfoAggregator();
+      return eia.createEntityPropertyInfo(property);
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  /**
+   * Create an map of <code>complex type property name</code> to {@link EntityPropertyInfo} based on given {@link EdmComplexType}
+   * 
+   * @param complexType
+   *          for which the {@link EntityPropertyInfo} is created.
+   * @return created map of <code>complex type property name</code> to {@link EntityPropertyInfo}
+   * @throws EntityProviderException
+   *           if create of {@link EntityPropertyInfo} something goes wrong (e.g. exceptions during
+   *           access of {@link EntityPropertyInfo}).
+   */
+  public static Map<String, EntityPropertyInfo> create(final EdmComplexType complexType) throws EntityProviderException {
+    try {
+      EntityInfoAggregator entityInfo = new EntityInfoAggregator();
+      return entityInfo.createPropertyInfoObjects(complexType, complexType.getPropertyNames());
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  /**
+   * Create an {@link EntityPropertyInfo} based on given {@link EdmFunctionImport}
+   * 
+   * @param functionImport
+   *          for which the {@link EntityPropertyInfo} is created.
+   * @return created {@link EntityPropertyInfo}
+   * @throws EntityProviderException
+   *           if create of {@link EntityPropertyInfo} something goes wrong (e.g. exceptions during
+   *           access of {@link EdmFunctionImport}).
+   */
+  public static EntityPropertyInfo create(final EdmFunctionImport functionImport) throws EntityProviderException {
+    try {
+      EntityInfoAggregator eia = new EntityInfoAggregator();
+      return eia.createEntityPropertyInfo(functionImport, functionImport.getReturnType().getType());
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  /**
+   * @return the edm entity set which was used to build this entity info aggregator object
+   */
+  public EdmEntitySet getEntitySet() {
+    return entitySet;
+  }
+
+  /**
+   * @return entity set name.
+   */
+  public String getEntitySetName() {
+    return entitySetName;
+  }
+
+  /**
+   * @return <code>true</code> if the entity container of {@link EdmEntitySet} is the default container,
+   *         otherwise <code>false</code>.
+   */
+  public boolean isDefaultEntityContainer() {
+    return isDefaultEntityContainer;
+  }
+
+  public EntityPropertyInfo getTargetPathInfo(final String targetPath) {
+    return targetPath2EntityPropertyInfo.get(targetPath);
+  }
+
+  public EdmEntityType getEntityType() {
+    return entityType;
+  }
+
+  public String getEntityContainerName() {
+    return entityContainerName;
+  }
+
+  /**
+   * @return unmodifiable set of all found target path names.
+   */
+  public Collection<String> getTargetPathNames() {
+    return Collections.unmodifiableCollection(targetPath2EntityPropertyInfo.keySet());
+  }
+
+  /**
+   * @return unmodifiable set of found <code>none syndication target path names</code> (all target path names which are
+   *         not pre-defined).
+   */
+  public List<String> getNoneSyndicationTargetPathNames() {
+    return Collections.unmodifiableList(noneSyndicationTargetPaths);
+  }
+
+  /**
+   * @return unmodifiable set of all found navigation property names.
+   */
+  public List<String> getNavigationPropertyNames() throws EntityProviderException {
+    return Collections.unmodifiableList(navigationPropertyNames);
+  }
+
+  /**
+   * @return unmodifiable set of all property names.
+    */
+  public List<String> getPropertyNames() throws EntityProviderException {
+    return Collections.unmodifiableList(propertyNames);
+  }
+
+  /**
+   * @return unmodifiable set of selected property names.
+   */
+  public List<String> getSelectedPropertyNames() throws EntityProviderException {
+    return Collections.unmodifiableList(selectedPropertyNames);
+  }
+
+  /**
+   * @return unmodifiable set of selected property names.
+   */
+  public List<String> getSelectedNavigationPropertyNames() throws EntityProviderException {
+    return Collections.unmodifiableList(selectedNavigationPropertyNames);
+  }
+
+  public Collection<EntityPropertyInfo> getPropertyInfos() {
+    return Collections.unmodifiableCollection(propertyInfo.values());
+  }
+
+  public EntityPropertyInfo getPropertyInfo(final String name) {
+    return propertyInfo.get(name);
+  }
+
+  public Collection<EntityPropertyInfo> getETagPropertyInfos() {
+    List<EntityPropertyInfo> keyProperties = new ArrayList<EntityPropertyInfo>();
+    for (String etagPropertyName : etagPropertyNames) {
+      EntityPropertyInfo e = propertyInfo.get(etagPropertyName);
+      keyProperties.add(e);
+    }
+    return keyProperties;
+  }
+
+  /**
+   * @return list of all key property infos
+   * @throws EntityProviderException 
+   */
+  public List<EntityPropertyInfo> getKeyPropertyInfos() throws EntityProviderException {
+
+    if (keyPropertyInfos == null) {
+      try {
+        keyPropertyInfos = new ArrayList<EntityPropertyInfo>();
+        for (String keyPropertyName : entityType.getKeyPropertyNames()) {
+          keyPropertyInfos.add(propertyInfo.get(keyPropertyName));
+        }
+      } catch (EdmException e) {
+        throw new EntityProviderException(EntityProviderException.COMMON, e);
+      }
+    }
+    return keyPropertyInfos;
+  }
+
+  public NavigationPropertyInfo getNavigationPropertyInfo(final String name) {
+    return navigationPropertyInfos.get(name);
+  }
+
+  private void initialize(final EdmEntitySet entitySet, final ExpandSelectTreeNode expandSelectTree) throws EntityProviderException {
+    try {
+      this.entitySet = entitySet;
+      entityType = entitySet.getEntityType();
+      entitySetName = entitySet.getName();
+      isDefaultEntityContainer = entitySet.getEntityContainer().isDefaultEntityContainer();
+      entityContainerName = entitySet.getEntityContainer().getName();
+
+      propertyNames = entityType.getPropertyNames();
+      navigationPropertyNames = entityType.getNavigationPropertyNames();
+
+      propertyInfo = createPropertyInfoObjects(entityType, propertyNames);
+      navigationPropertyInfos = createNavigationInfoObjects(entityType, navigationPropertyNames);
+
+      selectedPropertyNames = propertyNames;
+      selectedNavigationPropertyNames = navigationPropertyNames;
+      expandedNavigationPropertyNames = new ArrayList<String>();
+
+      if (expandSelectTree != null && !expandSelectTree.isAll()) {
+        selectedPropertyNames = new ArrayList<String>();
+        selectedNavigationPropertyNames = new ArrayList<String>();
+        for (EdmProperty property : expandSelectTree.getProperties()) {
+          selectedPropertyNames.add(property.getName());
+        }
+        for (String property : expandSelectTree.getLinks().keySet()) {
+          selectedNavigationPropertyNames.add(property);
+          if (expandSelectTree.getLinks().get(property) != null) {
+            expandedNavigationPropertyNames.add(property);
+          }
+        }
+      } else if (expandSelectTree != null) {
+        for (String property : expandSelectTree.getLinks().keySet()) {
+          if (expandSelectTree.getLinks().get(property) != null) {
+            expandedNavigationPropertyNames.add(property);
+          }
+        }
+      }
+
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private Map<String, EntityPropertyInfo> createPropertyInfoObjects(final EdmStructuralType type, final List<String> propertyNames) throws EntityProviderException {
+    try {
+      Map<String, EntityPropertyInfo> infos = new HashMap<String, EntityPropertyInfo>();
+
+      for (String propertyName : propertyNames) {
+        EdmProperty property = (EdmProperty) type.getProperty(propertyName);
+
+        checkETagRelevant(property);
+
+        EntityPropertyInfo info = createEntityPropertyInfo(property);
+        infos.put(info.getName(), info);
+        checkTargetPathInfo(property, info);
+      }
+
+      return infos;
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private Map<String, NavigationPropertyInfo> createNavigationInfoObjects(final EdmStructuralType type, final List<String> propertyNames) throws EntityProviderException {
+    try {
+      Map<String, NavigationPropertyInfo> infos = new HashMap<String, NavigationPropertyInfo>();
+
+      for (String propertyName : propertyNames) {
+        EdmNavigationProperty navProperty = (EdmNavigationProperty) type.getProperty(propertyName);
+        NavigationPropertyInfo info = NavigationPropertyInfo.create(navProperty);
+        infos.put(propertyName, info);
+      }
+
+      return infos;
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private EntityPropertyInfo createEntityPropertyInfo(final EdmProperty property) throws EdmException, EntityProviderException {
+    EdmType type = property.getType();
+    if (type instanceof EdmSimpleType) {
+      return EntityPropertyInfo.create(property);
+    } else if (type instanceof EdmComplexType) {
+      EdmComplexType complex = (EdmComplexType) type;
+      Map<String, EntityPropertyInfo> recursiveInfos = createPropertyInfoObjects(complex, complex.getPropertyNames());
+      return EntityComplexPropertyInfo.create(property, complex.getPropertyNames(), recursiveInfos);
+    } else {
+      throw new EntityProviderException(EntityProviderException.UNSUPPORTED_PROPERTY_TYPE);
+    }
+  }
+
+  private EntityPropertyInfo createEntityPropertyInfo(final EdmFunctionImport functionImport, final EdmType type) throws EdmException, EntityProviderException {
+    EntityPropertyInfo epi;
+
+    if (type.getKind() == EdmTypeKind.COMPLEX) {
+      EdmComplexType complex = (EdmComplexType) type;
+      Map<String, EntityPropertyInfo> eia = EntityInfoAggregator.create(complex);
+
+      List<EntityPropertyInfo> childEntityInfoList = new ArrayList<EntityPropertyInfo>();
+      for (String propertyName : complex.getPropertyNames()) {
+        childEntityInfoList.add(eia.get(propertyName));
+      }
+      epi = new EntityComplexPropertyInfo(functionImport.getName(), type, null, null, childEntityInfoList);
+
+    } else if (type.getKind() == EdmTypeKind.SIMPLE) {
+
+      epi = new EntityPropertyInfo(functionImport.getName(), type, null, null, null, null);
+    } else {
+      throw new EntityProviderException(EntityProviderException.UNSUPPORTED_PROPERTY_TYPE.addContent(type.getKind()));
+    }
+
+    return epi;
+  }
+
+  private void checkETagRelevant(final EdmProperty edmProperty) throws EntityProviderException {
+    try {
+      if (edmProperty.getFacets() != null && edmProperty.getFacets().getConcurrencyMode() == EdmConcurrencyMode.Fixed) {
+        etagPropertyNames.add(edmProperty.getName());
+      }
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  private void checkTargetPathInfo(final EdmProperty property, final EntityPropertyInfo propertyInfo) throws EntityProviderException {
+    try {
+      EdmCustomizableFeedMappings customizableFeedMappings = property.getCustomizableFeedMappings();
+      if (customizableFeedMappings != null) {
+        String targetPath = customizableFeedMappings.getFcTargetPath();
+        targetPath2EntityPropertyInfo.put(targetPath, propertyInfo);
+        if (!SYN_TARGET_PATHS.contains(targetPath)) {
+          noneSyndicationTargetPaths.add(targetPath);
+        }
+      }
+    } catch (EdmException e) {
+      throw new EntityProviderException(EntityProviderException.COMMON, e);
+    }
+  }
+
+  public List<String> getExpandedNavigationPropertyNames() {
+    return expandedNavigationPropertyNames;
+  }
+}


[02/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProvTest.java
new file mode 100644
index 0000000..7fe398c
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmServiceMetadataImplProvTest.java
@@ -0,0 +1,285 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
+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.Schema;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.EdmTestProvider;
+
+/**
+ * @author SAP AG
+ */
+public class EdmServiceMetadataImplProvTest extends BaseTest {
+
+  private static String metadata;
+
+  @BeforeClass
+  public static void setup() throws Exception {
+    EdmImplProv edmImplProv = new EdmImplProv(new EdmTestProvider());
+    EdmServiceMetadata serviceMetadata = edmImplProv.getServiceMetadata();
+    metadata = StringHelper.inputStreamToString(serviceMetadata.getMetadata());
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("a", Edm.NAMESPACE_EDM_2008_09);
+    prefixMap.put("edmx", Edm.NAMESPACE_EDMX_2007_06);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("annoPrefix", "http://annoNamespace");
+
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+  }
+
+  @Test
+  public void getEntitySetInfosForEmptyEdmProvider() throws Exception {
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    EdmServiceMetadata serviceMetadata = new EdmServiceMetadataImplProv(edmProvider);
+
+    List<EdmEntitySetInfo> infos = serviceMetadata.getEntitySetInfos();
+    assertNotNull(infos);
+    assertEquals(Collections.emptyList(), infos);
+  }
+
+  @Test
+  public void getEntitySetInfosForEmptyEdmProviderSchemas() throws Exception {
+    List<Schema> schemas = new ArrayList<Schema>();
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    when(edmProvider.getSchemas()).thenReturn(schemas);
+
+    EdmServiceMetadata serviceMetadata = new EdmServiceMetadataImplProv(edmProvider);
+
+    List<EdmEntitySetInfo> infos = serviceMetadata.getEntitySetInfos();
+    assertNotNull(infos);
+    assertEquals(Collections.emptyList(), infos);
+  }
+
+  @Test
+  public void oneEntitySetOneContainerForInfo() throws Exception {
+    String entitySetUriString = new URI("Employees").toASCIIString();
+
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    EntitySet entitySet = new EntitySet().setName("Employees");
+    entitySets.add(entitySet);
+
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    EntityContainer container = new EntityContainer().setDefaultEntityContainer(true).setName("Container").setEntitySets(entitySets);
+    entityContainers.add(container);
+
+    List<Schema> schemas = new ArrayList<Schema>();
+    schemas.add(new Schema().setEntityContainers(entityContainers));
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    when(edmProvider.getSchemas()).thenReturn(schemas);
+
+    EdmServiceMetadata serviceMetadata = new EdmServiceMetadataImplProv(edmProvider);
+
+    List<EdmEntitySetInfo> infos = serviceMetadata.getEntitySetInfos();
+    assertNotNull(infos);
+    assertEquals(1, infos.size());
+
+    assertEquals(infos.get(0).getEntitySetName(), "Employees");
+    assertEquals(infos.get(0).getEntityContainerName(), "Container");
+    assertEquals(infos.get(0).getEntitySetUri().toASCIIString(), entitySetUriString);
+    assertTrue(infos.get(0).isDefaultEntityContainer());
+  }
+
+  @Test
+  public void twoEntitySetsOneContainerForInfo() throws Exception {
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    EntitySet entitySet = new EntitySet().setName("Employees");
+    entitySets.add(entitySet);
+    entitySets.add(entitySet);
+
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    EntityContainer container = new EntityContainer().setDefaultEntityContainer(true).setName("Container").setEntitySets(entitySets);
+    entityContainers.add(container);
+
+    List<Schema> schemas = new ArrayList<Schema>();
+    schemas.add(new Schema().setEntityContainers(entityContainers));
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    when(edmProvider.getSchemas()).thenReturn(schemas);
+
+    EdmServiceMetadata serviceMetadata = new EdmServiceMetadataImplProv(edmProvider);
+
+    List<EdmEntitySetInfo> infos = serviceMetadata.getEntitySetInfos();
+    assertNotNull(infos);
+    assertEquals(2, infos.size());
+  }
+
+  @Test
+  public void twoContainersWithOneEntitySetEachForInfo() throws Exception {
+    String entitySetUriString = new URI("Employees").toASCIIString();
+    String entitySetUriString2 = new URI("Container2.Employees").toASCIIString();
+
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    EntitySet entitySet = new EntitySet().setName("Employees");
+    entitySets.add(entitySet);
+
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    EntityContainer container = new EntityContainer().setDefaultEntityContainer(true).setName("Container").setEntitySets(entitySets);
+    entityContainers.add(container);
+
+    EntityContainer container2 = new EntityContainer().setDefaultEntityContainer(false).setName("Container2").setEntitySets(entitySets);
+    entityContainers.add(container2);
+
+    List<Schema> schemas = new ArrayList<Schema>();
+    schemas.add(new Schema().setEntityContainers(entityContainers));
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    when(edmProvider.getSchemas()).thenReturn(schemas);
+
+    EdmServiceMetadata serviceMetadata = new EdmServiceMetadataImplProv(edmProvider);
+
+    List<EdmEntitySetInfo> infos = serviceMetadata.getEntitySetInfos();
+    assertNotNull(infos);
+    assertEquals(2, infos.size());
+
+    assertEquals(infos.get(0).getEntitySetName(), "Employees");
+    assertEquals(infos.get(0).getEntityContainerName(), "Container");
+    assertEquals(infos.get(0).getEntitySetUri().toASCIIString(), entitySetUriString);
+    assertTrue(infos.get(0).isDefaultEntityContainer());
+
+    assertEquals(infos.get(1).getEntitySetName(), "Employees");
+    assertEquals(infos.get(1).getEntityContainerName(), "Container2");
+    assertEquals(infos.get(1).getEntitySetUri().toASCIIString(), entitySetUriString2);
+    assertFalse(infos.get(1).isDefaultEntityContainer());
+  }
+
+  @Test
+  public void oneEntitySetsOneContainerTwoSchemadForInfo() throws Exception {
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    EntitySet entitySet = new EntitySet().setName("Employees");
+    entitySets.add(entitySet);
+
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    EntityContainer container = new EntityContainer().setDefaultEntityContainer(true).setName("Container").setEntitySets(entitySets);
+    entityContainers.add(container);
+
+    List<Schema> schemas = new ArrayList<Schema>();
+    schemas.add(new Schema().setEntityContainers(entityContainers));
+    schemas.add(new Schema().setEntityContainers(entityContainers));
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    when(edmProvider.getSchemas()).thenReturn(schemas);
+
+    EdmServiceMetadata serviceMetadata = new EdmServiceMetadataImplProv(edmProvider);
+
+    List<EdmEntitySetInfo> infos = serviceMetadata.getEntitySetInfos();
+    assertNotNull(infos);
+    assertEquals(2, infos.size());
+  }
+
+  @Test
+  public void dataServiceVersion() throws Exception {
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    EdmServiceMetadata serviceMetadata = edmImplProv.getServiceMetadata();
+    assertEquals("1.0", serviceMetadata.getDataServiceVersion());
+  }
+
+  @Test
+  public void testSchemaStructure() throws Exception {
+    assertXpathExists("/edmx:Edmx", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:ComplexType", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer", metadata);
+  }
+
+  @Test
+  public void testEntityTypeStructure() throws Exception {
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name and @m:HasStream]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name and @BaseType and @m:HasStream]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Key", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Key/a:PropertyRef[@Name]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @Nullable and @m:FC_TargetPath]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:NavigationProperty[@Name and @Relationship and @FromRole and @ToRole]", metadata);
+  }
+
+  @Test
+  public void testAnnotations() throws Exception {
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @Nullable and @annoPrefix:annoName]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @m:FC_TargetPath and @annoPrefix:annoName]", metadata);
+  }
+
+  @Test
+  public void testComplexTypeStructure() throws Exception {
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:ComplexType[@Name]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:ComplexType/a:Property[@Name and @Type]", metadata);
+  }
+
+  @Test
+  public void testEntityContainerStructure() throws Exception {
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer[@Name]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer/a:EntitySet[@Name and @EntityType]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer/a:AssociationSet[@Name and @Association]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer//a:AssociationSet/a:End[@EntitySet and @Role]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer/a:FunctionImport[@Name and @ReturnType and @EntitySet and @m:HttpMethod]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityContainer/a:FunctionImport/a:Parameter[@Name and @Type]", metadata);
+  }
+
+  @Test
+  public void testAssociationStructure() throws Exception {
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association[@Name]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association/a:End[@Type and @Multiplicity and @Role]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association/a:ReferentialConstraint/a:Principal[@Role]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association/a:ReferentialConstraint/a:Principal[@Role]/a:PropertyRef[@Name]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association/a:ReferentialConstraint/a:Dependent[@Role]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:Association/a:ReferentialConstraint/a:Dependent[@Role]/a:PropertyRef[@Name]", metadata);
+  }
+
+  @Test
+  public void testRefScenarioContent() throws Exception {
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name='Employee']", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name='Base']", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name='Team']", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name='Room']", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType[@Name='Building']", metadata);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractProviderTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractProviderTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractProviderTest.java
new file mode 100644
index 0000000..6a47e7a
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractProviderTest.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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.ep;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProvider.EntityProviderInterface;
+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.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+
+/**
+ * @author SAP AG
+*/
+public abstract class AbstractProviderTest extends AbstractXmlProducerTestHelper {
+
+  public AbstractProviderTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  protected final Logger log = LoggerFactory.getLogger(this.getClass());
+
+  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);
+    }
+  }
+
+  @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 ODataContext createContextMock() throws ODataException {
+    PathInfo pathInfo = mock(PathInfo.class);
+    when(pathInfo.getServiceRoot()).thenReturn(BASE_URI);
+    ODataContext ctx = mock(ODataContext.class);
+    when(ctx.getPathInfo()).thenReturn(pathInfo);
+    return ctx;
+  }
+
+  protected EntityProviderInterface createEntityProvider() throws ODataException, EdmException, EntityProviderException {
+    return new ProviderFacadeImpl();
+  }
+
+  protected AtomEntityProvider createAtomEntityProvider() throws EntityProviderException {
+    return new AtomEntityProvider();
+  }
+
+  public Map<String, Object> getEmployeeData() {
+    return employeeData;
+  }
+
+  public List<Map<String, Object>> getEmployeesData() {
+    return employeesData;
+  }
+
+  public Map<String, Object> getRoomData() {
+    return roomData;
+  }
+
+  public ArrayList<Map<String, Object>> getRoomsData() {
+    return roomsData;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
new file mode 100644
index 0000000..f86b658
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/AbstractXmlProducerTestHelper.java
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.ep;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+@RunWith(Parameterized.class)
+public abstract class AbstractXmlProducerTestHelper extends BaseTest {
+
+  public enum StreamWriterImplType {
+    WOODSTOCKIMPL, SUNINTERNALIMPL;
+  }
+
+  // CHECKSTYLE:OFF
+  public AbstractXmlProducerTestHelper(final StreamWriterImplType type) {
+    switch (type) {
+    case WOODSTOCKIMPL:
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory"); //NOSONAR
+      break;
+    case SUNINTERNALIMPL:
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); //NOSONAR
+      break;
+    default:
+      System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); //NOSONAR
+      break;
+    }
+  }
+
+  // CHECKSTYLE:On
+
+  @Parameterized.Parameters
+  public static List<Object[]> data() {
+    // If desired this can be made dependent on runtime variables
+    Object[][] a;
+    a = new Object[2][1];
+    a[0][0] = StreamWriterImplType.WOODSTOCKIMPL;
+    a[1][0] = StreamWriterImplType.SUNINTERNALIMPL;
+
+    return Arrays.asList(a);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/BasicProviderTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/BasicProviderTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/BasicProviderTest.java
new file mode 100644
index 0000000..34b9991
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/BasicProviderTest.java
@@ -0,0 +1,203 @@
+/*******************************************************************************
+ * 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.ep;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXpathExists;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.custommonkey.xmlunit.SimpleNamespaceContext;
+import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.EdmTestProvider;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ * @author SAP AG
+ */
+public class BasicProviderTest extends AbstractProviderTest {
+
+  public BasicProviderTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  protected static BasicEntityProvider provider = new BasicEntityProvider();
+
+  @Test
+  public void writeMetadata() throws Exception {
+    Map<String, String> predefinedNamespaces = new HashMap<String, String>();
+    predefinedNamespaces.put("annoPrefix", "http://annoNamespace");
+    predefinedNamespaces.put("sap", "http://sap");
+    predefinedNamespaces.put("annoPrefix2", "http://annoNamespace");
+    predefinedNamespaces.put("annoPrefix", "http://annoNamespace");
+
+    ODataResponse response = provider.writeMetadata(null, predefinedNamespaces);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertEquals(ContentType.APPLICATION_XML_CS_UTF_8.toString(), response.getContentHeader());
+    String metadata = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertTrue(metadata.contains("xmlns:sap=\"http://sap\""));
+    assertTrue(metadata.contains("xmlns:annoPrefix=\"http://annoNamespace\""));
+    assertTrue(metadata.contains("xmlns:annoPrefix2=\"http://annoNamespace\""));
+  }
+
+  private void setNamespaces() {
+    Map<String, String> prefixMap = new HashMap<String, String>();
+    prefixMap.put("edmx", Edm.NAMESPACE_EDMX_2007_06);
+    prefixMap.put("m", Edm.NAMESPACE_M_2007_08);
+    prefixMap.put("a", Edm.NAMESPACE_EDM_2008_09);
+    prefixMap.put("annoPrefix", "http://annoNamespace");
+    prefixMap.put("prefix", "namespace");
+    prefixMap.put("b", "RefScenario");
+    prefixMap.put("pre", "namespaceForAnno");
+    XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(prefixMap));
+  }
+
+  @Test
+  public void writeMetadata2() throws Exception {
+    EdmProvider testProvider = new EdmTestProvider();
+
+    Map<String, String> predefinedNamespaces = new HashMap<String, String>();
+    predefinedNamespaces.put("annoPrefix", "http://annoNamespace");
+    predefinedNamespaces.put("sap", "http://sap");
+    predefinedNamespaces.put("annoPrefix2", "http://annoNamespace");
+    predefinedNamespaces.put("annoPrefix", "http://annoNamespace");
+    predefinedNamespaces.put("prefix", "namespace");
+    predefinedNamespaces.put("pre", "namespaceForAnno");
+
+    ODataResponse response = provider.writeMetadata(testProvider.getSchemas(), predefinedNamespaces);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertEquals(ContentType.APPLICATION_XML_CS_UTF_8.toString(), response.getContentHeader());
+    String metadata = StringHelper.inputStreamToString((InputStream) response.getEntity());
+
+    setNamespaces();
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @Nullable and @annoPrefix:annoName]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @m:FC_TargetPath and @annoPrefix:annoName]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name=\"EmployeeName\"]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name=\"EmployeeName\"]/a:propertyAnnoElement", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name=\"EmployeeName\"]/a:propertyAnnoElement2", metadata);
+
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1/b:schemaElementTest2", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1/prefix:schemaElementTest3", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1/a:schemaElementTest4[@rel=\"self\" and @pre:href=\"http://google.com\"]", metadata);
+  }
+
+  @Test
+  public void writeMetadata3() throws Exception {
+    EdmProvider testProvider = new EdmTestProvider();
+
+    ODataResponse response = provider.writeMetadata(testProvider.getSchemas(), null);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertEquals(ContentType.APPLICATION_XML_CS_UTF_8.toString(), response.getContentHeader());
+    String metadata = StringHelper.inputStreamToString((InputStream) response.getEntity());
+
+    setNamespaces();
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @Nullable and @annoPrefix:annoName]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name and @Type and @m:FC_TargetPath and @annoPrefix:annoName]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name=\"EmployeeName\"]", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name=\"EmployeeName\"]/a:propertyAnnoElement", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:EntityType/a:Property[@Name=\"EmployeeName\"]/a:propertyAnnoElement2", metadata);
+
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1/b:schemaElementTest2", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1/prefix:schemaElementTest3", metadata);
+    assertXpathExists("/edmx:Edmx/edmx:DataServices/a:Schema/a:schemaElementTest1/a:schemaElementTest4[@rel=\"self\" and @pre:href=\"http://google.com\"]", metadata);
+  }
+
+  @Test
+  public void writePropertyValue() throws Exception {
+    EdmTyped edmTyped = MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+    EdmProperty edmProperty = (EdmProperty) edmTyped;
+
+    ODataResponse response = provider.writePropertyValue(edmProperty, employeeData.get("Age"));
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertEquals(ContentType.TEXT_PLAIN_CS_UTF_8.toString(), response.getContentHeader());
+    String value = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals(employeeData.get("Age").toString(), value);
+  }
+
+  @Test
+  public void readPropertyValue() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    final Integer age = (Integer) provider.readPropertyValue(property, new ByteArrayInputStream("42".getBytes("UTF-8")), null);
+    assertEquals(Integer.valueOf(42), age);
+  }
+
+  @Test
+  public void readPropertyValueWithMapping() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    final Long age = (Long) provider.readPropertyValue(property, new ByteArrayInputStream("42".getBytes("UTF-8")), Long.class);
+    assertEquals(Long.valueOf(42), age);
+  }
+
+  @Test(expected = EntityProviderException.class)
+  public void readPropertyValueWithInvalidMapping() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+
+    final Float age = (Float) provider.readPropertyValue(property, new ByteArrayInputStream("42".getBytes("UTF-8")), Float.class);
+    assertEquals(Float.valueOf(42), age);
+  }
+
+  @Test
+  public void readPropertyBinaryValue() throws Exception {
+    final byte[] bytes = new byte[] { 1, 2, 3, 4, -128 };
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario2", "Photo").getProperty("Image");
+
+    assertTrue(Arrays.equals(bytes, (byte[]) provider.readPropertyValue(property, new ByteArrayInputStream(bytes), null)));
+  }
+
+  @Test
+  public void writeBinary() throws Exception {
+    final byte[] bytes = new byte[] { 49, 50, 51, 52, 65 };
+    final ODataResponse response = provider.writeBinary(ContentType.TEXT_PLAIN_CS_UTF_8.toString(), bytes);
+    assertNotNull(response);
+    assertNotNull(response.getEntity());
+    assertEquals(ContentType.TEXT_PLAIN_CS_UTF_8.toString(), response.getContentHeader());
+    final String value = StringHelper.inputStreamToString((InputStream) response.getEntity());
+    assertEquals("1234A", value);
+  }
+
+  @Test
+  public void readBinary() throws Exception {
+    final byte[] bytes = new byte[] { 1, 2, 3, 4, -128 };
+    assertTrue(Arrays.equals(bytes, provider.readBinary(new ByteArrayInputStream(bytes))));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/LoadXMLFactoryTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/LoadXMLFactoryTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/LoadXMLFactoryTest.java
new file mode 100644
index 0000000..37c2534
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/LoadXMLFactoryTest.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.ep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import javax.xml.stream.XMLOutputFactory;
+
+import org.junit.Test;
+
+/**
+ * @author SAP AG
+ */
+public class LoadXMLFactoryTest {
+  // CHECKSTYLE:OFF
+  @Test
+  public void loadWoodstockFactory() throws Exception {
+    System.setProperty("javax.xml.stream.XMLOutputFactory", "com.ctc.wstx.stax.WstxOutputFactory"); //NOSONAR
+    XMLOutputFactory factory = XMLOutputFactory.newInstance();
+    assertNotNull(factory);
+    assertEquals("com.ctc.wstx.stax.WstxOutputFactory", factory.getClass().getName());
+  }
+
+  @Test
+  public void loadSunFactory() throws Exception {
+    System.setProperty("javax.xml.stream.XMLOutputFactory", "com.sun.xml.internal.stream.XMLOutputFactoryImpl"); //NOSONAR
+    XMLOutputFactory factory = XMLOutputFactory.newInstance();
+    assertNotNull(factory);
+    assertEquals("com.sun.xml.internal.stream.XMLOutputFactoryImpl", factory.getClass().getName());
+  }
+  // CHECKSTYLE:ON
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
new file mode 100644
index 0000000..f1590e3
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ODataEntityProviderPropertiesTest.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.ep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.net.URI;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class ODataEntityProviderPropertiesTest extends BaseTest {
+
+  @Test
+  public void buildFeedProperties() throws Exception {
+    URI serviceRoot = new URI("http://localhost:80/");
+    EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(serviceRoot)
+        .inlineCountType(InlineCount.ALLPAGES)
+        .inlineCount(1)
+        .nextLink("http://localhost")
+        .build();
+
+    assertEquals("Wrong base uri.", "http://localhost:80/", properties.getServiceRoot().toASCIIString());
+    assertEquals("Wrong inline count type.", InlineCount.ALLPAGES, properties.getInlineCountType());
+    assertEquals("Wrong inline count.", Integer.valueOf(1), properties.getInlineCount());
+    assertEquals("Wrong nextLink", "http://localhost", properties.getNextLink());
+  }
+
+  @Test
+  public void buildPropertiesDefaults() throws Exception {
+    URI baseUri = new URI("http://localhost:80/");
+    EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(baseUri).build();
+
+    assertEquals("http://localhost:80/", properties.getServiceRoot().toASCIIString());
+    assertNull(properties.getInlineCountType());
+    assertNull(properties.getInlineCount());
+    assertNull(properties.getMediaResourceMimeType());
+    assertNull(properties.getNextLink());
+  }
+
+  @Test
+  public void buildEntryProperties() throws Exception {
+    final String mediaResourceMimeType = "text/html";
+    final URI serviceRoot = new URI("http://localhost:80/");
+    final EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(serviceRoot)
+        .mediaResourceMimeType(mediaResourceMimeType)
+        .build();
+    assertEquals("Wrong mime type.", "text/html", properties.getMediaResourceMimeType());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/PerformanceTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/PerformanceTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/PerformanceTest.java
new file mode 100644
index 0000000..bfbfe69
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/PerformanceTest.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.ep;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.custommonkey.xmlunit.exceptions.XpathException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.ep.aggregator.EntityInfoAggregator;
+import org.apache.olingo.odata2.core.ep.producer.AtomEntryEntityProducer;
+import org.apache.olingo.odata2.core.ep.util.CircleStreamBuffer;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ * @author SAP AG
+ */
+public class PerformanceTest extends AbstractProviderTest {
+
+  public PerformanceTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  private static final long TIMES = 100L; // increase for manual performance testing (also increase vm memory -Xmx1G)
+
+  private AtomEntryEntityProducer provider;
+  private EdmEntitySet edmEntitySet;
+  private OutputStream outStream = null;
+  private CircleStreamBuffer csb;
+  private XMLStreamWriter writer;
+
+  private boolean useCsb = true;
+
+  @Before
+  public void before() throws Exception {
+    EntityProviderWriteProperties properties = EntityProviderWriteProperties.serviceRoot(BASE_URI).build();
+    provider = new AtomEntryEntityProducer(properties);
+    edmEntitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+
+    if (useCsb) {
+      csb = new CircleStreamBuffer();
+      outStream = csb.getOutputStream();
+    } else {
+      outStream = new ByteArrayOutputStream();
+    }
+
+    writer = XMLOutputFactory.newInstance().createXMLStreamWriter(outStream, "utf-8");
+
+    writer.writeStartElement("junit");
+    writer.writeDefaultNamespace(Edm.NAMESPACE_ATOM_2005);
+    writer.writeNamespace(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+    writer.writeNamespace(Edm.PREFIX_D, Edm.NAMESPACE_D_2007_08);
+    writer.writeAttribute(Edm.PREFIX_XML, Edm.NAMESPACE_XML_1998, "base", "xxx");
+  }
+
+  @After
+  public void after() throws Exception {
+    writer.writeEndElement();
+    writer.flush();
+    outStream.flush();
+
+    if (useCsb) {
+      String content = StringHelper.inputStreamToString(csb.getInputStream());
+      assertNotNull(content);
+    } else {
+      InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream) outStream).toByteArray());
+      String content = StringHelper.inputStreamToString(in);
+      assertNotNull(content);
+    }
+
+    try {
+
+    } finally {
+      outStream.close();
+    }
+  }
+
+  @Test
+  public void readAtomEntry() throws IOException, XpathException, SAXException, XMLStreamException, FactoryConfigurationError, ODataException {
+    long t = startTimer();
+
+    for (int i = 0; i < TIMES; i++) {
+      ExpandSelectTreeNode epProperties = null;
+      EntityInfoAggregator eia = EntityInfoAggregator.create(edmEntitySet, epProperties);
+      provider.append(writer, eia, roomData, false, false);
+    }
+    stopTimer(t, "readAtomEntry");
+  }
+
+  @Test
+  public void readAtomEntryCsb() throws Exception {
+    useCsb = true;
+    before();
+    assertNotNull(csb);
+
+    long t = startTimer();
+
+    for (int i = 0; i < TIMES; i++) {
+      ExpandSelectTreeNode epProperties = null;
+      EntityInfoAggregator eia = EntityInfoAggregator.create(edmEntitySet, epProperties);
+      provider.append(writer, eia, roomData, false, false);
+    }
+    stopTimer(t, "readAtomEntry");
+  }
+
+  @Test
+  public void readAtomEntryOptimized() throws IOException, XpathException, SAXException, XMLStreamException, FactoryConfigurationError, ODataException {
+    long t = startTimer();
+
+    ExpandSelectTreeNode epProperties = null;
+    EntityInfoAggregator eia = EntityInfoAggregator.create(edmEntitySet, epProperties);
+    for (int i = 0; i < TIMES; i++) {
+      provider.append(writer, eia, roomData, false, false);
+    }
+    stopTimer(t, "readAtomEntryOptimized");
+  }
+
+  @Test
+  public void readAtomEntryOptimizedCsb() throws Exception {
+    useCsb = true;
+    before();
+    assertNotNull(csb);
+
+    long t = startTimer();
+
+    ExpandSelectTreeNode epProperties = null;
+    EntityInfoAggregator eia = EntityInfoAggregator.create(edmEntitySet, epProperties);
+    for (int i = 0; i < TIMES; i++) {
+      provider.append(writer, eia, roomData, false, false);
+    }
+    stopTimer(t, "readAtomEntryOptimizedCsb");
+  }
+
+  private void stopTimer(long t, final String msg) {
+    t = (System.nanoTime() - t) / TIMES;
+
+    long millis = t / (1000L * 1000L);
+    long micros = t % (1000L * 1000L);
+
+    long sum = (t * TIMES) / (1000L * 1000L);
+
+    log.debug(msg + ": " + millis + "." + micros / 1000L + "[ms] (" + TIMES + " in " + sum + " [ms])");
+  }
+
+  private long startTimer() {
+    long t = System.nanoTime();
+    return t;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
new file mode 100644
index 0000000..e34131d
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/ProviderFacadeImplTest.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * 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.ep;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ * @author SAP AG
+ */
+public class ProviderFacadeImplTest {
+
+  private static final String EMPLOYEE_1_XML =
+      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
+          "<entry xmlns=\"" + Edm.NAMESPACE_ATOM_2005 + "\"" +
+          " xmlns:m=\"" + Edm.NAMESPACE_M_2007_08 + "\"" +
+          " xmlns:d=\"" + Edm.NAMESPACE_D_2007_08 + "\"" +
+          " xml:base=\"https://some.host.com/some.service.root.segment/ReferenceScenario.svc/\">" +
+          "<id>https://some.host.com/some.service.root.segment/ReferenceScenario.svc/Employees('1')</id>" +
+          "<title type=\"text\">Walter Winter</title>" +
+          "<updated>1999-01-01T00:00:00Z</updated>" +
+          "<category term=\"RefScenario.Employee\" scheme=\"" + Edm.NAMESPACE_SCHEME_2007_08 + "\"/>" +
+          "<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_Room\" rel=\"" + Edm.NAMESPACE_REL_2007_08 + "ne_Room\" type=\"application/atom+xml; type=entry\" title=\"ne_Room\"/>" +
+          "<link href=\"Employees('1')/ne_Manager\" rel=\"" + Edm.NAMESPACE_REL_2007_08 + "ne_Manager\" type=\"application/atom+xml; type=entry\" title=\"ne_Manager\"/>" +
+          "<link href=\"Employees('1')/ne_Team\" rel=\"" + Edm.NAMESPACE_REL_2007_08 + "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>male_1_WinterW.jpg</d:ImageUrl>" +
+          "</m:properties>" +
+          "</entry>";
+
+  @Test
+  public void readEntry() throws Exception {
+    final String contentType = ContentType.APPLICATION_ATOM_XML_ENTRY.toContentTypeString();
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+    InputStream content = new ByteArrayInputStream(EMPLOYEE_1_XML.getBytes("UTF-8"));
+
+    final ODataEntry result = new ProviderFacadeImpl().readEntry(contentType, entitySet, content, EntityProviderReadProperties.init().mergeSemantic(true).build());
+    assertNotNull(result);
+    assertFalse(result.containsInlineEntry());
+    assertNotNull(result.getExpandSelectTree());
+    assertTrue(result.getExpandSelectTree().isAll());
+    assertNotNull(result.getMetadata());
+    assertNull(result.getMetadata().getEtag());
+    assertNotNull(result.getMediaMetadata());
+    assertEquals(HttpContentType.APPLICATION_OCTET_STREAM, result.getMediaMetadata().getContentType());
+    assertNotNull(result.getProperties());
+    assertEquals(52, result.getProperties().get("Age"));
+  }
+
+  @Test
+  public void readPropertyValue() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("EntryDate");
+    InputStream content = new ByteArrayInputStream("2012-02-29T01:02:03".getBytes("UTF-8"));
+    final Object result = new ProviderFacadeImpl().readPropertyValue(property, content, Long.class);
+    assertEquals(1330477323000L, result);
+  }
+
+  @Test
+  public void readProperty() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("Age");
+    final String xml = "<Age xmlns=\"" + Edm.NAMESPACE_D_2007_08 + "\">42</Age>";
+    InputStream content = new ByteArrayInputStream(xml.getBytes("UTF-8"));
+    final Map<String, Object> result = new ProviderFacadeImpl().readProperty(HttpContentType.APPLICATION_XML, property, content, EntityProviderReadProperties.init().build());
+    assertFalse(result.isEmpty());
+    assertEquals(42, result.get("Age"));
+  }
+
+  @Test
+  public void readLink() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream content = new ByteArrayInputStream("{\"d\":{\"uri\":\"http://somelink\"}}".getBytes("UTF-8"));
+    final String result = new ProviderFacadeImpl().readLink(HttpContentType.APPLICATION_JSON, entitySet, content);
+    assertEquals("http://somelink", result);
+  }
+
+  @Test
+  public void readLinks() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    InputStream content = new ByteArrayInputStream("{\"d\":{\"__count\":\"42\",\"results\":[{\"uri\":\"http://somelink\"}]}}".getBytes("UTF-8"));
+    final List<String> result = new ProviderFacadeImpl().readLinks(HttpContentType.APPLICATION_JSON, entitySet, content);
+    assertEquals(Arrays.asList("http://somelink"), result);
+  }
+
+  @Test
+  public void writeFeed() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    List<Map<String, Object>> propertiesList = new ArrayList<Map<String, Object>>();
+    final ODataResponse result = new ProviderFacadeImpl().writeFeed(HttpContentType.APPLICATION_JSON, entitySet, propertiesList, EntityProviderWriteProperties.serviceRoot(URI.create("http://root/")).build());
+    assertEquals("{\"d\":{\"results\":[]}}", StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeEntry() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Teams");
+    Map<String, Object> properties = new HashMap<String, Object>();
+    properties.put("Id", "42");
+    final ODataResponse result = new ProviderFacadeImpl().writeEntry(HttpContentType.APPLICATION_JSON, entitySet, properties, EntityProviderWriteProperties.serviceRoot(URI.create("http://root/")).build());
+    assertEquals("{\"d\":{\"__metadata\":{\"id\":\"http://root/Teams('42')\","
+        + "\"uri\":\"http://root/Teams('42')\",\"type\":\"RefScenario.Team\"},"
+        + "\"Id\":\"42\",\"Name\":null,\"isScrumTeam\":null,"
+        + "\"nt_Employees\":{\"__deferred\":{\"uri\":\"http://root/Teams('42')/nt_Employees\"}}}}",
+        StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeProperty() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("EntryDate");
+    final ODataResponse result = new ProviderFacadeImpl().writeProperty(HttpContentType.APPLICATION_XML, property, 987654321000L);
+    assertEquals(HttpContentType.APPLICATION_XML_UTF8, result.getContentHeader());
+    assertTrue(StringHelper.inputStreamToString((InputStream) result.getEntity())
+        .endsWith("\">2001-04-19T04:25:21</EntryDate>"));
+  }
+
+  @Test
+  public void writeLink() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Map<String, Object> properties = new HashMap<String, Object>();
+    properties.put("Id", "42");
+    final ODataResponse result = new ProviderFacadeImpl().writeLink(HttpContentType.APPLICATION_JSON, entitySet, properties, EntityProviderWriteProperties.serviceRoot(URI.create("http://root/")).build());
+    assertEquals("{\"d\":{\"uri\":\"http://root/Rooms('42')\"}}",
+        StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeLinks() throws Exception {
+    final EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Rooms");
+    Map<String, Object> properties = new HashMap<String, Object>();
+    properties.put("Id", "42");
+    List<Map<String, Object>> propertiesList = new ArrayList<Map<String, Object>>();
+    propertiesList.add(properties);
+    propertiesList.add(properties);
+    final ODataResponse result = new ProviderFacadeImpl().writeLinks(HttpContentType.APPLICATION_JSON, entitySet, propertiesList, EntityProviderWriteProperties.serviceRoot(URI.create("http://root/")).build());
+    assertEquals("{\"d\":[{\"uri\":\"http://root/Rooms('42')\"},{\"uri\":\"http://root/Rooms('42')\"}]}",
+        StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeServiceDocument() throws Exception {
+    final ODataResponse result = new ProviderFacadeImpl().writeServiceDocument(HttpContentType.APPLICATION_JSON, MockFacade.getMockEdm(), "root");
+    assertEquals("{\"d\":{\"EntitySets\":[]}}", StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writePropertyValue() throws Exception {
+    final EdmProperty property = (EdmProperty) MockFacade.getMockEdm().getEntityType("RefScenario", "Employee").getProperty("EntryDate");
+    final ODataResponse result = new ProviderFacadeImpl().writePropertyValue(property, 987654321000L);
+    assertEquals(HttpContentType.TEXT_PLAIN_UTF8, result.getContentHeader());
+    assertEquals("2001-04-19T04:25:21", StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeText() throws Exception {
+    final ODataResponse result = new ProviderFacadeImpl().writeText("test");
+    assertEquals(HttpContentType.TEXT_PLAIN_UTF8, result.getContentHeader());
+    assertEquals("test", StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeBinary() throws Exception {
+    final ODataResponse result = new ProviderFacadeImpl().writeBinary(HttpContentType.APPLICATION_OCTET_STREAM, new byte[] { 102, 111, 111 });
+    assertEquals(HttpContentType.APPLICATION_OCTET_STREAM, result.getContentHeader());
+    assertEquals("foo", StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+  @Test
+  public void writeBinaryNoContent() throws Exception {
+    final ODataResponse result = new ProviderFacadeImpl().writeBinary(HttpContentType.APPLICATION_OCTET_STREAM, null);
+    assertNull(result.getEntity());
+    assertNull(result.getContentHeader());
+    assertEquals(HttpStatusCodes.NO_CONTENT, result.getStatus());
+  }
+
+  @Test
+  public void writeFunctionImport() throws Exception {
+    final EdmFunctionImport function = MockFacade.getMockEdm().getDefaultEntityContainer().getFunctionImport("MaximalAge");
+    Map<String, Object> properties = new HashMap<String, Object>();
+    properties.put("MaximalAge", 99);
+    final ODataResponse result = new ProviderFacadeImpl().writeFunctionImport(HttpContentType.APPLICATION_JSON, function, properties, null);
+    assertEquals("{\"d\":{\"MaximalAge\":99}}", StringHelper.inputStreamToString((InputStream) result.getEntity()));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregatorTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregatorTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregatorTest.java
new file mode 100644
index 0000000..be45e5d
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/aggregator/EntityInfoAggregatorTest.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.ep.aggregator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.core.ep.AbstractProviderTest;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ * @author SAP AG
+ */
+public class EntityInfoAggregatorTest extends AbstractProviderTest {
+
+  public EntityInfoAggregatorTest(final StreamWriterImplType type) {
+    super(type);
+  }
+
+  @Test
+  public void testEntitySet() throws Exception {
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet("Employees");
+
+    ExpandSelectTreeNode epProperties = null;
+    EntityInfoAggregator eia = EntityInfoAggregator.create(entitySet, epProperties);
+
+    assertNotNull(eia);
+    EntityPropertyInfo propertyInfoAge = eia.getPropertyInfo("Age");
+    assertFalse(propertyInfoAge.isComplex());
+    assertEquals("Age", propertyInfoAge.getName());
+    assertEquals("Int32", propertyInfoAge.getType().getName());
+    EntityPropertyInfo propertyInfoLocation = eia.getPropertyInfo("Location");
+    assertTrue(propertyInfoLocation.isComplex());
+    assertNull(eia.getPropertyInfo("City"));
+    assertEquals("Location", propertyInfoLocation.getName());
+    EntityComplexPropertyInfo locationInfo = (EntityComplexPropertyInfo) propertyInfoLocation;
+    assertEquals(2, locationInfo.getPropertyInfos().size());
+
+    assertEquals("Country", locationInfo.getPropertyInfo("Country").getName());
+    assertEquals("String", locationInfo.getPropertyInfo("Country").getType().getName());
+    assertEquals(EdmTypeKind.SIMPLE, locationInfo.getPropertyInfo("Country").getType().getKind());
+
+    EntityComplexPropertyInfo cityInfo = (EntityComplexPropertyInfo) locationInfo.getPropertyInfo("City");
+    assertTrue(cityInfo.isComplex());
+    assertEquals("City", cityInfo.getName());
+    assertEquals("c_City", cityInfo.getType().getName());
+    assertEquals(EdmTypeKind.COMPLEX, cityInfo.getType().getKind());
+    assertEquals("CityName", cityInfo.getPropertyInfo("CityName").getName());
+    assertFalse(cityInfo.getPropertyInfo("CityName").isComplex());
+    assertEquals("String", cityInfo.getPropertyInfo("CityName").getType().getName());
+    assertEquals("PostalCode", cityInfo.getPropertyInfo("PostalCode").getName());
+    assertFalse(cityInfo.getPropertyInfo("PostalCode").isComplex());
+    assertEquals("String", cityInfo.getPropertyInfo("PostalCode").getType().getName());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AbstractConsumerTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AbstractConsumerTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AbstractConsumerTest.java
new file mode 100644
index 0000000..b3a3968
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ep/consumer/AbstractConsumerTest.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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.ep.consumer;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+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.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ * @author SAP AG
+ */
+public abstract class AbstractConsumerTest extends BaseTest {
+
+  protected static final EntityProviderReadProperties DEFAULT_PROPERTIES = EntityProviderReadProperties.init().mergeSemantic(false).build();
+
+  protected XMLStreamReader createReaderForTest(final String input) throws XMLStreamException {
+    return createReaderForTest(input, false);
+  }
+
+  protected XMLStreamReader createReaderForTest(final String input, final boolean namespaceAware) throws XMLStreamException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, namespaceAware);
+
+    XMLStreamReader streamReader = factory.createXMLStreamReader(new StringReader(input));
+
+    return streamReader;
+  }
+
+  protected Map<String, Object> createTypeMappings(final String key, final Object value) {
+    Map<String, Object> typeMappings = new HashMap<String, Object>();
+    typeMappings.put(key, value);
+    return typeMappings;
+  }
+
+  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 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();
+  }
+
+  /**
+   * 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;
+  }
+
+  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"));
+  }
+
+  protected ODataEntry prepareAndExecuteEntry(final String fileName, final String entitySetName, final EntityProviderReadProperties readProperties) throws IOException, EdmException, ODataException, UnsupportedEncodingException, EntityProviderException {
+    //prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet(entitySetName);
+    String content = readFile(fileName);
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    JsonEntityConsumer xec = new JsonEntityConsumer();
+    ODataEntry result = xec.readEntry(entitySet, contentBody, readProperties);
+    assertNotNull(result);
+    return result;
+  }
+
+  protected ODataFeed prepareAndExecuteFeed(final String fileName, final String entitySetName, final EntityProviderReadProperties readProperties) throws IOException, EdmException, ODataException, UnsupportedEncodingException, EntityProviderException {
+    //prepare
+    EdmEntitySet entitySet = MockFacade.getMockEdm().getDefaultEntityContainer().getEntitySet(entitySetName);
+    String content = readFile(fileName);
+    assertNotNull(content);
+    InputStream contentBody = createContentAsStream(content);
+
+    // execute
+    JsonEntityConsumer xec = new JsonEntityConsumer();
+    ODataFeed result = xec.readFeed(entitySet, contentBody, readProperties);
+    assertNotNull(result);
+    return result;
+  }
+
+}


[29/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataApplicationException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataApplicationException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataApplicationException.java
new file mode 100644
index 0000000..318dbe0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataApplicationException.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * This class represents a translated application exception. Use this exception class to display custom exception messages. 
+ * <br>If a HTTP status is given this exception will result in the set status code like an HTTP exception. 
+ * <br>A set status code can be used to show a substatus to a HTTP status as described in the OData protocol specification. 
+ * @author SAP AG
+ */
+public class ODataApplicationException extends ODataException {
+
+  private static final long serialVersionUID = 1L;
+  private String errorCode;
+  private HttpStatusCodes httpStatus = HttpStatusCodes.INTERNAL_SERVER_ERROR;
+  private final Locale locale;
+
+  /**
+   * Since this is a translated application exception locale must not be null.
+   * @param message
+   * @param locale
+   */
+  public ODataApplicationException(final String message, final Locale locale) {
+    super(message);
+    this.locale = locale;
+  }
+
+  /**
+   * Since this is a translated application exception locale must not be null. 
+   * <br>The status code given will be  displayed at the client.
+   * @param message
+   * @param locale
+   * @param status
+   */
+  public ODataApplicationException(final String message, final Locale locale, final HttpStatusCodes status) {
+    this(message, locale);
+    httpStatus = status;
+  }
+
+  /**
+   * Since this is a translated application exception locale must not be null.
+   * <br>The status code given will be displayed at the client.
+   * <br>The error code may be used as a substatus for the HTTP status code as described in the OData protocol specification.
+   * @param message
+   * @param locale
+   * @param status
+   * @param errorCode
+   */
+  public ODataApplicationException(final String message, final Locale locale, final HttpStatusCodes status, final String errorCode) {
+    this(message, locale, status);
+    this.errorCode = errorCode;
+  }
+
+  /**   
+   * Since this is a translated application exception locale must not be null.  
+   * <br>The status code given will be displayed at the client.
+   * <br>The error code may be used as a substatus for the HTTP status code as described in the OData protocol specification.
+   * @param message
+   * @param locale
+   * @param status
+   * @param errorCode
+   * @param e
+   */
+  public ODataApplicationException(final String message, final Locale locale, final HttpStatusCodes status, final String errorCode, final Throwable e) {
+    super(message, e);
+    this.errorCode = errorCode;
+    httpStatus = status;
+    this.locale = locale;
+  }
+
+  /**
+   * Since this is a translated application exception locale must not be null.
+   * @param message
+   * @param locale
+   * @param e
+   */
+  public ODataApplicationException(final String message, final Locale locale, final Throwable e) {
+    super(message, e);
+    this.locale = locale;
+  }
+
+  /**
+   * Since this is a translated application exception locale must not be null.
+   * <br>The status code given will be displayed at the client.
+   * @param message
+   * @param locale
+   * @param status
+   * @param e
+   */
+  public ODataApplicationException(final String message, final Locale locale, final HttpStatusCodes status, final Throwable e) {
+    this(message, locale, e);
+    httpStatus = status;
+  }
+
+  /**
+   * Since this is a translated application exception locale must not be null.
+   * <br>The error code may be used as a substatus for the HTTP status code as described in the OData protocol specification.
+   * @param message
+   * @param locale
+   * @param errorCode
+   * @param e
+   */
+  public ODataApplicationException(final String message, final Locale locale, final String errorCode, final Throwable e) {
+    this(message, locale, e);
+    this.errorCode = errorCode;
+
+  }
+
+  /**
+   * @return {@link Locale} the locale
+   */
+  public Locale getLocale() {
+    return locale;
+  }
+
+  /**
+   * Default HttpStatusCodes.INTERNAL_SERVER_ERROR
+   * @return {@link HttpStatusCodes} the status code 
+   */
+  public HttpStatusCodes getHttpStatus() {
+    return httpStatus;
+  }
+
+  /**
+   * Default code is null
+   * @return <b>String</b>The error code displayed in the error message.
+   */
+  public String getCode() {
+    return errorCode;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataBadRequestException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataBadRequestException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataBadRequestException.java
new file mode 100644
index 0000000..19d19cc
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataBadRequestException.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 400 bad request
+ * @author SAP AG
+ */
+public class ODataBadRequestException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataBadRequestException.class, "COMMON");
+  public static final MessageReference NOTSUPPORTED = createMessageReference(ODataBadRequestException.class, "NOTSUPPORTED");
+  public static final MessageReference URLTOOSHORT = createMessageReference(ODataBadRequestException.class, "URLTOOSHORT");
+  public static final MessageReference VERSIONERROR = createMessageReference(ODataBadRequestException.class, "VERSIONERROR");
+  public static final MessageReference PARSEVERSIONERROR = createMessageReference(ODataBadRequestException.class, "PARSEVERSIONERROR");
+  public static final MessageReference BODY = createMessageReference(ODataBadRequestException.class, "BODY");
+  public static final MessageReference AMBIGUOUS_XMETHOD = createMessageReference(ODataBadRequestException.class, "AMBIGUOUS_XMETHOD");
+  /** INVALID_HEADER requires 2 content values ('header key' and 'header value') */
+  public static final MessageReference INVALID_HEADER = createMessageReference(ODataBadRequestException.class, "INVALID_HEADER");
+  /** INVALID_SYNTAX requires NO content values */
+  public static final MessageReference INVALID_SYNTAX = createMessageReference(ODataBadRequestException.class, "INVALID_SYNTAX");;
+
+  public ODataBadRequestException(final MessageReference messageReference) {
+    super(messageReference, HttpStatusCodes.BAD_REQUEST);
+  }
+
+  public ODataBadRequestException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, HttpStatusCodes.BAD_REQUEST, errorCode);
+  }
+
+  public ODataBadRequestException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause, HttpStatusCodes.BAD_REQUEST);
+  }
+
+  public ODataBadRequestException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, HttpStatusCodes.BAD_REQUEST, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataConflictException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataConflictException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataConflictException.java
new file mode 100644
index 0000000..edc2aaf
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataConflictException.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 409 Conflict
+ * @author SAP AG
+ */
+public class ODataConflictException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataConflictException.class, "COMMON");
+
+  public ODataConflictException(final MessageReference context) {
+    super(context, HttpStatusCodes.CONFLICT);
+  }
+
+  public ODataConflictException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.CONFLICT);
+  }
+
+  public ODataConflictException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.CONFLICT, errorCode);
+  }
+
+  public ODataConflictException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.CONFLICT, errorCode);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataException.java
new file mode 100644
index 0000000..09eb333
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataException.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+/**
+ * Base exception for all <code>OData</code>-related exceptions.
+ * @author SAP AG
+ */
+public class ODataException extends Exception {
+
+  private static final long serialVersionUID = 1L;
+
+  public ODataException() {
+    super();
+  }
+
+  public ODataException(final String msg) {
+    super(msg);
+  }
+
+  public ODataException(final String msg, final Throwable e) {
+    super(msg, e);
+  }
+
+  public ODataException(final Throwable e) {
+    super(e);
+  }
+
+  /**
+   * Checks whether this exception is an or was caused by an {@link ODataHttpException} exception.
+   *
+   * @return <code>true</code> if this is an or was caused by an {@link ODataHttpException}, otherwise <code>false</code>
+   */
+  public boolean isCausedByHttpException() {
+    return getHttpExceptionCause() != null;
+  }
+
+  /**
+   * Search for and return first (from top) {@link ODataHttpException} in the cause hierarchy.
+   * If there is no {@link ODataHttpException} in the cause hierarchy, <code>NULL</code> is returned.
+   * 
+   * @return the first found {@link ODataHttpException} in the cause exception hierarchy
+   *         or <code>NULL</code> if no {@link ODataHttpException} is found in the cause hierarchy
+   */
+  public ODataHttpException getHttpExceptionCause() {
+    return getSpecificCause(ODataHttpException.class);
+  }
+
+  /**
+   * Checks whether this exception is an or was caused by an {@link ODataApplicationException} exception.
+   *
+   * @return <code>true</code> if this is an or was caused by an {@link ODataApplicationException}, otherwise <code>false</code>
+   */
+  public boolean isCausedByApplicationException() {
+    return getApplicationExceptionCause() != null;
+  }
+
+  /**
+   * Checks whether this exception is an or was caused by an {@link ODataMessageException} exception.
+   * 
+   * @return <code>true</code> if this is an or was caused by an {@link ODataMessageException}, otherwise <code>false</code>
+   */
+  public boolean isCausedByMessageException() {
+    return getMessageExceptionCause() != null;
+  }
+
+  /**
+   * Search for and return first (from top) {@link ODataMessageException} in the cause hierarchy.
+   * If there is no {@link ODataMessageException} in the cause hierarchy <code>NULL</code> is returned.
+   *
+   * @return the first found {@link ODataMessageException} in the cause exception hierarchy 
+   *         or <code>NULL</code> if no {@link ODataMessageException} is found in the cause hierarchy
+   */
+  public ODataMessageException getMessageExceptionCause() {
+    return getSpecificCause(ODataMessageException.class);
+  }
+
+  /**
+   * Search for and return first (from top) {@link ODataApplicationException} in the cause hierarchy.
+   * If there is no {@link ODataApplicationException} in the cause hierarchy <code>NULL</code> is returned.
+   *
+   * @return the first found {@link ODataApplicationException} in the cause exception hierarchy
+   *         or <code>NULL</code> if no {@link ODataApplicationException} is found in the cause hierarchy
+   */
+  public ODataApplicationException getApplicationExceptionCause() {
+    return getSpecificCause(ODataApplicationException.class);
+  }
+
+  private <T extends ODataException> T getSpecificCause(final Class<T> causeClass) {
+    Throwable cause = this;
+    while (cause != null) {
+      if (causeClass.isInstance(cause)) {
+        return causeClass.cast(cause);
+      } else {
+        cause = cause.getCause();
+      }
+    }
+
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataForbiddenException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataForbiddenException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataForbiddenException.java
new file mode 100644
index 0000000..b90faf4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataForbiddenException.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 403 forbidden
+ * @author SAP AG
+ */
+public class ODataForbiddenException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataForbiddenException.class, "COMMON");
+
+  public ODataForbiddenException(final MessageReference context) {
+    super(context, HttpStatusCodes.FORBIDDEN);
+  }
+
+  public ODataForbiddenException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.FORBIDDEN);
+  }
+
+  public ODataForbiddenException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.FORBIDDEN, errorCode);
+  }
+
+  public ODataForbiddenException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.FORBIDDEN, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataHttpException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataHttpException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataHttpException.java
new file mode 100644
index 0000000..f18a921
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataHttpException.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * {@link ODataMessageException} with a HTTP status code.
+ * @author SAP AG
+ */
+public abstract class ODataHttpException extends ODataMessageException {
+
+  private static final long serialVersionUID = 1L;
+
+  protected final HttpStatusCodes httpStatus;
+
+  public static final MessageReference COMMON = createMessageReference(ODataHttpException.class, "COMMON");
+
+  public ODataHttpException(final MessageReference messageReference, final HttpStatusCodes httpStatus) {
+    this(messageReference, null, httpStatus);
+  }
+
+  public ODataHttpException(final MessageReference messageReference, final HttpStatusCodes httpStatus, final String errorCode) {
+    this(messageReference, null, httpStatus, errorCode);
+  }
+
+  public ODataHttpException(final MessageReference messageReference, final Throwable cause, final HttpStatusCodes httpStatus) {
+    this(messageReference, cause, httpStatus, null);
+  }
+
+  public ODataHttpException(final MessageReference messageReference, final Throwable cause, final HttpStatusCodes httpStatus, final String errorCode) {
+    super(messageReference, cause, errorCode);
+    this.httpStatus = httpStatus;
+  }
+
+  public HttpStatusCodes getHttpStatus() {
+    return httpStatus;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMessageException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMessageException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMessageException.java
new file mode 100644
index 0000000..7465913
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMessageException.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+/**
+ * <p>DO NOT EXTEND THIS EXCEPTION</p>
+ * APPLICATION DEVELOPERS: please use {@link ODataApplicationException} o throw custom exceptions.
+ * <p>Base exception class for all exceptions in the <code>OData</code> library.
+ * This class extends {@link ODataException} with a message that will be displayed
+ * to a possible client and therefore needs support for internationalization.
+ * <br>To support internationalization and translation of messages, this class
+ * and its sub classes contain a {@link MessageReference} object which can be
+ * mapped to a related key and message text in the resource bundles.
+ * @author SAP AG
+ */
+public abstract class ODataMessageException extends ODataException {
+
+  private static final long serialVersionUID = 42L;
+
+  /** Message reference for exception which is used for internationalization */
+  protected final MessageReference messageReference;
+  /** OData error code */
+  protected final String errorCode;
+
+  /** Reference to common message for a {@link ODataMessageException} */
+  public static final MessageReference COMMON = createMessageReference(ODataMessageException.class, "COMMON");
+
+  /**
+   * Creates {@link ODataMessageException} with given {@link MessageReference}.
+   * @param messageReference references the message text (and additional values)
+   *                         of this {@link ODataMessageException}
+   */
+  public ODataMessageException(final MessageReference messageReference) {
+    this(messageReference, null, null);
+  }
+
+  /**
+   * Creates {@link ODataMessageException} with given {@link MessageReference}
+   * and cause {@link Throwable} which caused this exception.
+   * @param messageReference references the message text (and additional values)
+   *                         of this {@link ODataMessageException}
+   * @param cause            exception which caused this exception
+   */
+  public ODataMessageException(final MessageReference messageReference, final Throwable cause) {
+    this(messageReference, cause, null);
+  }
+
+  /**
+   * Creates {@link ODataMessageException} with given {@link MessageReference},
+   * cause {@link Throwable} and error code.
+   * @param messageReference references the message text (and additional values)
+   *                         of this {@link ODataMessageException}
+   * @param cause            exception which caused this exception
+   * @param errorCode        a String with a unique code identifying this exception
+   */
+  public ODataMessageException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(cause);
+    this.messageReference = messageReference;
+    this.errorCode = errorCode;
+  }
+
+  /**
+   * Creates {@link ODataMessageException} with given {@link MessageReference} and error code.
+   * @param messageReference references the message text (and additional values)
+   *                         of this {@link ODataMessageException}
+   * @param errorCode        a String with a unique code identifying this exception
+   */
+  public ODataMessageException(final MessageReference messageReference, final String errorCode) {
+    this(messageReference, null, errorCode);
+  }
+
+  /**
+   * Creates {@link MessageReference} objects more conveniently.
+   * @param clazz               exception class for message reference
+   * @param messageReferenceKey unique (in exception class) key for message reference
+   * @return created message-reference instance
+   */
+  protected static final MessageReference createMessageReference(final Class<? extends ODataMessageException> clazz, final String messageReferenceKey) {
+    return MessageReference.create(clazz, messageReferenceKey);
+  }
+
+  /**
+   * Gets the related {@link MessageReference}.
+   * @return the message reference
+   */
+  public MessageReference getMessageReference() {
+    return messageReference;
+  }
+
+  /**
+   * Gets the error code for this {@link ODataMessageException}.
+   * Default is <code>null</code>.
+   * @return the error code
+   */
+  public String getErrorCode() {
+    return errorCode;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMethodNotAllowedException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMethodNotAllowedException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMethodNotAllowedException.java
new file mode 100644
index 0000000..e6973e8
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataMethodNotAllowedException.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 405 (method not allowed).
+ * @author SAP AG
+ */
+public class ODataMethodNotAllowedException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference DISPATCH = createMessageReference(ODataMethodNotAllowedException.class, "DISPATCH");
+
+  public ODataMethodNotAllowedException(final MessageReference messageReference) {
+    super(messageReference, HttpStatusCodes.METHOD_NOT_ALLOWED);
+  }
+
+  public ODataMethodNotAllowedException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause, HttpStatusCodes.METHOD_NOT_ALLOWED);
+  }
+
+  public ODataMethodNotAllowedException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, HttpStatusCodes.METHOD_NOT_ALLOWED, errorCode);
+  }
+
+  public ODataMethodNotAllowedException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, HttpStatusCodes.METHOD_NOT_ALLOWED, errorCode);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotAcceptableException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotAcceptableException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotAcceptableException.java
new file mode 100644
index 0000000..5cadf2e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotAcceptableException.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 406 not acceptable
+ * @author SAP AG
+ */
+public class ODataNotAcceptableException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataNotAcceptableException.class, "COMMON");
+  public static final MessageReference NOT_SUPPORTED_CONTENT_TYPE = createMessageReference(ODataNotAcceptableException.class, "NOT_SUPPORTED_CONTENT_TYPE");
+  public static final MessageReference NOT_SUPPORTED_ACCEPT_HEADER = createMessageReference(ODataNotAcceptableException.class, "NOT_SUPPORTED_ACCEPT_HEADER");
+
+  public ODataNotAcceptableException(final MessageReference context) {
+    super(context, HttpStatusCodes.NOT_ACCEPTABLE);
+  }
+
+  public ODataNotAcceptableException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.NOT_ACCEPTABLE);
+  }
+
+  public ODataNotAcceptableException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.NOT_ACCEPTABLE, errorCode);
+  }
+
+  public ODataNotAcceptableException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.NOT_ACCEPTABLE, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotFoundException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotFoundException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotFoundException.java
new file mode 100644
index 0000000..683502e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotFoundException.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 404 not found
+ * @author SAP AG
+ */
+public class ODataNotFoundException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference ENTITY = createMessageReference(ODataNotFoundException.class, "ENTITY");
+  public static final MessageReference MATRIX = createMessageReference(ODataNotFoundException.class, "MATRIX");
+
+  public ODataNotFoundException(final MessageReference messageReference) {
+    super(messageReference, HttpStatusCodes.NOT_FOUND);
+  }
+
+  public ODataNotFoundException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, HttpStatusCodes.NOT_FOUND, errorCode);
+  }
+
+  public ODataNotFoundException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause, HttpStatusCodes.NOT_FOUND);
+  }
+
+  public ODataNotFoundException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, HttpStatusCodes.NOT_FOUND, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotImplementedException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotImplementedException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotImplementedException.java
new file mode 100644
index 0000000..e20406d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataNotImplementedException.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 501 (Not implemented).
+ * @author SAP AG
+ */
+public class ODataNotImplementedException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataNotImplementedException.class, "COMMON");
+  public static final MessageReference TUNNELING = createMessageReference(ODataNotImplementedException.class, "TUNNELING");
+
+  public ODataNotImplementedException(final MessageReference context) {
+    super(context, HttpStatusCodes.NOT_IMPLEMENTED);
+  }
+
+  public ODataNotImplementedException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.NOT_IMPLEMENTED, errorCode);
+  }
+
+  public ODataNotImplementedException() {
+    this(COMMON);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionFailedException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionFailedException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionFailedException.java
new file mode 100644
index 0000000..41c81de
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionFailedException.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP Status 412 Precondition Failed.
+ * @author SAP AG
+ */
+public class ODataPreconditionFailedException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataPreconditionFailedException.class, "COMMON");
+
+  public ODataPreconditionFailedException(final MessageReference context) {
+    super(context, HttpStatusCodes.PRECONDITION_FAILED);
+  }
+
+  public ODataPreconditionFailedException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.PRECONDITION_FAILED);
+  }
+
+  public ODataPreconditionFailedException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.PRECONDITION_FAILED, errorCode);
+  }
+
+  public ODataPreconditionFailedException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.PRECONDITION_FAILED, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionRequiredException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionRequiredException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionRequiredException.java
new file mode 100644
index 0000000..c2ddcfd
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataPreconditionRequiredException.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 428 precondition required
+ * @author SAP AG
+ */
+public class ODataPreconditionRequiredException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataPreconditionRequiredException.class, "COMMON");
+
+  public ODataPreconditionRequiredException(final MessageReference context) {
+    super(context, HttpStatusCodes.PRECONDITION_REQUIRED);
+  }
+
+  public ODataPreconditionRequiredException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.PRECONDITION_REQUIRED);
+  }
+
+  public ODataPreconditionRequiredException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.PRECONDITION_REQUIRED, errorCode);
+  }
+
+  public ODataPreconditionRequiredException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.PRECONDITION_REQUIRED, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataServiceUnavailableException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataServiceUnavailableException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataServiceUnavailableException.java
new file mode 100644
index 0000000..67208ae
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataServiceUnavailableException.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 503 service unavailable
+ * @author SAP AG
+ */
+public class ODataServiceUnavailableException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final MessageReference COMMON = createMessageReference(ODataServiceUnavailableException.class, "COMMON");
+
+  public ODataServiceUnavailableException(final MessageReference context) {
+    super(context, HttpStatusCodes.SERVICE_UNAVAILABLE);
+  }
+
+  public ODataServiceUnavailableException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.SERVICE_UNAVAILABLE);
+  }
+
+  public ODataServiceUnavailableException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.SERVICE_UNAVAILABLE, errorCode);
+  }
+
+  public ODataServiceUnavailableException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.SERVICE_UNAVAILABLE, errorCode);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataUnsupportedMediaTypeException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataUnsupportedMediaTypeException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataUnsupportedMediaTypeException.java
new file mode 100644
index 0000000..793d97a
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/ODataUnsupportedMediaTypeException.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.api.exception;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+
+/**
+ * Exceptions of this class will result in a HTTP status 415 unsupported media type
+ * @author SAP AG
+ */
+public class ODataUnsupportedMediaTypeException extends ODataHttpException {
+
+  private static final long serialVersionUID = 1L;
+
+  /** NOT_SUPPORTED requires 1 content value ('media type') */
+  public static final MessageReference NOT_SUPPORTED = createMessageReference(ODataUnsupportedMediaTypeException.class, "NOT_SUPPORTED");
+  /** NOT_SUPPORTED_CONTENT_TYPE requires 1 content value ('media type') */
+  public static final MessageReference NOT_SUPPORTED_CONTENT_TYPE = createMessageReference(ODataUnsupportedMediaTypeException.class, "NOT_SUPPORTED_CONTENT_TYPE");
+  /** NOT_SUPPORTED_ACCEPT_HEADER requires 1 content value ('media type') */
+  public static final MessageReference NOT_SUPPORTED_ACCEPT_HEADER = createMessageReference(ODataUnsupportedMediaTypeException.class, "NOT_SUPPORTED_ACCEPT_HEADER");
+
+  public ODataUnsupportedMediaTypeException(final MessageReference context) {
+    super(context, HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE);
+  }
+
+  public ODataUnsupportedMediaTypeException(final MessageReference context, final Throwable cause) {
+    super(context, cause, HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE);
+  }
+
+  public ODataUnsupportedMediaTypeException(final MessageReference context, final String errorCode) {
+    super(context, HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE, errorCode);
+  }
+
+  public ODataUnsupportedMediaTypeException(final MessageReference context, final Throwable cause, final String errorCode) {
+    super(context, cause, HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE, errorCode);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/package-info.java
new file mode 100644
index 0000000..d14a2f1
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/exception/package-info.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * Exception Classes used in the OData library as well as the implementing application
+ * <p>APPLICATION DEVELOPERS: Please use {@link org.apache.olingo.odata2.api.exception.ODataApplicationException} for custom exceptions.
+ * 
+ * <p><b>Exception handling:</b>
+ * <br>Inside the OData library an ExceptionMapper exists which can transform any exception into an OData error format. 
+ * The ExceptionMapper behaves after the following algorithm:
+ * <br>1. The cause of the exception will be determined by looking into the stack trace.
+ * <br>1.1. If the cause is an ODataApplicationException meaning that somewhere in the stack an ODataApplicationException is found the 
+ * ExceptionMapper will take the following information from the ApplicationException and transform it into an OData error: 
+ * message text, Locale, Inner Error and Error Code. There will be no altering of information for the ODataApplicationException.
+ * <br>1.2. If no ODataApplicationException is found in the stack the cause can be three different types of exceptions: ODataHttpException, ODataMessageException or an uncaught RuntimeException.
+ * <br>The ExceptionMapper will process them in the following order: 1. ODataHttpException, 2. ODataMessageException, 3 Other Exceptions.
+ * <br>1.2.1. ODataHttpExceptions will be transformed as follows: If an error code is set it will be displayed. The HTTP status code will be derived from the ODataHttpException. The message text and its language depend on the AcceptLanguageHeaders. 
+ * The first supported language which is found in the Headers will result in the language of the message and the response. 
+ * <br>1.2.1. ODataMessageException will be transformed as follows: If an error code is set it will be displayed. The HTTP status code will be 500.
+ * The message text and its language depend on the AcceptLanguageHeaders. The first supported language which is found in the Headers will result in the language of the message and the response. 
+ * <br>1.2.1 Runtime Exceptions will be transformed as follows: No error code will be set. HTTP status will be 500. Message text will be taken from the exception and the language for the response will be English as default. 
+ * <p><b>Exception Hierarchy</b>
+ * <br> {@link org.apache.olingo.odata2.api.exception.ODataException}
+ * <br> *{@link org.apache.olingo.odata2.api.exception.ODataApplicationException}
+ * <br> *{@link org.apache.olingo.odata2.api.exception.ODataMessageException}
+ * <br> ** {@link org.apache.olingo.odata2.api.edm.EdmException}
+ * <br> ** {@link org.apache.olingo.odata2.api.ep.EntityProviderException}
+ * <br> ** {@link org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression}
+ * <br> ** {@link org.apache.olingo.odata2.api.exception.ODataHttpException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataConflictException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataForbiddenException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataNotAcceptableException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataNotImplementedException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataPreconditionFailedException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataPreconditionRequiredException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataServiceUnavailableException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataUnsupportedMediaTypeException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataNotFoundException}
+ * <br> **** {@link org.apache.olingo.odata2.api.uri.UriNotMatchingException}
+ * <br> *** {@link org.apache.olingo.odata2.api.exception.ODataBadRequestException}
+ * <br> **** {@link org.apache.olingo.odata2.api.uri.expression.ExpressionParserException}
+ * <br> **** {@link org.apache.olingo.odata2.api.uri.UriSyntaxException}
+ */
+package org.apache.olingo.odata2.api.exception;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/package-info.java
new file mode 100644
index 0000000..b758502
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/package-info.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * OData Library API
+ * <p>
+ * OData Library is a protocol implementation of the OData V2.0 standard. For details of this standard 
+ * see <a href="http://odata.org">odata.org</a>.
+ * <p>
+ * This API is intended to implement an OData service. An OData service consists of a metadata provider 
+ * implementation and an OData processor implementation.
+ * <p>
+ * An OData service can be exposed by a web application. For the runntime one JAX-RS 
+ * implementation is needed and the core implementation library of this API. Apache CXF for example is 
+ * one such JAX-RS implementation.
+ * <p>
+ * Entry point to the service is a JAX-RS servlet. At this servlet init parameters for a <code>ODataServiceFactory</code>
+ * is configured. The parameter <code>javax.ws.rs.Application</code> is a default by JAX-RS and has to be present always.
+ * <p>
+ * <pre>
+ * {@code
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ *   xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ *   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ *   id="WebApp_ID" version="2.5">
+ *   <display-name>Example OData Service</display-name>
+ *   <servlet>
+ *     <servlet-name>MyODataServlet</servlet-name>
+ *     <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
+ *     <init-param>
+ *      <param-name>javax.ws.rs.Application</param-name>
+ *      <param-value>org.apache.olingo.odata2.core.rest.app.ODataApplication</param-value>
+ *     </init-param>
+ *     <init-param>
+ *       <param-name>org.apache.olingo.odata2.service.factory</param-name>
+ *       <param-value>com.sample.service.MyServiceFactory</param-value>
+ *     </init-param>
+ *     <load-on-startup>1</load-on-startup>
+ *   </servlet>
+ *   <servlet-mapping>
+ *     <servlet-name>MyODataServlet</servlet-name>
+ *     <url-pattern>/MyService.svc/*</url-pattern>
+ *   </servlet-mapping>
+ * </web-app>
+ * }
+ * </pre>
+ * <p>
+ * This factory produces the service, a metadata provider and the data processor. The provider, typically 
+ * a derivative of the class <code>EdmProvider</code> provides the metadata of the service. The processor implements a 
+ * variety of service interfaces, and provides the data of the service. The processor is typically 
+ * a derivative of the class <code>ODataSingleProcessor</code> which can be used together with the class 
+ * <code>ODataSingleService</code>.
+ */
+package org.apache.olingo.odata2.api;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataContext.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataContext.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataContext.java
new file mode 100644
index 0000000..3c68488
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataContext.java
@@ -0,0 +1,235 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+
+/**
+ * Compilation of generic context objects.
+ * @author SAP AG
+ * @org.apache.olingo.odata2.DoNotImplement
+ */
+public interface ODataContext {
+
+  /**
+   * Gets the OData service.
+   * @return ODataService related for this context
+   * @throws ODataException
+   */
+  ODataService getService() throws ODataException;
+
+  /**
+   * @return the service factory instance
+   */
+  ODataServiceFactory getServiceFactory();
+
+  /**
+   * Gets information about the request path.
+   * @return an OData path info object
+   * @throws ODataException
+   */
+  PathInfo getPathInfo() throws ODataException;
+
+  /**
+   * If a request execution is part of batch processing then this method returns the context of the 
+   * outer batch request.
+   * @return a batch parent context or null
+   */
+  ODataContext getBatchParentContext();
+
+  /**
+   * @return true in case of this request is part of a batch processing queue
+   */
+  boolean isInBatchMode();
+
+  /**
+   * Starts runtime measurement.
+   * @param className class name where the runtime measurement starts
+   * @param methodName method name where the runtime measurement starts
+   * @return handle for the started runtime measurement which can be used for stopping
+   */
+  int startRuntimeMeasurement(String className, String methodName);
+
+  /**
+   * Stops runtime measurement.
+   * @param handle of runtime measurement to be stopped
+   */
+  void stopRuntimeMeasurement(int handle);
+
+  /**
+   * Gets the list of all runtime measurements.
+   * @return list of all runtime measurements of type {@link RuntimeMeasurement}
+   */
+  List<RuntimeMeasurement> getRuntimeMeasurements();
+
+  /**
+   * Gets the HTTP method of the request.
+   * @return HTTP method as {@link String}
+   */
+  String getHttpMethod();
+
+  /**
+   * Sets a parameter.
+   * @param name of parameter (name is used as key, existing values are overwritten)
+   * @param value of parameter as object
+   */
+  void setParameter(String name, Object value);
+
+  /**
+   * Removes parameter.
+   * @param name of parameter to be removed
+   */
+  void removeParameter(String name);
+
+  /**
+   * Gets a named parameter value.
+   * @param name of parameter
+   * @return parameter value as {@link Object} for the given name
+   */
+  Object getParameter(String name);
+
+  /**
+   * Returns the first found header value of the HTTP request.
+   * @param name name of the first found request header element (e.g. "Content-Type")
+   * @return null or a request header value if found
+   */
+  String getRequestHeader(String name);
+
+  /**
+   * Returns all header values of the HTTP request but never null.
+   * @return immutable map of request header values
+   */
+  Map<String, List<String>> getRequestHeaders();
+
+  /**
+   * Gets information about enabled debug mode.
+   * @return debugMode as boolean
+   */
+  boolean isInDebugMode();
+
+  /**
+   * Enables debug mode.
+   * @param debugMode as boolean
+   */
+  void setDebugMode(boolean debugMode);
+
+  /**
+   * Gets a list of languages that are acceptable for the response.
+   * If no acceptable languages are specified, a read-only list containing 
+   * a single wildcard java.util.Locale instance (with language field set to "*") is returned.
+   * @return a read-only list of acceptable languages sorted according to their q-value,
+   *         with highest preference first.
+   */
+  List<Locale> getAcceptableLanguages();
+
+  /**
+   * <p>Runtime measurements.</p>
+   * <p>All times are in nanoseconds since some fixed but arbitrary time
+   * (perhaps in the future, so values may be negative).</p>
+   * @see System#nanoTime()
+   */
+  public interface RuntimeMeasurement {
+    /**
+     * Sets the class name.
+     * @param className the name of the class that is measured
+     */
+    void setClassName(String className);
+
+    /**
+     * Gets the class name.
+     * @return the name of the class that is measured
+     */
+    String getClassName();
+
+    /**
+     * Sets the method name.
+     * @param methodName the name of the method that is measured
+     */
+    void setMethodName(String methodName);
+
+    /**
+     * Gets the method name.
+     * @return the name of the method that is measured
+     */
+    String getMethodName();
+
+    /**
+     * Sets the start time.
+     * @param timeStarted the start time in nanoseconds
+     * @see System#nanoTime()
+     */
+    void setTimeStarted(long timeStarted);
+
+    /**
+     * Gets the start time.
+     * @return the start time in nanoseconds or 0 if not set yet
+     * @see System#nanoTime()
+     */
+    long getTimeStarted();
+
+    /**
+     * Sets the stop time.
+     * @param timeStopped the stop time in nanoseconds
+     * @see System#nanoTime()
+     */
+    void setTimeStopped(long timeStopped);
+
+    /**
+     * Gets the stop time.
+     * @return the stop time in nanoseconds or 0 if not set yet
+     * @see System#nanoTime()
+     */
+    long getTimeStopped();
+
+    /**
+     * Sets the start heap memory used.
+     * @param usedHeap the start heap memory used in bytes
+     * @see ManagementFactory#getMemoryMXBean()
+     */
+    void setMemoryStarted(long usedHeap);
+
+    /**
+     * Sets the stop heap memory used.
+     * @param usedHeap the stop heap memory used in bytes
+     * @see ManagementFactory#getMemoryMXBean()
+     */
+    void setMemoryStopped(long usedHeap);
+
+    /**
+     * Gets the start heap memory used.
+     * @return start heap memory used or 0 if not set
+     * @see ManagementFactory#getMemoryMXBean()
+     */
+    long getMemoryStarted();
+
+    /**
+     * Gets the stop heap memory used.
+     * @return stop heap memory used or 0 if not set
+     * @see ManagementFactory#getMemoryMXBean()
+     */
+    long getMemoryStopped();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorCallback.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorCallback.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorCallback.java
new file mode 100644
index 0000000..1e7ddff
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorCallback.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+
+/**
+ * This interface is called if an error occurred and is process inside the exception mapper.
+ * @author SAP AG
+ *
+ */
+public interface ODataErrorCallback extends ODataCallback {
+  /**
+   * This method can be used to handle an error differently than the exception mapper would. 
+   * <br>Any returned Response will be directly transported to the client.
+   * <br>Any thrown {@link ODataApplicationException} will be transformed into the OData error format.
+   * <br>Any thrown runtime exception will result in an 500 Internal Server error with the Text: "Exception during error handling occurred!" No OData formatting will be applied.
+   * <br>To serialize an error into the OData format the {@link org.apache.olingo.odata2.api.ep.EntityProvider} writeErrorDocument can be used.
+   * @param context of this error
+   * @return the response which will be propagated to the client
+   * @throws ODataApplicationException
+   */
+  ODataResponse handleError(ODataErrorContext context) throws ODataApplicationException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorContext.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorContext.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorContext.java
new file mode 100644
index 0000000..889d961
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataErrorContext.java
@@ -0,0 +1,229 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+
+/**
+ * Error context information bean. Usually created and in error situations.
+ * @see org.apache.olingo.odata2.api.ep.EntityProvider EntityProvider
+ * @see ODataErrorCallback
+ * @author SAP AG
+ */
+public class ODataErrorContext {
+
+  private String contentType;
+  private HttpStatusCodes httpStatus;
+  private String errorCode;
+  private String message;
+  private Locale locale;
+  private Exception exception;
+  private Map<String, List<String>> requestHeaders;
+  private URI requestUri;
+  private String innerError;
+  private PathInfo pathInfo;
+
+  /**
+   * create a new context object
+   */
+  public ODataErrorContext() {
+    requestHeaders = new HashMap<String, List<String>>();
+  }
+
+  /**
+   * Returns the causing exception.
+   * @return exception object
+   */
+  public Exception getException() {
+    return exception;
+  }
+
+  /**
+   * Set the causing exception.
+   * @param exception exception object
+   */
+  public void setException(final Exception exception) {
+    this.exception = exception;
+  }
+
+  /** 
+   * Get the content type which should be used to serialize an error response.
+   * @return a content type
+   */
+  public String getContentType() {
+    return contentType;
+  }
+
+  /**
+   * Set content type which should be used to serialize an error response.
+   * @param contentType a content type
+   */
+  public void setContentType(final String contentType) {
+    this.contentType = contentType;
+  }
+
+  /**
+   * Get the status code which will be returned in error response.
+   * @return http status code
+   */
+  public HttpStatusCodes getHttpStatus() {
+    return httpStatus;
+  }
+
+  /**
+   * Set http status code that should be returned in error response.
+   * @param status http status code
+   */
+  public void setHttpStatus(final HttpStatusCodes status) {
+    httpStatus = status;
+  }
+
+  /**
+   * Return OData error code that is returned in error response. 
+   * @return an application defined error code
+   */
+  public String getErrorCode() {
+    return errorCode;
+  }
+
+  /**
+   * Set OData error code that should be returned in error response. 
+   * @param errorCode an application defined error code
+   */
+  public void setErrorCode(final String errorCode) {
+    this.errorCode = errorCode;
+  }
+
+  /**
+   * Return a translated error message.
+   * @return translated message
+   */
+  public String getMessage() {
+    return message;
+  }
+
+  /**
+   * Set a translated message.
+   * @param message translated message
+   */
+  public void setMessage(final String message) {
+    this.message = message;
+  }
+
+  /** 
+   * Return the locale of the translated message.
+   * @return a locale
+   */
+  public Locale getLocale() {
+    return locale;
+  }
+
+  /**
+   * Set the locale for a translated message.
+   * @param locale a locale
+   */
+  public void setLocale(final Locale locale) {
+    this.locale = locale;
+  }
+
+  /**
+   * Put http headers to be returned in error response.
+   * @param key header name
+   * @param value list of header values
+   */
+  public void putRequestHeader(final String key, final List<String> value) {
+    requestHeaders.put(key, value);
+  }
+
+  /**
+   * Return a map of http headers to be returned in error response.
+   * @return a map of http headers
+   */
+  public Map<String, List<String>> getRequestHeaders() {
+    return Collections.unmodifiableMap(requestHeaders);
+  }
+
+  /**
+   * Get the list of values for a request header.
+   * @param name header name
+   * @return list of values
+   */
+  public List<String> getRequestHeader(final String name) {
+    return requestHeaders.get(name);
+  }
+
+  /**
+   * Set the request uri to be used in a error response.
+   * @param requestUri a uri object
+   */
+  public void setRequestUri(final URI requestUri) {
+    this.requestUri = requestUri;
+  }
+
+  /**
+   * Get the request uri to be used in a error response.
+   * @return a uri object
+   */
+  public URI getRequestUri() {
+    return requestUri;
+  }
+
+  /**
+   * Get a string for a OData inner error to be returned in error response.
+   * @return a inner error message
+   */
+  public String getInnerError() {
+    return innerError;
+  }
+
+  /**
+   * Set a string for a OData inner error to be returned in error response.
+   * @param innerError a inner error message
+   */
+  public void setInnerError(final String innerError) {
+    this.innerError = innerError;
+  }
+
+  /**
+   * Get {@link PathInfo} object.
+   * May be <code>NULL</code> if no path info was created/set till error occurred (but may be over written by application).
+   * 
+   * @return {@link PathInfo} or <code>NULL</code>.
+   */
+  public PathInfo getPathInfo() {
+    return pathInfo;
+  }
+
+  /**
+   * Set {@link PathInfo} object.
+   * 
+   * @param pathInfo path info
+   */
+  public void setPathInfo(final PathInfo pathInfo) {
+    this.pathInfo = pathInfo;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataProcessor.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataProcessor.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataProcessor.java
new file mode 100644
index 0000000..b6c4f46
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataProcessor.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+/**
+ * An <code>ODataProcessor</code> is the root interface for processor implementation.
+ * A processor handles OData requests like reading or writing entities. All possible
+ * actions are defined in the {@link org.apache.olingo.odata2.api.processor.feature} package.
+ * @author SAP AG
+ * @org.apache.olingo.odata2.DoNotImplement
+ */
+public interface ODataProcessor {
+
+  /**
+   * @param context A request context object which is usually injected by the OData library itself.
+   * @throws ODataException
+   */
+  void setContext(ODataContext context) throws ODataException;
+
+  /**
+   * @return A request context object.
+   * @throws ODataException
+   */
+  ODataContext getContext() throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataRequest.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataRequest.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataRequest.java
new file mode 100644
index 0000000..00fbcb2
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/processor/ODataRequest.java
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * 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.api.processor;
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+
+/**
+ * 
+ * @author SAP AG
+ */
+public abstract class ODataRequest {
+
+  public abstract String getRequestHeaderValue(String name);
+
+  public abstract Map<String, List<String>> getRequestHeaders();
+
+  public abstract InputStream getBody();
+
+  public abstract PathInfo getPathInfo();
+
+  public abstract ODataHttpMethod getMethod();
+
+  public abstract List<Locale> getAcceptableLanguages();
+
+  public abstract String getContentType();
+
+  public abstract List<String> getAcceptHeaders();
+
+  public abstract Map<String, String> getQueryParameters();
+
+  public static ODataRequestBuilder requestHeaders(final Map<String, List<String>> headers) {
+    return newBuilder().requestHeaders(headers);
+  }
+
+  public static ODataRequestBuilder body(final InputStream body) {
+    return newBuilder().body(body);
+  }
+
+  public static ODataRequestBuilder pathInfo(final PathInfo pathInfo) {
+    return newBuilder().pathInfo(pathInfo);
+  }
+
+  public static ODataRequestBuilder method(final ODataHttpMethod method) {
+    return newBuilder().method(method);
+  }
+
+  public static ODataRequestBuilder acceptableLanguages(final List<Locale> acceptableLanguages) {
+    return newBuilder().acceptableLanguages(acceptableLanguages);
+  }
+
+  public static ODataRequestBuilder contentType(final String contentType) {
+    return newBuilder().contentType(contentType);
+  }
+
+  public static ODataRequestBuilder acceptHeaders(final List<String> acceptHeaders) {
+    return newBuilder().acceptHeaders(acceptHeaders);
+  }
+
+  public static ODataRequestBuilder queryParameters(final Map<String, String> queryParameters) {
+    return newBuilder().queryParameters(queryParameters);
+  }
+
+  public static ODataRequestBuilder fromRequest(final ODataRequest request) {
+    return newBuilder().fromRequest(request);
+  }
+
+  /**
+   * @return returns a new builder object
+   */
+  public static ODataRequestBuilder newBuilder() {
+    return ODataRequestBuilder.newInstance();
+  }
+
+  public static abstract class ODataRequestBuilder {
+
+    protected ODataRequestBuilder() {}
+
+    private static ODataRequestBuilder newInstance() {
+      return RuntimeDelegate.createODataRequestBuilder();
+    }
+
+    public abstract ODataRequest build();
+
+    public abstract ODataRequestBuilder requestHeaders(Map<String, List<String>> headers);
+
+    public abstract ODataRequestBuilder body(InputStream body);
+
+    public abstract ODataRequestBuilder pathInfo(PathInfo pathInfo);
+
+    public abstract ODataRequestBuilder method(ODataHttpMethod method);
+
+    public abstract ODataRequestBuilder acceptableLanguages(List<Locale> acceptableLanguages);
+
+    public abstract ODataRequestBuilder contentType(String contentType);
+
+    public abstract ODataRequestBuilder acceptHeaders(List<String> acceptHeaders);
+
+    public abstract ODataRequestBuilder queryParameters(Map<String, String> queryParameters);
+
+    public abstract ODataRequestBuilder fromRequest(ODataRequest request);
+
+  }
+
+}


[24/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataContextImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataContextImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataContextImpl.java
new file mode 100644
index 0000000..d155a87
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataContextImpl.java
@@ -0,0 +1,314 @@
+/*******************************************************************************
+ * 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;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataDebugCallback;
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.core.debug.ODataDebugResponseWrapper;
+
+/**
+ * @author SAP AG
+ */
+public class ODataContextImpl implements ODataContext {
+
+  private static final String ODATA_BATCH_PARENT_CONTEXT = "~odataBatchParentContext";
+  private static final String ODATA_REQUEST = "~odataRequest";
+  private static final String DEBUG_MODE = "~debugMode";
+  private static final String SERVICE = "~service";
+  private static final String SERVICE_FACTORY = "~serviceFactory";
+  private static final String PATH_INFO = "~pathInfo";
+  private static final String RUNTIME_MEASUREMENTS = "~runtimeMeasurements";
+  private static final String HTTP_METHOD = "~httpMethod";
+
+  private Map<String, Object> parameterTable = new HashMap<String, Object>();
+
+  private List<Locale> acceptableLanguages;
+
+  public ODataContextImpl(final ODataRequest request, final ODataServiceFactory factory) {
+    setServiceFactory(factory);
+    setRequest(request);
+    setPathInfo(request.getPathInfo());
+    if (request.getMethod() != null) {
+      setHttpMethod(request.getMethod().name());
+    }
+    setAcceptableLanguages(request.getAcceptableLanguages());
+    setDebugMode(checkDebugMode(request.getQueryParameters()));
+  }
+
+  @Override
+  public void setParameter(final String name, final Object value) {
+    parameterTable.put(name, value);
+  }
+
+  @Override
+  public void removeParameter(final String name) {
+    parameterTable.remove(name);
+  }
+
+  @Override
+  public Object getParameter(final String name) {
+    return parameterTable.get(name);
+  }
+
+  @Override
+  public boolean isInDebugMode() {
+    return getParameter(DEBUG_MODE) != null && (Boolean) getParameter(DEBUG_MODE);
+  }
+
+  @Override
+  public void setDebugMode(final boolean debugMode) {
+    setParameter(DEBUG_MODE, debugMode);
+  }
+
+  public void setService(final ODataService service) {
+    setParameter(SERVICE, service);
+  }
+
+  @Override
+  public ODataService getService() throws ODataException {
+    return (ODataService) getParameter(SERVICE);
+  }
+
+  public void setPathInfo(final PathInfo uriInfo) {
+    setParameter(PATH_INFO, uriInfo);
+  }
+
+  @Override
+  public PathInfo getPathInfo() throws ODataException {
+    return (PathInfo) getParameter(PATH_INFO);
+  }
+
+  public void setServiceFactory(final ODataServiceFactory serviceFactory) {
+    setParameter(SERVICE_FACTORY, serviceFactory);
+  }
+
+  @Override
+  public ODataServiceFactory getServiceFactory() {
+    return (ODataServiceFactory) getParameter(SERVICE_FACTORY);
+  }
+
+  @Override
+  public int startRuntimeMeasurement(final String className, final String methodName) {
+    if (isInDebugMode()) {
+      List<RuntimeMeasurement> runtimeMeasurements = getRuntimeMeasurements();
+      int handleId = runtimeMeasurements.size();
+
+      final RuntimeMeasurement measurement = new RuntimeMeasurementImpl();
+      measurement.setTimeStarted(System.nanoTime());
+      measurement.setClassName(className);
+      measurement.setMethodName(methodName);
+      measurement.setMemoryStarted(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed());
+
+      runtimeMeasurements.add(measurement);
+
+      return handleId;
+    } else {
+      return 0;
+    }
+  }
+
+  @Override
+  public void stopRuntimeMeasurement(final int handle) {
+    if (isInDebugMode()) {
+      long stopTime = System.nanoTime();
+      long stopMemory = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed();
+
+      RuntimeMeasurement runtimeMeasurement = getRuntimeMeasurement(handle);
+      if (runtimeMeasurement != null) {
+        runtimeMeasurement.setTimeStopped(stopTime);
+        runtimeMeasurement.setMemoryStopped(stopMemory);
+      }
+    }
+  }
+
+  private RuntimeMeasurement getRuntimeMeasurement(final int handle) {
+    List<RuntimeMeasurement> runtimeMeasurements = getRuntimeMeasurements();
+    if (handle >= 0 && handle < runtimeMeasurements.size()) {
+      return runtimeMeasurements.get(handle);
+    }
+    return null;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public List<RuntimeMeasurement> getRuntimeMeasurements() {
+    List<RuntimeMeasurement> runtimeMeasurements = (List<RuntimeMeasurement>) getParameter(RUNTIME_MEASUREMENTS);
+    if (runtimeMeasurements == null) {
+      runtimeMeasurements = new ArrayList<RuntimeMeasurement>();
+      setParameter(RUNTIME_MEASUREMENTS, runtimeMeasurements);
+    }
+    return runtimeMeasurements;
+  }
+
+  protected class RuntimeMeasurementImpl implements RuntimeMeasurement {
+    private String className;
+    private String methodName;
+    private long timeStarted;
+    private long timeStopped;
+    private long memoryStarted;
+    private long memoryStopped;
+
+    @Override
+    public void setClassName(final String className) {
+      this.className = className;
+    }
+
+    @Override
+    public String getClassName() {
+      return className;
+    }
+
+    @Override
+    public void setMethodName(final String methodName) {
+      this.methodName = methodName;
+    }
+
+    @Override
+    public String getMethodName() {
+      return methodName;
+    }
+
+    @Override
+    public void setTimeStarted(final long start) {
+      timeStarted = start;
+    }
+
+    @Override
+    public long getTimeStarted() {
+      return timeStarted;
+    }
+
+    @Override
+    public void setTimeStopped(final long stop) {
+      timeStopped = stop;
+    }
+
+    @Override
+    public long getTimeStopped() {
+      return timeStopped;
+    }
+
+    @Override
+    public String toString() {
+      return className + "." + methodName + ": duration: " + (timeStopped - timeStarted) + ", memory: " + (memoryStopped - memoryStarted);
+    }
+
+    @Override
+    public void setMemoryStarted(final long used) {
+      memoryStarted = used;
+    }
+
+    @Override
+    public void setMemoryStopped(final long used) {
+      memoryStopped = used;
+    }
+
+    @Override
+    public long getMemoryStarted() {
+      return memoryStarted;
+    }
+
+    @Override
+    public long getMemoryStopped() {
+      return memoryStopped;
+    }
+  }
+
+  @Override
+  public String getRequestHeader(final String name) {
+    ODataRequest request = (ODataRequest) parameterTable.get(ODATA_REQUEST);
+    return request.getRequestHeaderValue(name);
+  }
+
+  @Override
+  public Map<String, List<String>> getRequestHeaders() {
+    ODataRequest request = (ODataRequest) parameterTable.get(ODATA_REQUEST);
+    return request.getRequestHeaders();
+  }
+
+  @Override
+  public List<Locale> getAcceptableLanguages() {
+    return Collections.unmodifiableList(acceptableLanguages);
+  }
+
+  public void setAcceptableLanguages(final List<Locale> acceptableLanguages) {
+    this.acceptableLanguages = acceptableLanguages;
+
+    if (this.acceptableLanguages.isEmpty()) {
+      final Locale wildcard = new Locale("*");
+      this.acceptableLanguages.add(wildcard);
+    }
+  }
+
+  public void setHttpMethod(final String httpMethod) {
+    setParameter(HTTP_METHOD, httpMethod);
+  }
+
+  @Override
+  public String getHttpMethod() {
+    return (String) getParameter(HTTP_METHOD);
+  }
+
+  public void setRequest(final ODataRequest request) {
+    setParameter(ODATA_REQUEST, request);
+  }
+
+  private boolean checkDebugMode(final Map<String, String> queryParameters) {
+    if (getQueryDebugValue(queryParameters) == null) {
+      return false;
+    } else {
+      final ODataDebugCallback callback = getServiceFactory().getCallback(ODataDebugCallback.class);
+      return callback != null && callback.isDebugEnabled();
+    }
+  }
+
+  private static String getQueryDebugValue(final Map<String, String> queryParameters) {
+    final String debugValue = queryParameters.get(ODataDebugResponseWrapper.ODATA_DEBUG_QUERY_PARAMETER);
+    return ODataDebugResponseWrapper.ODATA_DEBUG_JSON.equals(debugValue) ?
+        debugValue : null;
+  }
+
+  public void setBatchParentContext(final ODataContext ctx) {
+    setParameter(ODATA_BATCH_PARENT_CONTEXT, ctx);
+  }
+
+  @Override
+  public ODataContext getBatchParentContext() {
+    return (ODataContext) parameterTable.get(ODATA_BATCH_PARENT_CONTEXT);
+  }
+
+  @Override
+  public boolean isInBatchMode() {
+    return parameterTable.containsKey(ODATA_BATCH_PARENT_CONTEXT);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataExceptionWrapper.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataExceptionWrapper.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataExceptionWrapper.java
new file mode 100644
index 0000000..63483c7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataExceptionWrapper.java
@@ -0,0 +1,338 @@
+/*******************************************************************************
+ * 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;
+
+import java.net.URI;
+import java.text.ParseException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataHttpException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataErrorCallback;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.ProviderFacadeImpl;
+import org.apache.olingo.odata2.core.exception.MessageService;
+import org.apache.olingo.odata2.core.exception.MessageService.Message;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class ODataExceptionWrapper {
+
+  private static final String DOLLAR_FORMAT = "$format";
+  private static final String DOLLAR_FORMAT_JSON = "json";
+  private static final Locale DEFAULT_RESPONSE_LOCALE = Locale.ENGLISH;
+
+  private final String contentType;
+  private final Locale messageLocale;
+  private final Map<String, List<String>> httpRequestHeaders;
+  private final ODataErrorCallback callback;
+  private final ODataErrorContext errorContext = new ODataErrorContext();
+  private final URI requestUri;
+
+  public ODataExceptionWrapper(final ODataContext context, final Map<String, String> queryParameters, final List<String> acceptHeaderContentTypes) {
+    contentType = getContentType(queryParameters, acceptHeaderContentTypes).toContentTypeString();
+    messageLocale = MessageService.getSupportedLocale(getLanguages(context), DEFAULT_RESPONSE_LOCALE);
+    httpRequestHeaders = context.getRequestHeaders();
+    try {
+      requestUri = context.getPathInfo().getRequestUri();
+      errorContext.setPathInfo(context.getPathInfo());
+      callback = getErrorHandlerCallbackFromContext(context);
+    } catch (Exception e) {
+      throw new ODataRuntimeException("Exception occurred", e);
+    }
+  }
+
+  public ODataExceptionWrapper(final UriInfo uriInfo, final HttpHeaders httpHeaders, final ServletConfig servletConfig, final HttpServletRequest servletRequest) {
+    contentType = getContentType(uriInfo, httpHeaders).toContentTypeString();
+    messageLocale = MessageService.getSupportedLocale(getLanguages(httpHeaders), DEFAULT_RESPONSE_LOCALE);
+    httpRequestHeaders = httpHeaders.getRequestHeaders();
+    requestUri = uriInfo.getRequestUri();
+    try {
+      callback = getErrorHandlerCallbackFromServletConfig(servletConfig, servletRequest);
+    } catch (Exception e) {
+      throw new ODataRuntimeException("Exception occurred", e);
+    }
+  }
+
+  public ODataResponse wrapInExceptionResponse(final Exception exception) {
+    try {
+      final Exception toHandleException = extractException(exception);
+      fillErrorContext(toHandleException);
+      if (toHandleException instanceof ODataApplicationException) {
+        enhanceContextWithApplicationException((ODataApplicationException) toHandleException);
+      } else if (toHandleException instanceof ODataMessageException) {
+        enhanceContextWithMessageException((ODataMessageException) toHandleException);
+      }
+
+      ODataResponse oDataResponse;
+      if (callback != null) {
+        oDataResponse = handleErrorCallback(callback);
+      } else {
+        oDataResponse = EntityProvider.writeErrorDocument(errorContext);
+      }
+      return oDataResponse;
+    } catch (Exception e) {
+      ODataResponse response = ODataResponse.entity("Exception during error handling occured!")
+          .contentHeader(ContentType.TEXT_PLAIN.toContentTypeString())
+          .status(HttpStatusCodes.INTERNAL_SERVER_ERROR).build();
+      return response;
+    }
+  }
+
+  private ODataResponse handleErrorCallback(final ODataErrorCallback callback) throws EntityProviderException {
+    ODataResponse oDataResponse;
+    try {
+      oDataResponse = callback.handleError(errorContext);
+    } catch (ODataApplicationException e) {
+      fillErrorContext(e);
+      enhanceContextWithApplicationException(e);
+      oDataResponse = new ProviderFacadeImpl().writeErrorDocument(errorContext);
+    }
+    return oDataResponse;
+  }
+
+  private void enhanceContextWithApplicationException(final ODataApplicationException toHandleException) {
+    errorContext.setHttpStatus(toHandleException.getHttpStatus());
+    errorContext.setErrorCode(toHandleException.getCode());
+  }
+
+  private void enhanceContextWithMessageException(final ODataMessageException toHandleException) {
+    errorContext.setErrorCode(toHandleException.getErrorCode());
+    MessageReference messageReference = toHandleException.getMessageReference();
+    Message localizedMessage = messageReference == null ? null : extractEntity(messageReference);
+    if (localizedMessage != null) {
+      errorContext.setMessage(localizedMessage.getText());
+      errorContext.setLocale(localizedMessage.getLocale());
+    }
+    if (toHandleException instanceof ODataHttpException) {
+      errorContext.setHttpStatus(((ODataHttpException) toHandleException).getHttpStatus());
+    } else if (toHandleException instanceof EntityProviderException) {
+      errorContext.setHttpStatus(HttpStatusCodes.BAD_REQUEST);
+    } else if (toHandleException instanceof BatchException) {
+      errorContext.setHttpStatus(HttpStatusCodes.BAD_REQUEST);
+    }
+
+  }
+
+  /**
+   * Fill current error context ({@link #errorContext}) with values from given {@link Exception} parameter.
+   * 
+   * @param exception exception with values to be set on error context
+   */
+  private void fillErrorContext(final Exception exception) {
+    errorContext.setContentType(contentType);
+    errorContext.setException(exception);
+    errorContext.setHttpStatus(HttpStatusCodes.INTERNAL_SERVER_ERROR);
+    errorContext.setErrorCode(null);
+    errorContext.setMessage(exception.getMessage());
+    errorContext.setLocale(DEFAULT_RESPONSE_LOCALE);
+    errorContext.setRequestUri(requestUri);
+
+    if (httpRequestHeaders != null) {
+      for (Entry<String, List<String>> entry : httpRequestHeaders.entrySet()) {
+        errorContext.putRequestHeader(entry.getKey(), entry.getValue());
+      }
+    }
+  }
+
+  private Exception extractException(final Exception exception) {
+    if (exception instanceof ODataException) {
+      ODataException odataException = (ODataException) exception;
+      if (odataException.isCausedByApplicationException()) {
+        return odataException.getApplicationExceptionCause();
+      } else if (odataException.isCausedByHttpException()) {
+        return odataException.getHttpExceptionCause();
+      } else if (odataException.isCausedByMessageException()) {
+        return odataException.getMessageExceptionCause();
+      }
+    }
+    return exception;
+  }
+
+  private Message extractEntity(final MessageReference context) {
+    return MessageService.getMessage(messageLocale, context);
+  }
+
+  private List<Locale> getLanguages(final ODataContext context) {
+    try {
+      if (context.getAcceptableLanguages().isEmpty()) {
+        return Arrays.asList(DEFAULT_RESPONSE_LOCALE);
+      }
+      return context.getAcceptableLanguages();
+    } catch (WebApplicationException e) {
+      if (e.getCause() != null && e.getCause().getClass() == ParseException.class) {
+        // invalid accept-language string in http header
+        // compensate exception with using default locale
+        return Arrays.asList(DEFAULT_RESPONSE_LOCALE);
+      }
+      // not able to compensate exception -> re-throw
+      throw e;
+    }
+  }
+
+  private List<Locale> getLanguages(final HttpHeaders httpHeaders) {
+    try {
+      if (httpHeaders.getAcceptableLanguages().isEmpty()) {
+        return Arrays.asList(DEFAULT_RESPONSE_LOCALE);
+      }
+      return httpHeaders.getAcceptableLanguages();
+    } catch (WebApplicationException e) {
+      if (e.getCause() != null && e.getCause().getClass() == ParseException.class) {
+        // invalid accept-language string in http header
+        // compensate exception with using default locale
+        return Arrays.asList(DEFAULT_RESPONSE_LOCALE);
+      }
+      // not able to compensate exception -> re-throw
+      throw e;
+    }
+  }
+
+  private ContentType getContentType(final Map<String, String> queryParameters, final List<String> acceptHeaderContentTypes) {
+    ContentType contentType = getContentTypeByUriInfo(queryParameters);
+    if (contentType == null) {
+      contentType = getContentTypeByAcceptHeader(acceptHeaderContentTypes);
+    }
+    return contentType;
+  }
+
+  private ContentType getContentTypeByUriInfo(final Map<String, String> queryParameters) {
+    ContentType contentType = null;
+    if (queryParameters != null) {
+      if (queryParameters.containsKey(DOLLAR_FORMAT)) {
+        String contentTypeString = queryParameters.get(DOLLAR_FORMAT);
+        if (DOLLAR_FORMAT_JSON.equals(contentTypeString)) {
+          contentType = ContentType.APPLICATION_JSON;
+        } else {
+          //Any format mentioned in the $format parameter other than json results in an application/xml content type for error messages
+          //due to the OData V2 Specification
+          contentType = ContentType.APPLICATION_XML;
+        }
+      }
+    }
+    return contentType;
+  }
+
+  private ContentType getContentTypeByAcceptHeader(final List<String> acceptHeaderContentTypes) {
+    for (String acceptContentType : acceptHeaderContentTypes) {
+      if (ContentType.isParseable(acceptContentType)) {
+        ContentType convertedContentType = ContentType.create(acceptContentType);
+        if (convertedContentType.isWildcard()
+            || ContentType.APPLICATION_XML.equals(convertedContentType) || ContentType.APPLICATION_XML_CS_UTF_8.equals(convertedContentType)
+            || ContentType.APPLICATION_ATOM_XML.equals(convertedContentType) || ContentType.APPLICATION_ATOM_XML_CS_UTF_8.equals(convertedContentType)) {
+          return ContentType.APPLICATION_XML;
+        } else if (ContentType.APPLICATION_JSON.equals(convertedContentType) || ContentType.APPLICATION_JSON_CS_UTF_8.equals(convertedContentType)) {
+          return ContentType.APPLICATION_JSON;
+        }
+      }
+    }
+    return ContentType.APPLICATION_XML;
+  }
+
+  private ContentType getContentType(final UriInfo uriInfo, final HttpHeaders httpHeaders) {
+    ContentType contentType = getContentTypeByUriInfo(uriInfo);
+    if (contentType == null) {
+      contentType = getContentTypeByAcceptHeader(httpHeaders);
+    }
+    return contentType;
+  }
+
+  private ContentType getContentTypeByUriInfo(final UriInfo uriInfo) {
+    ContentType contentType = null;
+    if (uriInfo != null && uriInfo.getQueryParameters() != null) {
+      MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
+      if (queryParameters.containsKey(DOLLAR_FORMAT)) {
+        String contentTypeString = queryParameters.getFirst(DOLLAR_FORMAT);
+        if (DOLLAR_FORMAT_JSON.equals(contentTypeString)) {
+          contentType = ContentType.APPLICATION_JSON;
+        } else {
+          //Any format mentioned in the $format parameter other than json results in an application/xml content type 
+          //for error messages due to the OData V2 Specification.
+          contentType = ContentType.APPLICATION_XML;
+        }
+      }
+    }
+    return contentType;
+  }
+
+  private ContentType getContentTypeByAcceptHeader(final HttpHeaders httpHeaders) {
+    for (MediaType type : httpHeaders.getAcceptableMediaTypes()) {
+      if (ContentType.isParseable(type.toString())) {
+        ContentType convertedContentType = ContentType.create(type.toString());
+        if (convertedContentType.isWildcard()
+            || ContentType.APPLICATION_XML.equals(convertedContentType) || ContentType.APPLICATION_XML_CS_UTF_8.equals(convertedContentType)
+            || ContentType.APPLICATION_ATOM_XML.equals(convertedContentType) || ContentType.APPLICATION_ATOM_XML_CS_UTF_8.equals(convertedContentType)) {
+          return ContentType.APPLICATION_XML;
+        } else if (ContentType.APPLICATION_JSON.equals(convertedContentType) || ContentType.APPLICATION_JSON_CS_UTF_8.equals(convertedContentType)) {
+          return ContentType.APPLICATION_JSON;
+        }
+      }
+    }
+    return ContentType.APPLICATION_XML;
+  }
+
+  private ODataErrorCallback getErrorHandlerCallbackFromContext(final ODataContext context) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+    ODataErrorCallback callback = null;
+    ODataServiceFactory serviceFactory = context.getServiceFactory();
+    callback = serviceFactory.getCallback(ODataErrorCallback.class);
+    return callback;
+  }
+
+  private ODataErrorCallback getErrorHandlerCallbackFromServletConfig(final ServletConfig servletConfig, final HttpServletRequest servletRequest) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+    ODataErrorCallback callback = null;
+    final String factoryClassName = servletConfig.getInitParameter(ODataServiceFactory.FACTORY_LABEL);
+    if (factoryClassName != null) {
+      ClassLoader cl = (ClassLoader) servletRequest.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
+      Class<?> factoryClass;
+      if (cl == null) {
+        factoryClass = Class.forName(factoryClassName);
+      } else {
+        factoryClass = Class.forName(factoryClassName, true, cl);
+      }
+      final ODataServiceFactory serviceFactory = (ODataServiceFactory) factoryClass.newInstance();
+
+      callback = serviceFactory.getCallback(ODataErrorCallback.class);
+    }
+    return callback;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataPathSegmentImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataPathSegmentImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataPathSegmentImpl.java
new file mode 100644
index 0000000..2ddc194
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataPathSegmentImpl.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.uri.PathSegment;
+
+/**
+ * @author SAP AG
+ */
+public class ODataPathSegmentImpl implements PathSegment {
+
+  private String path;
+  private Map<String, List<String>> matrixParameter;
+
+  public ODataPathSegmentImpl(final String path, final Map<String, List<String>> matrixParameters) {
+    this.path = path;
+
+    Map<String, List<String>> unmodifiableMap = new HashMap<String, List<String>>();
+    if (matrixParameters != null) {
+      for (String key : matrixParameters.keySet()) {
+        List<String> values = Collections.unmodifiableList(matrixParameters.get(key));
+        unmodifiableMap.put(key, values);
+      }
+    }
+
+    matrixParameter = Collections.unmodifiableMap(unmodifiableMap);
+  }
+
+  @Override
+  public String getPath() {
+    return path;
+  }
+
+  @Override
+  public Map<String, List<String>> getMatrixParameters() {
+    return matrixParameter;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
new file mode 100644
index 0000000..fbe3736
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestHandler.java
@@ -0,0 +1,456 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.ODataServiceVersion;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.ODataHttpHeaders;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
+import org.apache.olingo.odata2.api.exception.ODataUnsupportedMediaTypeException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
+import org.apache.olingo.odata2.core.debug.ODataDebugResponseWrapper;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.core.uri.UriParserImpl;
+import org.apache.olingo.odata2.core.uri.UriType;
+
+/**
+ * @author SAP AG
+ */
+public class ODataRequestHandler {
+
+  private final ODataServiceFactory serviceFactory;
+  private final ODataService service;
+  private final ODataContext context;
+
+  public ODataRequestHandler(final ODataServiceFactory factory, final ODataService service, final ODataContext context) {
+    serviceFactory = factory;
+    this.service = service;
+    this.context = context;
+  }
+
+  /**
+   * <p>Handles the {@link ODataRequest} in a way that it results in a corresponding {@link ODataResponse}.</p>
+   * <p>This includes delegation of URI parsing and dispatching of the request internally.
+   * Building of the {@link ODataContext} takes place outside of this method.</p>
+   * @param request the incoming request
+   * @return the corresponding result
+   */
+  public ODataResponse handle(final ODataRequest request) {
+    UriInfoImpl uriInfo = null;
+    Exception exception = null;
+    ODataResponse odataResponse;
+    final int timingHandle = context.startRuntimeMeasurement("ODataRequestHandler", "handle");
+    try {
+      UriParser uriParser = new UriParserImpl(service.getEntityDataModel());
+      Dispatcher dispatcher = new Dispatcher(serviceFactory, service);
+
+      final String serverDataServiceVersion = getServerDataServiceVersion();
+      final String requestDataServiceVersion = context.getRequestHeader(ODataHttpHeaders.DATASERVICEVERSION);
+      validateDataServiceVersion(serverDataServiceVersion, requestDataServiceVersion);
+
+      final List<PathSegment> pathSegments = context.getPathInfo().getODataSegments();
+      int timingHandle2 = context.startRuntimeMeasurement("UriParserImpl", "parse");
+      uriInfo = (UriInfoImpl) uriParser.parse(pathSegments, request.getQueryParameters());
+      context.stopRuntimeMeasurement(timingHandle2);
+
+      final ODataHttpMethod method = request.getMethod();
+      final UriType uriType = uriInfo.getUriType();
+      validateMethodAndUri(method, uriInfo);
+
+      if (method == ODataHttpMethod.POST || method == ODataHttpMethod.PUT
+          || method == ODataHttpMethod.PATCH || method == ODataHttpMethod.MERGE) {
+        checkRequestContentType(uriInfo, request.getContentType());
+      }
+
+      final String acceptContentType = new ContentNegotiator().doContentNegotiation(uriInfo, request.getAcceptHeaders(), getSupportedContentTypes(uriInfo));
+
+      timingHandle2 = context.startRuntimeMeasurement("Dispatcher", "dispatch");
+      odataResponse = dispatcher.dispatch(method, uriInfo, request.getBody(), request.getContentType(), acceptContentType);
+      context.stopRuntimeMeasurement(timingHandle2);
+
+      final String location = (method == ODataHttpMethod.POST && (uriType == UriType.URI1 || uriType == UriType.URI6B)) ? odataResponse.getIdLiteral() : null;
+      final HttpStatusCodes s = odataResponse.getStatus() == null ? method == ODataHttpMethod.POST ? uriType == UriType.URI9 ? HttpStatusCodes.OK : uriType == UriType.URI7B ? HttpStatusCodes.NO_CONTENT : HttpStatusCodes.CREATED : method == ODataHttpMethod.PUT || method == ODataHttpMethod.PATCH || method == ODataHttpMethod.MERGE || method == ODataHttpMethod.DELETE ? HttpStatusCodes.NO_CONTENT : HttpStatusCodes.OK : odataResponse.getStatus();
+
+      ODataResponseBuilder extendedResponse = ODataResponse.fromResponse(odataResponse);
+      if (!odataResponse.containsHeader(ODataHttpHeaders.DATASERVICEVERSION)) {
+        extendedResponse = extendedResponse.header(ODataHttpHeaders.DATASERVICEVERSION, serverDataServiceVersion);
+      }
+      extendedResponse = extendedResponse.idLiteral(location).status(s);
+      odataResponse = extendedResponse.build();
+
+    } catch (final Exception e) {
+      exception = e;
+      odataResponse = new ODataExceptionWrapper(context, request.getQueryParameters(), request.getAcceptHeaders())
+          .wrapInExceptionResponse(e);
+    }
+    context.stopRuntimeMeasurement(timingHandle);
+
+    final String debugValue = getDebugValue(context, request.getQueryParameters());
+    return debugValue == null ?
+        odataResponse : new ODataDebugResponseWrapper(context, odataResponse, uriInfo, exception, debugValue).wrapResponse();
+  }
+
+  private String getServerDataServiceVersion() throws ODataException {
+    return service.getVersion() == null ? ODataServiceVersion.V20 : service.getVersion();
+  }
+
+  private static void validateDataServiceVersion(final String serverDataServiceVersion, final String requestDataServiceVersion) throws ODataException {
+    if (requestDataServiceVersion != null) {
+      try {
+        final boolean isValid = ODataServiceVersion.validateDataServiceVersion(requestDataServiceVersion);
+        if (!isValid || ODataServiceVersion.isBiggerThan(requestDataServiceVersion, serverDataServiceVersion)) {
+          throw new ODataBadRequestException(ODataBadRequestException.VERSIONERROR.addContent(requestDataServiceVersion.toString()));
+        }
+      } catch (final IllegalArgumentException e) {
+        throw new ODataBadRequestException(ODataBadRequestException.PARSEVERSIONERROR.addContent(requestDataServiceVersion), e);
+      }
+    }
+  }
+
+  private static void validateMethodAndUri(final ODataHttpMethod method, final UriInfoImpl uriInfo) throws ODataException {
+    validateUriMethod(method, uriInfo);
+    checkFunctionImport(method, uriInfo);
+    if (method != ODataHttpMethod.GET) {
+      checkNotGetSystemQueryOptions(method, uriInfo);
+      checkNumberOfNavigationSegments(uriInfo);
+      checkProperty(method, uriInfo);
+    }
+  }
+
+  private static void validateUriMethod(final ODataHttpMethod method, final UriInfoImpl uriInfo) throws ODataException {
+    switch (uriInfo.getUriType()) {
+    case URI0:
+    case URI8:
+    case URI15:
+    case URI16:
+    case URI50A:
+    case URI50B:
+      if (method != ODataHttpMethod.GET) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI1:
+    case URI6B:
+    case URI7B:
+      if (method != ODataHttpMethod.GET && method != ODataHttpMethod.POST) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI2:
+    case URI6A:
+    case URI7A:
+      if (method != ODataHttpMethod.GET
+          && method != ODataHttpMethod.PUT
+          && method != ODataHttpMethod.DELETE
+          && method != ODataHttpMethod.PATCH && method != ODataHttpMethod.MERGE) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI3:
+      if (method != ODataHttpMethod.GET
+          && method != ODataHttpMethod.PUT
+          && method != ODataHttpMethod.PATCH && method != ODataHttpMethod.MERGE) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI4:
+    case URI5:
+      if (method != ODataHttpMethod.GET
+          && method != ODataHttpMethod.PUT
+          && method != ODataHttpMethod.DELETE
+          && method != ODataHttpMethod.PATCH && method != ODataHttpMethod.MERGE) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      } else if (method == ODataHttpMethod.DELETE && !uriInfo.isValue()) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI9:
+      if (method != ODataHttpMethod.POST) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI10:
+    case URI11:
+    case URI12:
+    case URI13:
+    case URI14:
+      break;
+
+    case URI17:
+      if (method != ODataHttpMethod.GET
+          && method != ODataHttpMethod.PUT
+          && method != ODataHttpMethod.DELETE) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    default:
+      throw new ODataRuntimeException("Unknown or not implemented URI type: " + uriInfo.getUriType());
+    }
+  }
+
+  private static void checkFunctionImport(final ODataHttpMethod method, final UriInfoImpl uriInfo) throws ODataException {
+    if (uriInfo.getFunctionImport() != null
+        && uriInfo.getFunctionImport().getHttpMethod() != null
+        && !uriInfo.getFunctionImport().getHttpMethod().equals(method.toString())) {
+      throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+    }
+  }
+
+  private static void checkNotGetSystemQueryOptions(final ODataHttpMethod method, final UriInfoImpl uriInfo) throws ODataException {
+    switch (uriInfo.getUriType()) {
+    case URI1:
+    case URI6B:
+      if (uriInfo.getFormat() != null
+          || uriInfo.getFilter() != null
+          || uriInfo.getInlineCount() != null
+          || uriInfo.getOrderBy() != null
+          || uriInfo.getSkipToken() != null
+          || uriInfo.getSkip() != null
+          || uriInfo.getTop() != null
+          || !uriInfo.getExpand().isEmpty()
+          || !uriInfo.getSelect().isEmpty()) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI2:
+      if (uriInfo.getFormat() != null
+          || !uriInfo.getExpand().isEmpty()
+          || !uriInfo.getSelect().isEmpty()) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      if (method == ODataHttpMethod.DELETE) {
+        if (uriInfo.getFilter() != null) {
+          throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+        }
+      }
+      break;
+
+    case URI3:
+      if (uriInfo.getFormat() != null) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI4:
+    case URI5:
+      if (method == ODataHttpMethod.PUT || method == ODataHttpMethod.PATCH || method == ODataHttpMethod.MERGE) {
+        if (!uriInfo.isValue() && uriInfo.getFormat() != null) {
+          throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+        }
+      }
+      break;
+
+    case URI7A:
+      if (uriInfo.getFormat() != null || uriInfo.getFilter() != null) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI7B:
+      if (uriInfo.getFormat() != null
+          || uriInfo.getFilter() != null
+          || uriInfo.getInlineCount() != null
+          || uriInfo.getOrderBy() != null
+          || uriInfo.getSkipToken() != null
+          || uriInfo.getSkip() != null
+          || uriInfo.getTop() != null) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    case URI17:
+      if (uriInfo.getFormat() != null || uriInfo.getFilter() != null) {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  private static void checkNumberOfNavigationSegments(final UriInfoImpl uriInfo) throws ODataException {
+    switch (uriInfo.getUriType()) {
+    case URI1:
+    case URI6B:
+    case URI7A:
+    case URI7B:
+      if (uriInfo.getNavigationSegments().size() > 1) {
+        throw new ODataBadRequestException(ODataBadRequestException.NOTSUPPORTED);
+      }
+      break;
+
+    case URI3:
+    case URI4:
+    case URI5:
+    case URI17:
+      if (!uriInfo.getNavigationSegments().isEmpty()) {
+        throw new ODataBadRequestException(ODataBadRequestException.NOTSUPPORTED);
+      }
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  private static void checkProperty(final ODataHttpMethod method, final UriInfoImpl uriInfo) throws ODataException {
+    if ((uriInfo.getUriType() == UriType.URI4 || uriInfo.getUriType() == UriType.URI5)
+        && (isPropertyKey(uriInfo)
+        || method == ODataHttpMethod.DELETE && !isPropertyNullable(getProperty(uriInfo)))) {
+      throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+    }
+  }
+
+  private static EdmProperty getProperty(final UriInfo uriInfo) {
+    final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
+    return propertyPath == null || propertyPath.isEmpty() ? null : propertyPath.get(propertyPath.size() - 1);
+  }
+
+  private static boolean isPropertyKey(final UriInfo uriInfo) throws EdmException {
+    return uriInfo.getTargetEntitySet().getEntityType().getKeyProperties().contains(getProperty(uriInfo));
+  }
+
+  private static boolean isPropertyNullable(final EdmProperty property) throws EdmException {
+    return property.getFacets() == null || property.getFacets().isNullable();
+  }
+
+  /**
+   * <p>Checks if <code>content type</code> is a valid request content type for the given {@link UriInfoImpl}.</p>
+   * <p>If the combination of <code>content type</code> and {@link UriInfoImpl}
+   * is not valid, an {@link ODataUnsupportedMediaTypeException} is thrown.</p>
+   * @param uriInfo information about request URI
+   * @param contentType request content type
+   * @throws ODataException in the case of an error during {@link UriInfoImpl} access;
+   *                        if the combination of <code>content type</code> and {@link UriInfoImpl}
+   *                        is invalid, as {@link ODataUnsupportedMediaTypeException}
+   */
+  private void checkRequestContentType(final UriInfoImpl uriInfo, final String contentType) throws ODataException {
+    Class<? extends ODataProcessor> processorFeature = Dispatcher.mapUriTypeToProcessorFeature(uriInfo);
+
+    // Don't check the request content type for function imports
+    // because the request body is not used at all.
+    if (processorFeature == FunctionImportProcessor.class
+        || processorFeature == FunctionImportValueProcessor.class) {
+      return;
+    }
+
+    // Adjust processor feature.
+    if (processorFeature == EntitySetProcessor.class) {
+      processorFeature = uriInfo.getTargetEntitySet().getEntityType().hasStream() ?
+          EntityMediaProcessor.class : // A media resource can have any type.
+          EntityProcessor.class; // The request must contain a single entity!
+    } else if (processorFeature == EntityLinksProcessor.class)
+    {
+      processorFeature = EntityLinkProcessor.class; // The request must contain a single link!
+    }
+
+    final ContentType parsedContentType = ContentType.parse(contentType);
+    if (parsedContentType == null || parsedContentType.hasWildcard()) {
+      throw new ODataUnsupportedMediaTypeException(ODataUnsupportedMediaTypeException.NOT_SUPPORTED.addContent(parsedContentType));
+    }
+
+    // Get list of supported content types based on processor feature.
+    final List<ContentType> supportedContentTypes =
+        processorFeature == EntitySimplePropertyValueProcessor.class ?
+            getSupportedContentTypes(getProperty(uriInfo)) :
+            getSupportedContentTypes(processorFeature);
+
+    if (!hasMatchingContentType(parsedContentType, supportedContentTypes)) {
+      throw new ODataUnsupportedMediaTypeException(ODataUnsupportedMediaTypeException.NOT_SUPPORTED.addContent(parsedContentType));
+    }
+  }
+
+  /**
+   * Checks if the given list of {@link ContentType}s contains a matching {@link ContentType}
+   * for the given <code>contentType</code> parameter.
+   * @param contentType for which a matching content type is searched
+   * @param allowedContentTypes list against which is checked for possible matching {@link ContentType}s
+   * @return <code>true</code> if a matching content type is in given list, otherwise <code>false</code>
+   */
+  private static boolean hasMatchingContentType(final ContentType contentType, final List<ContentType> allowedContentTypes) {
+    final ContentType requested = contentType.receiveWithCharsetParameter(ContentNegotiator.DEFAULT_CHARSET);
+    if (requested.getODataFormat() == ODataFormat.CUSTOM || requested.getODataFormat() == ODataFormat.MIME) {
+      return requested.hasCompatible(allowedContentTypes);
+    }
+    return requested.hasMatch(allowedContentTypes);
+  }
+
+  private static List<ContentType> getSupportedContentTypes(final EdmProperty property) throws EdmException {
+    return property.getType() == EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance() ?
+        Arrays.asList(property.getMimeType() == null ? ContentType.WILDCARD : ContentType.create(property.getMimeType())) :
+        Arrays.asList(ContentType.TEXT_PLAIN, ContentType.TEXT_PLAIN_CS_UTF_8);
+  }
+
+  private List<String> getSupportedContentTypes(final UriInfoImpl uriInfo) throws ODataException {
+    return service.getSupportedContentTypes(Dispatcher.mapUriTypeToProcessorFeature(uriInfo));
+  }
+
+  private List<ContentType> getSupportedContentTypes(final Class<? extends ODataProcessor> processorFeature) throws ODataException {
+    return ContentType.create(service.getSupportedContentTypes(processorFeature));
+  }
+
+  private static String getDebugValue(final ODataContext context, final Map<String, String> queryParameters) {
+    return context.isInDebugMode() ? getQueryDebugValue(queryParameters) : null;
+  }
+
+  private static String getQueryDebugValue(final Map<String, String> queryParameters) {
+    final String debugValue = queryParameters.get(ODataDebugResponseWrapper.ODATA_DEBUG_QUERY_PARAMETER);
+    return ODataDebugResponseWrapper.ODATA_DEBUG_JSON.equals(debugValue) ?
+        debugValue : null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestImpl.java
new file mode 100644
index 0000000..a5d6d3f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataRequestImpl.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.core.commons.ContentType;
+
+/**
+ * @author SAP AG
+ */
+public class ODataRequestImpl extends ODataRequest {
+
+  private ODataHttpMethod method;
+  private Map<String, List<String>> requestHeaders = new HashMap<String, List<String>>();
+  private InputStream body;
+  private PathInfo pathInfo;
+  private Map<String, String> queryParameters;
+  private List<String> acceptHeaders;
+  private ContentType contentType;
+  private List<Locale> acceptableLanguages;
+
+  @Override
+  public Map<String, String> getQueryParameters() {
+    return queryParameters;
+  }
+
+  @Override
+  public List<String> getAcceptHeaders() {
+    return acceptHeaders;
+  }
+
+  @Override
+  public String getContentType() {
+    return contentType == null ? null : contentType.toContentTypeString();
+  }
+
+  @Override
+  public List<Locale> getAcceptableLanguages() {
+    return acceptableLanguages;
+  }
+
+  @Override
+  public String getRequestHeaderValue(final String name) {
+    final List<String> headerList = requestHeaders.get(name);
+    return headerList == null || headerList.isEmpty() ? null : headerList.get(0);
+  }
+
+  @Override
+  public Map<String, List<String>> getRequestHeaders() {
+    return Collections.unmodifiableMap(requestHeaders);
+  }
+
+  @Override
+  public InputStream getBody() {
+    return body;
+  }
+
+  @Override
+  public ODataHttpMethod getMethod() {
+    return method;
+  }
+
+  @Override
+  public PathInfo getPathInfo() {
+    return pathInfo;
+  }
+
+  public class ODataRequestBuilderImpl extends ODataRequestBuilder {
+    private ODataHttpMethod method;
+    private Map<String, List<String>> requestHeaders = new HashMap<String, List<String>>();
+    private InputStream body;
+    private PathInfo pathInfo;
+    private Map<String, String> queryParameters;
+    private List<String> acceptHeaders;
+    private ContentType contentType;
+    private List<Locale> acceptableLanguages;
+
+    @Override
+    public ODataRequest build() {
+      ODataRequestImpl.this.method = method;
+      ODataRequestImpl.this.requestHeaders = requestHeaders;
+      ODataRequestImpl.this.body = body;
+      ODataRequestImpl.this.pathInfo = pathInfo;
+      ODataRequestImpl.this.queryParameters = queryParameters;
+      ODataRequestImpl.this.acceptHeaders = acceptHeaders;
+      ODataRequestImpl.this.contentType = contentType;
+      ODataRequestImpl.this.acceptableLanguages = acceptableLanguages;
+      return ODataRequestImpl.this;
+    }
+
+    @Override
+    public ODataRequestBuilder requestHeaders(final Map<String, List<String>> headers) {
+      requestHeaders = headers;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder body(final InputStream body) {
+      this.body = body;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder pathInfo(final PathInfo pathInfo) {
+      this.pathInfo = pathInfo;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder method(final ODataHttpMethod method) {
+      this.method = method;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder acceptableLanguages(final List<Locale> acceptableLanguages) {
+      this.acceptableLanguages = acceptableLanguages;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder acceptHeaders(final List<String> acceptHeaders) {
+      this.acceptHeaders = acceptHeaders;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder queryParameters(final Map<String, String> queryParameters) {
+      this.queryParameters = queryParameters;
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder contentType(final String contentType) {
+      this.contentType = ContentType.create(contentType);
+      return this;
+    }
+
+    @Override
+    public ODataRequestBuilder fromRequest(final ODataRequest request) {
+      pathInfo = request.getPathInfo();
+      method = request.getMethod();
+      body = request.getBody();
+      if (request.getContentType() != null) {
+        contentType = ContentType.create(request.getContentType());
+      }
+      requestHeaders = request.getRequestHeaders();
+
+      if (request.getAcceptHeaders() != null) {
+        acceptHeaders = new ArrayList<String>();
+        for (String acceptHeader : request.getAcceptHeaders()) {
+          acceptHeaders.add(acceptHeader);
+        }
+      }
+      if (request.getAcceptableLanguages() != null) {
+        acceptableLanguages = new ArrayList<Locale>();
+        for (Locale acceptLanguage : request.getAcceptableLanguages()) {
+          acceptableLanguages.add(acceptLanguage);
+        }
+      }
+      if (request.getQueryParameters() != null) {
+        queryParameters = new HashMap<String, String>();
+        for (Map.Entry<String, String> queryParameter : request.getQueryParameters().entrySet()) {
+          String queryParameterName = queryParameter.getKey();
+          queryParameters.put(queryParameterName, queryParameter.getValue());
+        }
+      }
+      return this;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataResponseImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataResponseImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataResponseImpl.java
new file mode 100644
index 0000000..b614d02
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ODataResponseImpl.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+/**
+ * @author SAP AG
+ */
+public class ODataResponseImpl extends ODataResponse {
+
+  private HttpStatusCodes status;
+  private Object entity;
+  private HashMap<String, String> headers;
+
+  @Override
+  public HttpStatusCodes getStatus() {
+    return status;
+  }
+
+  @Override
+  public Object getEntity() {
+    return entity;
+  }
+
+  @Override
+  public void close() throws IOException {
+    if (entity != null && entity instanceof Closeable) {
+      Closeable closeableEntity = (Closeable) entity;
+      closeableEntity.close();
+    }
+  }
+
+  @Override
+  public String getHeader(final String name) {
+    return headers.get(name);
+  }
+
+  @Override
+  public Set<String> getHeaderNames() {
+    return headers.keySet();
+  }
+
+  @Override
+  public String getIdLiteral() {
+    return headers.get(HttpHeaders.LOCATION);
+  }
+
+  @Override
+  public String getETag() {
+    return headers.get(HttpHeaders.ETAG);
+  }
+
+  @Override
+  public String getContentHeader() {
+    return headers.get(HttpHeaders.CONTENT_TYPE);
+  }
+
+  @Override
+  public boolean containsHeader(final String header) {
+    boolean contains = false;
+    for (String containedHeader : headers.keySet()) {
+      if (containedHeader.equalsIgnoreCase(header)) {
+        contains = true;
+        break;
+      }
+    }
+    return contains;
+  }
+
+  public class ODataResponseBuilderImpl extends ODataResponseBuilder {
+    private HttpStatusCodes status;
+    private Object entity;
+    private HashMap<String, String> headers = new HashMap<String, String>();
+
+    @Override
+    public ODataResponse build() {
+      ODataResponseImpl.this.status = status;
+      ODataResponseImpl.this.entity = entity;
+      ODataResponseImpl.this.headers = headers;
+
+      return ODataResponseImpl.this;
+    }
+
+    @Override
+    public ODataResponseBuilder status(final HttpStatusCodes status) {
+      this.status = status;
+      return this;
+    }
+
+    @Override
+    public ODataResponseBuilder entity(final Object entity) {
+      this.entity = entity;
+      return this;
+    }
+
+    @Override
+    public ODataResponseBuilder header(final String name, final String value) {
+      if (value == null) {
+        headers.remove(name);
+      } else {
+        headers.put(name, value);
+      }
+
+      return this;
+    }
+
+    @Override
+    public ODataResponseBuilder idLiteral(final String idLiteral) {
+      return header(HttpHeaders.LOCATION, idLiteral);
+    }
+
+    @Override
+    public ODataResponseBuilder eTag(final String eTag) {
+      return header(HttpHeaders.ETAG, eTag);
+    }
+
+    @Override
+    public ODataResponseBuilder contentHeader(final String value) {
+      return header(HttpHeaders.CONTENT_TYPE, value);
+    }
+
+    @Override
+    protected ODataResponseBuilder fromResponse(final ODataResponse response) {
+      status = response.getStatus();
+      entity = response.getEntity();
+
+      headers = new HashMap<String, String>();
+      for (String key : response.getHeaderNames()) {
+        headers.put(key, response.getHeader(key));
+      }
+
+      return this;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/PathInfoImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/PathInfoImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/PathInfoImpl.java
new file mode 100644
index 0000000..3420094
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/PathInfoImpl.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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;
+
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+
+/**
+ * @author SAP AG
+ */
+public class PathInfoImpl implements PathInfo {
+
+  private List<PathSegment> precedingPathSegment = Collections.emptyList();
+  private List<PathSegment> odataPathSegment = Collections.emptyList();
+  private URI serviceRoot;
+  private URI requestUri;
+
+  public void setODataPathSegment(final List<PathSegment> odataPathSegement) {
+    odataPathSegment = odataPathSegement;
+  }
+
+  public void setPrecedingPathSegment(final List<PathSegment> precedingPathSegement) {
+    precedingPathSegment = precedingPathSegement;
+  }
+
+  public void setServiceRoot(final URI uri) {
+    serviceRoot = uri;
+  }
+
+  @Override
+  public List<PathSegment> getPrecedingSegments() {
+    return Collections.unmodifiableList(precedingPathSegment);
+  }
+
+  @Override
+  public List<PathSegment> getODataSegments() {
+    return Collections.unmodifiableList(odataPathSegment);
+  }
+
+  @Override
+  public URI getServiceRoot() {
+    return serviceRoot;
+  }
+
+  @Override
+  public URI getRequestUri() {
+    return requestUri;
+  }
+
+  public void setRequestUri(final URI requestUri) {
+    this.requestUri = requestUri;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
new file mode 100644
index 0000000..f3cd4cd
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/AcceptParser.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Scanner;
+import java.util.TreeSet;
+import java.util.regex.MatchResult;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+
+/**
+ * @author SAP AG
+ */
+public class AcceptParser {
+
+  private static final String BAD_REQUEST = "400";
+  private static final String ALL = "*";
+  private static final String REG_EX_QUALITY_FACTOR = "q=((?:1\\.0{0,3})|(?:0\\.[0-9]{0,2}[1-9]))";
+  private static final String REG_EX_OPTIONAL_WHITESPACE = "\\s?";
+  private static final Pattern REG_EX_ACCEPT = Pattern.compile("([a-z\\*]+/[a-z0-9\\+\\*\\-=;\\s]+)");
+  private static final Pattern REG_EX_ACCEPT_WITH_Q_FACTOR = Pattern.compile(REG_EX_ACCEPT + "(?:;" + REG_EX_OPTIONAL_WHITESPACE + REG_EX_QUALITY_FACTOR + ")?");
+  private static final Pattern REG_EX_ACCEPT_LANGUAGES = Pattern.compile("((?:(?:[a-z]{1,8})|(?:\\*))\\-?(?:[a-zA-Z]{1,8})?)");
+  private static final Pattern REG_EX_ACCEPT_LANGUAGES_WITH_Q_FACTOR = Pattern.compile(REG_EX_ACCEPT_LANGUAGES + "(?:;" + REG_EX_OPTIONAL_WHITESPACE + REG_EX_QUALITY_FACTOR + ")?");
+
+  private static final double QUALITY_PARAM_FACTOR = 0.001;
+
+  public static List<String> parseAcceptHeaders(final String headerValue) throws BatchException {
+    TreeSet<Accept> acceptTree = getAcceptTree();
+    List<String> acceptHeaders = new ArrayList<String>();
+    Scanner acceptHeaderScanner = new Scanner(headerValue).useDelimiter(",\\s?");
+    while (acceptHeaderScanner.hasNext()) {
+      if (acceptHeaderScanner.hasNext(REG_EX_ACCEPT_WITH_Q_FACTOR)) {
+        acceptHeaderScanner.next(REG_EX_ACCEPT_WITH_Q_FACTOR);
+        MatchResult result = acceptHeaderScanner.match();
+        if (result.groupCount() == 2) {
+          String acceptHeaderValue = result.group(1);
+          double qualityFactor = result.group(2) != null ? Double.parseDouble(result.group(2)) : 1d;
+          qualityFactor = getQualityFactor(acceptHeaderValue, qualityFactor);
+          Accept acceptHeader = new Accept().setQuality(qualityFactor).setValue(acceptHeaderValue);
+          acceptTree.add(acceptHeader);
+        } else {
+          String header = acceptHeaderScanner.next();
+          acceptHeaderScanner.close();
+          throw new BatchException(BatchException.INVALID_ACCEPT_HEADER.addContent(header), BAD_REQUEST);
+        }
+      } else {
+        String header = acceptHeaderScanner.next();
+        acceptHeaderScanner.close();
+        throw new BatchException(BatchException.INVALID_ACCEPT_HEADER.addContent(header), BAD_REQUEST);
+      }
+    }
+    for (Accept accept : acceptTree) {
+      acceptHeaders.add(accept.getValue());
+    }
+    acceptHeaderScanner.close();
+    return acceptHeaders;
+  }
+
+  private static double getQualityFactor(final String acceptHeaderValue, double qualityFactor) {
+    int paramNumber = 0;
+    double typeFactor = 0.0;
+    double subtypeFactor = 0.0;
+    String[] mediaRange = acceptHeaderValue.split("(?=[^;]+);");
+    String[] mediaTypes = mediaRange[0].split("/");
+    if (mediaTypes.length == 2) {
+      String type = mediaTypes[0];
+      String subtype = mediaTypes[1];
+      if (!ALL.equals(type)) {
+        typeFactor = 0.001;
+      }
+      if (!ALL.equals(subtype)) {
+        subtypeFactor = 0.001;
+      }
+    }
+    if (mediaRange.length == 2) {
+      String[] parameters = mediaRange[1].split(";\\s?");
+      paramNumber = parameters.length;
+    }
+    qualityFactor = qualityFactor + paramNumber * QUALITY_PARAM_FACTOR + typeFactor + subtypeFactor;
+    return qualityFactor;
+  }
+
+  public static List<String> parseAcceptableLanguages(final String headerValue) throws BatchException {
+    List<String> acceptLanguages = new LinkedList<String>();
+    TreeSet<Accept> acceptTree = getAcceptTree();
+    Scanner acceptLanguageScanner = new Scanner(headerValue).useDelimiter(",\\s?");
+    while (acceptLanguageScanner.hasNext()) {
+      if (acceptLanguageScanner.hasNext(REG_EX_ACCEPT_LANGUAGES_WITH_Q_FACTOR)) {
+        acceptLanguageScanner.next(REG_EX_ACCEPT_LANGUAGES_WITH_Q_FACTOR);
+        MatchResult result = acceptLanguageScanner.match();
+        if (result.groupCount() == 2) {
+          String languagerange = result.group(1);
+          double qualityFactor = result.group(2) != null ? Double.parseDouble(result.group(2)) : 1d;
+          acceptTree.add(new Accept().setQuality(qualityFactor).setValue(languagerange));
+        } else {
+          String acceptLanguage = acceptLanguageScanner.next();
+          acceptLanguageScanner.close();
+          throw new BatchException(BatchException.INVALID_ACCEPT_LANGUAGE_HEADER.addContent(acceptLanguage), BAD_REQUEST);
+        }
+      } else {
+        String acceptLanguage = acceptLanguageScanner.next();
+        acceptLanguageScanner.close();
+        throw new BatchException(BatchException.INVALID_ACCEPT_LANGUAGE_HEADER.addContent(acceptLanguage), BAD_REQUEST);
+      }
+    }
+    for (Accept accept : acceptTree) {
+      acceptLanguages.add(accept.getValue());
+    }
+    acceptLanguageScanner.close();
+    return acceptLanguages;
+  }
+
+  private static TreeSet<Accept> getAcceptTree() {
+    TreeSet<Accept> treeSet = new TreeSet<Accept>(new Comparator<Accept>() {
+      @Override
+      public int compare(final Accept o1, final Accept o2) {
+        if (o1.getQuality() <= o2.getQuality()) {
+          return 1;
+        } else {
+          return -1;
+        }
+      }
+    });
+    return treeSet;
+  }
+
+  private static class Accept {
+    private double quality;
+    private String value;
+
+    public String getValue() {
+      return value;
+    }
+
+    public Accept setValue(final String value) {
+      this.value = value;
+      return this;
+    }
+
+    public double getQuality() {
+      return quality;
+    }
+
+    public Accept setQuality(final double quality) {
+      this.quality = quality;
+      return this;
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java
new file mode 100644
index 0000000..052365d
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchConstants.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+public class BatchConstants {
+
+  public static final String HTTP_APPLICATION_HTTP = "application/http";
+
+  public static final String MULTIPART_MIXED = "multipart/mixed";
+
+  public static final String BINARY_ENCODING = "binary";
+
+  public static final String HTTP_CONTENT_TRANSFER_ENCODING = "Content-Transfer-Encoding";
+
+  public static final String HTTP_CONTENT_ID = "Content-Id";
+
+  public static final String MIME_HEADER_CONTENT_ID = "MimeHeader-ContentId";
+
+  public static final String REQUEST_HEADER_CONTENT_ID = "RequestHeader-ContentId";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
new file mode 100644
index 0000000..22dfd70
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchHandlerImpl.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.batch.BatchHandler;
+import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.core.ODataContextImpl;
+import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
+import org.apache.olingo.odata2.core.ODataRequestHandler;
+import org.apache.olingo.odata2.core.PathInfoImpl;
+
+public class BatchHandlerImpl implements BatchHandler {
+  private static final int BAD_REQUEST = 400;
+  private ODataServiceFactory factory;
+  private ODataService service;
+  private Map<String, String> contentIdMap;
+
+  public BatchHandlerImpl(final ODataServiceFactory factory, final ODataService service) {
+    this.factory = factory;
+    this.service = service;
+  }
+
+  @Override
+  public BatchResponsePart handleBatchPart(final BatchPart batchPart) throws ODataException {
+    if (batchPart.isChangeSet()) {
+      List<ODataRequest> changeSetRequests = batchPart.getRequests();
+      contentIdMap = new HashMap<String, String>();
+      return service.getBatchProcessor().executeChangeSet(this, changeSetRequests);
+    } else {
+      if (batchPart.getRequests().size() != 1) {
+        throw new ODataException("Query Operation should contain one request");
+      }
+      ODataRequest request = batchPart.getRequests().get(0);
+      ODataRequestHandler handler = createHandler(request);
+      String mimeHeaderContentId = request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+      String requestHeaderContentId = request.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+      ODataResponse response = setContentIdHeader(handler.handle(request), mimeHeaderContentId, requestHeaderContentId);
+      List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+      responses.add(response);
+      return BatchResponsePart.responses(responses).changeSet(false).build();
+    }
+  }
+
+  @Override
+  public ODataResponse handleRequest(final ODataRequest suppliedRequest) throws ODataException {
+    ODataRequest request;
+    String mimeHeaderContentId = suppliedRequest.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+    String requestHeaderContentId = suppliedRequest.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase(Locale.ENGLISH));
+
+    List<PathSegment> odataSegments = suppliedRequest.getPathInfo().getODataSegments();
+    if (!odataSegments.isEmpty() && odataSegments.get(0).getPath().matches("\\$.*")) {
+      request = modifyRequest(suppliedRequest, odataSegments);
+    } else {
+      request = suppliedRequest;
+    }
+    ODataRequestHandler handler = createHandler(request);
+    ODataResponse response = handler.handle(request);
+    if (response.getStatus().getStatusCode() < BAD_REQUEST) {
+      response = setContentIdHeader(response, mimeHeaderContentId, requestHeaderContentId);
+    }
+    if (request.getMethod().equals(ODataHttpMethod.POST)) {
+      String baseUri = getBaseUri(request);
+      if (mimeHeaderContentId != null) {
+        fillContentIdMap(response, mimeHeaderContentId, baseUri);
+      } else if (requestHeaderContentId != null) {
+        fillContentIdMap(response, requestHeaderContentId, baseUri);
+      }
+    }
+    return response;
+  }
+
+  private void fillContentIdMap(final ODataResponse response, final String contentId, final String baseUri) {
+    String location = response.getHeader(HttpHeaders.LOCATION);
+    String relLocation = location.replace(baseUri + "/", "");
+    contentIdMap.put("$" + contentId, relLocation);
+  }
+
+  private ODataRequest modifyRequest(final ODataRequest request, final List<PathSegment> odataSegments) throws ODataException {
+    String contentId = contentIdMap.get(odataSegments.get(0).getPath());
+    PathInfoImpl pathInfo = new PathInfoImpl();
+    try {
+      List<PathSegment> modifiedODataSegments = new ArrayList<PathSegment>();
+      String[] segments = contentId.split("/");
+      for (String segment : segments) {
+        modifiedODataSegments.add(new ODataPathSegmentImpl(segment, null));
+      }
+      String newRequestUri = getBaseUri(request);
+      newRequestUri += "/" + contentId;
+      for (int i = 1; i < odataSegments.size(); i++) {
+        newRequestUri += "/" + odataSegments.get(i).getPath();
+        modifiedODataSegments.add(odataSegments.get(i));
+      }
+      for (Map.Entry<String, String> entry : request.getQueryParameters().entrySet()) {
+        newRequestUri += "/" + entry;
+      }
+
+      pathInfo.setServiceRoot(request.getPathInfo().getServiceRoot());
+      pathInfo.setPrecedingPathSegment(request.getPathInfo().getPrecedingSegments());
+      pathInfo.setRequestUri(new URI(newRequestUri));
+      pathInfo.setODataPathSegment(modifiedODataSegments);
+    } catch (URISyntaxException e) {
+      throw new ODataException(e);
+    }
+    ODataRequest modifiedRequest = ODataRequest.fromRequest(request).pathInfo(pathInfo).build();
+    return modifiedRequest;
+  }
+
+  private ODataResponse setContentIdHeader(final ODataResponse response, final String mimeHeaderContentId, final String requestHeaderContentId) {
+    ODataResponse modifiedResponse;
+    if (requestHeaderContentId != null && mimeHeaderContentId != null) {
+      modifiedResponse = ODataResponse.fromResponse(response).header(BatchConstants.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId)
+          .header(BatchConstants.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build();
+    } else if (requestHeaderContentId != null) {
+      modifiedResponse = ODataResponse.fromResponse(response).header(BatchConstants.REQUEST_HEADER_CONTENT_ID, requestHeaderContentId).build();
+    } else if (mimeHeaderContentId != null) {
+      modifiedResponse = ODataResponse.fromResponse(response).header(BatchConstants.MIME_HEADER_CONTENT_ID, mimeHeaderContentId).build();
+    } else {
+      return response;
+    }
+    return modifiedResponse;
+  }
+
+  private String getBaseUri(final ODataRequest request) {
+    String baseUri = request.getPathInfo().getServiceRoot().toASCIIString();
+    if (baseUri.endsWith("/")) {
+      baseUri = baseUri.substring(0, baseUri.length() - 1);
+    }
+    for (PathSegment segment : request.getPathInfo().getPrecedingSegments()) {
+      baseUri += "/" + segment.getPath();
+    }
+    return baseUri;
+  }
+
+  private ODataRequestHandler createHandler(final ODataRequest request) throws ODataException {
+    ODataContextImpl context = new ODataContextImpl(request, factory);
+    ODataContext parentContext = service.getProcessor().getContext();
+    context.setBatchParentContext(parentContext);
+    context.setService(service);
+    service.getProcessor().setContext(context);
+    return new ODataRequestHandler(factory, service, context);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java
new file mode 100644
index 0000000..665b01b
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/batch/BatchPartImpl.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+
+public class BatchPartImpl implements BatchPart {
+
+  private List<ODataRequest> requests = new ArrayList<ODataRequest>();
+  private boolean isChangeSet;
+
+  public BatchPartImpl() {}
+
+  public BatchPartImpl(final boolean isChangeSet, final List<ODataRequest> requests) {
+    this.isChangeSet = isChangeSet;
+    this.requests = requests;
+  }
+
+  @Override
+  public boolean isChangeSet() {
+    return isChangeSet;
+  }
+
+  public void setChangeSet(final boolean isChangeSet) {
+    this.isChangeSet = isChangeSet;
+  }
+
+  @Override
+  public List<ODataRequest> getRequests() {
+    return Collections.unmodifiableList(requests);
+  }
+
+  public void setRequests(final List<ODataRequest> requests) {
+    this.requests = requests;
+  }
+
+}


[13/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/MessageService.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/MessageService.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/MessageService.java
new file mode 100644
index 0000000..0964488
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/MessageService.java
@@ -0,0 +1,222 @@
+/*******************************************************************************
+ * 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.exception;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Formatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.MissingFormatArgumentException;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+
+/**
+ * @author SAP AG
+ */
+public class MessageService {
+  private static final String BUNDLE_NAME = "i18n";
+
+  private final ResourceBundle resourceBundle;
+  private final Locale requestedLocale;
+
+  private static final Map<Locale, MessageService> LOCALE_2_MESSAGE_SERVICE = new HashMap<Locale, MessageService>();
+
+  private MessageService(final Locale locale) {
+    requestedLocale = locale;
+    resourceBundle = createResourceBundle(locale);
+  }
+
+  /**
+   * Create a {@link ResourceBundle} based on given locale and name ({@value #BUNDLE_NAME}).
+   * If during creation an exception occurs it is catched and an special bundle is created with error type and message of
+   * this exception.
+   * 
+   * @param locale for which locale the {@link ResourceBundle} is created
+   * @return a {@link ResourceBundle}
+   */
+  private ResourceBundle createResourceBundle(final Locale locale) {
+    ResourceBundle bundle;
+    try {
+      if (locale == null) {
+        throw new IllegalArgumentException("Parameter locale MUST NOT be NULL.");
+      }
+      bundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
+    } catch (final Exception e) {
+      bundle = new ResourceBundle() {
+        @Override
+        protected Object handleGetObject(final String key) {
+          return "MessageService could not be created because of exception '" +
+              e.getClass().getSimpleName() + " with message '" + e.getMessage() + "'.";
+        }
+
+        @Override
+        public Locale getLocale() {
+          return Locale.ENGLISH;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Enumeration<String> getKeys() {
+          return (Enumeration<String>) Collections.emptySet();
+        }
+      };
+    }
+    return bundle;
+  }
+
+  public static class Message {
+    private final String localizedText;
+    private final Locale locale;
+
+    public Message(final Locale locale, final String localizedMessage) {
+      super();
+      localizedText = localizedMessage;
+      this.locale = locale;
+    }
+
+    public String getText() {
+      return localizedText;
+    }
+
+    public Locale getLocale() {
+      return locale;
+    }
+
+    /**
+     * Get language as defined in RFC 4646 based on {@link Locale}.
+     * 
+     * @return the language label
+     */
+    public String getLang() {
+      Locale locale = getLocale();
+      if (locale.getCountry().isEmpty()) {
+        return locale.getLanguage();
+      }
+      return locale.getLanguage() + "-" + locale.getCountry();
+    }
+  }
+
+  public static MessageService getInstance(final Locale locale) {
+    MessageService messagesInstance = LOCALE_2_MESSAGE_SERVICE.get(locale);
+    if (messagesInstance == null) {
+      messagesInstance = new MessageService(locale);
+      LOCALE_2_MESSAGE_SERVICE.put(locale, messagesInstance);
+    }
+    return messagesInstance;
+  }
+
+  public static boolean isLocaleSupported(final Locale locale) {
+    if (locale == null) {
+      return false;
+    }
+    MessageService service = getInstance(locale);
+    return service.getLocale().equals(locale);
+  }
+
+  /**
+   * Return first found supported {@link Locale} (iterating over list starting with first element).
+   * If no {@link Locale} is supported <code>NULL</code> is returned.
+   * 
+   * @param locales
+   * @return first supported {@link Locale} or <code>NULL</code>.
+   */
+  public static Locale getSupportedLocale(final List<Locale> locales) {
+    return getSupportedLocale(locales, null);
+  }
+
+  /**
+   * Return first found supported {@link Locale} (iterating over list starting with first element).
+   * If no {@link Locale} is supported given <code>defaultLocale</code> is returned.
+   * 
+   * @param locales to be checked locales
+   * @param defaultLocale local which is returned if no supported local is in given <code>locales</code> list
+   * @return first supported {@link Locale} or given <code>defaultLocale</code>.
+   */
+  public static Locale getSupportedLocale(final List<Locale> locales, final Locale defaultLocale) {
+    for (Locale locale : locales) {
+      if (isLocaleSupported(locale)) {
+        return locale;
+      }
+    }
+    return defaultLocale;
+  }
+
+  public static MessageService getInstance(final List<Locale> locales) {
+    MessageService service = null;
+
+    for (Locale locale : locales) {
+      service = getInstance(locale);
+      if (service.getLocale().equals(locale)) {
+        break;
+      }
+    }
+
+    return service;
+  }
+
+  public static Message getMessage(final Locale language, final MessageReference context) {
+    Object[] contentAsArray = context.getContent().toArray(new Object[0]);
+    return getMessage(language, context.getKey(), contentAsArray);
+  }
+
+  public static Message getMessage(final Locale locale, final String key, final Object... replacements) {
+    MessageService messages = MessageService.getInstance(locale);
+    return messages.getMessage(key, replacements);
+  }
+
+  /**
+   * 
+   * @param key
+   * @param replacements
+   * @return the message
+   */
+  private Message getMessage(final String key, final Object... replacements) {
+    String value = null;
+
+    try {
+      value = resourceBundle.getString(key);
+      StringBuilder builder = new StringBuilder();
+      Formatter f = new Formatter(builder, requestedLocale);
+      f.format(value, replacements);
+      f.close();
+
+      return new Message(getLocale(), builder.toString());
+
+    } catch (MissingResourceException e) {
+      return new Message(Locale.ENGLISH, "Missing message for key '" + key + "'!");
+    } catch (MissingFormatArgumentException e) {
+      return new Message(Locale.ENGLISH, "Missing replacement for place holder in value '" + value +
+          "' for following arguments '" + Arrays.toString(replacements) + "'!");
+    }
+  }
+
+  public Locale getLocale() {
+    return resourceBundle.getLocale();
+  }
+
+  public Enumeration<String> getKeys() {
+    return resourceBundle.getKeys();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/ODataRuntimeException.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/ODataRuntimeException.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/ODataRuntimeException.java
new file mode 100644
index 0000000..b369de8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/exception/ODataRuntimeException.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.exception;
+
+/**
+ * Common un-checked exception for the <code>OData</code> library and
+ * base exception for all <code>OData</code>-related exceptions
+ * caused by programming errors and/or unexpected behavior within the code.
+ * @author SAP AG
+ */
+public final class ODataRuntimeException extends RuntimeException {
+
+  private static final long serialVersionUID = 1L;
+
+  public ODataRuntimeException() {
+    super();
+  }
+
+  public ODataRuntimeException(final Throwable throwable) {
+    super(throwable);
+  }
+
+  public ODataRuntimeException(final String message) {
+    super(message);
+  }
+
+  public ODataRuntimeException(final String message, final Throwable throwable) {
+    super(message, throwable);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/processor/ODataSingleProcessorService.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/processor/ODataSingleProcessorService.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/processor/ODataSingleProcessorService.java
new file mode 100644
index 0000000..0ebcf4f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/processor/ODataSingleProcessorService.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * 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.processor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceVersion;
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.api.processor.feature.CustomContentType;
+import org.apache.olingo.odata2.api.processor.part.BatchProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityComplexPropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.MetadataProcessor;
+import org.apache.olingo.odata2.api.processor.part.ServiceDocumentProcessor;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * <p>An {@link ODataService} implementation that uses {@link ODataSingleProcessor}.</p>
+ * <p>Usually custom services create an instance by their implementation of
+ * {@link org.apache.olingo.odata2.api.ODataServiceFactory} and populate it with their custom {@link EdmProvider}
+ * and custom {@link ODataSingleProcessor} implementations.</p>
+ *
+ * @author SAP AG
+ */
+public class ODataSingleProcessorService implements ODataService {
+
+  private final ODataSingleProcessor processor;
+  private final Edm edm;
+
+  /**
+   * Construct service
+   * @param provider A custom {@link EdmProvider}
+   * @param processor A custom {@link ODataSingleProcessor}
+   */
+  public ODataSingleProcessorService(final EdmProvider provider, final ODataSingleProcessor processor) {
+    this.processor = processor;
+    edm = RuntimeDelegate.createEdm(provider);
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public String getVersion() throws ODataException {
+    return ODataServiceVersion.V20;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public Edm getEntityDataModel() throws ODataException {
+    return edm;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public MetadataProcessor getMetadataProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public ServiceDocumentProcessor getServiceDocumentProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntityProcessor getEntityProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntitySetProcessor getEntitySetProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntityComplexPropertyProcessor getEntityComplexPropertyProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntityLinkProcessor getEntityLinkProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntityLinksProcessor getEntityLinksProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntityMediaProcessor getEntityMediaProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntitySimplePropertyProcessor getEntitySimplePropertyProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public EntitySimplePropertyValueProcessor getEntitySimplePropertyValueProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public FunctionImportProcessor getFunctionImportProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public FunctionImportValueProcessor getFunctionImportValueProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public BatchProcessor getBatchProcessor() throws ODataException {
+    return processor;
+  }
+
+  /**
+   * @see ODataService
+   */
+  @Override
+  public ODataProcessor getProcessor() throws ODataException {
+    return processor;
+  }
+
+  @Override
+  public List<String> getSupportedContentTypes(final Class<? extends ODataProcessor> processorFeature) throws ODataException {
+    List<String> result = new ArrayList<String>();
+
+    if (processor instanceof CustomContentType) {
+      result.addAll(((CustomContentType) processor).getCustomContentTypes(processorFeature));
+    }
+
+    if (processorFeature == BatchProcessor.class) {
+      result.add(HttpContentType.MULTIPART_MIXED);
+    } else if (processorFeature == EntityProcessor.class) {
+      result.add(HttpContentType.APPLICATION_ATOM_XML_ENTRY_UTF8);
+      result.add(HttpContentType.APPLICATION_ATOM_XML_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8_VERBOSE);
+      result.add(HttpContentType.APPLICATION_XML_UTF8);
+    } else if (processorFeature == FunctionImportProcessor.class
+        || processorFeature == EntityLinkProcessor.class
+        || processorFeature == EntityLinksProcessor.class
+        || processorFeature == EntitySimplePropertyProcessor.class
+        || processorFeature == EntityComplexPropertyProcessor.class) {
+      result.add(HttpContentType.APPLICATION_XML_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8_VERBOSE);
+    } else if (processorFeature == EntityMediaProcessor.class
+        || processorFeature == EntitySimplePropertyValueProcessor.class
+        || processorFeature == FunctionImportValueProcessor.class) {
+      result.add(HttpContentType.WILDCARD);
+    } else if (processorFeature == EntitySetProcessor.class) {
+      result.add(HttpContentType.APPLICATION_ATOM_XML_FEED_UTF8);
+      result.add(HttpContentType.APPLICATION_ATOM_XML_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8_VERBOSE);
+      result.add(HttpContentType.APPLICATION_XML_UTF8);
+    } else if (processorFeature == MetadataProcessor.class) {
+      result.add(HttpContentType.APPLICATION_XML_UTF8);
+    } else if (processorFeature == ServiceDocumentProcessor.class) {
+      result.add(HttpContentType.APPLICATION_ATOM_SVC_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8);
+      result.add(HttpContentType.APPLICATION_JSON_UTF8_VERBOSE);
+      result.add(HttpContentType.APPLICATION_XML_UTF8);
+    } else {
+      throw new ODataNotImplementedException();
+    }
+
+    return result;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/MERGE.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/MERGE.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/MERGE.java
new file mode 100644
index 0000000..ec05a98
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/MERGE.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.rest;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@HttpMethod("MERGE")
+public @interface MERGE {}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataExceptionMapperImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataExceptionMapperImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataExceptionMapperImpl.java
new file mode 100644
index 0000000..437e014
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataExceptionMapperImpl.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * 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.rest;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.NotAllowedException;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.ext.ExceptionMapper;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.processor.ODataErrorCallback;
+import org.apache.olingo.odata2.api.processor.ODataErrorContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.ODataExceptionWrapper;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.ep.ProviderFacadeImpl;
+
+/**
+ * Creates an error response according to the format defined by the OData standard
+ * if an exception occurs that is not handled elsewhere.
+ * @author SAP AG
+ */
+@Provider
+public class ODataExceptionMapperImpl implements ExceptionMapper<Exception> {
+
+  private static final String DOLLAR_FORMAT = "$format";
+  private static final String DOLLAR_FORMAT_JSON = "json";
+
+  private static final Locale DEFAULT_RESPONSE_LOCALE = Locale.ENGLISH;
+
+  @Context
+  UriInfo uriInfo;
+  @Context
+  HttpHeaders httpHeaders;
+  @Context
+  ServletConfig servletConfig;
+  @Context
+  HttpServletRequest servletRequest;
+
+  @Override
+  public Response toResponse(final Exception exception) {
+    ODataResponse response;
+    try {
+      if (exception instanceof WebApplicationException) {
+        response = handleWebApplicationException(exception);
+      } else {
+        response = handleException(exception);
+      }
+    } catch (Exception e) {
+      response = ODataResponse.entity("Exception during error handling occured!")
+          .contentHeader(ContentType.TEXT_PLAIN.toContentTypeString())
+          .status(HttpStatusCodes.INTERNAL_SERVER_ERROR).build();
+    }
+    // Convert OData response to JAX-RS response.
+    return RestUtil.convertResponse(response);
+  }
+
+  private ODataResponse handleException(final Exception exception) {
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(uriInfo, httpHeaders, servletConfig, servletRequest);
+    ODataResponse oDataResponse = exceptionWrapper.wrapInExceptionResponse(exception);
+    return oDataResponse;
+  }
+
+  private ODataResponse handleWebApplicationException(final Exception exception) throws ClassNotFoundException, InstantiationException, IllegalAccessException, EntityProviderException {
+    ODataErrorContext errorContext = createErrorContext((WebApplicationException) exception);
+    ODataErrorCallback callback = getErrorHandlerCallback();
+    return callback == null ?
+        new ProviderFacadeImpl().writeErrorDocument(errorContext) : executeErrorCallback(errorContext, callback);
+  }
+
+  private ODataResponse executeErrorCallback(final ODataErrorContext errorContext, final ODataErrorCallback callback) {
+    ODataResponse oDataResponse;
+    try {
+      oDataResponse = callback.handleError(errorContext);
+    } catch (ODataApplicationException e) {
+      oDataResponse = handleException(e);
+    }
+    return oDataResponse;
+  }
+
+  private ODataErrorContext createErrorContext(final WebApplicationException exception) {
+    ODataErrorContext context = new ODataErrorContext();
+    if (uriInfo != null) {
+      context.setRequestUri(uriInfo.getRequestUri());
+    }
+    if (httpHeaders != null && httpHeaders.getRequestHeaders() != null) {
+      MultivaluedMap<String, String> requestHeaders = httpHeaders.getRequestHeaders();
+      Set<Entry<String, List<String>>> entries = requestHeaders.entrySet();
+      for (Entry<String, List<String>> entry : entries) {
+        context.putRequestHeader(entry.getKey(), entry.getValue());
+      }
+    }
+    context.setContentType(getContentType().toContentTypeString());
+    context.setException(exception);
+    context.setErrorCode(null);
+    context.setMessage(exception.getMessage());
+    context.setLocale(DEFAULT_RESPONSE_LOCALE);
+    context.setHttpStatus(HttpStatusCodes.fromStatusCode(exception.getResponse().getStatus()));
+    if (exception instanceof NotAllowedException) {
+      // RFC 2616, 5.1.1: " An origin server SHOULD return the status code
+      // 405 (Method Not Allowed) if the method is known by the origin server
+      // but not allowed for the requested resource, and 501 (Not Implemented)
+      // if the method is unrecognized or not implemented by the origin server."
+      // Since all recognized methods are handled elsewhere, we unconditionally
+      // switch to 501 here for not-allowed exceptions thrown directly from
+      // JAX-RS implementations.
+      context.setHttpStatus(HttpStatusCodes.NOT_IMPLEMENTED);
+      context.setMessage("The request dispatcher does not allow the HTTP method used for the request.");
+      context.setLocale(Locale.ENGLISH);
+    }
+    return context;
+  }
+
+  private ContentType getContentType() {
+    ContentType contentType = getContentTypeByUriInfo();
+    if (contentType == null) {
+      contentType = getContentTypeByAcceptHeader();
+    }
+    return contentType;
+  }
+
+  private ContentType getContentTypeByUriInfo() {
+    ContentType contentType = null;
+    if (uriInfo != null && uriInfo.getQueryParameters() != null) {
+      MultivaluedMap<String, String> queryParameters = uriInfo.getQueryParameters();
+      if (queryParameters.containsKey(DOLLAR_FORMAT)) {
+        String contentTypeString = queryParameters.getFirst(DOLLAR_FORMAT);
+        if (DOLLAR_FORMAT_JSON.equals(contentTypeString)) {
+          contentType = ContentType.APPLICATION_JSON;
+        } else {
+          //Any format mentioned in the $format parameter other than json results in an application/xml content type 
+          //for error messages due to the OData V2 Specification.
+          contentType = ContentType.APPLICATION_XML;
+        }
+      }
+    }
+    return contentType;
+  }
+
+  private ContentType getContentTypeByAcceptHeader() {
+    for (MediaType type : httpHeaders.getAcceptableMediaTypes()) {
+      if (ContentType.isParseable(type.toString())) {
+        ContentType convertedContentType = ContentType.create(type.toString());
+        if (convertedContentType.isWildcard()
+            || ContentType.APPLICATION_XML.equals(convertedContentType) || ContentType.APPLICATION_XML_CS_UTF_8.equals(convertedContentType)
+            || ContentType.APPLICATION_ATOM_XML.equals(convertedContentType) || ContentType.APPLICATION_ATOM_XML_CS_UTF_8.equals(convertedContentType)) {
+          return ContentType.APPLICATION_XML;
+        } else if (ContentType.APPLICATION_JSON.equals(convertedContentType) || ContentType.APPLICATION_JSON_CS_UTF_8.equals(convertedContentType)) {
+          return ContentType.APPLICATION_JSON;
+        }
+      }
+    }
+    return ContentType.APPLICATION_XML;
+  }
+
+  private ODataErrorCallback getErrorHandlerCallback() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+    ODataErrorCallback callback = null;
+    final String factoryClassName = servletConfig.getInitParameter(ODataServiceFactory.FACTORY_LABEL);
+    if (factoryClassName != null) {
+      ClassLoader cl = (ClassLoader) servletRequest.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
+      Class<?> factoryClass;
+      if (cl == null) {
+        factoryClass = Class.forName(factoryClassName);
+      } else {
+        factoryClass = Class.forName(factoryClassName, true, cl);
+      }
+      final ODataServiceFactory serviceFactory = (ODataServiceFactory) factoryClass.newInstance();
+
+      callback = serviceFactory.getCallback(ODataErrorCallback.class);
+    }
+    return callback;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRedirectLocator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRedirectLocator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRedirectLocator.java
new file mode 100644
index 0000000..654e29f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRedirectLocator.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.rest;
+
+import java.net.URI;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.core.Response;
+
+/**
+ * @author SAP AG
+ */
+public class ODataRedirectLocator {
+
+  @GET
+  public Response redirectGet() {
+    return redirect();
+  }
+
+  @PUT
+  public Response redirectPut() {
+    return redirect();
+  }
+
+  @POST
+  public Response redirectPost() {
+    return redirect();
+  }
+
+  @DELETE
+  public Response redirectDelete() {
+    return redirect();
+  }
+
+  @OPTIONS
+  public Response redirectOptions() {
+    return redirect();
+  }
+
+  @HEAD
+  public Response redirectHead() {
+    return redirect();
+  }
+
+  @PATCH
+  public Response redirectPatch() {
+    return redirect();
+  }
+
+  @MERGE
+  public Response redirectMerge() {
+    return redirect();
+  }
+
+  private Response redirect() {
+    return Response.temporaryRedirect(URI.create("/")).build();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRootLocator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRootLocator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRootLocator.java
new file mode 100644
index 0000000..e68bbff
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataRootLocator.java
@@ -0,0 +1,133 @@
+/*******************************************************************************
+ * 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.rest;
+
+import java.util.List;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.Encoded;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.PathSegment;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * Default OData root locator responsible to handle the whole path and delegate all calls to a sub locator:<p>
+ * <code>/{odata path}  e.g. http://host:port/webapp/odata.svc/$metadata</code><br>
+ * All path segments defined by a servlet mapping belong to the odata uri.
+ * </p>
+ * This behavior can be changed:<p>
+ * <code>/{custom path}{odata path}  e.g. http://host:port/webapp/bmw/odata.svc/$metadata</code><br>
+ * The first segment defined by a servlet mapping belong to customer context and the following segments are OData specific.
+ * </p>
+ * @author SAP AG
+ */
+public class ODataRootLocator {
+
+  @Context
+  private HttpHeaders httpHeaders;
+  @Context
+  private UriInfo uriInfo;
+  @Context
+  private Request request;
+  @Context
+  private ServletConfig servletConfig;
+  @Context
+  private HttpServletRequest servletRequest;
+
+  /**
+   * Default root behavior which will delegate all paths to a ODataLocator.
+   * @param pathSegments        URI path segments - all segments have to be OData
+   * @param xHttpMethod         HTTP Header X-HTTP-Method for tunneling through POST
+   * @param xHttpMethodOverride HTTP Header X-HTTP-Method-Override for tunneling through POST
+   * @return a locator handling OData protocol
+   * @throws ODataException 
+   * @throws ClassNotFoundException 
+   * @throws IllegalAccessException 
+   * @throws InstantiationException 
+   */
+  @Path("/{pathSegments: .*}")
+  public Object handleRequest(
+      @Encoded @PathParam("pathSegments") final List<PathSegment> pathSegments,
+      @HeaderParam("X-HTTP-Method") final String xHttpMethod,
+      @HeaderParam("X-HTTP-Method-Override") final String xHttpMethodOverride)
+      throws ODataException, ClassNotFoundException, InstantiationException, IllegalAccessException {
+
+    if (xHttpMethod != null && xHttpMethodOverride != null) {
+
+      /*
+       * X-HTTP-Method-Override : implemented by CXF
+       * X-HTTP-Method          : implemented in ODataSubLocator:handlePost
+       */
+
+      if (!xHttpMethod.equalsIgnoreCase(xHttpMethodOverride)) {
+        throw new ODataBadRequestException(ODataBadRequestException.AMBIGUOUS_XMETHOD);
+      }
+    }
+
+    if (servletRequest.getPathInfo() == null) {
+      return handleRedirect();
+    }
+
+    final String factoryClassName = servletConfig.getInitParameter(ODataServiceFactory.FACTORY_LABEL);
+    if (factoryClassName == null) {
+      throw new ODataRuntimeException("servlet config missing: org.apache.olingo.odata2.processor.factory");
+    }
+
+    ClassLoader cl = (ClassLoader) servletRequest.getAttribute(ODataServiceFactory.FACTORY_CLASSLOADER_LABEL);
+    Class<?> factoryClass;
+    if (cl == null) {
+      factoryClass = Class.forName(factoryClassName);
+    } else {
+      factoryClass = Class.forName(factoryClassName, true, cl);
+    }
+    ODataServiceFactory serviceFactory = (ODataServiceFactory) factoryClass.newInstance();
+
+    int pathSplit = 0;
+    final String pathSplitAsString = servletConfig.getInitParameter(ODataServiceFactory.PATH_SPLIT_LABEL);
+    if (pathSplitAsString != null) {
+      pathSplit = Integer.parseInt(pathSplitAsString);
+    }
+
+    final SubLocatorParameter param = new SubLocatorParameter();
+    param.setServiceFactory(serviceFactory);
+    param.setPathSegments(pathSegments);
+    param.setHttpHeaders(httpHeaders);
+    param.setUriInfo(uriInfo);
+    param.setRequest(request);
+    param.setServletRequest(servletRequest);
+    param.setPathSplit(pathSplit);
+
+    return ODataSubLocator.create(param);
+  }
+
+  private Object handleRedirect() {
+    return new ODataRedirectLocator();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataSubLocator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataSubLocator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataSubLocator.java
new file mode 100644
index 0000000..0805282
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/ODataSubLocator.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * 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.rest;
+
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.OPTIONS;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.core.Response;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.core.ODataContextImpl;
+import org.apache.olingo.odata2.core.ODataExceptionWrapper;
+import org.apache.olingo.odata2.core.ODataRequestHandler;
+
+/**
+ * @author SAP AG
+ */
+public final class ODataSubLocator {
+
+  private ODataServiceFactory serviceFactory;
+  private ODataRequest request;
+
+  @GET
+  public Response handleGet() throws ODataException {
+    return handle(ODataHttpMethod.GET);
+  }
+
+  @PUT
+  public Response handlePut() throws ODataException {
+    return handle(ODataHttpMethod.PUT);
+  }
+
+  @PATCH
+  public Response handlePatch() throws ODataException {
+    return handle(ODataHttpMethod.PATCH);
+  }
+
+  @MERGE
+  public Response handleMerge() throws ODataException {
+    return handle(ODataHttpMethod.MERGE);
+  }
+
+  @DELETE
+  public Response handleDelete() throws ODataException {
+    return handle(ODataHttpMethod.DELETE);
+  }
+
+  @POST
+  public Response handlePost(@HeaderParam("X-HTTP-Method") final String xHttpMethod) throws ODataException {
+    Response response;
+
+    if (xHttpMethod == null) {
+      response = handle(ODataHttpMethod.POST);
+    } else {
+      /* tunneling */
+      if ("MERGE".equals(xHttpMethod)) {
+        response = handle(ODataHttpMethod.MERGE);
+      } else if ("PATCH".equals(xHttpMethod)) {
+        response = handle(ODataHttpMethod.PATCH);
+      } else if (HttpMethod.DELETE.equals(xHttpMethod)) {
+        response = handle(ODataHttpMethod.DELETE);
+      } else if (HttpMethod.PUT.equals(xHttpMethod)) {
+        response = handle(ODataHttpMethod.PUT);
+      } else if (HttpMethod.GET.equals(xHttpMethod)) {
+        response = handle(ODataHttpMethod.GET);
+      } else if (HttpMethod.POST.equals(xHttpMethod)) {
+        response = handle(ODataHttpMethod.POST);
+      } else if (HttpMethod.HEAD.equals(xHttpMethod)) {
+        response = handleHead();
+      } else if (HttpMethod.OPTIONS.equals(xHttpMethod)) {
+        response = handleOptions();
+      } else {
+        response = returnNotImplementedResponse(ODataNotImplementedException.TUNNELING);
+      }
+    }
+    return response;
+  }
+
+  private Response returnNotImplementedResponse(final MessageReference messageReference) {
+    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
+    // 501 (Not Implemented) if the method is unrecognized [...] by the origin server."
+    ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
+    context.setRequest(request);
+    context.setAcceptableLanguages(request.getAcceptableLanguages());
+    context.setPathInfo(request.getPathInfo());
+    context.setServiceFactory(serviceFactory);
+    ODataExceptionWrapper exceptionWrapper = new ODataExceptionWrapper(context, request.getQueryParameters(), request.getAcceptHeaders());
+    ODataResponse response = exceptionWrapper.wrapInExceptionResponse(new ODataNotImplementedException(messageReference));
+    return RestUtil.convertResponse(response);
+  }
+
+  @OPTIONS
+  public Response handleOptions() throws ODataException {
+    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
+    // 501 (Not Implemented) if the method is unrecognized or not implemented
+    // by the origin server."
+    return returnNotImplementedResponse(ODataNotImplementedException.COMMON);
+  }
+
+  @HEAD
+  public Response handleHead() throws ODataException {
+    // RFC 2616, 5.1.1: "An origin server SHOULD return the status code [...]
+    // 501 (Not Implemented) if the method is unrecognized or not implemented
+    // by the origin server."
+    return returnNotImplementedResponse(ODataNotImplementedException.COMMON);
+  }
+
+  private Response handle(final ODataHttpMethod method) throws ODataException {
+    request = ODataRequest.fromRequest(request).method(method).build();
+
+    ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
+    ODataService service = serviceFactory.createService(context);
+    context.setService(service);
+    service.getProcessor().setContext(context);
+
+    ODataRequestHandler requestHandler = new ODataRequestHandler(serviceFactory, service, context);
+
+    final ODataResponse odataResponse = requestHandler.handle(request);
+    final Response response = RestUtil.convertResponse(odataResponse);
+
+    return response;
+  }
+
+  public static ODataSubLocator create(final SubLocatorParameter param) throws ODataException {
+    ODataSubLocator subLocator = new ODataSubLocator();
+
+    subLocator.serviceFactory = param.getServiceFactory();
+    subLocator.request = ODataRequest.acceptableLanguages(param.getHttpHeaders().getAcceptableLanguages())
+        .acceptHeaders(RestUtil.extractAcceptHeaders(param))
+        .body(RestUtil.contentAsStream(RestUtil.extractRequestContent(param)))
+        .pathInfo(RestUtil.buildODataPathInfo(param))
+        .queryParameters(RestUtil.convertToSinglevaluedMap(param.getUriInfo().getQueryParameters()))
+        .requestHeaders(param.getHttpHeaders().getRequestHeaders())
+        .contentType(RestUtil.extractRequestContentType(param).toContentTypeString())
+        .build();
+
+    return subLocator;
+  }
+
+  private ODataSubLocator() {
+    super();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/PATCH.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/PATCH.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/PATCH.java
new file mode 100644
index 0000000..c348d42
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/PATCH.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.rest;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.ws.rs.HttpMethod;
+
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@HttpMethod("PATCH")
+public @interface PATCH {}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/RestUtil.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/RestUtil.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/RestUtil.java
new file mode 100644
index 0000000..0129d2a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/RestUtil.java
@@ -0,0 +1,266 @@
+/*******************************************************************************
+ * 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.rest;
+
+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.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.ResponseBuilder;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.UriInfo;
+
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
+import org.apache.olingo.odata2.core.PathInfoImpl;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.Decoder;
+
+/**
+ * @author SAP AG
+ */
+public class RestUtil {
+  public static Response convertResponse(final ODataResponse odataResponse) {
+    try {
+      ResponseBuilder responseBuilder = Response.noContent().status(odataResponse.getStatus().getStatusCode()).entity(odataResponse.getEntity());
+
+      for (final String name : odataResponse.getHeaderNames()) {
+        responseBuilder = responseBuilder.header(name, odataResponse.getHeader(name));
+      }
+
+      return responseBuilder.build();
+    } catch (RuntimeException e) {
+      if (odataResponse != null) {
+        try {
+          odataResponse.close();
+        } catch (IOException inner) {
+          // if close throw an exception we ignore these and re-theow our exception
+          throw e;
+        }
+      }
+      throw e;
+    }
+  }
+
+  public static ContentType extractRequestContentType(final SubLocatorParameter param) throws ODataBadRequestException {
+    final String contentType = param.getHttpHeaders().getHeaderString(HttpHeaders.CONTENT_TYPE);
+    if (contentType == null || contentType.isEmpty()) {
+      // RFC 2616, 7.2.1:
+      // "Any HTTP/1.1 message containing an entity-body SHOULD include a
+      // Content-Type header field defining the media type of that body. [...]
+      // If the media type remains unknown, the recipient SHOULD treat it
+      // as type "application/octet-stream"."
+      return ContentType.APPLICATION_OCTET_STREAM;
+    } else if (ContentType.isParseable(contentType)) {
+      return ContentType.create(contentType);
+    } else {
+      throw new ODataBadRequestException(ODataBadRequestException.INVALID_HEADER.addContent(HttpHeaders.CONTENT_TYPE, contentType));
+    }
+  }
+
+  /**
+   * Extracts the request content from the servlet as input stream.
+   * @param param initialization parameters
+   * @return the request content as input stream
+   * @throws ODataException
+   */
+  public static ServletInputStream extractRequestContent(final SubLocatorParameter param) throws ODataException {
+    try {
+      return param.getServletRequest().getInputStream();
+    } catch (final IOException e) {
+      throw new ODataException("Error getting request content as ServletInputStream.", e);
+    }
+  }
+
+  public static <T> InputStream contentAsStream(final T content) throws ODataException {
+    if (content == null) {
+      throw new ODataBadRequestException(ODataBadRequestException.COMMON);
+    }
+
+    InputStream inputStream;
+    if (content instanceof InputStream) {
+      inputStream = (InputStream) content;
+    } else if (content instanceof String) {
+      try {
+        inputStream = new ByteArrayInputStream(((String) content).getBytes("UTF-8"));
+      } catch (final UnsupportedEncodingException e) {
+        throw new ODataBadRequestException(ODataBadRequestException.COMMON, e);
+      }
+    } else {
+      throw new ODataBadRequestException(ODataBadRequestException.COMMON);
+    }
+    return inputStream;
+  }
+
+  public static List<String> extractAcceptHeaders(final SubLocatorParameter param) throws ODataBadRequestException {
+    // first validate all accept header content types are 'parseable' and valif from our point of view
+    List<String> acceptHeaders = param.getHttpHeaders().getRequestHeader(HttpHeaders.ACCEPT);
+
+    for (String acceptHeader : acceptHeaders) {
+      String[] contentTypes = acceptHeader.split(",");
+      for (String contentType : contentTypes) {
+        if (!ContentType.isParseable(contentType.trim())) {
+          throw new ODataBadRequestException(ODataBadRequestException.INVALID_HEADER.addContent(HttpHeaders.ACCEPT, acceptHeader));
+        }
+      }
+    }
+
+    // then get sorted list of acceptable media type from jax-rs
+    final List<String> mediaTypes = new ArrayList<String>();
+    final List<MediaType> acceptableMediaTypes = param.getHttpHeaders().getAcceptableMediaTypes();
+    for (final MediaType mediaType : acceptableMediaTypes) {
+      mediaTypes.add(mediaType.toString());
+    }
+
+    return mediaTypes;
+  }
+
+  public static Map<String, String> extractRequestHeaders(final javax.ws.rs.core.HttpHeaders httpHeaders) {
+    final MultivaluedMap<String, String> headers = httpHeaders.getRequestHeaders();
+    Map<String, String> headerMap = new HashMap<String, String>();
+
+    for (final String key : headers.keySet()) {
+      List<String> header = httpHeaders.getRequestHeader(key);
+      if (header != null && !header.isEmpty()) {
+        /*
+         * consider first header value only
+         * avoid using jax-rs 2.0 (getHeaderString())
+         */
+        String value = header.get(0);
+        if (value != null && !"".equals(value)) {
+          headerMap.put(key, value);
+        }
+      }
+
+    }
+    return headerMap;
+  }
+
+  public static PathInfoImpl buildODataPathInfo(final SubLocatorParameter param) throws ODataException {
+    final UriInfo uriInfo = param.getUriInfo();
+    PathInfoImpl pathInfo = splitPath(param);
+    pathInfo.setServiceRoot(buildBaseUri(param.getServletRequest(), uriInfo, pathInfo.getPrecedingSegments()));
+    pathInfo.setRequestUri(uriInfo.getRequestUri());
+
+    return pathInfo;
+  }
+
+  private static PathInfoImpl splitPath(final SubLocatorParameter param) throws ODataException {
+    PathInfoImpl pathInfo = new PathInfoImpl();
+
+    List<javax.ws.rs.core.PathSegment> precedingPathSegments;
+    List<javax.ws.rs.core.PathSegment> pathSegments;
+
+    if (param.getPathSplit() == 0) {
+      precedingPathSegments = Collections.emptyList();
+      pathSegments = param.getPathSegments();
+    } else {
+      if (param.getPathSegments().size() < param.getPathSplit()) {
+        throw new ODataBadRequestException(ODataBadRequestException.URLTOOSHORT);
+      }
+
+      precedingPathSegments = param.getPathSegments().subList(0, param.getPathSplit());
+      final int pathSegmentCount = param.getPathSegments().size();
+      pathSegments = param.getPathSegments().subList(param.getPathSplit(), pathSegmentCount);
+    }
+
+    // Percent-decode only the preceding path segments.
+    // The OData path segments are decoded during URI parsing.
+    pathInfo.setPrecedingPathSegment(convertPathSegmentList(precedingPathSegments));
+
+    List<PathSegment> odataSegments = new ArrayList<PathSegment>();
+    for (final javax.ws.rs.core.PathSegment segment : pathSegments) {
+      if (segment.getMatrixParameters() == null || segment.getMatrixParameters().isEmpty()) {
+        odataSegments.add(new ODataPathSegmentImpl(segment.getPath(), null));
+      } else {
+        // post condition: we do not allow matrix parameters in OData path segments
+        throw new ODataNotFoundException(ODataNotFoundException.MATRIX.addContent(segment.getMatrixParameters().keySet(), segment.getPath()));
+      }
+    }
+    pathInfo.setODataPathSegment(odataSegments);
+
+    return pathInfo;
+  }
+
+  private static URI buildBaseUri(final HttpServletRequest request, final javax.ws.rs.core.UriInfo uriInfo, final List<PathSegment> precedingPathSegments) throws ODataException {
+    try {
+      UriBuilder uriBuilder = uriInfo.getBaseUriBuilder();
+      for (final PathSegment ps : precedingPathSegments) {
+        uriBuilder = uriBuilder.path(ps.getPath());
+        for (final String key : ps.getMatrixParameters().keySet()) {
+          final Object[] v = ps.getMatrixParameters().get(key).toArray();
+          uriBuilder = uriBuilder.matrixParam(key, v);
+        }
+      }
+
+      /*
+       * workaround because of host name is cached by uriInfo
+       */
+      uriBuilder.host(request.getServerName());
+
+      String uriString = uriBuilder.build().toString();
+      if (!uriString.endsWith("/")) {
+        uriString = uriString + "/";
+      }
+
+      return new URI(uriString);
+    } catch (final URISyntaxException e) {
+      throw new ODataException(e);
+    }
+  }
+
+  private static List<PathSegment> convertPathSegmentList(final List<javax.ws.rs.core.PathSegment> pathSegments) {
+    ArrayList<PathSegment> converted = new ArrayList<PathSegment>();
+    for (final javax.ws.rs.core.PathSegment pathSegment : pathSegments) {
+      final PathSegment segment = new ODataPathSegmentImpl(Decoder.decode(pathSegment.getPath()), pathSegment.getMatrixParameters());
+      converted.add(segment);
+    }
+    return converted;
+  }
+
+  public static Map<String, String> convertToSinglevaluedMap(final MultivaluedMap<String, String> multi) {
+    final Map<String, String> single = new HashMap<String, String>();
+
+    for (final String key : multi.keySet()) {
+      final String value = multi.getFirst(key);
+      single.put(key, value);
+    }
+
+    return single;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/SubLocatorParameter.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/SubLocatorParameter.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/SubLocatorParameter.java
new file mode 100644
index 0000000..0f89e35
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/SubLocatorParameter.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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.rest;
+
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.core.Request;
+
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+
+/**
+ * @author SAP AG
+ */
+public class SubLocatorParameter {
+
+  private List<javax.ws.rs.core.PathSegment> pathSegments;
+  private javax.ws.rs.core.HttpHeaders httpHeaders;
+  private javax.ws.rs.core.UriInfo uriInfo;
+  private Request request;
+  private int pathSplit;
+  private ODataServiceFactory serviceFactory;
+  private HttpServletRequest servletRequest;
+
+  public ODataServiceFactory getServiceFactory() {
+    return serviceFactory;
+  }
+
+  public void setServiceFactory(final ODataServiceFactory serviceFactory) {
+    this.serviceFactory = serviceFactory;
+  }
+
+  public List<javax.ws.rs.core.PathSegment> getPathSegments() {
+    return pathSegments;
+  }
+
+  public void setPathSegments(final List<javax.ws.rs.core.PathSegment> pathSegments) {
+    this.pathSegments = pathSegments;
+  }
+
+  public javax.ws.rs.core.HttpHeaders getHttpHeaders() {
+    return httpHeaders;
+  }
+
+  public void setHttpHeaders(final javax.ws.rs.core.HttpHeaders httpHeaders) {
+    this.httpHeaders = httpHeaders;
+  }
+
+  public javax.ws.rs.core.UriInfo getUriInfo() {
+    return uriInfo;
+  }
+
+  public void setUriInfo(final javax.ws.rs.core.UriInfo uriInfo) {
+    this.uriInfo = uriInfo;
+  }
+
+  public Request getRequest() {
+    return request;
+  }
+
+  public void setRequest(final Request request) {
+    this.request = request;
+  }
+
+  public int getPathSplit() {
+    return pathSplit;
+  }
+
+  public void setPathSplit(final int pathSplit) {
+    this.pathSplit = pathSplit;
+  }
+
+  public void setServletRequest(final HttpServletRequest servletRequest) {
+    this.servletRequest = servletRequest;
+  }
+
+  public HttpServletRequest getServletRequest() {
+    return servletRequest;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/app/ODataApplication.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/app/ODataApplication.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/app/ODataApplication.java
new file mode 100644
index 0000000..ab81d98
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rest/app/ODataApplication.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.rest.app;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Application;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import javax.ws.rs.ext.Provider;
+
+import org.apache.olingo.odata2.core.rest.ODataExceptionMapperImpl;
+import org.apache.olingo.odata2.core.rest.ODataRootLocator;
+
+/**
+ * @author SAP AG
+ */
+public class ODataApplication extends Application {
+
+  @Override
+  public Set<Class<?>> getClasses() {
+    Set<Class<?>> classes = new HashSet<Class<?>>();
+    classes.add(ODataRootLocator.class);
+    classes.add(ODataExceptionMapperImpl.class);
+    classes.add(MyProvider.class);
+    return classes;
+  }
+
+  /**
+   * Singletons are not recommended because they break the state less REST principle.
+   */
+  @Override
+  public Set<Object> getSingletons() {
+    return Collections.emptySet();
+  }
+
+  @Provider
+  @Produces({ "generic/value", "multipart/mixed" })
+  public static final class MyProvider implements MessageBodyWriter<String> {
+
+    @Override
+    public boolean isWriteable(final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
+      return (type == String.class);
+    }
+
+    @Override
+    public long getSize(final String t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType) {
+      return t.length();
+    }
+
+    @Override
+    public void writeTo(final String t, final Class<?> type, final Type genericType, final Annotation[] annotations, final MediaType mediaType, final MultivaluedMap<String, Object> httpHeaders, final OutputStream entityStream) throws IOException, WebApplicationException {
+      StringBuilder b = new StringBuilder();
+      b.append(t);
+      entityStream.write(b.toString().getBytes("UTF-8"));
+      entityStream.flush();
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/rt/RuntimeDelegateImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/rt/RuntimeDelegateImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/rt/RuntimeDelegateImpl.java
new file mode 100644
index 0000000..beac82a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/rt/RuntimeDelegateImpl.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.rt;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart.BatchResponsePartBuilder;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.ep.EntityProvider.EntityProviderInterface;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.processor.ODataRequest.ODataRequestBuilder;
+import org.apache.olingo.odata2.api.processor.ODataResponse.ODataResponseBuilder;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate.RuntimeDelegateInstance;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.core.ODataRequestImpl;
+import org.apache.olingo.odata2.core.ODataResponseImpl;
+import org.apache.olingo.odata2.core.batch.BatchResponsePartImpl;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+import org.apache.olingo.odata2.core.edm.parser.EdmxProvider;
+import org.apache.olingo.odata2.core.edm.provider.EdmImplProv;
+import org.apache.olingo.odata2.core.ep.ProviderFacadeImpl;
+import org.apache.olingo.odata2.core.processor.ODataSingleProcessorService;
+import org.apache.olingo.odata2.core.uri.UriParserImpl;
+
+/**
+ * @author SAP AG
+ */
+public class RuntimeDelegateImpl extends RuntimeDelegateInstance {
+
+  @Override
+  protected ODataResponseBuilder createODataResponseBuilder() {
+    ODataResponseImpl r = new ODataResponseImpl();
+    return r.new ODataResponseBuilderImpl();
+  }
+
+  @Override
+  protected EdmSimpleType getEdmSimpleType(final EdmSimpleTypeKind edmSimpleType) {
+    return EdmSimpleTypeFacadeImpl.getEdmSimpleType(edmSimpleType);
+  }
+
+  @Override
+  protected UriParser getUriParser(final Edm edm) {
+    return new UriParserImpl(edm);
+  }
+
+  @Override
+  protected EdmSimpleTypeFacade getSimpleTypeFacade() {
+    return new EdmSimpleTypeFacadeImpl();
+  }
+
+  @Override
+  protected Edm createEdm(final EdmProvider provider) {
+    return new EdmImplProv(provider);
+  }
+
+  @Override
+  protected EntityProviderInterface createEntityProvider() {
+    return new ProviderFacadeImpl();
+  }
+
+  @Override
+  protected ODataService createODataSingleProcessorService(final EdmProvider provider, final ODataSingleProcessor processor) {
+    return new ODataSingleProcessorService(provider, processor);
+  }
+
+  @Override
+  protected EdmProvider createEdmProvider(final InputStream metadataXml, final boolean validate) throws EntityProviderException {
+    return new EdmxProvider().parse(metadataXml, validate);
+  }
+
+  @Override
+  protected BatchResponsePartBuilder createBatchResponsePartBuilder() {
+    BatchResponsePartImpl part = new BatchResponsePartImpl();
+    return part.new BatchResponsePartBuilderImpl();
+  }
+
+  @Override
+  protected ODataRequestBuilder createODataRequestBuilder() {
+    ODataRequestImpl request = new ODataRequestImpl();
+    return request.new ODataRequestBuilderImpl();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AcceptImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AcceptImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AcceptImpl.java
new file mode 100644
index 0000000..98dcbba
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AcceptImpl.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import org.apache.olingo.odata2.api.servicedocument.Accept;
+import org.apache.olingo.odata2.api.servicedocument.CommonAttributes;
+
+/**
+ * @author SAP AG
+ */
+public class AcceptImpl implements Accept {
+  private String value;
+  private CommonAttributes commonAttributes;
+
+  @Override
+  public String getValue() {
+    return value;
+  }
+
+  @Override
+  public CommonAttributes getCommonAttributes() {
+    return commonAttributes;
+  }
+
+  public AcceptImpl setText(final String text) {
+    value = text;
+    return this;
+  }
+
+  public AcceptImpl setCommonAttributes(final CommonAttributes commonAttributes) {
+    this.commonAttributes = commonAttributes;
+    return this;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AtomInfoImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AtomInfoImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AtomInfoImpl.java
new file mode 100644
index 0000000..07d59a2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/AtomInfoImpl.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.servicedocument.AtomInfo;
+import org.apache.olingo.odata2.api.servicedocument.Collection;
+import org.apache.olingo.odata2.api.servicedocument.CommonAttributes;
+import org.apache.olingo.odata2.api.servicedocument.ExtensionElement;
+import org.apache.olingo.odata2.api.servicedocument.Workspace;
+import org.apache.olingo.odata2.core.edm.provider.EdmEntitySetInfoImplProv;
+
+/**
+ * @author SAP AG
+ */
+public class AtomInfoImpl implements AtomInfo {
+  private List<Workspace> workspaces;
+  private CommonAttributes attributes;
+  private List<ExtensionElement> extensionElements;
+
+  @Override
+  public CommonAttributes getCommonAttributes() {
+    return attributes;
+  }
+
+  @Override
+  public List<Workspace> getWorkspaces() {
+    return workspaces;
+  }
+
+  @Override
+  public List<ExtensionElement> getExtesionElements() {
+    return extensionElements;
+  }
+
+  public AtomInfoImpl setWorkspaces(final List<Workspace> workspaces) {
+    this.workspaces = workspaces;
+    return this;
+  }
+
+  public AtomInfoImpl setCommonAttributes(final CommonAttributes attributes) {
+    this.attributes = attributes;
+    return this;
+  }
+
+  public AtomInfoImpl setExtesionElements(final List<ExtensionElement> elements) {
+    extensionElements = elements;
+    return this;
+  }
+
+  public List<EdmEntitySetInfo> getEntitySetsInfo() throws EntityProviderException {
+    List<EdmEntitySetInfo> entitySets = new ArrayList<EdmEntitySetInfo>();
+    for (Workspace workspace : workspaces) {
+      for (Collection collection : workspace.getCollections()) {
+        String[] names = collection.getHref().split("\\" + Edm.DELIMITER + "(?=[^" + Edm.DELIMITER + "]+$)");
+        try {
+          if (names.length == 1) {
+            EntitySet entitySet = new EntitySet().setName(names[0]);
+            EntityContainerInfo container = new EntityContainerInfo().setDefaultEntityContainer(true);
+            EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+            entitySets.add(entitySetInfo);
+          } else if (names.length == 2) {
+            EntitySet entitySet = new EntitySet().setName(names[1]);
+            EntityContainerInfo container = new EntityContainerInfo().setName(names[0]).setDefaultEntityContainer(false);
+            EdmEntitySetInfo entitySetInfo = new EdmEntitySetInfoImplProv(entitySet, container);
+            entitySets.add(entitySetInfo);
+          }
+        } catch (EdmException e) {
+          throw new EntityProviderException(EntityProviderException.COMMON, e);
+        }
+      }
+    }
+    return entitySets;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoriesImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoriesImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoriesImpl.java
new file mode 100644
index 0000000..cebb225
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoriesImpl.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.servicedocument.Categories;
+import org.apache.olingo.odata2.api.servicedocument.Category;
+import org.apache.olingo.odata2.api.servicedocument.Fixed;
+
+/**
+ * @author SAP AG
+ */
+public class CategoriesImpl implements Categories {
+  private String href;
+  private Fixed fixed;
+  private String scheme;
+  private List<Category> categoryList;
+
+  @Override
+  public String getHref() {
+    return href;
+  }
+
+  @Override
+  public Fixed getFixed() {
+    return fixed;
+  }
+
+  @Override
+  public String getScheme() {
+    return scheme;
+  }
+
+  @Override
+  public List<Category> getCategoryList() {
+    return categoryList;
+  }
+
+  public CategoriesImpl setHref(final String href) {
+    this.href = href;
+    return this;
+  }
+
+  public CategoriesImpl setFixed(final Fixed fixed) {
+    this.fixed = fixed;
+    return this;
+  }
+
+  public CategoriesImpl setScheme(final String scheme) {
+    this.scheme = scheme;
+    return this;
+  }
+
+  public CategoriesImpl setCategoryList(final List<Category> categoryList) {
+    this.categoryList = categoryList;
+    return this;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoryImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoryImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoryImpl.java
new file mode 100644
index 0000000..7a3bcb7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/servicedocument/CategoryImpl.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.servicedocument;
+
+import org.apache.olingo.odata2.api.servicedocument.Category;
+import org.apache.olingo.odata2.api.servicedocument.CommonAttributes;
+
+/**
+ * @author SAP AG
+ */
+public class CategoryImpl implements Category {
+  private String scheme;
+  private String term;
+  private CommonAttributes commonAttributes;
+  private String label;
+
+  @Override
+  public String getScheme() {
+    return scheme;
+  }
+
+  @Override
+  public String getTerm() {
+    return term;
+  }
+
+  @Override
+  public CommonAttributes getCommonAttributes() {
+    return commonAttributes;
+  }
+
+  @Override
+  public String getLabel() {
+    return label;
+  }
+
+  public CategoryImpl setScheme(final String scheme) {
+    this.scheme = scheme;
+    return this;
+  }
+
+  public CategoryImpl setTerm(final String term) {
+    this.term = term;
+    return this;
+  }
+
+  public CategoryImpl setCommonAttributes(final CommonAttributes commonAttribute) {
+    commonAttributes = commonAttribute;
+    return this;
+  }
+
+  public CategoryImpl setLabel(final String label) {
+    this.label = label;
+    return this;
+  }
+}


[50/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAContext.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAContext.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAContext.java
new file mode 100644
index 0000000..c0e743d
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAContext.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * 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.processor.api.jpa;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmExtension;
+
+/**
+ * This class does the compilation of context objects required for OData JPA
+ * Runtime. The context object should be properly initialized with values else
+ * the behavior of processor and EDM provider can result in exception.
+ * 
+ * Following are the mandatory parameter to be set into the context object
+ * <ol>
+ * <li>Persistence Unit Name</li>
+ * <li>An instance of Java Persistence Entity Manager Factory</li>
+ * </ol>
+ * 
+ * @author SAP AG <br>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAAccessFactory
+ * 
+ */
+public interface ODataJPAContext {
+
+  /**
+   * The method gets the Java Persistence Unit Name set into the context.
+   * 
+   * @return Java Persistence Unit Name
+   */
+  public String getPersistenceUnitName();
+
+  /**
+   * The method sets the Java Persistence Unit Name into the context.
+   * 
+   * @param pUnitName
+   *            is the Java Persistence Unit Name.
+   * 
+   */
+  public void setPersistenceUnitName(String pUnitName);
+
+  /**
+   * The method gets the OData Processor for JPA from the context.
+   * 
+   * @return OData JPA Processor
+   */
+  public ODataProcessor getODataProcessor();
+
+  /**
+   * The method sets the OData Processor for JPA into the context.
+   * 
+   * @param processor
+   *            is the specific implementation of
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAProcessor}
+   *            for processing OData service requests.
+   */
+  public void setODataProcessor(ODataProcessor processor);
+
+  /**
+   * The method gets the EDM provider for JPA from the context.
+   * 
+   * @return EDM provider
+   */
+  public EdmProvider getEdmProvider();
+
+  /**
+   * The method sets EDM provider into the context
+   * 
+   * @param edmProvider
+   *            is the specific implementation of
+   *            {@link org.apache.olingo.odata2.api.edm.provider.EdmProvider} for
+   *            transforming Java persistence models to Entity Data Model
+   * 
+   */
+  public void setEdmProvider(EdmProvider edmProvider);
+
+  /**
+   * The method gets the Java Persistence Entity Manager factory from the
+   * context. <br>
+   * <b>CAUTION:-</b> Don't use the Entity Manager Factory to instantiate
+   * Entity Managers. Instead get reference to Entity Manager using
+   * {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext#getEntityManager()}
+   * 
+   * @return an instance of Java Persistence Entity Manager Factory
+   */
+  public EntityManagerFactory getEntityManagerFactory();
+
+  /**
+   * The method sets the Java Persistence Entity Manager factory into the
+   * context.
+   * 
+   * @param emf
+   *            is of type {@link javax.persistence.EntityManagerFactory}
+   * 
+   */
+  public void setEntityManagerFactory(EntityManagerFactory emf);
+
+  /**
+   * The method gets OData Context into the context.
+   * 
+   * @return OData Context
+   */
+  public ODataContext getODataContext();
+
+  /**
+   * The method sets OData context into the context.
+   * 
+   * @param ctx
+   *            is an OData context of type
+   *            {@link org.apache.olingo.odata2.api.processor.ODataContext}
+   */
+  public void setODataContext(ODataContext ctx);
+
+  /**
+   * The method sets the JPA EDM mapping model name into the context. JPA EDM
+   * mapping model is an XML document based on JPAEDMMappingModel.xsd
+   * 
+   * @param name
+   *            is the name of JPA EDM mapping model
+   */
+  public void setJPAEdmMappingModel(String name);
+
+  /**
+   * The method gets the JPA EDM mapping model name from the context.
+   * 
+   * @return name of JPA EDM mapping model
+   */
+  public String getJPAEdmMappingModel();
+
+  /**
+   * The method returns an instance of type entity manager. The entity manager
+   * thus returns a single persistence context for the current OData request.
+   * Hence all entities that are accessed within JPA processor are managed by
+   * single entity manager.
+   * 
+   * @return an instance of type {@link javax.persistence.EntityManager}
+   */
+  public EntityManager getEntityManager();
+
+  /**
+   * The method sets the JPA Edm Extension instance into the context. There
+   * can be at most only one extension for a context. Invoking the method
+   * several times overwrites already set extension instance in the context.
+   * 
+   * @param jpaEdmExtension
+   *            is an instance of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmExtension}
+   * 
+   */
+  public void setJPAEdmExtension(JPAEdmExtension jpaEdmExtension);
+
+  /**
+   * The method returns the JPA Edm Extension instance set into the context.
+   * 
+   * @return
+   */
+  public JPAEdmExtension getJPAEdmExtension();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAProcessor.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAProcessor.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAProcessor.java
new file mode 100644
index 0000000..611dcb8
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAProcessor.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.processor.api.jpa;
+
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+
+/**
+ * Extend this class and implement an OData JPA processor if the default
+ * behavior of OData JPA Processor library has to be overwritten.
+ * 
+ * @author SAP AG
+ * 
+ * 
+ */
+public abstract class ODataJPAProcessor extends ODataSingleProcessor {
+
+  /**
+   * An instance of
+   * {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext} object
+   */
+  protected ODataJPAContext oDataJPAContext;
+
+  /**
+   * An instance of
+   * {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor}. The
+   * instance is created using
+   * {@link org.apache.olingo.odata2.processor.api.jpa.factory.JPAAccessFactory}.
+   */
+  protected JPAProcessor jpaProcessor;
+
+  public ODataJPAContext getOdataJPAContext() {
+    return oDataJPAContext;
+  }
+
+  public void setOdataJPAContext(final ODataJPAContext odataJPAContext) {
+    oDataJPAContext = odataJPAContext;
+  }
+
+  /**
+   * Constructor
+   * 
+   * @param oDataJPAContext
+   *            non null OData JPA Context object
+   */
+  public ODataJPAProcessor(final ODataJPAContext oDataJPAContext) {
+    if (oDataJPAContext == null) {
+      throw new IllegalArgumentException(
+          ODataJPAException.ODATA_JPACTX_NULL);
+    }
+    this.oDataJPAContext = oDataJPAContext;
+    jpaProcessor = ODataJPAFactory.createFactory().getJPAAccessFactory()
+        .getJPAProcessor(this.oDataJPAContext);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAServiceFactory.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAServiceFactory.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAServiceFactory.java
new file mode 100644
index 0000000..bc9b69d
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/ODataJPAServiceFactory.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * 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.processor.api.jpa;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAAccessFactory;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+
+/**
+ * <p>
+ * Extend this factory class and create own instance of
+ * {@link org.apache.olingo.odata2.api.ODataService} that transforms Java Persistence
+ * Models into an OData Service. The factory class instantiates instances of
+ * type {@link org.apache.olingo.odata2.api.edm.provider.EdmProvider} and
+ * {@link org.apache.olingo.odata2.api.processor.ODataSingleProcessor}. The OData
+ * JPA Processor library provides a default implementation for EdmProvider and
+ * OData Single Processor.
+ * </p>
+ * <p>
+ * The factory implementation is passed as servlet init parameter to a JAX-RS
+ * runtime which will instantiate a {@link org.apache.olingo.odata2.api.ODataService}
+ * implementation using this factory.
+ * </p>
+ * 
+ * <p>
+ * <b>Mandatory:</b> Implement the abstract method initializeODataJPAContext. Fill
+ * {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext} with context
+ * values.
+ * </p>
+ * 
+ * <b>Sample Configuration:</b>
+ * 
+ * <pre>
+ * {@code
+ * <servlet>
+ *  <servlet-name>ReferenceScenarioServlet</servlet-name>
+ *  <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
+ *  <init-param>
+ *    <param-name>javax.ws.rs.Application</param-name>
+ *    <param-value>org.apache.olingo.odata2.core.rest.ODataApplication</param-value>
+ *  </init-param>
+ *  <init-param>
+ *    <param-name>org.apache.olingo.odata2.processor.factory</param-name>
+ *    <param-value>com.sap.sample.processor.SampleProcessorFactory</param-value>
+ *  </init-param>
+ *  <init-param>
+ *    <param-name>org.apache.olingo.odata2.path.split</param-name>
+ *    <param-value>2</param-value>
+ *  </init-param>
+ *  <load-on-startup>1</load-on-startup>
+ * </servlet>
+ * }
+ * </pre>
+ */
+
+public abstract class ODataJPAServiceFactory extends ODataServiceFactory {
+
+  private ODataJPAContext oDataJPAContext;
+  private ODataContext oDataContext;
+
+  /**
+   * Creates an OData Service based on the values set in
+   * {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext} and
+   * {@link org.apache.olingo.odata2.api.processor.ODataContext}.
+   */
+  @Override
+  public final ODataService createService(final ODataContext ctx)
+      throws ODataException {
+
+    oDataContext = ctx;
+
+    // Initialize OData JPA Context
+    oDataJPAContext = initializeODataJPAContext();
+
+    validatePreConditions();
+
+    ODataJPAFactory factory = ODataJPAFactory.createFactory();
+    ODataJPAAccessFactory accessFactory = factory
+        .getODataJPAAccessFactory();
+
+    // OData JPA Processor
+    if (oDataJPAContext.getODataContext() == null)
+      oDataJPAContext.setODataContext(ctx);
+
+    ODataSingleProcessor odataJPAProcessor = accessFactory
+        .createODataProcessor(oDataJPAContext);
+
+    // OData Entity Data Model Provider based on JPA
+    EdmProvider edmProvider = accessFactory
+        .createJPAEdmProvider(oDataJPAContext);
+
+    return createODataSingleProcessorService(edmProvider, odataJPAProcessor);
+  }
+
+  private void validatePreConditions() throws ODataJPARuntimeException {
+
+    if (oDataJPAContext.getEntityManagerFactory() == null) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ENTITY_MANAGER_NOT_INITIALIZED,
+          null);
+    }
+
+  }
+
+  /**
+   * Implement this method and initialize OData JPA Context. It is mandatory
+   * to set an instance of type {@link javax.persistence.EntityManagerFactory}
+   * into the context. An exception of type
+   * {@link org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException}
+   * is thrown if EntityManagerFactory is not initialized. <br>
+   * <br>
+   * <b>Sample Code:</b> <code>
+   * 	<p>public class JPAReferenceServiceFactory extends ODataJPAServiceFactory{</p>
+   * 	
+   * 	<blockquote>private static final String PUNIT_NAME = "punit";
+   * <br>
+   * public ODataJPAContext initializeODataJPAContext() { 
+   * <blockquote>ODataJPAContext oDataJPAContext = this.getODataJPAContext();
+   * <br>
+   * EntityManagerFactory emf = Persistence.createEntityManagerFactory(PUNIT_NAME);
+   * <br>
+   * oDataJPAContext.setEntityManagerFactory(emf);
+   * oDataJPAContext.setPersistenceUnitName(PUNIT_NAME);
+   * <br> return oDataJPAContext;</blockquote>
+   * }</blockquote>
+   * } </code>
+   * <p>
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}
+   * @throws ODataJPARuntimeException
+   */
+  public abstract ODataJPAContext initializeODataJPAContext()
+      throws ODataJPARuntimeException;
+
+  /**
+   * @return an instance of type {@link ODataJPAContext}
+   * @throws ODataJPARuntimeException
+   */
+  public final ODataJPAContext getODataJPAContext()
+      throws ODataJPARuntimeException {
+    if (oDataJPAContext == null) {
+      oDataJPAContext = ODataJPAFactory.createFactory()
+          .getODataJPAAccessFactory().createODataJPAContext();
+    }
+    if (oDataContext != null)
+      oDataJPAContext.setODataContext(oDataContext);
+    return oDataJPAContext;
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmBuilder.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmBuilder.java
new file mode 100644
index 0000000..c9f3df4
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmBuilder.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+/**
+ * JPAEdmBuilder interface provides methods for building elements of an Entity Data Model (EDM) from
+ * a Java Persistence Model.
+ * 
+ * @author SAP AG
+ * 
+ */
+public interface JPAEdmBuilder {
+  /**
+   * The Method builds EDM Elements by transforming JPA MetaModel. The method
+   * processes EDM JPA Containers which could be accessed using the following
+   * views,
+   * <ul>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView}
+   * </li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}</li>
+   * <li> {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmBaseView}</li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView}
+   * </li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView}</li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView}
+   * </li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView}</li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView}</li>
+   * <li> {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView}</li>
+   * <li> {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView}</li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView}
+   * </li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView}</li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView}
+   * </li>
+   * <li>
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView}
+   * </li>
+   * <li> {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView}</li>
+   * </ul>
+   * 
+   * @throws ODataJPARuntimeException
+   **/
+  public void build() throws ODataJPAModelException, ODataJPARuntimeException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmMappingModelAccess.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmMappingModelAccess.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmMappingModelAccess.java
new file mode 100644
index 0000000..ef6f984
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAEdmMappingModelAccess.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAEdmMappingModel;
+
+/**
+ * Interface provides methods to access JPA EDM mapping model.
+ * 
+ * @author SAP AG
+ * @see JPAEdmMappingModel
+ * 
+ */
+public interface JPAEdmMappingModelAccess {
+
+  /**
+   * The method searches and loads the mapping model stored in &ltfile&gt.xml
+   * file into the java object
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAEdmMappingModel}
+   * . The name of the file is set into ODataJPAContext method.
+   * 
+   * @see org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext#setJPAEdmMappingModel(String)
+   */
+  public void loadMappingModel();
+
+  /**
+   * The method returns if there exists a mapping model.
+   * 
+   * @return true - if there exists a mapping model for the OData service else
+   *         false
+   */
+  public boolean isMappingModelExists();
+
+  /**
+   * The method returns a JPA EDM mapping model Java object. The mapping model
+   * in XML files is un-marshaled into the Java object.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAEdmMappingModel}
+   */
+  public JPAEdmMappingModel getJPAEdmMappingModel();
+
+  /**
+   * The method returns EDM Schema namespace for the persistence unit name
+   * 
+   * @param persistenceUnitName
+   *            is the Java persistence unit name
+   * @return EDM schema name space mapped to Java persistence unit name or
+   *         null if no mapping is available
+   */
+  public String mapJPAPersistenceUnit(String persistenceUnitName);
+
+  /**
+   * The method returns EDM entity type name for the Java persistence entity
+   * type name
+   * 
+   * @param jpaEntityTypeName
+   *            is the Java persistence entity type name
+   * @return EDM entity type name mapped to Java persistence entity type name
+   *         or null if no mapping is available
+   */
+  public String mapJPAEntityType(String jpaEntityTypeName);
+
+  /**
+   * The method returns EDM entity set name for the Java persistence entity
+   * type name
+   * 
+   * @param jpaEntityTypeName
+   *            is the Java persistence entity type name
+   * @return EDM entity set name mapped to Java persistence entity type name
+   *         or null if no mapping is available
+   */
+  public String mapJPAEntitySet(String jpaEntityTypeName);
+
+  /**
+   * The method returns EDM property name for the Java persistence entity
+   * attribute name.
+   * 
+   * @param jpaEntityTypeName
+   *            is the Java persistence entity type name
+   * @param jpaAttributeName
+   *            is the Java persistence attribute name
+   * @return EDM property name mapped to Java persistence attribute name or
+   *         null if no mapping is available
+   */
+  public String mapJPAAttribute(String jpaEntityTypeName,
+      String jpaAttributeName);
+
+  /**
+   * The method returns EDM navigation property name for the Java persistence
+   * entity relationship name.
+   * 
+   * @param jpaEntityTypeName
+   *            is the Java persistence entity type name
+   * @param jpaRelationshipName
+   *            is the Java persistence relationship name
+   * @return EDM navigation property name mapped to Java persistence entity
+   *         relationship name or null if no mapping is available
+   */
+  public String mapJPARelationship(String jpaEntityTypeName,
+      String jpaRelationshipName);
+
+  /**
+   * The method returns EDM complex type name for the Java embeddable type
+   * name.
+   * 
+   * @param jpaEmbeddableTypeName
+   *            is the Java persistence embeddable type name
+   * @return EDM complex type name mapped to Java persistence entity
+   *         relationship name or null if no mapping is available
+   */
+  public String mapJPAEmbeddableType(String jpaEmbeddableTypeName);
+
+  /**
+   * The method returns EDM property name for the Java persistence embeddable
+   * type's attribute name.
+   * 
+   * @param jpaEmbeddableTypeName
+   *            is the Java persistence
+   * @param jpaAttributeName
+   *            is the Java persistence attribute name
+   * @return EDM property name mapped to Java persistence attribute name or
+   *         null if no mapping is available
+   */
+  public String mapJPAEmbeddableTypeAttribute(String jpaEmbeddableTypeName,
+      String jpaAttributeName);
+
+  /**
+   * The method returns whether the JPA Entity should be excluded from EDM
+   * model
+   * 
+   * @param jpaEntityTypeName
+   *            is the name of JPA Entity Type
+   * @return <b>true</b> - if JPA Entity should be excluded<br>
+   *         <b>false</b> - if JPA Entity should be not be excluded
+   * 
+   */
+  public boolean checkExclusionOfJPAEntityType(String jpaEntityTypeName);
+
+  /**
+   * The method returns whether the JPA Attribute should be excluded from EDM
+   * Entity Type
+   * 
+   * @param jpaEntityTypeName
+   *            is the name of JPA Entity Type
+   * @param jpaAttributeName
+   *            is the name of JPA attribute
+   * @return <b>true</b> - if JPA attribute should be excluded<br>
+   *         <b>false</b> - if JPA attribute should be not be excluded
+   * 
+   */
+  public boolean checkExclusionOfJPAAttributeType(String jpaEntityTypeName,
+      String jpaAttributeName);
+
+  /**
+   * The method returns whether the JPA Embeddable Type should be excluded
+   * from EDM model
+   * 
+   * @param jpaEmbeddableTypeName
+   *            is the name of JPA Embeddable Type
+   * @return <b>true</b> - if JPA Embeddable Type should be excluded<br>
+   *         <b>false</b> - if JPA Embeddable Type should be not be excluded
+   * 
+   */
+  public boolean checkExclusionOfJPAEmbeddableType(
+      String jpaEmbeddableTypeName);
+
+  /**
+   * The method returns whether the JPA Embeddable Attribute Type should be
+   * excluded from EDM model
+   * 
+   * @param jpaEmbeddableTypeName
+   *            is the name of JPA Embeddable Attribute Type
+   * @param jpaAttributeName
+   * 				is the name of JPA Attribute name
+   * @return <b>true</b> - if JPA Embeddable Attribute Type should be excluded<br>
+   *         <b>false</b> - if JPA Embeddable Attribute Type should be not be
+   *         excluded
+   * 
+   */
+  public boolean checkExclusionOfJPAEmbeddableAttributeType(
+      String jpaEmbeddableTypeName, String jpaAttributeName);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAFunction.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAFunction.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAFunction.java
new file mode 100644
index 0000000..ab6c3d1
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAFunction.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+
+/**
+ * A container for JPA Functions. A JPA function can be
+ * <ol>
+ * <li>Property Access method</li>
+ * <li>Custom Operation (Annotated with EDM Annotation FunctionImport)</li>
+ * </ol>
+ * 
+ * @author SAP AG
+ * 
+ */
+public class JPAFunction {
+
+  private Method function;
+  private Class<?>[] parameterTypes;
+  private Type returnType;
+  private Object[] args;
+
+  public JPAFunction(final Method function, final Class<?>[] parameterTypes,
+      final Type returnType, final Object[] args) {
+    this.function = function;
+    this.parameterTypes = parameterTypes;
+    this.returnType = returnType;
+    this.args = args;
+  }
+
+  /**
+   * The method returns the Java method.
+   * 
+   * @return an instance of {@link java.lang.reflect.Method}
+   */
+  public Method getFunction() {
+    return function;
+  }
+
+  /**
+   * The method returns the parameter types for the Java method.
+   * 
+   * @return an array of type {@link java.lang.Class<?>}
+   */
+  public Class<?>[] getParameterTypes() {
+    return parameterTypes;
+  }
+
+  /**
+   * The method returns the return type for the Java method.
+   * 
+   * @return an instance of {@link java.lang.reflect.Type}
+   */
+  public Type getReturnType() {
+    return returnType;
+  }
+
+  /**
+   * The method returns an array of arguments for invoking the Java method.
+   * 
+   * @return an array of Objects
+   */
+  public Object[] getArguments() {
+    return args;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAJoinClause.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAJoinClause.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAJoinClause.java
new file mode 100644
index 0000000..0012137
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAJoinClause.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+/**
+ * A container for Java Persistence Join Clause that can be used for building
+ * JPQL statements. The container has two main elements <b>
+ * <ol>
+ * <li>Java Persistence Entity -</li> is the source entity participating in the
+ * join. <br>
+ * <li>Java Persistence Entity Relationship -</li> is the entity relationship of
+ * the source entity participating in the join.
+ * </ol>
+ * </b>
+ * 
+ * @author SAP AG
+ * 
+ */
+public class JPAJoinClause {
+
+  /**
+   * Enumerated list of possible Joins in JPQL
+   * <ol>
+   * <li>LEFT - left outer join</li>
+   * <li>FETCH - enable fetching of an association as a side effect of the
+   * execution of a query</li>
+   * <li>INNER - inner join
+   * </ol>
+   * 
+   * @author SAP AG
+   * 
+   */
+  public enum JOIN {
+    LEFT, FETCH, INNER
+  }
+
+  private String entityName;
+  private String entityAlias;
+  private String entityRelationShip;
+  private String entityRelationShipAlias;
+  private JOIN joinType;
+  private String joinCondition;
+
+  /**
+   * The method returns Java Persistence Entity participating in the join.
+   * 
+   * @return an entity name
+   */
+  public String getEntityName() {
+    return entityName;
+  }
+
+  /**
+   * The method returns Java Persistence Entity alias name participating in
+   * the join.
+   * 
+   * @return a entity alias name
+   */
+  public String getEntityAlias() {
+    return entityAlias;
+  }
+
+  /**
+   * The method returns Java Persistence Entity Relationship name
+   * participating in the join.
+   * 
+   * @return entity alias relationship
+   */
+  public String getEntityRelationShip() {
+    return entityRelationShip;
+  }
+
+  /**
+   * The method returns Java Persistence Entity Relationship Alias name
+   * participating in the join.
+   * 
+   * @return entity entity relationship alias
+   */
+  public String getEntityRelationShipAlias() {
+    return entityRelationShipAlias;
+  }
+
+  /**
+   * Constructor for creating elements of JPA Join Clause container.
+   * 
+   * @param entityName
+   *            is the name of the JPA entity participating in the join
+   * @param entityAlias
+   *            is the alias for the JPA entity participating in the join
+   * @param entityRelationShip
+   *            is the name of the JPA entity relationship participating in
+   *            the join
+   * @param entityRelationShipAlias
+   *            is the alias name of the JPA entity relationship participating
+   *            in the join
+   * @param joinCondition
+   *            is the condition on which the joins should occur
+   * @param joinType
+   *            is the type of join
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause.JOIN}
+   *            to execute
+   */
+  public JPAJoinClause(final String entityName, final String entityAlias,
+      final String entityRelationShip, final String entityRelationShipAlias,
+      final String joinCondition, final JOIN joinType) {
+
+    this.entityName = entityName;
+    this.entityAlias = entityAlias;
+    this.entityRelationShip = entityRelationShip;
+    this.entityRelationShipAlias = entityRelationShipAlias;
+    this.joinCondition = joinCondition;
+    this.joinType = joinType;
+  }
+
+  /**
+   * The method returns a join condition that can be used for building JPQL
+   * join statements.
+   * 
+   * @return a join condition
+   */
+  public String getJoinCondition() {
+    return joinCondition;
+  }
+
+  /**
+   * The method returns the type of
+   * {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause.JOIN}
+   * that can be used for building JPQL join statements.
+   * 
+   * @return join type
+   */
+  public JOIN getJoinType() {
+    return joinType;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContext.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContext.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContext.java
new file mode 100644
index 0000000..c65faa1
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContext.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+
+/**
+ * The abstract class is a compilation of objects required for building specific
+ * instances of JPA Method Context. Extend this class to implement specific
+ * implementations of JPQL context types (Create,Update,Function). A JPA method
+ * Context is constructed from an OData request. Depending on OData
+ * CUD/FunctionImport operation performed on an Entity, a corresponding JPA
+ * method context object is built. The object thus built can be used for
+ * executing operations on JPA Entity/Custom processor objects. <br>
+ * A default implementation is provided by the library.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContextView
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType
+ * 
+ */
+
+public abstract class JPAMethodContext implements JPAMethodContextView {
+
+  protected Object enclosingObject;
+  protected ArrayList<JPAFunction> jpaFunction;
+
+  @Override
+  /**
+   * The method returns list of JPA functions that can be executed on the
+   * enclosing object.
+   * 
+   * @return an instance of list of JPA Function
+   */
+  public Object getEnclosingObject() {
+    return enclosingObject;
+  }
+
+  @Override
+  /**
+   * The method returns list of JPA functions that can be executed on the
+   * enclosing object.
+   * 
+   * @return an instance of list of JPA Function
+   */
+  public List<JPAFunction> getJPAFunctionList() {
+    return jpaFunction;
+  }
+
+  protected void setEnclosingObject(final Object enclosingObject) {
+    this.enclosingObject = enclosingObject;
+  }
+
+  protected void setJpaFunction(final List<JPAFunction> jpaFunctionList) {
+    jpaFunction = (ArrayList<JPAFunction>) jpaFunctionList;
+  }
+
+  /**
+   * the method instantiates an instance of type JPAMethodContextBuilder.
+   * 
+   * @param contextType
+   *            indicates the type of JPQLContextBuilder to instantiate.
+   * @param resultsView
+   *            is the OData request view
+   * @return {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext.JPAMethodContextBuilder}
+   * 
+   * @throws ODataJPARuntimeException
+   */
+  public final static JPAMethodContextBuilder createBuilder(
+      final JPQLContextType contextType, final Object resultsView)
+      throws ODataJPARuntimeException {
+    return JPAMethodContextBuilder.create(contextType, resultsView);
+  }
+
+  /**
+   * The abstract class is extended by specific JPA Method Context Builder to
+   * build JPA Method Context types.
+   * 
+   * @author SAP AG
+   * 
+   */
+  public static abstract class JPAMethodContextBuilder {
+
+    /**
+     * Implement this method to build JPAMethodContext
+     * 
+     * @return an instance of type JPAMethodContext
+     * @throws ODataJPAModelException
+     * @throws ODataJPARuntimeException
+     */
+    public abstract JPAMethodContext build() throws ODataJPAModelException,
+        ODataJPARuntimeException;
+
+    protected JPAMethodContextBuilder() {}
+
+    private static JPAMethodContextBuilder create(
+        final JPQLContextType contextType, final Object resultsView)
+        throws ODataJPARuntimeException {
+      JPAMethodContextBuilder contextBuilder = ODataJPAFactory
+          .createFactory().getJPQLBuilderFactory()
+          .getJPAMethodContextBuilder(contextType);
+
+      if (contextBuilder == null) {
+        throw ODataJPARuntimeException
+            .throwException(
+                ODataJPARuntimeException.ERROR_JPQLCTXBLDR_CREATE,
+                null);
+      }
+      contextBuilder.setResultsView(resultsView);
+      return contextBuilder;
+    }
+
+    protected abstract void setResultsView(Object resultsView);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContextView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContextView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContextView.java
new file mode 100644
index 0000000..02f5a97
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAMethodContextView.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import java.util.List;
+
+/**
+ * The interface provides view on JPA Method Context. JPA Method context can be
+ * used to access custom operations or JPA Entity property access methods.
+ * 
+ * @author SAP AG
+ * 
+ */
+public interface JPAMethodContextView {
+  /**
+   * The method returns an instance of Object on which the methods/custom
+   * operations can be executed.
+   * 
+   * @return instance of enclosing object for the method
+   */
+  public Object getEnclosingObject();
+
+  /**
+   * The method returns list of JPA functions that can be executed on the
+   * enclosing object.
+   * 
+   * @return an instance of list of JPA Function
+   */
+  public List<JPAFunction> getJPAFunctionList();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessor.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessor.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessor.java
new file mode 100644
index 0000000..8940626
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessor.java
@@ -0,0 +1,230 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+/**
+ * The interface provides methods for processing OData Requests for Create, Read, Update, Delete operations. 
+ * You need to pass the OData request and the API created a JPA response. The JPA response is a JPA entity. 
+ * You can now work with the JPA entities directly once it is retrieved from the persistence.
+ * 
+ * @author SAP AG
+ */
+public interface JPAProcessor {
+  /**
+   * Processes OData request for querying an Entity Set. The method returns
+   * list of Objects of type representing JPA Entity Types.
+   * 
+   * @param <T>
+   *            Template parameter representing Java Persistence Entity Type.
+   *            <p>
+   *            <b>Note:-</b> Default parameter is Object.
+   *            </p>
+   * 
+   * @param requestView
+   *            is an OData request for querying an entity set
+   *            <p>
+   * @return list of objects representing JPA entity types
+   **/
+  public <T> List<T> process(GetEntitySetUriInfo requestView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for reading an Entity. The method returns an
+   * Object of type representing JPA Entity Type.
+   * 
+   * @param <T>
+   *            Template parameter representing Java Persistence Entity Type.
+   *            <p>
+   *            <b>Note:-</b> Default parameter is Object.
+   *            </p>
+   * 
+   * @param requestView
+   *            OData request for reading an entity
+   * 
+   *            <p>
+   * @return object representing JPA entity type
+   **/
+  public <T> Object process(GetEntityUriInfo requestView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for fetching Entity count. The method returns JPA Entity count
+   * 
+   * @param requestView
+   *            OData request for counting an entity set
+   * @return long value representing count of JPA entity set
+   * 
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+
+  public long process(GetEntitySetCountUriInfo requestView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for fetching Entity count. The method returns count of target entity.
+   * This is specific to situation where cardinality is 1:1
+   * 
+   * @param resultsView 
+   * 			OData request for counting target entity.
+   * @return long value representing count of JPA entity
+   * 
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+  public long process(GetEntityCountUriInfo resultsView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for creating Entity. The method returns an Object
+   * which is created. Null means object was not created.
+   * 
+   * @param createView
+   * @param content
+   * @param requestContentType
+   * @param contentType
+   * @return Created Object
+   * 
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+
+  public <T> List<T> process(PostUriInfo createView, InputStream content,
+      String requestContentType) throws ODataJPAModelException,
+      ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for updating Entity. The method returns an Object
+   * which is updated. Null means object was not found or updated.
+   * 
+   * @param deleteuriInfo
+   * @param contentType
+   * @return Deleted Object
+   * 
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+  public <T> Object process(PutMergePatchUriInfo updateView,
+      InputStream content, String requestContentType)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for deleting Entity. The method returns an Object
+   * which is deleted. Null means object was not found.
+   * 
+   * @param deleteuriInfo
+   * @param contentType
+   * @return Deleted Object
+   * 
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+  public Object process(DeleteUriInfo deleteuriInfo, String contentType)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for executing custom operations. The method
+   * returns a List of Object. The list contains one entry if the the custom
+   * operations return type has multiplicity of ONE.
+   * 
+   * @param requestView
+   *            OData request for executing function import
+   * @return result of executing function import
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+  public List<Object> process(GetFunctionImportUriInfo requestView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for executing $links OData command for N:1 relation. 
+   * The method returns an Object of type representing OData entity.
+   * 
+   * @param uriParserResultView
+   *          OData request for Entity Link URI
+   * @return an object representing JPA entity
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+  public Object process(GetEntityLinkUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Processes OData request for executing $links OData command for N:1 relation. 
+   * The method returns an Object of type representing OData entity.
+   * 
+   * @param uriParserResultView
+   *          OData request for Entity Set Link URI
+   * @return a list of object representing JPA entities
+   * @throws ODataJPAModelException
+   * @throws ODataJPARuntimeException
+   */
+  public <T> List<T> process(GetEntitySetLinksUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException;
+
+  /**
+   * Process OData request for creating Links. The OData request should contain
+   * $links OData command.
+   * 
+   * @param uriParserResultView
+   *          OData request for creating Links
+   * @param content
+   * @param requestContentType
+   * @param contentType
+   * 
+   * @throws ODataJPARuntimeException
+   * @throws ODataJPAModelException
+   */
+  public void process(PostUriInfo uriParserResultView,
+      InputStream content, String requestContentType, String contentType)
+      throws ODataJPARuntimeException, ODataJPAModelException;
+
+  /**
+   * Process OData request for updating Links. The OData request should contain
+   * $links OData command.
+   * 
+   * @param uriParserResultView
+   *          OData request for updating Links
+   * @param content
+   * @param requestContentType
+   * @param contentType
+   * 
+   * @throws ODataJPARuntimeException
+   * @throws ODataJPAModelException
+   */
+  public void process(PutMergePatchUriInfo uriParserResultView,
+      InputStream content, String requestContentType, String contentType)
+      throws ODataJPARuntimeException, ODataJPAModelException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorExtension.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorExtension.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorExtension.java
new file mode 100644
index 0000000..fb1364e
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorExtension.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+import java.util.HashMap;
+import java.util.List;
+
+public class JPAProcessorExtension {
+
+  private JPAProcessor jpaProcessor;
+  private HashMap<JPAProcessorOperation, List<String>> operationEntityMap;
+
+  public JPAProcessor getJpaProcessor() {
+    return jpaProcessor;
+  }
+
+  public void setJpaProcessor(final JPAProcessor jpaProcessor) {
+    this.jpaProcessor = jpaProcessor;
+  }
+
+  public HashMap<JPAProcessorOperation, List<String>> getOperationEntityMap() {
+    return operationEntityMap;
+  }
+
+  public void setOperationEntityMap(final HashMap<JPAProcessorOperation, List<String>> operationEntityMap) {
+    this.operationEntityMap = operationEntityMap;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorOperation.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorOperation.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorOperation.java
new file mode 100644
index 0000000..219bbf7
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorOperation.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+public enum JPAProcessorOperation {
+  Read,
+  Query,
+  Create,
+  Update,
+  Delete
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorRegistry.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorRegistry.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorRegistry.java
new file mode 100644
index 0000000..8ee298c
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/JPAProcessorRegistry.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.access;
+
+/**
+ * 
+ * @author SAP AG
+ *
+ */
+public class JPAProcessorRegistry {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/package-info.java
new file mode 100644
index 0000000..7caabd3
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/access/package-info.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library - Java Persistence Access</h3>
+ * The library provides a set of APIs to access Java Persistence Models and Data.
+ * 
+ * @author SAP AG
+ */
+package org.apache.olingo.odata2.processor.api.jpa.access;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAException.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAException.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAException.java
new file mode 100644
index 0000000..badd20c
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAException.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.exception;
+
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+/**
+ * The exception class is the base of OData JPA exceptions. The class also
+ * provides non localized error texts that can be used for raising OData JPA
+ * exceptions with non localized error texts.
+ * 
+ * @author SAP AG
+ * 
+ */
+public abstract class ODataJPAException extends ODataException {
+
+  protected MessageReference messageReference;
+
+  public static final String ODATA_JPACTX_NULL = "OData JPA Context cannot be null";
+
+  private static final long serialVersionUID = -6884673558124441214L;
+  protected static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
+
+  protected ODataJPAException(final String localizedMessage, final Throwable e, final MessageReference msgRef) {
+    super(localizedMessage, e);
+    messageReference = msgRef;
+  }
+
+  /**
+   * The method creates a Reference to Message Object
+   * {@link org.apache.olingo.odata2.api.exception.MessageReference} . The message
+   * text key is derived out of parameters clazz.messageReferenceKey.
+   * 
+   * @param clazz
+   *            is name of the class extending
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAException}
+   * @param messageReferenceKey
+   *            is the key of the message
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.exception.MessageReference}
+   */
+  protected static MessageReference createMessageReference(
+      final Class<? extends ODataJPAException> clazz, final String messageReferenceKey) {
+    return MessageReference.create(clazz, messageReferenceKey);
+  }
+
+  public MessageReference getMessageReference() {
+    return messageReference;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAMessageService.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAMessageService.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAMessageService.java
new file mode 100644
index 0000000..ba41a6d
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAMessageService.java
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.exception;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+
+/**
+ * The interface is used to access language dependent message texts. Default
+ * language is "English - EN". <br>
+ * The default implementation of the interface shipped with the library loads
+ * message texts from language dependent property files. If the message text is
+ * not found for the given language then the default language -EN is used for
+ * the message texts.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAException
+ * @see org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException
+ * @see org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException
+ * @see org.apache.olingo.odata2.api.exception.MessageReference
+ */
+public interface ODataJPAMessageService {
+  /**
+   * The method returns a language dependent message texts for the given
+   * {@link org.apache.olingo.odata2.api.exception.MessageReference}.
+   * 
+   * @param context
+   *            is a Message Reference
+   *        exception
+   *        	  is a Throwable Exception
+   * @return a language dependent message text
+   */
+  public String getLocalizedMessage(MessageReference context, Throwable exception);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAModelException.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAModelException.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAModelException.java
new file mode 100644
index 0000000..4312e24
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPAModelException.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.exception;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+
+/**
+ * The exception is thrown for any unexpected errors raising while
+ * accessing/transforming Java Persistence Models.
+ * 
+ * @author SAP AG
+ * 
+ */
+public class ODataJPAModelException extends ODataJPAException {
+
+  public static final MessageReference INVALID_ENTITY_TYPE = createMessageReference(
+      ODataJPAModelException.class, "INVALID_ENTITY_TYPE");
+  public static final MessageReference INVALID_COMPLEX_TYPE = createMessageReference(
+      ODataJPAModelException.class, "INVLAID_COMPLEX_TYPE");
+  public static final MessageReference INVALID_ASSOCIATION = createMessageReference(
+      ODataJPAModelException.class, "INVALID_ASSOCIATION");
+  public static final MessageReference INVALID_ENTITYSET = createMessageReference(
+      ODataJPAModelException.class, "INVALID_ENTITYSET");
+  public static final MessageReference INVALID_ENTITYCONTAINER = createMessageReference(
+      ODataJPAModelException.class, "INVALID_ENTITYCONTAINER");
+  public static final MessageReference INVALID_ASSOCIATION_SET = createMessageReference(
+      ODataJPAModelException.class, "INVALID_ASSOCIATION_SET");
+  public static final MessageReference INVALID_FUNC_IMPORT = createMessageReference(
+      ODataJPAModelException.class, "INVALID_FUNC_IMPORT");
+
+  public static final MessageReference BUILDER_NULL = createMessageReference(
+      ODataJPAModelException.class, "BUILDER_NULL");
+  public static final MessageReference TYPE_NOT_SUPPORTED = createMessageReference(
+      ODataJPAModelException.class, "TYPE_NOT_SUPPORTED");
+  public static final MessageReference FUNC_ENTITYSET_EXP = createMessageReference(
+      ODataJPAModelException.class, "FUNC_ENTITYSET_EXP");
+  public static final MessageReference FUNC_RETURN_TYPE_EXP = createMessageReference(
+      ODataJPAModelException.class, "FUNC_RETURN_TYPE_EXP");
+  public static final MessageReference FUNC_RETURN_TYPE_ENTITY_NOT_FOUND = createMessageReference(
+      ODataJPAModelException.class, "FUNC_RETURN_TYPE_ENTITY_NOT_FOUND");
+  public static final MessageReference GENERAL = createMessageReference(
+      ODataJPAModelException.class, "GENERAL");
+  public static final MessageReference INNER_EXCEPTION = createMessageReference(
+      ODataJPAModelException.class, "INNER_EXCEPTION");
+  public static final MessageReference FUNC_PARAM_NAME_EXP = createMessageReference(
+      ODataJPAModelException.class, "FUNC_PARAM_NAME_EXP");
+
+  private ODataJPAModelException(final String localizedMessage, final Throwable e,
+      final MessageReference msgRef) {
+    super(localizedMessage, e, msgRef);
+  }
+
+  /**
+   * The method creates an exception object of type ODataJPAModelException
+   * with localized error texts.
+   * 
+   * @param messageReference
+   *            is a <b>mandatory</b> parameter referring to a literal that
+   *            could be translated to localized error texts.
+   * @param e
+   *            is an optional parameter representing the previous exception
+   *            in the call stack
+   * @return an instance of ODataJPAModelException which can be then raised.
+   * @throws ODataJPARuntimeException
+   */
+  public static ODataJPAModelException throwException(
+      final MessageReference messageReference, final Throwable e) {
+
+    ODataJPAMessageService messageService;
+    messageService = ODataJPAFactory.createFactory()
+        .getODataJPAAccessFactory()
+        .getODataJPAMessageService(DEFAULT_LOCALE);
+    String message = messageService
+        .getLocalizedMessage(messageReference, e);
+    return new ODataJPAModelException(message, e, messageReference);
+  }
+
+  private static final long serialVersionUID = 7940106375606950703L;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPARuntimeException.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPARuntimeException.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPARuntimeException.java
new file mode 100644
index 0000000..88af5b9
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/ODataJPARuntimeException.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.exception;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+
+/**
+ * The exception is thrown for any unexpected errors raising while accessing
+ * data from Java Persistence Models.
+ * 
+ * The exception object is created with localized error texts provided error
+ * texts are maintained in localized languages.
+ * 
+ * @author SAP AG
+ * 
+ */
+public class ODataJPARuntimeException extends ODataJPAException {
+
+  public static final MessageReference ENTITY_MANAGER_NOT_INITIALIZED = createMessageReference(
+      ODataJPARuntimeException.class, "ENTITY_MANAGER_NOT_INITIALIZED");
+  public static final MessageReference RESOURCE_NOT_FOUND = createMessageReference(
+      ODataJPARuntimeException.class, "RESOURCE_NOT_FOUND");
+  public static final MessageReference GENERAL = createMessageReference(
+      ODataJPARuntimeException.class, "GENERAL");
+  public static final MessageReference INNER_EXCEPTION = createMessageReference(
+      ODataJPARuntimeException.class, "INNER_EXCEPTION");
+  public static final MessageReference JOIN_CLAUSE_EXPECTED = createMessageReference(
+      ODataJPARuntimeException.class, "JOIN_CLAUSE_EXPECTED");
+  public static final MessageReference ERROR_JPQLCTXBLDR_CREATE = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQLCTXBLDR_CREATE");
+  public static final MessageReference ERROR_ODATA_FILTER_CONDITION = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_ODATA_FILTER_CONDITION");
+  public static final MessageReference ERROR_JPQL_QUERY_CREATE = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_QUERY_CREATE");
+  public static final MessageReference ERROR_JPQL_CREATE_REQUEST = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_CREATE_REQUEST");
+  public static final MessageReference ERROR_JPQL_UPDATE_REQUEST = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_UPDATE_REQUEST");
+  public static final MessageReference ERROR_JPQL_DELETE_REQUEST = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_DELETE_REQUEST");
+  public static final MessageReference ERROR_JPQL_KEY_VALUE = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_KEY_VALUE");
+  public static final MessageReference ERROR_JPQL_PARAM_VALUE = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_PARAM_VALUE");
+  public static final MessageReference ERROR_JPQL_UNIQUE_CONSTRAINT = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_UNIQUE_CONSTRAINT");
+  public static final MessageReference ERROR_JPQL_INTEGRITY_CONSTRAINT = createMessageReference(
+      ODataJPARuntimeException.class, "ERROR_JPQL_INTEGRITY_CONSTRAINT");
+  public static final MessageReference RELATIONSHIP_INVALID = createMessageReference(
+      ODataJPARuntimeException.class, "RELATIONSHIP_INVALID");
+  public static final MessageReference RESOURCE_X_NOT_FOUND = createMessageReference(
+      ODataJPARuntimeException.class, "RESOURCE_X_NOT_FOUND");
+
+  private ODataJPARuntimeException(final String localizedMessage, final Throwable e,
+      final MessageReference msgRef) {
+    super(localizedMessage, e, msgRef);
+  }
+
+  /**
+   * The method creates an exception object of type ODataJPARuntimeException
+   * with localized error texts.
+   * 
+   * @param messageReference
+   *            is a <b>mandatory</b> parameter referring to a literal that
+   *            could be translated to localized error texts.
+   * @param e
+   *            is an optional parameter representing the previous exception
+   *            in the call stack
+   * @return an instance of ODataJPARuntimeException which can be then raised.
+   * @throws ODataJPARuntimeException
+   */
+  public static ODataJPARuntimeException throwException(
+      final MessageReference messageReference, final Throwable e) {
+    ODataJPAMessageService messageService;
+    messageService = ODataJPAFactory.createFactory()
+        .getODataJPAAccessFactory()
+        .getODataJPAMessageService(DEFAULT_LOCALE);
+    String message = messageService
+        .getLocalizedMessage(messageReference, e);
+    return new ODataJPARuntimeException(message, e, messageReference);
+  }
+
+  private static final long serialVersionUID = -5230976355642443012L;
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/package-info.java
new file mode 100644
index 0000000..2ec67d5
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/exception/package-info.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library - Exceptions</h3>
+ * There are two main types of exceptions thrown from the library
+ * <ol><li>Model Exception</li>
+ * <li>Runtime Exception</li></ol>
+ * <br>
+ * The Model Exception is thrown while processing JPA metamodels and 
+ * runtime exception is thrown while processing persistence data.
+ * 
+ * @author SAP AG
+ */
+package org.apache.olingo.odata2.processor.api.jpa.exception;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPAAccessFactory.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPAAccessFactory.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPAAccessFactory.java
new file mode 100644
index 0000000..3ca86fe
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPAAccessFactory.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.factory;
+
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView;
+
+/**
+ * Factory interface for creating
+ * <ol>
+ * <li>JPA EDM Model view</li>
+ * <li>JPA Processor</li>
+ * </ol>
+ * 
+ * @author SAP AG
+ * 
+ */
+public interface JPAAccessFactory {
+  /**
+   * The method returns an instance of JPA EDM model view based on OData JPA
+   * Context. The JPA EDM model view thus returned can be used for building
+   * EDM models from Java persistence models.
+   * 
+   * @param oDataJPAContext
+   *            a non null instance of
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView}
+   */
+  public JPAEdmModelView getJPAEdmModelView(ODataJPAContext oDataJPAContext);
+
+  /**
+   * The method returns an instance of JPA processor based on OData JPA
+   * Context. The JPA Processor thus returned can be used for building and
+   * processing JPQL statements.
+   * 
+   * @param oDataJPAContext
+   *            a non null instance of
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor}
+   */
+  public JPAProcessor getJPAProcessor(ODataJPAContext oDataJPAContext);
+
+  /**
+   * The method returns an instance of JPA EDM mapping model access based on
+   * OData JPA context. The instance thus returned can be used for accessing
+   * the mapping details maintained for an OData service
+   * 
+   * @param oDataJPAContext
+   *            a non null instance of
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess}
+   */
+  public JPAEdmMappingModelAccess getJPAEdmMappingModelAccess(
+      ODataJPAContext oDataJPAContext);
+}


[35/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRoleTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRoleTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRoleTest.java
new file mode 100644
index 0000000..62dbfa0
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintRoleTest.java
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintRoleView.RoleType;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAJavaMemberMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAManagedTypeMock;
+
+public class JPAEdmReferentialConstraintRoleTest extends JPAEdmTestModelView {
+
+  private static JPAEdmReferentialConstraintRole objJPAEdmReferentialConstraintRole = null;
+  private static JPAEdmReferentialConstraintRoleTest objJPAEdmReferentialConstraintRoleTest = null;
+
+  @Before
+  public void setUp() {
+    objJPAEdmReferentialConstraintRoleTest = new JPAEdmReferentialConstraintRoleTest();
+
+    objJPAEdmReferentialConstraintRole = new JPAEdmReferentialConstraintRole(
+        RoleType.PRINCIPAL, objJPAEdmReferentialConstraintRoleTest,
+        objJPAEdmReferentialConstraintRoleTest,
+        objJPAEdmReferentialConstraintRoleTest);
+
+    try {
+      objJPAEdmReferentialConstraintRole.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testIsExists() {
+    assertTrue(objJPAEdmReferentialConstraintRole.isExists());// Default
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmReferentialConstraintRole.getBuilder());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmReferentialConstraintRole
+        .getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmReferentialConstraintRole
+        .getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetRoleTypePrincipal() {
+    assertEquals(objJPAEdmReferentialConstraintRole.getRoleType(),
+        RoleType.PRINCIPAL);
+  }
+
+  @Test
+  public void testGetRoleTypeDependent() {
+    objJPAEdmReferentialConstraintRoleTest = new JPAEdmReferentialConstraintRoleTest();
+    objJPAEdmReferentialConstraintRole = new JPAEdmReferentialConstraintRole(
+        RoleType.DEPENDENT, objJPAEdmReferentialConstraintRoleTest,
+        objJPAEdmReferentialConstraintRoleTest,
+        objJPAEdmReferentialConstraintRoleTest);
+
+    try {
+      objJPAEdmReferentialConstraintRole.getBuilder().build();
+      objJPAEdmReferentialConstraintRole.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals(objJPAEdmReferentialConstraintRole.getRoleType(),
+        RoleType.DEPENDENT);
+  }
+
+  @Test
+  public void testGetEdmReferentialConstraintRole() {
+    try {
+      objJPAEdmReferentialConstraintRole.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(objJPAEdmReferentialConstraintRole
+        .getEdmReferentialConstraintRole());
+  }
+
+  @Test
+  public void testGetJPAColumnName() {
+    assertNull(objJPAEdmReferentialConstraintRole.getJPAColumnName());
+  }
+
+  @Test
+  public void testGetEdmEntityTypeName() {
+    assertNull(objJPAEdmReferentialConstraintRole.getEdmEntityTypeName());
+  }
+
+  @Test
+  public void testGetEdmAssociationName() {
+    assertNull(objJPAEdmReferentialConstraintRole.getEdmAssociationName());
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return getJPAAttributeLocal();
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    Association association = new Association();
+    association.setName("Assoc_SalesOrderHeader_SalesOrderItem");
+    association.setEnd1(new AssociationEnd().setType(
+        new FullQualifiedName("salesorderprocessing", "String"))
+        .setRole("SalesOrderHeader"));
+    association.setEnd2(new AssociationEnd()
+        .setType(
+            new FullQualifiedName("salesorderprocessing",
+                "SalesOrderItem")).setRole("SalesOrderItem"));
+    return association;
+  }
+
+  @Override
+  public EntityType searchEdmEntityType(final String arg0) {
+
+    EntityType entityType = new EntityType();
+
+    JPAEdmMappingImpl mapping = new JPAEdmMappingImpl();
+    mapping.setJPAColumnName("SOID");
+
+    List<Property> propList = new ArrayList<Property>();
+
+    Property property = new Property() {};
+    property.setMapping((Mapping) mapping);
+    property.setName("SOID");
+    propList.add(property);
+
+    entityType.setProperties(propList);
+
+    return entityType;
+  }
+
+  private Attribute<?, ?> getJPAAttributeLocal() {
+    AttributeMock<Object, String> attr = new AttributeMock<Object, String>();
+    return attr;
+  }
+
+  @SuppressWarnings("hiding")
+  private class AttributeMock<Object, String> extends
+      JPAAttributeMock<Object, String> {
+
+    @Override
+    public Member getJavaMember() {
+      return new JavaMemberMock();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ManagedType<Object> getDeclaringType() {
+      return (ManagedType<Object>) getManagedTypeLocal();
+    }
+
+    private ManagedType<?> getManagedTypeLocal() {
+      ManagedTypeMock<String> managedTypeMock = new ManagedTypeMock<String>();
+      return managedTypeMock;
+    }
+  }
+
+  @SuppressWarnings("hiding")
+  private class ManagedTypeMock<String> extends JPAManagedTypeMock<String> {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+  }
+
+  private class JavaMemberMock extends JPAJavaMemberMock {
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Annotation> T getAnnotation(final Class<T> annotationClass) {
+      JoinColumn joinColumn = EasyMock.createMock(JoinColumn.class);
+      EasyMock.expect(joinColumn.referencedColumnName())
+          .andReturn("SOID");
+      EasyMock.expect(joinColumn.name()).andReturn("SOID");
+
+      EasyMock.replay(joinColumn);
+      return (T) joinColumn;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintTest.java
new file mode 100644
index 0000000..b5a341a
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmReferentialConstraintTest.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Member;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.ManagedType;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAAttributeMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAJavaMemberMock;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAManagedTypeMock;
+
+public class JPAEdmReferentialConstraintTest extends JPAEdmTestModelView {
+
+  private static JPAEdmReferentialConstraint objJPAEdmReferentialConstraint = null;
+  private static JPAEdmReferentialConstraintTest objJPAEdmReferentialConstraintTest = null;
+
+  @Before
+  public void setUp() {
+    objJPAEdmReferentialConstraintTest = new JPAEdmReferentialConstraintTest();
+    objJPAEdmReferentialConstraint = new JPAEdmReferentialConstraint(
+        objJPAEdmReferentialConstraintTest,
+        objJPAEdmReferentialConstraintTest,
+        objJPAEdmReferentialConstraintTest);
+    try {
+      objJPAEdmReferentialConstraint.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmReferentialConstraint.getBuilder());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmReferentialConstraint.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmReferentialConstraint.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetEdmReferentialConstraint() {
+    assertNotNull(objJPAEdmReferentialConstraint
+        .getEdmReferentialConstraint());
+  }
+
+  @Test
+  public void testIsExistsTrue() {
+    objJPAEdmReferentialConstraintTest = new JPAEdmReferentialConstraintTest();
+    objJPAEdmReferentialConstraint = new JPAEdmReferentialConstraint(
+        objJPAEdmReferentialConstraintTest,
+        objJPAEdmReferentialConstraintTest,
+        objJPAEdmReferentialConstraintTest);
+    try {
+      objJPAEdmReferentialConstraint.getBuilder().build();
+      objJPAEdmReferentialConstraint.getBuilder().build();
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertTrue(objJPAEdmReferentialConstraint.isExists());
+  }
+
+  @Test
+  public void testGetRelationShipName() {
+    assertEquals("Assoc_SalesOrderHeader_SalesOrderItem",
+        objJPAEdmReferentialConstraint.getEdmRelationShipName());
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    Association association = new Association();
+    association.setName("Assoc_SalesOrderHeader_SalesOrderItem");
+    association.setEnd1(new AssociationEnd().setType(
+        new FullQualifiedName("salesorderprocessing", "String"))
+        .setRole("SalesOrderHeader"));
+    association.setEnd2(new AssociationEnd()
+        .setType(
+            new FullQualifiedName("salesorderprocessing",
+                "SalesOrderItem")).setRole("SalesOrderItem"));
+    return association;
+  }
+
+  private Attribute<?, ?> getJPAAttributeLocal() {
+    AttributeMock<Object, String> attr = new AttributeMock<Object, String>();
+    return attr;
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return getJPAAttributeLocal();
+  }
+
+  @SuppressWarnings("hiding")
+  private class AttributeMock<Object, String> extends
+      JPAAttributeMock<Object, String> {
+
+    @Override
+    public Member getJavaMember() {
+      return new JavaMemberMock();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ManagedType<Object> getDeclaringType() {
+      return (ManagedType<Object>) getManagedTypeLocal();
+    }
+
+    private ManagedType<?> getManagedTypeLocal() {
+      ManagedTypeMock<String> managedTypeMock = new ManagedTypeMock<String>();
+      return managedTypeMock;
+    }
+  }
+
+  @SuppressWarnings("hiding")
+  private class ManagedTypeMock<String> extends JPAManagedTypeMock<String> {
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Class<String> getJavaType() {
+      return (Class<String>) java.lang.String.class;
+    }
+  }
+
+  private class JavaMemberMock extends JPAJavaMemberMock {
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Annotation> T getAnnotation(final Class<T> annotationClass) {
+      JoinColumn joinColumn = EasyMock.createMock(JoinColumn.class);
+      EasyMock.expect(joinColumn.referencedColumnName())
+          .andReturn("SOID");
+      EasyMock.expect(joinColumn.name()).andReturn("SOID");
+
+      EasyMock.replay(joinColumn);
+      return (T) joinColumn;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchemaTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchemaTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchemaTest.java
new file mode 100644
index 0000000..d3936b0
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmSchemaTest.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.persistence.metamodel.Metamodel;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.core.jpa.mock.model.JPAMetaModelMock;
+
+public class JPAEdmSchemaTest extends JPAEdmTestModelView {
+  private JPAEdmSchemaTest objJPAEdmSchemaTest;
+  private JPAEdmSchema objJPAEdmSchema;
+
+  @Before
+  public void setUp() {
+    objJPAEdmSchemaTest = new JPAEdmSchemaTest();
+    objJPAEdmSchema = new JPAEdmSchema(objJPAEdmSchemaTest);
+    //building schema is not required as downstream structure already tested
+
+  }
+
+  @Test
+  public void testClean() {
+    assertTrue(objJPAEdmSchema.isConsistent());
+    objJPAEdmSchema.clean();
+    assertFalse(objJPAEdmSchema.isConsistent());
+  }
+
+  @Test
+  public void testGetEdmSchema() {
+    assertNull(objJPAEdmSchema.getEdmSchema());
+  }
+
+  @Test
+  public void testGetJPAEdmEntityContainerView() {
+    assertNull(objJPAEdmSchema.getJPAEdmEntityContainerView());
+  }
+
+  @Test
+  public void testGetJPAEdmComplexTypeView() {
+    assertNull(objJPAEdmSchema.getJPAEdmComplexTypeView());
+  }
+
+  @Test
+  public void testGetBuilder() {
+    assertNotNull(objJPAEdmSchema.getBuilder());
+  }
+
+  @Test
+  public void testGetBuilderIdempotent() {
+    JPAEdmBuilder builder1 = objJPAEdmSchema.getBuilder();
+    JPAEdmBuilder builder2 = objJPAEdmSchema.getBuilder();
+
+    assertEquals(builder1.hashCode(), builder2.hashCode());
+  }
+
+  @Test
+  public void testGetJPAEdmAssociationView() {
+    assertNull(objJPAEdmSchema.getJPAEdmAssociationView());
+  }
+
+  @Test
+  public void testIsConsistent() {
+    assertTrue(objJPAEdmSchema.isConsistent());
+    objJPAEdmSchema.clean();
+    assertFalse(objJPAEdmSchema.isConsistent());
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return new JPAMetaModelMock();
+  }
+
+  @Override
+  public String getpUnitName() {
+    return "salesorderprocessing";
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmTestModelView.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmTestModelView.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmTestModelView.java
new file mode 100644
index 0000000..18f77b2
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/model/JPAEdmTestModelView.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.model;
+
+import java.util.HashMap;
+import java.util.List;
+
+import javax.persistence.metamodel.Attribute;
+import javax.persistence.metamodel.EmbeddableType;
+import javax.persistence.metamodel.Metamodel;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+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.Key;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmBaseView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmExtension;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmModelView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView;
+
+public class JPAEdmTestModelView implements JPAEdmAssociationEndView,
+    JPAEdmAssociationSetView, JPAEdmAssociationView, JPAEdmBaseView,
+    JPAEdmComplexPropertyView, JPAEdmComplexTypeView,
+    JPAEdmEntityContainerView, JPAEdmEntitySetView, JPAEdmEntityTypeView,
+    JPAEdmKeyView, JPAEdmModelView, JPAEdmNavigationPropertyView,
+    JPAEdmPropertyView, JPAEdmReferentialConstraintView, JPAEdmSchemaView {
+
+  protected JPAEdmMappingModelAccess mappingModelAccess;
+
+  @Override
+  public Schema getEdmSchema() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmAssociationView getJPAEdmAssociationView() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmComplexTypeView getJPAEdmComplexTypeView() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmEntityContainerView getJPAEdmEntityContainerView() {
+    return null;
+  }
+
+  @Override
+  public Attribute<?, ?> getJPAAttribute() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmKeyView getJPAEdmKeyView() {
+    return null;
+  }
+
+  @Override
+  public List<Property> getEdmPropertyList() {
+    return null;
+  }
+
+  @Override
+  public SimpleProperty getEdmSimpleProperty() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmSchemaView getEdmSchemaView() {
+    return null;
+  }
+
+  @Override
+  public Key getEdmKey() {
+    return null;
+  }
+
+  @Override
+  public List<EntityType> getConsistentEdmEntityTypes() {
+    return null;
+  }
+
+  @Override
+  public EntityType getEdmEntityType() {
+    return null;
+  }
+
+  @Override
+  public javax.persistence.metamodel.EntityType<?> getJPAEntityType() {
+    return null;
+  }
+
+  @Override
+  public List<EntitySet> getConsistentEdmEntitySetList() {
+    return null;
+  }
+
+  @Override
+  public EntitySet getEdmEntitySet() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView() {
+    return null;
+  }
+
+  @Override
+  public List<EntityContainer> getConsistentEdmEntityContainerList() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmAssociationSetView getEdmAssociationSetView() {
+    return null;
+  }
+
+  @Override
+  public EntityContainer getEdmEntityContainer() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmEntitySetView getJPAEdmEntitySetView() {
+    return null;
+  }
+
+  @Override
+  public void addJPAEdmCompleTypeView(final JPAEdmComplexTypeView arg0) {
+
+  }
+
+  @Override
+  public List<ComplexType> getConsistentEdmComplexTypes() {
+    return null;
+  }
+
+  @Override
+  public ComplexType getEdmComplexType() {
+    return null;
+  }
+
+  @Override
+  public EmbeddableType<?> getJPAEmbeddableType() {
+    return null;
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public ComplexType searchEdmComplexType(final FullQualifiedName arg0) {
+    return null;
+  }
+
+  @Override
+  public ComplexProperty getEdmComplexProperty() {
+    return null;
+  }
+
+  @Override
+  public void clean() {
+
+  }
+
+  @Override
+  public JPAEdmBuilder getBuilder() {
+    return null;
+  }
+
+  @Override
+  public Metamodel getJPAMetaModel() {
+    return null;
+  }
+
+  @Override
+  public String getpUnitName() {
+    return null;
+  }
+
+  @Override
+  public boolean isConsistent() {
+    return false;
+  }
+
+  @Override
+  public void addJPAEdmRefConstraintView(final JPAEdmReferentialConstraintView arg0) {
+
+  }
+
+  @Override
+  public ReferentialConstraint getEdmReferentialConstraint() {
+    return null;
+  }
+
+  @Override
+  public String getEdmRelationShipName() {
+    return null;
+  }
+
+  @Override
+  public boolean isExists() {
+    return false;
+  }
+
+  @Override
+  public EntityType searchEdmEntityType(final String arg0) {
+    return null;
+  }
+
+  @Override
+  public JPAEdmReferentialConstraintView getJPAEdmReferentialConstraintView() {
+    return null;
+  }
+
+  @Override
+  public List<Association> getConsistentEdmAssociationList() {
+    return null;
+  }
+
+  @Override
+  public Association searchAssociation(final JPAEdmAssociationEndView arg0) {
+    return null;
+  }
+
+  @Override
+  public List<AssociationSet> getConsistentEdmAssociationSetList() {
+    return null;
+  }
+
+  @Override
+  public Association getEdmAssociation() {
+    return null;
+  }
+
+  @Override
+  public AssociationSet getEdmAssociationSet() {
+    return null;
+  }
+
+  @Override
+  public boolean compare(final AssociationEnd arg0, final AssociationEnd arg1) {
+    return false;
+  }
+
+  @Override
+  public AssociationEnd getEdmAssociationEnd1() {
+    return null;
+  }
+
+  @Override
+  public AssociationEnd getEdmAssociationEnd2() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmNavigationPropertyView getJPAEdmNavigationPropertyView() {
+    return null;
+  }
+
+  @Override
+  public void addJPAEdmNavigationPropertyView(
+      final JPAEdmNavigationPropertyView view) {
+
+  }
+
+  @Override
+  public List<NavigationProperty> getConsistentEdmNavigationProperties() {
+    return null;
+  }
+
+  @Override
+  public NavigationProperty getEdmNavigationProperty() {
+    return null;
+  }
+
+  @Override
+  public void expandEdmComplexType(final ComplexType complexType,
+      final List<Property> expandedPropertyList, final String embeddablePropertyName) {
+
+  }
+
+  @Override
+  public List<String> getNonKeyComplexTypeList() {
+    return null;
+  }
+
+  @Override
+  public void addNonKeyComplexName(final String complexTypeName) {}
+
+  @Override
+  public JPAEdmMappingModelAccess getJPAEdmMappingModelAccess() {
+    return null;
+  }
+
+  @Override
+  public void registerOperations(final Class<?> customClass, final String[] methodNames) {
+    // Do nothing
+  }
+
+  @Override
+  public HashMap<Class<?>, String[]> getRegisteredOperations() {
+    return null;
+  }
+
+  @Override
+  public JPAEdmExtension getJPAEdmExtension() {
+    return null;
+  }
+
+  @Override
+  public void addJPAEdmAssociationView(final JPAEdmAssociationView associationView,
+      final JPAEdmAssociationEndView associationEndView) {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public int getNumberOfAssociationsWithSimilarEndPoints(
+      final JPAEdmAssociationEndView view) {
+    // TODO Auto-generated method stub
+    return 0;
+  }
+
+  @Override
+  public String getJoinColumnName() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String getJoinColumnReferenceColumnName() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String getMappedByName() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+  @Override
+  public String getOwningPropertyName() {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/resources/SalesOrderProcessingMappingModels.xml
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/resources/SalesOrderProcessingMappingModels.xml b/jpa-core/src/test/resources/SalesOrderProcessingMappingModels.xml
new file mode 100644
index 0000000..54d9c46
--- /dev/null
+++ b/jpa-core/src/test/resources/SalesOrderProcessingMappingModels.xml
@@ -0,0 +1,62 @@
+<?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.
+-->
+<JPAEDMMappingModel
+	xmlns="http://www.sap.com/core/odata/processor/api/jpa/model/mapping">
+	<PersistenceUnit name="salesorderprocessing">
+		<EDMSchemaNamespace>SalesOrderProcessing</EDMSchemaNamespace>
+		<JPAEntityTypes>
+			<JPAEntityType name="SalesOrderHeader">
+				<EDMEntityType>SalesOrder</EDMEntityType>
+				<EDMEntitySet>SalesOrders</EDMEntitySet>
+				<JPAAttributes>
+					<JPAAttribute name="soId"></JPAAttribute>
+					<JPAAttribute name="netAmount">NetAmount</JPAAttribute>
+					<JPAAttribute name="buyerAddress">BuyerAddressInfo</JPAAttribute>
+				</JPAAttributes>
+				<JPARelationships>
+					<JPARelationship name="salesOrderItems">SalesOrderItemDetails</JPARelationship>
+					<JPARelationship name="notes">NoteDetails</JPARelationship>
+				</JPARelationships>
+			</JPAEntityType>
+			<JPAEntityType name="SalesOrderItem">
+				<EDMEntityType>SalesOrderItem</EDMEntityType>
+				<EDMEntitySet>SalesOrderItems</EDMEntitySet>
+				<JPAAttributes>
+					<JPAAttribute name="liId">ID</JPAAttribute>
+					<JPAAttribute name="soId">SalesOrderID</JPAAttribute>
+				</JPAAttributes>
+				<JPARelationships>
+					<JPARelationship name="salesOrderHeader">SalesOrderHeaderDetails</JPARelationship>
+					<JPARelationship name="materials">MaterialDetails
+					</JPARelationship>
+				</JPARelationships>
+			</JPAEntityType>
+		</JPAEntityTypes>
+		<JPAEmbeddableTypes>
+			<JPAEmbeddableType name="SalesOrderItemKey">
+				<EDMComplexType>SalesOrderLineItemKey</EDMComplexType>
+					<JPAAttributes>
+						<JPAAttribute name="liId">ID</JPAAttribute>
+						<JPAAttribute name="soId">SalesOrderID</JPAAttribute>
+					</JPAAttributes>
+			</JPAEmbeddableType>
+		</JPAEmbeddableTypes>
+	</PersistenceUnit>
+</JPAEDMMappingModel>

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/pom.xml
----------------------------------------------------------------------
diff --git a/odata-api/pom.xml b/odata-api/pom.xml
new file mode 100644
index 0000000..8d42c5d
--- /dev/null
+++ b/odata-api/pom.xml
@@ -0,0 +1,76 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>org.apache.olingo.odata2.api</artifactId>
+	<packaging>jar</packaging>
+
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>org.apache.olingo.odata2.parent</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+		<relativePath>..</relativePath>
+	</parent>
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<executions>
+					<execution>
+						<id>bundle-manifest</id>
+						<phase>process-classes</phase>
+						<goals>
+							<goal>manifest</goal>
+						</goals>
+					</execution>
+				</executions>
+				<configuration>
+					<instructions>
+						<Import-Package>
+							org.apache.olingo.odata2.core.rt;resolution:=optional,
+							*
+						</Import-Package>
+						<Export-Package>
+							org.apache.olingo.odata2.api;version=${project.version},
+							org.apache.olingo.odata2.api.*;version=${project.version}
+						</Export-Package>
+						<Bundle-DocURL>${project.url}</Bundle-DocURL>
+						<Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
+						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataCallback.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataCallback.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataCallback.java
new file mode 100644
index 0000000..e58e41d
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataCallback.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.api;
+
+/**
+ * Common OData callback interface. Every callback implementation has to implement this interface as a marker.
+ * 
+ * @author SAP AG
+ *
+ */
+public interface ODataCallback {}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataDebugCallback.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataDebugCallback.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataDebugCallback.java
new file mode 100644
index 0000000..38b5e56
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataDebugCallback.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.api;
+
+/**
+ * @author SAP AG
+ *
+ */
+public interface ODataDebugCallback extends ODataCallback {
+
+  /**
+   * Determines whether additional debug information can be retrieved
+   * from this OData service for the current request.
+   * @return <code>true</code> if the system is in debug mode
+   *         and the current user has the rights to debug the OData service
+   */
+  boolean isDebugEnabled();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataService.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataService.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataService.java
new file mode 100644
index 0000000..5579427
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataService.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * 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.api;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.part.BatchProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityComplexPropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.MetadataProcessor;
+import org.apache.olingo.odata2.api.processor.part.ServiceDocumentProcessor;
+
+/**
+ * Root interface for a custom OData service.
+ * 
+ * @author SAP AG
+ *
+ */
+public interface ODataService {
+
+  /**
+   * @return implemented OData version of this service
+   * @throws ODataException
+   * @see ODataServiceVersion
+   */
+  String getVersion() throws ODataException;
+
+  /**
+   * @return entity data model of this service 
+   * @see Edm
+   * @throws ODataException
+   */
+  Edm getEntityDataModel() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see MetadataProcessor
+   */
+  MetadataProcessor getMetadataProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see ServiceDocumentProcessor
+   */
+  ServiceDocumentProcessor getServiceDocumentProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntityProcessor
+   */
+  EntityProcessor getEntityProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntitySetProcessor
+   */
+  EntitySetProcessor getEntitySetProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntityComplexPropertyProcessor
+   */
+  EntityComplexPropertyProcessor getEntityComplexPropertyProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntityLinkProcessor
+   */
+  EntityLinkProcessor getEntityLinkProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntityLinksProcessor
+   */
+  EntityLinksProcessor getEntityLinksProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntityMediaProcessor
+   */
+  EntityMediaProcessor getEntityMediaProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntitySimplePropertyProcessor
+   */
+  EntitySimplePropertyProcessor getEntitySimplePropertyProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see EntitySimplePropertyValueProcessor
+   */
+  EntitySimplePropertyValueProcessor getEntitySimplePropertyValueProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see FunctionImportProcessor
+   */
+  FunctionImportProcessor getFunctionImportProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see FunctionImportValueProcessor
+   */
+  FunctionImportValueProcessor getFunctionImportValueProcessor() throws ODataException;
+
+  /**
+   * @return a processor which handles this request 
+   * @throws ODataException
+   * @see BatchProcessor
+   */
+  BatchProcessor getBatchProcessor() throws ODataException;
+
+  /**
+   * @return root processor interface 
+   * @throws ODataException
+   * @see ODataProcessor
+   */
+  ODataProcessor getProcessor() throws ODataException;
+
+  /**
+   * @param processorFeature 
+   * @return ordered list of all <code>content types</code> this service supports
+   * @throws ODataException
+   */
+  List<String> getSupportedContentTypes(Class<? extends ODataProcessor> processorFeature) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
new file mode 100644
index 0000000..f847cfa
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceFactory.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.api;
+
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+ * Creates instance of custom OData service.
+ * 
+ * @author SAP AG
+ */
+public abstract class ODataServiceFactory {
+
+  /**
+   * Label used in web.xml to assign servlet init parameter to factory class instance.
+   */
+  public static final String FACTORY_LABEL = "org.apache.olingo.odata2.service.factory";
+
+  /**
+   * Label used in core to access application class loader 
+   */
+  public static final String FACTORY_CLASSLOADER_LABEL = "org.apache.olingo.odata2.service.factory.classloader";
+
+  /**
+   * Label used in web.xml to assign servlet init parameter for a path split (service resolution).
+   */
+  public static final String PATH_SPLIT_LABEL = "org.apache.olingo.odata2.path.split";
+
+  /**
+   * Create instance of custom {@link ODataService}.
+   * @param ctx OData context object
+   * @return A new service instance.
+   * @throws ODataException in case of error
+   */
+  public abstract ODataService createService(ODataContext ctx) throws ODataException;
+
+  /**
+   * Create a default service instance based on </code>ODataSingleProcessor<code>.
+   * @param provider A custom <code>EdmProvider</code> implementation.
+   * @param processor A custom processor implementation derived from <code>ODataSingleProcessor</code> .
+   * @return A new default <code>ODataSingleProcessorService</code> instance.
+   */
+  public ODataService createODataSingleProcessorService(final EdmProvider provider, final ODataSingleProcessor processor) {
+    return RuntimeDelegate.createODataSingleProcessorService(provider, processor);
+  }
+
+  /**
+   * A service can return implementation classes for various callback interfaces.
+   * @param callbackInterface a interface type to query for implementation
+   * @return a callback implementation for this interface or null
+   */
+  public <T extends ODataCallback> T getCallback(final Class<? extends ODataCallback> callbackInterface) {
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceVersion.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceVersion.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceVersion.java
new file mode 100644
index 0000000..bf3d42e
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/ODataServiceVersion.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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.api;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * This class is a container for the supported ODataServiceVersions.
+ * @author SAP AG
+ *
+ */
+public class ODataServiceVersion {
+
+  private static final Pattern DATASERVICEVERSIONPATTERN = Pattern.compile("(\\p{Digit}+\\.\\p{Digit}+)(:?;.*)?");
+
+  /**
+   * ODataServiceVersion 1.0
+   */
+  public static final String V10 = "1.0";
+  /**
+   * ODataServiceVersion 2.0
+   */
+  public static final String V20 = "2.0";
+  /**
+   * ODataServiceVersion 3.0
+   */
+  public static final String V30 = "3.0";
+
+  /**
+   * Validates format and range of a data service version string.
+   * @param version version string
+   * @return <code>true</code> for a valid version
+   */
+  public static boolean validateDataServiceVersion(final String version) {
+    final Matcher matcher = DATASERVICEVERSIONPATTERN.matcher(version);
+    if (matcher.matches()) {
+      final String possibleDataServiceVersion = matcher.group(1);
+      return V10.equals(possibleDataServiceVersion)
+          || V20.equals(possibleDataServiceVersion)
+          || V30.equals(possibleDataServiceVersion);
+    } else {
+      throw new IllegalArgumentException(version);
+    }
+  }
+
+  /**
+   * actual > comparedTo
+   * @param actual
+   * @param comparedTo
+   * @return <code>true</code> if actual is bigger than comparedTo
+   */
+  public static boolean isBiggerThan(final String actual, final String comparedTo) {
+    if (!validateDataServiceVersion(comparedTo) || !validateDataServiceVersion(actual)) {
+      throw new IllegalArgumentException("Illegal arguments: " + comparedTo + " and " + actual);
+    }
+
+    final double me = Double.parseDouble(extractDataServiceVersionString(actual));
+    final double other = Double.parseDouble(extractDataServiceVersionString(comparedTo));
+
+    return me > other;
+  }
+
+  private static String extractDataServiceVersionString(final String rawDataServiceVersion) {
+    if (rawDataServiceVersion != null) {
+      final String[] pattern = rawDataServiceVersion.split(";");
+      return pattern[0];
+    }
+
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
new file mode 100644
index 0000000..6511f22
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchException.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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.api.batch;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+
+public class BatchException extends ODataMessageException {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+
+  /** INVALID_CHANGESET_BOUNDARY requires 1 content value ('line number') */
+  public static final MessageReference INVALID_CHANGESET_BOUNDARY = createMessageReference(BatchException.class, "INVALID_CHANGESET_BOUNDARY");
+
+  /** INVALID_BOUNDARY_DELIMITER requires 1 content value ('line number')*/
+  public static final MessageReference INVALID_BOUNDARY_DELIMITER = createMessageReference(BatchException.class, "INVALID_BOUNDARY_DELIMITER");
+
+  /** MISSING_BOUNDARY_DELIMITER requires 1 content value('line number') */
+  public static final MessageReference MISSING_BOUNDARY_DELIMITER = createMessageReference(BatchException.class, "MISSING_BOUNDARY_DELIMITER");
+
+  /** MISSING_CLOSE_DELIMITER requires 1 content value ('line number') */
+  public static final MessageReference MISSING_CLOSE_DELIMITER = createMessageReference(BatchException.class, "MISSING_CLOSE_DELIMITER");
+
+  /** INVALID_QUERY_OPERATION_METHOD requires 1 content value ('line number') */
+  public static final MessageReference INVALID_QUERY_OPERATION_METHOD = createMessageReference(BatchException.class, "INVALID_QUERY_OPERATION_METHOD");
+
+  /** INVALID_CHANGESET_METHOD requires 1 content value ('line number') */
+  public static final MessageReference INVALID_CHANGESET_METHOD = createMessageReference(BatchException.class, "INVALID_CHANGESET_METHOD");
+
+  /** INVALID_QUERY_PARAMETER requires no content value */
+  public static final MessageReference INVALID_QUERY_PARAMETER = createMessageReference(BatchException.class, "INVALID_QUERY_PARAMETER");
+
+  /** INVALID_URI requires no content value */
+  public static final MessageReference INVALID_URI = createMessageReference(BatchException.class, "INVALID_URI");
+
+  /** INVALID_BOUNDARY requires 1 content value('line number') */
+  public static final MessageReference INVALID_BOUNDARY = createMessageReference(BatchException.class, "INVALID_BOUNDARY");
+
+  /** NO_MATCH_WITH_BOUNDARY_STRING requires 2 content value ('required boundary', 'line number') */
+  public static final MessageReference NO_MATCH_WITH_BOUNDARY_STRING = createMessageReference(BatchException.class, "NO_MATCH_WITH_BOUNDARY_STRING");
+
+  /** MISSING_CONTENT_TYPE requires no content value */
+  public static final MessageReference MISSING_CONTENT_TYPE = createMessageReference(BatchException.class, "MISSING_CONTENT_TYPE");
+
+  /** INVALID_CONTENT_TYPE requires 1 content value ('required content-type') */
+  public static final MessageReference INVALID_CONTENT_TYPE = createMessageReference(BatchException.class, "INVALID_CONTENT_TYPE");
+
+  /** MISSING_PARAMETER_IN_CONTENT_TYPE requires no content value */
+  public static final MessageReference MISSING_PARAMETER_IN_CONTENT_TYPE = createMessageReference(BatchException.class, "MISSING_PARAMETER_IN_CONTENT_TYPE");
+
+  /** INVALID_HEADER requires 1 content value ('header', 'line number') */
+  public static final MessageReference INVALID_HEADER = createMessageReference(BatchException.class, "INVALID_HEADER");
+
+  /** INVALID_ACCEPT_HEADER requires 1 content value ('header') */
+  public static final MessageReference INVALID_ACCEPT_HEADER = createMessageReference(BatchException.class, "INVALID_ACCEPT_HEADER");
+
+  /** INVALID_ACCEPT_LANGUAGE_HEADER requires 1 content value ('header') */
+  public static final MessageReference INVALID_ACCEPT_LANGUAGE_HEADER = createMessageReference(BatchException.class, "INVALID_ACCEPT_LANGUAGE_HEADER");
+
+  /** INVALID_CONTENT_TRANSFER_ENCODING requires no content value */
+  public static final MessageReference INVALID_CONTENT_TRANSFER_ENCODING = createMessageReference(BatchException.class, "INVALID_CONTENT_TRANSFER_ENCODING");
+
+  /** MISSING_BLANK_LINE requires 2 content value ('supplied line','line number') */
+  public static final MessageReference MISSING_BLANK_LINE = createMessageReference(BatchException.class, "MISSING_BLANK_LINE");
+
+  /** INVALID_PATHINFO requires no content value */
+  public static final MessageReference INVALID_PATHINFO = createMessageReference(BatchException.class, "INVALID_PATHINFO");
+
+  /** MISSING_METHOD requires 1 content value ('request line') */
+  public static final MessageReference MISSING_METHOD = createMessageReference(BatchException.class, "MISSING_METHOD");
+
+  /** INVALID_REQUEST_LINE requires 2 content value ('request line', 'line number') */
+  public static final MessageReference INVALID_REQUEST_LINE = createMessageReference(BatchException.class, "INVALID_REQUEST_LINE");
+
+  /** TRUNCETED_BODY requires 1 content value ('line number') */
+  public static final MessageReference TRUNCATED_BODY = createMessageReference(BatchException.class, "TRUNCATED_BODY");
+
+  public BatchException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public BatchException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  public BatchException(final MessageReference messageReference, final String errorCode) {
+    super(messageReference, errorCode);
+  }
+
+  public BatchException(final MessageReference messageReference, final Throwable cause, final String errorCode) {
+    super(messageReference, cause, errorCode);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
new file mode 100644
index 0000000..2066690
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchHandler.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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.api.batch;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+/**
+ * @author SAP AG
+ */
+public interface BatchHandler {
+  /**
+   * <p>Handles the {@link BatchPart} in a way that it results in a corresponding {@link BatchResponsePart}.</p>
+   * @param batchPart the incoming batchPart
+   * @return the corresponding result
+   * @throws ODataException
+   */
+  public BatchResponsePart handleBatchPart(BatchPart batchPart) throws ODataException;
+
+  /**
+   * <p>Delegates a handling of the request {@link ODataRequest} to the request handler and provides ODataResponse {@link ODataResponse}.</p>
+   * @param request the incoming request
+   * @return the corresponding result
+   * @throws ODataException
+   */
+  public ODataResponse handleRequest(ODataRequest request) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java
new file mode 100644
index 0000000..0c8eace
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchPart.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.api.batch;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+
+/**
+ * A BatchPart
+ * <p> BatchPart represents a distinct MIME part of a Batch Request body. It can be ChangeSet or Query Operation
+ * @author SAP AG
+ */
+public interface BatchPart {
+
+  /**
+   * Get the info if a BatchPart is a ChangeSet
+   * @return true or false
+   */
+  public boolean isChangeSet();
+
+  /**
+   * Get requests. If a BatchPart is a Query Operation, the list contains one request.
+   * @return a list of {@link ODataRequest}
+   */
+  public List<ODataRequest> getRequests();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchResponsePart.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchResponsePart.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchResponsePart.java
new file mode 100644
index 0000000..58822fa
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/batch/BatchResponsePart.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.api.batch;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.rt.RuntimeDelegate;
+
+/**
+* A BatchResponsePart
+* <p> BatchResponsePart represents a distinct part of a Batch Response body. It can be a ChangeSet response or a response to a retrieve request
+* @author SAP AG
+*/
+public abstract class BatchResponsePart {
+
+  /**
+   * Get responses. If a BatchResponsePart is a response to a retrieve request, the list consists of one response.
+   * @return a list of {@link ODataResponse}
+   */
+  public abstract List<ODataResponse> getResponses();
+
+  /**
+   * Get the info if a BatchResponsePart is a ChangeSet response
+   * @return true or false
+   */
+  public abstract boolean isChangeSet();
+
+  /**
+   * 
+   * @param responses a list of {@link ODataResponse}
+   * @return a builder object
+   */
+  public static BatchResponsePartBuilder responses(final List<ODataResponse> responses) {
+    return newBuilder().responses(responses);
+  }
+
+  /**
+   * @param isChangeSet true if a BatchResponsePart is a ChangeSet response
+   * @return a builder object
+   */
+  public static BatchResponsePartBuilder changeSet(final boolean isChangeSet) {
+    return newBuilder().changeSet(isChangeSet);
+  }
+
+  /**
+   * @return returns a new builder object
+   */
+  public static BatchResponsePartBuilder newBuilder() {
+    return BatchResponsePartBuilder.newInstance();
+  }
+
+  /**
+   * Implementation of the builder pattern to create instances of this type of object. 
+   * @author SAP AG
+   */
+  public static abstract class BatchResponsePartBuilder {
+    public abstract BatchResponsePart build();
+
+    private static BatchResponsePartBuilder newInstance() {
+      return RuntimeDelegate.createBatchResponsePartBuilder();
+    }
+
+    public abstract BatchResponsePartBuilder responses(List<ODataResponse> responses);
+
+    public abstract BatchResponsePartBuilder changeSet(boolean isChangeSet);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpContentType.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpContentType.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpContentType.java
new file mode 100644
index 0000000..12c0b60
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpContentType.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.api.commons;
+
+/**
+ * Constants for <code>Http Content Type</code> definitions as specified in 
+ * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html">RFC 2616 Section 14</a>.
+ * @author SAP AG
+ */
+public interface HttpContentType {
+
+  public static final String APPLICATION_XML = "application/xml";
+  public static final String APPLICATION_XML_UTF8 = APPLICATION_XML + ";charset=utf-8";
+
+  public static final String APPLICATION_ATOM_XML = "application/atom+xml";
+  public static final String APPLICATION_ATOM_XML_UTF8 = APPLICATION_ATOM_XML + ";charset=utf-8";
+  public static final String APPLICATION_ATOM_XML_ENTRY = APPLICATION_ATOM_XML + ";type=entry";
+  public static final String APPLICATION_ATOM_XML_ENTRY_UTF8 = APPLICATION_ATOM_XML_ENTRY + ";charset=utf-8";
+  public static final String APPLICATION_ATOM_XML_FEED = APPLICATION_ATOM_XML + ";type=feed";
+  public static final String APPLICATION_ATOM_XML_FEED_UTF8 = APPLICATION_ATOM_XML_FEED + ";charset=utf-8";
+  public static final String APPLICATION_ATOM_SVC = "application/atomsvc+xml";
+  public static final String APPLICATION_ATOM_SVC_UTF8 = APPLICATION_ATOM_SVC + ";charset=utf-8";
+
+  public static final String APPLICATION_JSON = "application/json";
+  public static final String APPLICATION_JSON_UTF8 = APPLICATION_JSON + ";charset=utf-8";
+  public static final String APPLICATION_JSON_UTF8_VERBOSE = APPLICATION_JSON_UTF8 + ";odata=verbose";
+
+  public static final String TEXT_PLAIN = "text/plain";
+  public static final String TEXT_PLAIN_UTF8 = TEXT_PLAIN + ";charset=utf-8";
+
+  public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
+
+  public static final String APPLICATION_HTTP = "application/http";
+
+  public static final String MULTIPART_MIXED = "multipart/mixed";
+
+  public static final String WILDCARD = "*/*";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpHeaders.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpHeaders.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpHeaders.java
new file mode 100644
index 0000000..5ee27c6
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpHeaders.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * 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.api.commons;
+
+/**
+ * HTTP header constants
+ * @author SAP AG
+ *
+ */
+public interface HttpHeaders {
+
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1">HTTP/1.1 documentation</a>}.
+   */
+  public static final String ACCEPT = "Accept";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.2">HTTP/1.1 documentation</a>}.
+   */
+  public static final String ACCEPT_CHARSET = "Accept-Charset";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3">HTTP/1.1 documentation</a>}.
+   */
+  public static final String ACCEPT_ENCODING = "Accept-Encoding";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4">HTTP/1.1 documentation</a>}.
+   */
+  public static final String ACCEPT_LANGUAGE = "Accept-Language";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.7">HTTP/1.1 documentation</a>}.
+   */
+  public static final String ALLOW = "Allow";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.8">HTTP/1.1 documentation</a>}.
+   */
+  public static final String AUTHORIZATION = "Authorization";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9">HTTP/1.1 documentation</a>}.
+   */
+  public static final String CACHE_CONTROL = "Cache-Control";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11">HTTP/1.1 documentation</a>}.
+   */
+  public static final String CONTENT_ENCODING = "Content-Encoding";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.12">HTTP/1.1 documentation</a>}.
+   */
+  public static final String CONTENT_LANGUAGE = "Content-Language";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13">HTTP/1.1 documentation</a>}.
+   */
+  public static final String CONTENT_LENGTH = "Content-Length";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.14">HTTP/1.1 documentation</a>}.
+   */
+  public static final String CONTENT_LOCATION = "Content-Location";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">HTTP/1.1 documentation</a>}.
+   */
+  public static final String CONTENT_TYPE = "Content-Type";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.18">HTTP/1.1 documentation</a>}.
+   */
+  public static final String DATE = "Date";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.19">HTTP/1.1 documentation</a>}.
+   */
+  public static final String ETAG = "ETag";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21">HTTP/1.1 documentation</a>}.
+   */
+  public static final String EXPIRES = "Expires";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.23">HTTP/1.1 documentation</a>}.
+   */
+  public static final String HOST = "Host";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.24">HTTP/1.1 documentation</a>}.
+   */
+  public static final String IF_MATCH = "If-Match";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25">HTTP/1.1 documentation</a>}.
+   */
+  public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26">HTTP/1.1 documentation</a>}.
+   */
+  public static final String IF_NONE_MATCH = "If-None-Match";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.28">HTTP/1.1 documentation</a>}.
+   */
+  public static final String IF_UNMODIFIED_SINCE = "If-Unmodified-Since";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.29">HTTP/1.1 documentation</a>}.
+   */
+  public static final String LAST_MODIFIED = "Last-Modified";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30">HTTP/1.1 documentation</a>}.
+   */
+  public static final String LOCATION = "Location";
+  /**
+   * See {@link <a href="http://tools.ietf.org/html/rfc5988#page-6">Web Linking (IETF RFC-5988) documentation</a>}.
+   */
+  public static final String LINK = "Link";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.37">HTTP/1.1 documentation</a>}.
+   */
+  public static final String RETRY_AFTER = "Retry-After";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43">HTTP/1.1 documentation</a>}.
+   */
+  public static final String USER_AGENT = "User-Agent";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44">HTTP/1.1 documentation</a>}.
+   */
+  public static final String VARY = "Vary";
+  /**
+   * See {@link <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.47">HTTP/1.1 documentation</a>}.
+   */
+  public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
+  /**
+   * See {@link <a href="http://www.ietf.org/rfc/rfc2109.txt">IETF RFC 2109</a>}.
+   */
+  public static final String COOKIE = "Cookie";
+  /**
+   * See {@link <a href="http://www.ietf.org/rfc/rfc2109.txt">IETF RFC 2109</a>}.
+   */
+  public static final String SET_COOKIE = "Set-Cookie";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpStatusCodes.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpStatusCodes.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpStatusCodes.java
new file mode 100644
index 0000000..4b42156
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/commons/HttpStatusCodes.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.api.commons;
+
+/**
+ * HTTP status codes as defined in RFC2616-sec10
+ * and additional status codes as defined in RFC6585
+ * @author SAP AG
+ */
+public enum HttpStatusCodes {
+
+  OK(200, "OK"), CREATED(201, "Created"), ACCEPTED(202, "Accepted"), NO_CONTENT(204, "No Content"), RESET_CONTENT(205, "Reset Content"), PARTIAL_CONTENT(206, "Partial Content"),
+
+  MOVED_PERMANENTLY(301, "Moved Permanently"), FOUND(302, "Found"), SEE_OTHER(303, "See Other"), NOT_MODIFIED(304, "Not Modified"), USE_PROXY(305, "Use Proxy"), TEMPORARY_REDIRECT(307, "Temporary Redirect"),
+
+  BAD_REQUEST(400, "Bad Request"), UNAUTHORIZED(401, "Unauthorized"), PAYMENT_REQUIRED(402, "Payment Required"), FORBIDDEN(403, "Forbidden"), NOT_FOUND(404, "Not Found"), METHOD_NOT_ALLOWED(405, "Method Not Allowed"), NOT_ACCEPTABLE(406, "Not Acceptable"), PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"), REQUEST_TIMEOUT(408, "Request Timeout"), CONFLICT(409, "Conflict"), GONE(410, "Gone"), LENGTH_REQUIRED(411, "Length Required"), PRECONDITION_FAILED(412, "Precondition Failed"), REQUEST_ENTITY_TOO_LARGE(413, "Request Entity Too Large"), REQUEST_URI_TOO_LONG(414, "Request-URI Too Long"), UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"), REQUESTED_RANGE_NOT_SATISFIABLE(416, "Requested Range Not Satisfiable"), EXPECTATION_FAILED(417, "Expectation Failed"), PRECONDITION_REQUIRED(428, "Precondition Required"),
+
+  INTERNAL_SERVER_ERROR(500, "Internal Server Error"), NOT_IMPLEMENTED(501, "Not Implemented"), BAD_GATEWAY(502, "Bad Gateway"), SERVICE_UNAVAILABLE(503, "Service Unavailable"), GATEWAY_TIMEOUT(504, "Gateway Timeout"), HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported");
+
+  private final int code;
+  private final String info;
+
+  HttpStatusCodes(final int statusCode, final String info) {
+    code = statusCode;
+    this.info = info;
+  }
+
+  /**
+   * Convert a numerical status code into the corresponding status enum object.
+   *
+   * @param statusCode the numerical status code
+   * @return the matching status enum object or null if no matching enum is defined
+   */
+  public static HttpStatusCodes fromStatusCode(final int statusCode) {
+    for (final HttpStatusCodes s : HttpStatusCodes.values()) {
+      if (s.code == statusCode) {
+        return s;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Get the associated status code.
+   *
+   * @return the status code.
+   */
+  public int getStatusCode() {
+    return code;
+  }
+
+  /**
+   * Get the status code info.
+   *
+   * @return the status code info
+   */
+  public String getInfo() {
+    return toString();
+  }
+
+  /**
+   * Get the status code info.
+   *
+   * @return the status code info
+   */
+  @Override
+  public String toString() {
+    return info;
+  }
+
+}


[49/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPQLBuilderFactory.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPQLBuilderFactory.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPQLBuilderFactory.java
new file mode 100644
index 0000000..5f664f6
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/JPQLBuilderFactory.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.factory;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext.JPAMethodContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder;
+
+/**
+ * Factory interface for creating following instances
+ * 
+ * <p>
+ * <ul>
+ * <li>JPQL statement builders of type
+ * {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder}
+ * </li>
+ * <li>JPQL context builder of type
+ * {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder}
+ * </li>
+ * </ul>
+ * </p>
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory
+ */
+public interface JPQLBuilderFactory {
+  /**
+   * The method returns JPQL statement builder for building JPQL statements.
+   * 
+   * @param context
+   *            is
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext}
+   *            that determines the type of JPQL statement builder. The
+   *            parameter cannot be null.
+   * @return an instance of JPQLStatementBuilder
+   */
+  public JPQLStatementBuilder getStatementBuilder(JPQLContextView context);
+
+  /**
+   * The method returns a JPQL context builder for building JPQL Context
+   * object.
+   * 
+   * @param contextType
+   *            is
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType}
+   *            that determines the type of JPQL context builder. The
+   *            parameter cannot be null.
+   * @return an instance of JPQLContextBuilder
+   */
+  public JPQLContextBuilder getContextBuilder(JPQLContextType contextType);
+
+  /**
+   * The method returns a JPA method context builder for building JPA Method
+   * context object.
+   * 
+   * @param contextType
+   *            is
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType}
+   *            that determines the type of JPQL context builder. The
+   *            parameter cannot be null.
+   * @return an instance of JPAMethodContextBuilder
+   */
+  public JPAMethodContextBuilder getJPAMethodContextBuilder(
+      JPQLContextType contextType);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAAccessFactory.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAAccessFactory.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAAccessFactory.java
new file mode 100644
index 0000000..072a069
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAAccessFactory.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.factory;
+
+import java.util.Locale;
+
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.processor.ODataSingleProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAMessageService;
+
+/**
+ * Factory interface for creating following instances
+ * 
+ * <p>
+ * <ul>
+ * <li>OData JPA Processor of type
+ * {@link org.apache.olingo.odata2.api.processor.ODataSingleProcessor}</li>
+ * <li>JPA EDM Provider of type
+ * {@link org.apache.olingo.odata2.api.edm.provider.EdmProvider}</li>
+ * <li>OData JPA Context
+ * {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}</li>
+ * </ul>
+ * </p>
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory
+ */
+public interface ODataJPAAccessFactory {
+  /**
+   * The method creates an OData JPA Processor. The processor handles runtime
+   * behavior of an OData service.
+   * 
+   * @param oDataJPAContext
+   *            an instance of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}.
+   *            The context should be initialized properly and cannot be null.
+   * @return An implementation of OData JPA Processor.
+   */
+  public ODataSingleProcessor createODataProcessor(
+      ODataJPAContext oDataJPAContext);
+
+  /**
+   * 
+   * @param oDataJPAContext
+   *            an instance of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}.
+   *            The context should be initialized properly and cannot be null.
+   * @return An implementation of JPA EdmProvider. EdmProvider handles
+   *         meta-data.
+   */
+  public EdmProvider createJPAEdmProvider(ODataJPAContext oDataJPAContext);
+
+  /**
+   * The method creates an instance of OData JPA Context. An empty instance is
+   * returned.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext}
+   */
+  public ODataJPAContext createODataJPAContext();
+
+  /**
+   * The method creates an instance of message service for loading language
+   * dependent message text.
+   * 
+   * @param locale
+   *            is the language in which the message service should load
+   *            message texts.
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAMessageService}
+   */
+  public ODataJPAMessageService getODataJPAMessageService(Locale locale);
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAFactory.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAFactory.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAFactory.java
new file mode 100644
index 0000000..0f538c1
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/ODataJPAFactory.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.factory;
+
+/**
+ * The class is an abstract factory for creating default ODataJPAFactory. The
+ * class's actual implementation is responsible for creating other factory
+ * implementations.The class creates factories implementing interfaces
+ * <ul>
+ * <li>{@link org.apache.olingo.odata2.processor.api.jpa.factory.JPAAccessFactory}</li>
+ * <li>{@link org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory}</li>
+ * <li>{@link org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory}</li>
+ * </ul>
+ * 
+ * <b>Note: </b>Extend this class only if you don't require library's default
+ * factory implementation.
+ * <p>
+ * 
+ * @author SAP AG
+ * 
+ * 
+ * 
+ */
+public abstract class ODataJPAFactory {
+
+  private static final String IMPLEMENTATION = "org.apache.olingo.odata2.processor.core.jpa.factory.ODataJPAFactoryImpl";
+  private static ODataJPAFactory factoryImpl;
+
+  /**
+   * Method creates a factory instance. The instance returned is singleton.
+   * The instance of this factory can be used for creating other factory
+   * implementations.
+   * 
+   * @return instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory}
+   *         .
+   */
+  public static ODataJPAFactory createFactory() {
+
+    if (factoryImpl != null) {
+      return factoryImpl;
+    } else {
+      try {
+        Class<?> clazz = Class.forName(ODataJPAFactory.IMPLEMENTATION);
+
+        Object object = clazz.newInstance();
+        factoryImpl = (ODataJPAFactory) object;
+
+      } catch (Exception e) {
+        throw new RuntimeException(e);
+      }
+
+      return factoryImpl;
+    }
+  }
+
+  /**
+   * The method returns a null reference to JPQL Builder Factory. Override
+   * this method to return an implementation of JPQLBuilderFactory if default
+   * implementation from library is not required.
+   * 
+   * @return instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory}
+   */
+  public JPQLBuilderFactory getJPQLBuilderFactory() {
+    return null;
+  };
+
+  /**
+   * The method returns a null reference to JPA Access Factory. Override this
+   * method to return an implementation of JPAAccessFactory if default
+   * implementation from library is not required.
+   * 
+   * @return instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory}
+   */
+  public JPAAccessFactory getJPAAccessFactory() {
+    return null;
+  };
+
+  /**
+   * The method returns a null reference to OData JPA Access Factory. Override
+   * this method to return an implementation of ODataJPAAccessFactory if
+   * default implementation from library is not required.
+   * 
+   * @return instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAAccessFactory}
+   */
+  public ODataJPAAccessFactory getODataJPAAccessFactory() {
+    return null;
+  };
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/package-info.java
new file mode 100644
index 0000000..6c785eb
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/factory/package-info.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library - Factory</h3>
+ * The library provides different types of factories for creating instances for
+ * <ul>
+ * <li>Accessing Java Persistence Model/Data</li>
+ * <li>Building different types of JPQL statements</li>
+ * <li>Accessing OData EDM provider and processor</li>
+ * </ul>
+ * 
+ * The instances of these factories can be obtained from an abstract ODataJPAFactory.
+ * 
+ * @author SAP AG
+ */
+package org.apache.olingo.odata2.processor.api.jpa.factory;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContext.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContext.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContext.java
new file mode 100644
index 0000000..c227a86
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContext.java
@@ -0,0 +1,211 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+
+/**
+ * The abstract class is a compilation of objects required for building
+ * {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement}. Extend this
+ * class to implement specific implementations of JPQL context types (Select,
+ * Join). A JPQL Context is constructed from an OData
+ * request. Depending on OData CRUD operation performed on an Entity, a
+ * corresponding JPQL context object is built. The JPQL context object thus
+ * built can be used for constructing JPQL statements. <br>
+ * A default implementation is provided by the library.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory
+ * 
+ */
+public abstract class JPQLContext implements JPQLContextView {
+
+  /**
+   * An alias for Java Persistence Entity
+   */
+  protected String jpaEntityAlias;
+  /**
+   * Java Persistence Entity name
+   */
+  protected String jpaEntityName;
+  /**
+   * The type of JPQL context. Based on the type JPQL statements can be built.
+   */
+  protected JPQLContextType type;
+
+  /**
+   * sets JPA Entity Name into the context
+   * 
+   * @param jpaEntityName
+   *            is the name of JPA Entity
+   */
+  protected final void setJPAEntityName(final String jpaEntityName) {
+    this.jpaEntityName = jpaEntityName;
+  }
+
+  /**
+   * sets JPA Entity alias name into the context
+   * 
+   * @param jpaEntityAlias
+   *            is the JPA entity alias name
+   */
+  protected final void setJPAEntityAlias(final String jpaEntityAlias) {
+    this.jpaEntityAlias = jpaEntityAlias;
+  }
+
+  /**
+   * gets the JPA entity alias name set into the context
+   */
+  @Override
+  public final String getJPAEntityAlias() {
+    return jpaEntityAlias;
+  }
+
+  /**
+   * sets the JPQL context type into the context
+   * 
+   * @param type
+   *            is JPQLContextType
+   */
+  protected final void setType(final JPQLContextType type) {
+    this.type = type;
+  }
+
+  /**
+   * gets the JPA entity name set into the context
+   */
+  @Override
+  public final String getJPAEntityName() {
+    return jpaEntityName;
+  }
+
+  /**
+   * gets the JPQL context type set into the context
+   */
+  @Override
+  public final JPQLContextType getType() {
+    return type;
+  }
+
+  /**
+   * the method returns an instance of type
+   * {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder}
+   * based on the JPQLContextType. The context builder can be used for
+   * building different JPQL contexts.
+   * 
+   * @param contextType
+   *            is the JPQLContextType
+   * @param resultsView
+   *            is the OData request view
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder}
+   * @throws ODataJPARuntimeException
+   */
+  public final static JPQLContextBuilder createBuilder(
+      final JPQLContextType contextType, final Object resultsView)
+      throws ODataJPARuntimeException {
+    return JPQLContextBuilder.create(contextType, resultsView);
+  }
+
+  /**
+   * The abstract class is extended by specific JPQLContext builder for
+   * building JPQLContexts.
+   * 
+   * @author SAP AG
+   * 
+   */
+  public static abstract class JPQLContextBuilder {
+    /**
+     * alias counter is an integer counter that is incremented by "1" for
+     * every new alias name generation. The value of counter is used in the
+     * generation of JPA entity alias names.
+     */
+    protected int aliasCounter = 0;
+
+    protected JPQLContextBuilder() {}
+
+    /**
+     * the method instantiates an instance of type JPQLContextBuilder.
+     * 
+     * @param contextType
+     *            indicates the type of JPQLContextBuilder to instantiate.
+     * @param resultsView
+     *            is the OData request view
+     * @return an instance of type
+     *         {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext.JPQLContextBuilder}
+     * @throws ODataJPARuntimeException
+     */
+    private static JPQLContextBuilder create(final JPQLContextType contextType,
+        final Object resultsView) throws ODataJPARuntimeException {
+      JPQLContextBuilder contextBuilder = ODataJPAFactory.createFactory()
+          .getJPQLBuilderFactory().getContextBuilder(contextType);
+      if (contextBuilder == null) {
+        throw ODataJPARuntimeException
+            .throwException(
+                ODataJPARuntimeException.ERROR_JPQLCTXBLDR_CREATE,
+                null);
+      }
+      contextBuilder.setResultsView(resultsView);
+      return contextBuilder;
+    }
+
+    /**
+     * The abstract method is implemented by specific JPQL context builders
+     * to build JPQL Contexts. The build method makes use of information set
+     * into the context to built JPQL Context Types.
+     * 
+     * @return an instance of
+     *         {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext}
+     * @throws ODataJPAModelException
+     * @throws ODataJPARuntimeException
+     */
+    public abstract JPQLContext build() throws ODataJPAModelException,
+        ODataJPARuntimeException;
+
+    /**
+     * The abstract method is implemented by specific JPQL context builder.
+     * The method sets the OData request view into the JPQL context.
+     * 
+     * @param resultsView
+     *            is an instance representing OData request.
+     */
+    protected abstract void setResultsView(Object resultsView);
+
+    /**
+     * The method resets the alias counter value to "0".
+     */
+    protected void resetAliasCounter() {
+      aliasCounter = 0;
+    }
+
+    /**
+     * The method returns a system generated alias name starting with prefix
+     * "E" and ending with suffix "aliasCounter".
+     * 
+     * @return a String representing JPA entity alias name
+     */
+    protected String generateJPAEntityAlias() {
+      return new String("E" + ++aliasCounter);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextType.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextType.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextType.java
new file mode 100644
index 0000000..3a379b7
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextType.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+/**
+ * Enumerated list of JPQL context Types.
+ * 
+ * @author SAP AG
+ * 
+ */
+public enum JPQLContextType {
+  /**
+   * indicates that the JPQL context can be used for building JPQL select
+   * statements
+   */
+  SELECT,
+  /**
+   * indicates that the JPQL context can be used for building JPQL modify
+   * statements
+   */
+  MODIFY,
+  /**
+   * indicates that the JPQL context can be used for building JPQL delete
+   * statements
+   */
+  DELETE,
+  /**
+   * indicates that the JPQL context can be used for building JPQL select
+   * statement that fetches single record
+   */
+  SELECT_SINGLE,
+  /**
+   * indicates that the JPQL context can be used for building JPQL join
+   * statement
+   */
+  JOIN,
+  /**
+   * indicates that the JPQL context can be used for building JPQL join
+   * statement that fetches single record
+   */
+  JOIN_SINGLE,
+  /**
+   * indicates that the JPQL context can be used for building JPQL select
+   * statement that fetches record counts
+   */
+  SELECT_COUNT,
+  /**
+   * indicates that the JPQL context can be used for building JPQL join
+   * statement that fetches single record
+   */
+  JOIN_COUNT,
+  /**
+   * indicates that the JPQL context can be used for building JPA Method
+   * context that can be used for invoking custom functions
+   */
+  FUNCTION
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextView.java
new file mode 100644
index 0000000..0d907b0
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLContextView.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+/**
+ * The interface provides a view on JPQL Context. The view can be used to access
+ * different JPQL context type implementations.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType
+ */
+public interface JPQLContextView {
+  /**
+   * The method returns a JPA entity name for which the JPQL context is
+   * relevant.
+   * 
+   * @return JPA entity name
+   */
+  public String getJPAEntityName();
+
+  /**
+   * The method returns a JPA entity alias name for which the JPQL context is
+   * relevant.
+   * 
+   * @return JPA entity alias name
+   */
+
+  public String getJPAEntityAlias();
+
+  /**
+   * The method returns a JPQL context type
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType}
+   */
+  public JPQLContextType getType();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinContextView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinContextView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinContextView.java
new file mode 100644
index 0000000..7227da7
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinContextView.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+
+/**
+ * The interface provide a view on JPQL Join context.The interface provides
+ * methods for accessing the Join Clause which can be part of JPQL Select
+ * statement. The interface extends the JPQL Select Context to add JQPL Join
+ * clauses to the Select statement. The JPQL Join context view is built from
+ * OData read entity set with navigation request.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLSelectContextView
+ * 
+ */
+public interface JPQLJoinContextView extends JPQLSelectContextView {
+  /**
+   * The method returns a list of JPA Join Clauses. The returned list of
+   * values can be used for building JPQL Statements with Join clauses.
+   * 
+   * @return a list of
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause}
+   */
+  public List<JPAJoinClause> getJPAJoinClauses();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinSelectSingleContextView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinSelectSingleContextView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinSelectSingleContextView.java
new file mode 100644
index 0000000..de923d0
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLJoinSelectSingleContextView.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause;
+
+/**
+ * The interface provide a view on JPQL Join Clauses.The interface is an
+ * extension to JPQL select single context and provides methods for accessing
+ * JPQL Join clauses. The view can be used for building JPQL statements without
+ * any WHERE,ORDERBY clauses. The clauses are built from OData read entity
+ * request views.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLSelectSingleContextView
+ * 
+ */
+public interface JPQLJoinSelectSingleContextView extends
+    JPQLSelectSingleContextView {
+
+  /**
+   * The method returns a list of JPA Join Clauses. The returned list of
+   * values can be used for building JPQL Statements with Join clauses.
+   * 
+   * @return a list of
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAJoinClause}
+   */
+  public abstract List<JPAJoinClause> getJPAJoinClauses();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectContextView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectContextView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectContextView.java
new file mode 100644
index 0000000..3958c9f
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectContextView.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+import java.util.HashMap;
+
+/**
+ * The interface provide a view on JPQL select context.The interface provides
+ * methods for accessing the clauses of a JPQL SELECT statement like "SELECT",
+ * "ORDERBY", "WHERE". The clauses are built from OData read entity set request
+ * views. The clauses thus built can be used for building JPQL Statements.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement
+ * 
+ */
+public interface JPQLSelectContextView extends JPQLContextView {
+  /**
+   * The method returns a JPQL SELECT clause. The SELECT clause is built from
+   * $select OData system Query option.
+   * 
+   * @return a String representing a SELECT clause in JPQL
+   */
+  public String getSelectExpression();
+
+  /**
+   * The method returns a Hash Map of JPQL ORDERBY clause. The ORDERBY clause
+   * is built from $orderby OData system query option. The hash map contains
+   * <ol>
+   * <li>Key - JPA Entity Property name to be ordered</li>
+   * <li>Value - Sort Order in JPQL (desc,asc)</li>
+   * </ol>
+   * 
+   * @return a hash map of (JPA Property Name,Sort Order)
+   */
+  public HashMap<String, String> getOrderByCollection();
+
+  /**
+   * The method returns a JPQL WHERE condition as string. The WHERE condition
+   * can be built from $filter OData System Query Option and/or Key predicates
+   * of an OData Request.
+   * 
+   * @return a String representing a WHERE condition in JPQL
+   */
+  public String getWhereExpression();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectSingleContextView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectSingleContextView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectSingleContextView.java
new file mode 100644
index 0000000..68c73ff
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLSelectSingleContextView.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+
+/**
+ * The interface provide a view on JPQL select single context.The interface
+ * provides methods for accessing the clause of a JPQL SELECT statement like
+ * "SELECT". The view can be used for building JPQL statements without any
+ * WHERE,JOIN,ORDERBY clauses. The clauses are built from OData read entity
+ * request views.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement
+ * 
+ */
+public interface JPQLSelectSingleContextView extends JPQLContextView {
+  /**
+   * The method returns a JPQL SELECT clause. The SELECT clause is built from
+   * $select OData system Query option.
+   * 
+   * @return a String representing a SELECT clause in JPQL
+   */
+  public String getSelectExpression();
+
+  /**
+   * The method returns the list of key predicates that can be used for
+   * constructing the WHERE clause in JPQL statements. The OData entity key
+   * predicates are thus converted into JPA entity keys.
+   * 
+   * @return a list of key predicates
+   */
+  public List<KeyPredicate> getKeyPredicates();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLStatement.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLStatement.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLStatement.java
new file mode 100644
index 0000000..934fe02
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/JPQLStatement.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.jpql;
+
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.factory.ODataJPAFactory;
+
+/**
+ * The class represents a Java Persistence Query Language (JPQL) Statement. 
+ * The JPQL statement is built using a builder namely 
+ * {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement.JPQLStatementBuilder}
+ * . Based upon the JPQL Context types (
+ * {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType} different
+ * kinds of JPQL statements are built. 
+ * The JPQL statements thus generated can be executed using JPA Query APIs to fetch JPA entities.
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.factory.JPQLBuilderFactory
+ * @see org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView
+ */
+public class JPQLStatement {
+
+  protected String statement;
+
+  /**
+   * The method is used for creating an instance of JPQL Statement Builder for
+   * building JPQL statements. The JPQL Statement builder is created based
+   * upon the JPQL Context.
+   * 
+   * @param context
+   *            a non null value of
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextView}
+   *            . The context is expected to be set to be built with no
+   *            errors.
+   * @return an instance of JPQL statement builder
+   * @throws ODataJPARuntimeException
+   */
+  public static JPQLStatementBuilder createBuilder(final JPQLContextView context)
+      throws ODataJPARuntimeException {
+    return JPQLStatementBuilder.create(context);
+  }
+
+  private JPQLStatement(final String statement) {
+    this.statement = statement;
+  }
+
+  /**
+   * The method provides a String representation of JPQLStatement.
+   */
+  @Override
+  public String toString() {
+    return statement;
+  }
+
+  /**
+   * The abstract class is extended by specific JPQL statement builders for
+   * building JPQL statements like
+   * <ol>
+   * <li>Select statements</li>
+   * <li>Select single statements</li>
+   * <li>Select statements with Join</li>
+   * <li>Insert/Modify/Delete statements</li>
+   * </ol>
+   * 
+   * A default statement builder for building each kind of JPQL statements is
+   * provided by the library.
+   * 
+   * @author SAP AG
+   * 
+   */
+  public static abstract class JPQLStatementBuilder {
+
+    protected JPQLStatementBuilder() {}
+
+    private static final JPQLStatementBuilder create(final JPQLContextView context)
+        throws ODataJPARuntimeException {
+      return ODataJPAFactory.createFactory().getJPQLBuilderFactory()
+          .getStatementBuilder(context);
+    }
+
+    protected final JPQLStatement createStatement(final String statement) {
+      return new JPQLStatement(statement);
+    }
+
+    /**
+     * The abstract method is implemented by specific statement builder for
+     * building JPQL Statement.
+     * 
+     * @return an instance of
+     *         {@link org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement}
+     * @throws ODataJPARuntimeException
+     *             in case there are errors building the statements
+     */
+    public abstract JPQLStatement build() throws ODataJPARuntimeException;
+
+  }
+
+  public static final class Operator {
+    public static final String EQ = "=";
+    public static final String NE = "<>";
+    public static final String LT = "<";
+    public static final String LE = "<=";
+    public static final String GT = ">";
+    public static final String GE = ">=";
+    public static final String AND = "AND";
+    public static final String NOT = "NOT";
+    public static final String OR = "OR";
+
+  }
+
+  public static final class KEYWORD {
+    public static final String SELECT = "SELECT";
+    public static final String FROM = "FROM";
+    public static final String WHERE = "WHERE";
+    public static final String LEFT_OUTER_JOIN = "LEFT OUTER JOIN";
+    public static final String OUTER = "OUTER";
+    public static final String JOIN = "JOIN";
+    public static final String ORDERBY = "ORDER BY";
+    public static final String COUNT = "COUNT";
+    public static final String OFFSET = ".000";
+    public static final String TIMESTAMP = "ts";
+
+  }
+
+  public static final class DELIMITER {
+    public static final char SPACE = ' ';
+    public static final char COMMA = ',';
+    public static final char PERIOD = '.';
+    public static final char PARENTHESIS_LEFT = '(';
+    public static final char PARENTHESIS_RIGHT = ')';
+    public static final char COLON = ':';
+    public static final char HYPHEN = '-';
+    public static final char LEFT_BRACE = '{';
+    public static final char RIGHT_BRACE = '}';
+    public static final char LONG = 'L';
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/package-info.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/package-info.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/package-info.java
new file mode 100644
index 0000000..b03bd31
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/jpql/package-info.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <h3>OData JPA Processor API Library - Java Persistence Query Language</h3>
+ * The library provides set of APIs for building JPQL contexts from OData Requests.
+ * The JPQL contexts thus built can be used for building JPQL Statements.
+ * 
+ * @author SAP AG
+ */
+package org.apache.olingo.odata2.processor.api.jpa.jpql;
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationEndView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationEndView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationEndView.java
new file mode 100644
index 0000000..e9b0d40
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationEndView.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+
+/**
+ * <p>
+ * A view on Java Persistence Entity Relationship and Entity Data Model
+ * Association End.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM Association Ends
+ * created from Java Persistence Entity Relationships. The implementation acts
+ * as a container for Association Ends.
+ * </p>
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView
+ * 
+ */
+public interface JPAEdmAssociationEndView extends JPAEdmBaseView {
+
+  /**
+   * The method gets the one of the association ends present in the container.
+   * 
+   * @return one of the
+   *         {@link org.apache.olingo.odata2.api.edm.provider.AssociationEnd} for an
+   *         {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   */
+  AssociationEnd getEdmAssociationEnd2();
+
+  /**
+   * The method gets the other association end present in the container.
+   * 
+   * @return one of the
+   *         {@link org.apache.olingo.odata2.api.edm.provider.AssociationEnd} for an
+   *         {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   */
+  AssociationEnd getEdmAssociationEnd1();
+
+  /**
+   * The method compares two ends {<b>end1, end2</b>} of an
+   * {@link org.apache.olingo.odata2.api.edm.provider.AssociationEnd} against its
+   * two ends.
+   * 
+   * The Method compares the following properties in each end for equality <i>
+   * <ul>
+   * <li>{@link org.apache.olingo.odata2.api.edm.FullQualifiedName} of End Type</li>
+   * <li>{@link org.apache.olingo.odata2.api.edm.EdmMultiplicity} of End</li>
+   * </ul>
+   * </i>
+   * 
+   * @param end1
+   *            one end of type
+   *            {@link org.apache.olingo.odata2.api.edm.provider.AssociationEnd} of
+   *            an {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   * @param end2
+   *            other end of type
+   *            {@link org.apache.olingo.odata2.api.edm.provider.AssociationEnd} of
+   *            an {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   *            <p>
+   * @return <ul>
+   *         <li><i>true</i> - Only if the properties of <b>end1</b> matches
+   *         with all the properties of any one end and only if the properties
+   *         of <b>end2</b> matches with all the properties of the remaining
+   *         end</li> <li><i>false</i> - Otherwise</li>
+   *         </ul>
+   */
+  boolean compare(AssociationEnd end1, AssociationEnd end2);
+
+  String getJoinColumnName();
+
+  String getJoinColumnReferenceColumnName();
+
+  String getMappedByName();
+
+  String getOwningPropertyName();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationSetView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationSetView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationSetView.java
new file mode 100644
index 0000000..86bf6fc
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationSetView.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+
+/**
+ * <p>
+ * A view on Java Persistence Entity Relationship and Entity Data Model
+ * Association Set.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM Association Set created
+ * from Java Persistence Entity Relationship. The implementation act as a
+ * container for list of association sets that are consistent.
+ * </p>
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView
+ */
+public interface JPAEdmAssociationSetView extends JPAEdmBaseView {
+
+  /**
+   * The method returns a consistent list of association sets. An association
+   * set is set to be consistent only if all its mandatory properties can be
+   * completely built from a Java Persistence Relationship.
+   * 
+   * @return a consistent list of {@link org.apache.olingo.odata2.api.edm.provider.AssociationSet}
+   * 
+   */
+  List<AssociationSet> getConsistentEdmAssociationSetList();
+
+  /**
+   * The method returns an association set that is currently being processed.
+   * 
+   * @return an instance of type {@link org.apache.olingo.odata2.api.edm.provider.AssociationSet}
+   */
+  AssociationSet getEdmAssociationSet();
+
+  /**
+   * The method returns an association from which the association set is
+   * currently being processed.
+   * 
+   * @return an instance of type {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   */
+  Association getEdmAssociation();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationView.java
new file mode 100644
index 0000000..07ab135
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmAssociationView.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.Association;
+
+/**
+ * <p>
+ * A View on Java Persistence Entity Relationship and Entity Data Model
+ * Association.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to EDM Association created
+ * from Java Persistence Entity Relationships. The implementation acts as a
+ * container for list of association that are consistent.
+ * 
+ * An Association is said to be consistent only
+ * <ol>
+ * <li>If both the Ends of Association are consistent</li>
+ * <li>If referential constraint exists for the Association then it should be
+ * consistent</li>
+ * </ol>
+ * </p>
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView
+ * 
+ */
+public interface JPAEdmAssociationView extends JPAEdmBaseView {
+
+  /**
+   * The method returns an association which is currently being processed.
+   * 
+   * @return an {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   */
+  public Association getEdmAssociation();
+
+  /**
+   * The method returns a consistent list of associations. An association is
+   * set to be consistent only if all its mandatory properties can be
+   * completely built from a Java Persistence Relationship.
+   * 
+   * @return a consistent list of
+   *         {@link org.apache.olingo.odata2.api.edm.provider.Association}
+   * 
+   */
+  public List<Association> getConsistentEdmAssociationList();
+
+  /**
+   * The method adds
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}
+   * to its container
+   * 
+   * @param associationView
+   *            of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}
+   */
+  public void addJPAEdmAssociationView(JPAEdmAssociationView associationView, JPAEdmAssociationEndView associationEndView);
+
+  /**
+   * The method searches for an Association in its container against the
+   * search parameter <b>view</b> of type
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}.
+   * 
+   * The Association in the container <b>view</b> is searched against the
+   * consistent list of Association stored in this container.
+   * 
+   * @param view
+   *            of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}
+   * @return {@link org.apache.olingo.odata2.api.edm.provider.Association} if found
+   *         in the container
+   */
+  public Association searchAssociation(JPAEdmAssociationEndView view);
+
+  /**
+   * The method adds the referential constraint view to its container.
+   * <p>
+   * <b>Note: </b>The referential constraint view is added only if it exists.
+   * </p>
+   * 
+   * @param refView
+   *            of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView}
+   */
+  public void addJPAEdmRefConstraintView(
+      JPAEdmReferentialConstraintView refView);
+
+  /**
+   * The method returns the referential constraint view that is currently
+   * being processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmReferentialConstraintView}
+   */
+  public JPAEdmReferentialConstraintView getJPAEdmReferentialConstraintView();
+
+  /**
+   * The method searches for the number of associations with similar endpoints in its container against the
+   * search parameter <b>view</b> of type
+   * {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}.
+   * 
+   * The Association in the container <b>view</b> is searched against the
+   * consistent list of Association stored in this container.
+   * 
+   * @param view
+   *            of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationView}
+   * @return {@link org.apache.olingo.odata2.api.edm.provider.Association} if found
+   *         in the container
+   */
+  int getNumberOfAssociationsWithSimilarEndPoints(JPAEdmAssociationEndView view);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmBaseView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmBaseView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmBaseView.java
new file mode 100644
index 0000000..0a01c2d
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmBaseView.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import javax.persistence.metamodel.Metamodel;
+
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+
+/**
+ * <p>
+ * A base view on Java Persistence Model and Entity Data Model.
+ * </p>
+ * <p>
+ * The implementation of the view acts as a base container for containers of
+ * Java Persistence Model and Entity Data Model elements.
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * 
+ */
+public interface JPAEdmBaseView {
+  /**
+   * 
+   * @return Java Persistence Unit Name
+   */
+  public String getpUnitName();
+
+  /**
+   * The method returns the Java Persistence MetaModel
+   * 
+   * @return a meta model of type
+   *         {@link javax.persistence.metamodel.Metamodel}
+   */
+  public Metamodel getJPAMetaModel();
+
+  /**
+   * The method returns a builder for building Entity Data Model elements from
+   * Java Persistence Model Elements
+   * 
+   * @return a builder of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmBuilder}
+   */
+  public JPAEdmBuilder getBuilder();
+
+  /**
+   * The method returns the if the container is consistent without any errors
+   * 
+   * @return <ul>
+   *         <li>true - if the container is consistent without errors</li>
+   *         <li>false - if the container is inconsistent with errors</li>
+   * 
+   */
+  public boolean isConsistent();
+
+  /**
+   * The method cleans the container.
+   */
+  public void clean();
+
+  /**
+   * The method returns a reference to JPA EDM mapping model access.
+   * 
+   * @return an instance to JPA EDM mapping model access
+   */
+  public JPAEdmMappingModelAccess getJPAEdmMappingModelAccess();
+
+  /**
+   * The method returns a reference to JPA EDM extension if available else
+   * null.
+   * 
+   * @return an instance of JPA Edm Extension
+   */
+  public JPAEdmExtension getJPAEdmExtension();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexPropertyView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexPropertyView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexPropertyView.java
new file mode 100644
index 0000000..27d8afe
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexPropertyView.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+
+/**
+ * <p>
+ * A view on properties of Java Persistence embeddable type and EDM complex
+ * type. Properties of JPA embeddable types are converted into EDM properties of
+ * EDM complex type.
+ * </p>
+ * <p>
+ * The implementation of the view provides access to properties of EDM complex
+ * type created for a given JPA EDM complex type. The implementation acts as a
+ * container for the properties of EDM complex type.
+ * </p>
+ * 
+ * @author SAP AG
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView
+ */
+public interface JPAEdmComplexPropertyView extends JPAEdmBaseView {
+  /**
+   * The method returns a complex property for a complex type.
+   * 
+   * @return an instance of
+   *         {@link org.apache.olingo.odata2.api.edm.provider.ComplexProperty}
+   */
+  ComplexProperty getEdmComplexProperty();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexTypeView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexTypeView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexTypeView.java
new file mode 100644
index 0000000..8ee0b25
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmComplexTypeView.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+
+/**
+ * A view on Java Persistence embeddable types and EDM complex types. Java
+ * persistence embeddable types are converted into EDM entity types. Only those
+ * embeddable types that are
+ * <ol>
+ * <li>used in a java persistence Entity type</li>
+ * <li>used as non embeddable id of a java persistence entity type</li>
+ * </ol>
+ * are converted into EDM complex types.
+ * <p>
+ * The implementation of the view provides access to EDM complex types for the
+ * given JPA EDM model. The view acts as a container for consistent list of EDM
+ * complex types. An EDM complex type is said to be consistent only if it used
+ * in at least one of the EDM entity type.
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexPropertyView
+ * 
+ */
+public interface JPAEdmComplexTypeView extends JPAEdmBaseView {
+
+  /**
+   * The method returns an EDM complex type that is currently being processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.ComplexType}
+   */
+  public ComplexType getEdmComplexType();
+
+  /**
+   * The method returns an JPA embeddable type that is currently being
+   * processed.
+   * 
+   * @return an instance of type
+   *         {@link javax.persistence.metamodel.EmbeddableType}
+   */
+  public javax.persistence.metamodel.EmbeddableType<?> getJPAEmbeddableType();
+
+  /**
+   * The method returns a consistent list of EDM complex types.
+   * 
+   * @return a list of {@link org.apache.olingo.odata2.api.edm.provider.ComplexType}
+   */
+  public List<ComplexType> getConsistentEdmComplexTypes();
+
+  /**
+   * The method searches for the EDM complex type with in the container for
+   * the given JPA embeddable type name.
+   * 
+   * @param embeddableTypeName
+   *            is the name of JPA embeddable type
+   * @return a reference to EDM complex type if found else null
+   */
+  public ComplexType searchEdmComplexType(String embeddableTypeName);
+
+  /**
+   * The method add a JPA EDM complex type view to the container.
+   * 
+   * @param view
+   *            is an instance of type
+   *            {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmComplexTypeView}
+   */
+  public void addJPAEdmCompleTypeView(JPAEdmComplexTypeView view);
+
+  /**
+   * The method searches for the EDM complex type with in the container for
+   * the given EDM complex type's fully qualified name.
+   * 
+   * @param type
+   *            is the fully qualified name of EDM complex type
+   * @return a reference to EDM complex type if found else null
+   */
+  public ComplexType searchEdmComplexType(FullQualifiedName type);
+
+  /**
+   * The method expands the given EDM complex type into a list of EDM simple
+   * properties.
+   * 
+   * @param complexType
+   *            is the EDM complex type to expand
+   * @param expandedPropertyList
+   *            is the list to be populated with expanded EDM simple
+   *            properties
+   * @param embeddablePropertyName
+   *            is the name of the complex property. The name is used as the
+   *            qualifier for the expanded simple property names.
+   */
+  public void expandEdmComplexType(ComplexType complexType,
+      List<Property> expandedPropertyList, String embeddablePropertyName);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityContainerView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityContainerView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityContainerView.java
new file mode 100644
index 0000000..00f5eaf
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityContainerView.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.EntityContainer;
+
+/**
+ * A view on JPA EDM entity container. JPA EDM entity container is built from
+ * consistent JPA EDM entity set and consistent JPA EDM association set views.
+ * 
+ * <p>
+ * The implementation of the view provides access to EDM entity containers. The
+ * view acts as container for JPA EDM entity containers. A JPA EDM entity
+ * container is said to be consistent only if the JPA EDM association set and
+ * JPA EDM Entity Set view are consistent.
+ * 
+ * @author SAP AG
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView
+ * 
+ */
+public interface JPAEdmEntityContainerView extends JPAEdmBaseView {
+  /**
+   * The method returns the EDM entity container that is currently being
+   * processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.EntityContainer}
+   */
+  public EntityContainer getEdmEntityContainer();
+
+  /**
+   * The method returns a list of consistent EDM entity containers
+   * 
+   * @return a list of consistent EDM entity containers
+   */
+  public List<EntityContainer> getConsistentEdmEntityContainerList();
+
+  /**
+   * The method returns the JPA EDM entity set view that is currently being
+   * processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntitySetView}
+   */
+  public JPAEdmEntitySetView getJPAEdmEntitySetView();
+
+  /**
+   * The method returns the JPA EDM association set view that is currently
+   * being processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmAssociationSetView}
+   */
+  public JPAEdmAssociationSetView getEdmAssociationSetView();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntitySetView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntitySetView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntitySetView.java
new file mode 100644
index 0000000..25f4557
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntitySetView.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+
+/**
+ * A view on Java Persistence entity type and EDM entity sets. Java persistence
+ * entity types are converted into EDM entity types and EDM entity sets.
+ * <p>
+ * The implementation of the view provides access to EDM entity sets for the
+ * given JPA EDM entity type. The view acts as a container for consistent list
+ * of EDM entity sets. An EDM entity set is said to be consistent only if it has
+ * consistent EDM entity types.
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView
+ * 
+ */
+public interface JPAEdmEntitySetView extends JPAEdmBaseView {
+  /**
+   * The method returns an EDM entity set that is currently being processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.EntitySet}
+   */
+  public EntitySet getEdmEntitySet();
+
+  /**
+   * The method returns a list of consistent EDM entity sets.
+   * 
+   * @return a list of EDM entity sets
+   */
+  public List<EntitySet> getConsistentEdmEntitySetList();
+
+  /**
+   * The method returns a JPA EDM entity type view that is currently being
+   * processed. JPA EDM entity set view is built from JPA EDM entity type
+   * view.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmEntityTypeView}
+   */
+  public JPAEdmEntityTypeView getJPAEdmEntityTypeView();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityTypeView.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityTypeView.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityTypeView.java
new file mode 100644
index 0000000..6a5219b
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmEntityTypeView.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+
+/**
+ * A view on Java Persistence entity types and EDM entity types. Java
+ * persistence entity types are converted into EDM entity types.
+ * <p>
+ * The implementation of the view provides access to EDM entity types for the
+ * given JPA EDM model. The view acts as a container for consistent list of EDM
+ * entity types. An EDM entity type is said to be consistent only if it has at
+ * least one consistent EDM property and at least one consistent EDM key.
+ * 
+ * @author SAP AG
+ *         <p>
+ * @DoNotImplement
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmPropertyView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmKeyView
+ * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmNavigationPropertyView
+ * 
+ */
+public interface JPAEdmEntityTypeView extends JPAEdmBaseView {
+  /**
+   * The method returns an EDM entity currently being processed.
+   * 
+   * @return an instance of type
+   *         {@link org.apache.olingo.odata2.api.edm.provider.EntityType}
+   */
+  public EntityType getEdmEntityType();
+
+  /**
+   * The method returns java persistence Entity type currently being
+   * processed.
+   * 
+   * @return an instance of type
+   *         {@link javax.persistence.metamodel.EntityType}
+   */
+  public javax.persistence.metamodel.EntityType<?> getJPAEntityType();
+
+  /**
+   * The method returns a consistent list of EDM entity types for a given java
+   * persistence meta model.
+   * 
+   * @return a list of {@link org.apache.olingo.odata2.api.edm.provider.EntityType}
+   */
+  public List<EntityType> getConsistentEdmEntityTypes();
+
+  /**
+   * The method searches in the consistent list of EDM entity types for the
+   * given EDM entity type's name.
+   * 
+   * @param jpaEntityTypeName
+   *            is the name of EDM entity type
+   * @return a reference to EDM entity type if found else null
+   */
+  public EntityType searchEdmEntityType(String jpaEntityTypeName);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmExtension.java
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmExtension.java b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmExtension.java
new file mode 100644
index 0000000..4294741
--- /dev/null
+++ b/jpa-api/src/main/java/org/apache/olingo/odata2/processor/api/jpa/model/JPAEdmExtension.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.processor.api.jpa.model;
+
+/**
+ * The interface provides methods to extend JPA EDM containers.
+ * 
+ * @author SAP AG
+ * 
+ */
+public interface JPAEdmExtension {
+  /**
+   * The method is used to extend the JPA EDM schema view. Use this method to
+   * register custom operations.
+   * 
+   * @param view
+   *            is the schema view
+   * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView#registerOperations(Class,
+   *      String[])
+   * @deprecated Use {@link org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmExtension#extendWithOperations(JPAEdmSchemaView view)}
+   * 
+   */
+  @Deprecated
+  public void extend(JPAEdmSchemaView view);
+
+  /**
+   * The method is used to extend the JPA EDM schema view with custom operations. Use this method to
+   * register custom operations.
+   * 
+   * @param view
+   *            is the schema view
+   * @see org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmSchemaView#registerOperations(Class,
+   *      String[])
+   * 
+   */
+  public void extendWithOperation(JPAEdmSchemaView view);
+
+  /**
+   * The method is used to extend the JPA EDM schema view with Entities, Entity Sets, Navigation Property and Association. 
+   * 
+   * @param view
+   *            is the schema view
+   * 
+   */
+  public void extendJPAEdmSchema(JPAEdmSchemaView view);
+
+}


[46/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java
new file mode 100644
index 0000000..72e81fa
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java
@@ -0,0 +1,423 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+
+public final class JPAEntityParser {
+
+  /*
+   * List of buffers used by the Parser
+   */
+  private static short MAX_SIZE = 10;
+  public static final String ACCESS_MODIFIER_GET = "get";
+  public static final String ACCESS_MODIFIER_SET = "set";
+
+  private HashMap<String, HashMap<String, Method>> jpaEntityAccessMap = null;
+  private HashMap<String, HashMap<String, String>> jpaEmbeddableKeyMap = null;
+
+  private static JPAEntityParser jpaEntityParser;
+
+  private JPAEntityParser() {
+    jpaEntityAccessMap = new HashMap<String, HashMap<String, Method>>(
+        MAX_SIZE);
+    jpaEmbeddableKeyMap = new HashMap<String, HashMap<String, String>>();
+  };
+
+  public static final JPAEntityParser create() {
+    if (jpaEntityParser == null) {
+      jpaEntityParser = new JPAEntityParser();
+    }
+    return jpaEntityParser;
+  }
+
+  /**
+   * The method returns a Hash Map of Properties and values for selected
+   * properties of an EdmEntity Type
+   * 
+   * @param jpaEntity
+   * @param selectedItems
+   * @return a Hash Map of Properties and values for given selected properties
+   *         of an EdmEntity Type
+   * @throws ODataJPARuntimeException
+   */
+
+  public final HashMap<String, Object> parse2EdmPropertyValueMap(
+      final Object jpaEntity, final List<EdmProperty> selectPropertyList)
+      throws ODataJPARuntimeException {
+    HashMap<String, Object> edmEntity = new HashMap<String, Object>();
+    String methodName = null;
+    Method method = null;
+    for (int i = 0; i < selectPropertyList.size(); i++) {
+      String key = null;
+      Object propertyValue = null;
+      EdmProperty property = null;
+      property = selectPropertyList.get(i);
+
+      try {
+        methodName = getAccessModifierName(property.getName(),
+            property.getMapping(), ACCESS_MODIFIER_GET);
+        String[] nameParts = methodName.split("\\.");
+        if (nameParts.length > 1) {
+          Object propertyVal = new Object();
+          propertyVal = jpaEntity;
+          for (String namePart : nameParts) {
+            method = propertyVal.getClass().getMethod(
+                namePart, (Class<?>[]) null);
+            method.setAccessible(true);
+            propertyVal = method.invoke(propertyVal);
+          }
+          edmEntity.put(property.getName(), propertyVal);
+        } else {
+          method = jpaEntity.getClass().getMethod(methodName,
+              (Class<?>[]) null);
+          method.setAccessible(true);
+          propertyValue = method.invoke(jpaEntity);
+          key = property.getName();
+          if (property.getType().getKind()
+              .equals(EdmTypeKind.COMPLEX)) {
+            try {
+              propertyValue = parse2EdmPropertyValueMap(
+                  propertyValue,
+                  (EdmStructuralType) property.getType());
+            } catch (ODataJPARuntimeException e) {
+              throw e;
+            }
+          }
+          edmEntity.put(key, propertyValue);
+        }
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (SecurityException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (NoSuchMethodException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (IllegalArgumentException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (IllegalAccessException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (InvocationTargetException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      }
+    }
+
+    return edmEntity;
+  }
+
+  /**
+   * The method returns a Hash Map of Properties and values for an EdmEntity
+   * Type The method uses reflection on object jpaEntity to get the list of
+   * accessModifier method. Then uses the accessModifier method to extract the value from
+   * JPAEntity.
+   * 
+   * @param jpaEntity
+   * @param structuralType
+   * @return a Hash Map of Properties and values for given EdmEntity Type
+   * @throws ODataJPARuntimeException
+   */
+  public final HashMap<String, Object> parse2EdmPropertyValueMap(
+      final Object jpaEntity, final EdmStructuralType structuralType)
+      throws ODataJPARuntimeException {
+
+    if (jpaEntity == null || structuralType == null) {
+      return null;
+    }
+
+    String jpaEntityAccessKey = jpaEntity.getClass().getName();
+
+    if (!jpaEntityAccessMap.containsKey(jpaEntityAccessKey)) {
+      jpaEntityAccessMap.put(jpaEntityAccessKey,
+          getAccessModifier(jpaEntity, structuralType, ACCESS_MODIFIER_GET));
+    }
+
+    HashMap<String, Object> edmEntity = new HashMap<String, Object>();
+    HashMap<String, Method> getters = jpaEntityAccessMap
+        .get(jpaEntityAccessKey);
+    HashMap<String, String> embeddableKeys = jpaEmbeddableKeyMap
+        .get(jpaEntityAccessKey);
+
+    try {
+      for (String key : getters.keySet()) {
+
+        EdmProperty property = (EdmProperty) structuralType
+            .getProperty(key);
+
+        Method method = getters.get(key);
+        Object propertyValue = null;
+
+        if (method != null) {
+          getters.get(key).setAccessible(true);
+          propertyValue = getters.get(key).invoke(jpaEntity);
+        }
+
+        if (property.getType().getKind().equals(EdmTypeKind.COMPLEX)) {
+          propertyValue = parse2EdmPropertyValueMap(propertyValue,
+              (EdmStructuralType) property.getType());
+        }
+
+        edmEntity.put(key, propertyValue);
+
+      }
+
+      if (embeddableKeys != null) {
+        for (String key : embeddableKeys.keySet()) {
+          String name = embeddableKeys.get(key);
+          String[] nameParts = name.split("\\.");
+          Object propertyValue = jpaEntity;
+          Method method = null;
+          for (String namePart : nameParts) {
+            method = propertyValue.getClass().getMethod(
+                namePart, (Class<?>[]) null);
+            method.setAccessible(true);
+            propertyValue = method.invoke(propertyValue);
+          }
+          edmEntity.put(key, propertyValue);
+        }
+      }
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (SecurityException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (NoSuchMethodException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    return edmEntity;
+  }
+
+  // This method appends the associated entities as a java list to an expanded
+  // map of a source entity
+  public final HashMap<String, Object> parse2EdmNavigationValueMap(
+      final Object jpaEntity, final List<EdmNavigationProperty> navigationPropertyList)
+      throws ODataJPARuntimeException {
+    Object result = null;
+    String methodName = null;
+    HashMap<String, Object> navigationMap = new HashMap<String, Object>();
+    if (navigationPropertyList != null
+        && navigationPropertyList.size() != 0) {
+
+      try {
+        for (EdmNavigationProperty navigationProperty : navigationPropertyList) {
+          methodName = getAccessModifierName(navigationProperty.getName(),
+              navigationProperty.getMapping(), ACCESS_MODIFIER_GET);
+          Method getterMethod = jpaEntity.getClass()
+              .getDeclaredMethod(methodName, (Class<?>[]) null);
+          getterMethod.setAccessible(true);
+          result = getterMethod.invoke(jpaEntity);
+          navigationMap.put(navigationProperty.getName(), result);
+        }
+      } catch (IllegalArgumentException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (IllegalAccessException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (InvocationTargetException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (SecurityException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (NoSuchMethodException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      }
+    }
+    return navigationMap;
+  }
+
+  public HashMap<String, Method> getAccessModifier(final Object jpaEntity,
+      final EdmStructuralType structuralType, final String accessModifier) throws ODataJPARuntimeException {
+
+    HashMap<String, Method> accessModifierMap = new HashMap<String, Method>();
+    HashMap<String, String> embeddableKey = new HashMap<String, String>();
+    try {
+      for (String propertyName : structuralType.getPropertyNames()) {
+
+        EdmProperty property = (EdmProperty) structuralType
+            .getProperty(propertyName);
+
+        String name = getAccessModifierName(property.getName(),
+            property.getMapping(), accessModifier);
+        String[] nameParts = name.split("\\.");
+        if (nameParts.length > 1) {
+          embeddableKey.put(propertyName, name);
+        } else {
+          accessModifierMap.put(
+              propertyName,
+              jpaEntity.getClass().getMethod(name,
+                  (Class<?>[]) null));
+        }
+      }
+    } catch (NoSuchMethodException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (SecurityException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    if (!embeddableKey.isEmpty()) {
+      jpaEmbeddableKeyMap.put(jpaEntity.getClass().getName(),
+          embeddableKey);
+    }
+    return accessModifierMap;
+  }
+
+  private static String getAccessModifierName(final String propertyName, final EdmMapping mapping, final String accessModifier)
+      throws ODataJPARuntimeException {
+    String name = null;
+    StringBuilder builder = new StringBuilder();
+    String[] nameParts = {};
+    if (mapping == null || mapping.getInternalName() == null) {
+      name = propertyName;
+    } else {
+      name = mapping.getInternalName();
+    }
+    if (name != null) {
+      nameParts = name.split("\\.");
+    }
+    if (nameParts.length == 1) {
+      if (name != null) {
+        char c = Character.toUpperCase(name.charAt(0));
+
+        builder.append(accessModifier).append(c).append(name.substring(1))
+            .toString();
+      }
+    } else if (nameParts.length > 1) {
+
+      for (int i = 0; i < nameParts.length; i++) {
+        name = nameParts[i];
+        char c = Character.toUpperCase(name.charAt(0));
+        if (i == 0) {
+          builder.append(accessModifier).append(c).append(name.substring(1));
+        } else {
+          builder.append(".").append(accessModifier).append(c)
+              .append(name.substring(1));
+        }
+      }
+    } else {
+      return null;
+    }
+
+    if (builder.length() > 0) {
+      return builder.toString();
+    } else {
+      return null;
+    }
+
+  }
+
+  public Method getAccessModifier(final Object jpaEntity, final EdmNavigationProperty navigationProperty, final String accessModifier)
+      throws ODataJPARuntimeException {
+
+    try {
+
+      String name = getAccessModifierName(navigationProperty.getName(),
+          navigationProperty.getMapping(), accessModifier);
+
+      Class<?>[] params = null;
+      if (accessModifier.equals(ACCESS_MODIFIER_SET)) {
+        EdmAssociationEnd end = navigationProperty.getRelationship().getEnd(navigationProperty.getToRole());
+        switch (end.getMultiplicity()) {
+        case MANY:
+          params = new Class<?>[] { List.class };
+          break;
+        case ONE:
+          params = new Class<?>[] { ((JPAEdmMapping) end.getEntityType().getMapping()).getJPAType() };
+        default:
+          break;
+        }
+      }
+      return jpaEntity.getClass().getMethod(name,
+          params);
+
+    } catch (NoSuchMethodException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (SecurityException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java
new file mode 100644
index 0000000..eb875d8
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties.ODataEntityProviderPropertiesBuilder;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteEntryContent;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent;
+import org.apache.olingo.odata2.api.ep.callback.WriteCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+public class JPAExpandCallBack implements OnWriteFeedContent, OnWriteEntryContent, ODataCallback {
+
+  private URI baseUri;
+  private List<ArrayList<NavigationPropertySegment>> expandList;
+  private EdmEntitySet nextEntitySet = null;
+
+  private JPAExpandCallBack(final URI baseUri, final List<ArrayList<NavigationPropertySegment>> expandList) {
+    super();
+    this.baseUri = baseUri;
+    this.expandList = expandList;
+  }
+
+  @Override
+  public WriteEntryCallbackResult retrieveEntryResult(
+      final WriteEntryCallbackContext context) {
+    WriteEntryCallbackResult result = new WriteEntryCallbackResult();
+    Map<String, Object> entry = context.getEntryData();
+    Map<String, Object> edmPropertyValueMap = null;
+    List<EdmNavigationProperty> currentNavPropertyList = null;
+    Map<String, ExpandSelectTreeNode> navigationLinks = null;
+    JPAEntityParser jpaResultParser = JPAEntityParser.create();
+    EdmNavigationProperty currentNavigationProperty = context.getNavigationProperty();
+    try {
+      Object inlinedEntry = entry.get(currentNavigationProperty.getName());
+      if (nextEntitySet == null) {
+        nextEntitySet = context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty);
+      }
+      edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(inlinedEntry, nextEntitySet.getEntityType());
+      result.setEntryData(edmPropertyValueMap);
+      navigationLinks = context.getCurrentExpandSelectTreeNode().getLinks();
+      if (navigationLinks.size() > 0)
+      {
+        currentNavPropertyList = new ArrayList<EdmNavigationProperty>();
+        currentNavPropertyList.add(getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), context.getNavigationProperty()));
+        HashMap<String, Object> navigationMap = jpaResultParser.parse2EdmNavigationValueMap(inlinedEntry, currentNavPropertyList);
+        edmPropertyValueMap.putAll(navigationMap);
+        result.setEntryData(edmPropertyValueMap);
+      }
+      result.setInlineProperties(getInlineEntityProviderProperties(context));
+    } catch (EdmException e) {
+
+    } catch (ODataJPARuntimeException e) {
+
+    }
+
+    return result;
+  }
+
+  @Override
+  public WriteFeedCallbackResult retrieveFeedResult(
+      final WriteFeedCallbackContext context) {
+    WriteFeedCallbackResult result = new WriteFeedCallbackResult();
+    HashMap<String, Object> inlinedEntry = (HashMap<String, Object>) context.getEntryData();
+    List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
+    Map<String, Object> edmPropertyValueMap = null;
+    JPAEntityParser jpaResultParser = JPAEntityParser.create();
+    List<EdmNavigationProperty> currentNavPropertyList = null;
+    EdmNavigationProperty currentNavigationProperty = context.getNavigationProperty();
+    try {
+      @SuppressWarnings({ "unchecked" })
+      List<Object> listOfItems = (List<Object>) inlinedEntry.get(context.getNavigationProperty().getName());
+      if (nextEntitySet == null) {
+        nextEntitySet = context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty);
+      }
+      for (Object object : listOfItems)
+      {
+        edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(object, nextEntitySet.getEntityType());
+        edmEntityList.add(edmPropertyValueMap);
+      }
+      result.setFeedData(edmEntityList);
+      if (context.getCurrentExpandSelectTreeNode().getLinks().size() > 0)
+      {
+        currentNavPropertyList = new ArrayList<EdmNavigationProperty>();
+        currentNavPropertyList.add(getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), context.getNavigationProperty()));
+        int count = 0;
+        for (Object object : listOfItems)
+        {
+          HashMap<String, Object> navigationMap = jpaResultParser.parse2EdmNavigationValueMap(object, currentNavPropertyList);
+          edmEntityList.get(count).putAll(navigationMap);
+          count++;
+        }
+        result.setFeedData(edmEntityList);
+      }
+      result.setInlineProperties(getInlineEntityProviderProperties(context));
+    } catch (EdmException e) {
+
+    } catch (ODataJPARuntimeException e) {
+
+    }
+    return result;
+  }
+
+  private EdmNavigationProperty getNextNavigationProperty(
+      final EdmEntityType sourceEntityType, final EdmNavigationProperty navigationProperty) throws EdmException {
+    int count;
+    for (ArrayList<NavigationPropertySegment> navPropSegments : expandList)
+    {
+      count = 0;
+      for (NavigationPropertySegment navPropSegment : navPropSegments)
+      {
+        EdmNavigationProperty navProperty = navPropSegment.getNavigationProperty();
+        if (navProperty.getFromRole().equalsIgnoreCase(sourceEntityType.getName()) && navProperty.getName().equals(navigationProperty.getName())) {
+          return navPropSegments.get(count + 1).getNavigationProperty();
+        } else {
+          count++;
+        }
+
+      }
+    }
+    return null;
+  }
+
+  public static <T> Map<String, ODataCallback> getCallbacks(final URI baseUri, final ExpandSelectTreeNode expandSelectTreeNode, final List<ArrayList<NavigationPropertySegment>> expandList) throws EdmException {
+    Map<String, ODataCallback> callbacks = new HashMap<String, ODataCallback>();
+
+    for (String navigationPropertyName : expandSelectTreeNode.getLinks().keySet()) {
+      callbacks.put(navigationPropertyName, new JPAExpandCallBack(baseUri, expandList));
+    }
+
+    return callbacks;
+
+  }
+
+  private EntityProviderWriteProperties getInlineEntityProviderProperties(final WriteCallbackContext context) throws EdmException {
+    ODataEntityProviderPropertiesBuilder propertiesBuilder = EntityProviderWriteProperties.serviceRoot(baseUri);
+    propertiesBuilder.callbacks(getCallbacks(baseUri, context.getCurrentExpandSelectTreeNode(), expandList));
+    propertiesBuilder.expandSelectTree(context.getCurrentExpandSelectTreeNode());
+    return propertiesBuilder.build();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java
new file mode 100644
index 0000000..ecebd48
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAFunction;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+
+public class JPAFunctionContext extends JPAMethodContext {
+
+  public class JPAFunctionContextBuilder extends JPAMethodContextBuilder {
+
+    protected GetFunctionImportUriInfo functiontView;
+    private EdmFunctionImport functionImport;
+    private EdmMapping mapping;
+
+    @Override
+    public JPAMethodContext build() throws ODataJPAModelException,
+        ODataJPARuntimeException {
+      if (functiontView != null) {
+
+        functionImport = functiontView.getFunctionImport();
+        try {
+          mapping = functionImport.getMapping();
+
+          List<JPAFunction> jpaFunctionList = new ArrayList<JPAFunction>();
+          jpaFunctionList.add(generateJPAFunction());
+          setJpaFunction(jpaFunctionList);
+          setEnclosingObject(generateEnclosingObject());
+        } catch (EdmException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (InstantiationException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (IllegalAccessException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (IllegalArgumentException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (InvocationTargetException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (NoSuchMethodException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        } catch (SecurityException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        }
+      }
+
+      return JPAFunctionContext.this;
+    }
+
+    private JPAFunction generateJPAFunction() throws EdmException,
+        NoSuchMethodException, SecurityException,
+        ODataJPAModelException, ODataJPARuntimeException {
+
+      Class<?>[] parameterTypes = getParameterTypes();
+      Method method = getMethod(parameterTypes);
+      Type returnType = getReturnType();
+      Object[] args = getAruguments();
+
+      JPAFunction jpafunction = new JPAFunction(method, parameterTypes,
+          returnType, args);
+
+      return jpafunction;
+    }
+
+    private Object[] getAruguments() throws EdmException {
+      Map<String, EdmLiteral> edmArguements = functiontView
+          .getFunctionImportParameters();
+
+      if (edmArguements == null) {
+        return null;
+      } else {
+        Object[] args = new Object[edmArguements.size()];
+        int i = 0;
+        for (String paramName : functionImport.getParameterNames()) {
+          EdmLiteral literal = edmArguements.get(paramName);
+          EdmParameter parameter = functionImport
+              .getParameter(paramName);
+          JPAEdmMapping mapping = (JPAEdmMapping) parameter
+              .getMapping();
+          args[i] = convertArguement(literal, parameter.getFacets(),
+              mapping.getJPAType());
+          i++;
+        }
+        return args;
+      }
+
+    }
+
+    private Object convertArguement(final EdmLiteral edmLiteral,
+        final EdmFacets facets, final Class<?> targetType)
+        throws EdmSimpleTypeException {
+      EdmSimpleType edmType = edmLiteral.getType();
+      Object value = edmType.valueOfString(edmLiteral.getLiteral(),
+          EdmLiteralKind.DEFAULT, facets, targetType);
+
+      return value;
+    }
+
+    private Class<?>[] getParameterTypes() throws EdmException {
+
+      Class<?>[] parameterTypes = new Class<?>[functionImport
+          .getParameterNames().size()];
+      int i = 0;
+      for (String parameterName : functionImport.getParameterNames()) {
+        EdmParameter parameter = functionImport
+            .getParameter(parameterName);
+        parameterTypes[i] = ((JPAEdmMapping) parameter.getMapping())
+            .getJPAType();
+        i++;
+      }
+
+      return parameterTypes;
+    }
+
+    private Method getMethod(final Class<?>[] parameterTypes)
+        throws NoSuchMethodException, SecurityException {
+
+      Class<?> type = ((JPAEdmMapping) mapping).getJPAType();
+      Method method;
+      method = type.getMethod(mapping.getInternalName(), parameterTypes);
+
+      return method;
+    }
+
+    private Type getReturnType() throws ODataJPAModelException,
+        ODataJPARuntimeException, EdmException {
+      return null;
+    }
+
+    private Object generateEnclosingObject() throws InstantiationException,
+        IllegalAccessException, IllegalArgumentException,
+        InvocationTargetException, NoSuchMethodException,
+        SecurityException {
+
+      Class<?> type = ((JPAEdmMapping) mapping).getJPAType();
+      Object[] params = null;
+
+      return type.getConstructor((Class<?>[]) params).newInstance(params);
+
+    }
+
+    @Override
+    protected void setResultsView(final Object resultsView) {
+      if (resultsView instanceof GetFunctionImportUriInfo) {
+        functiontView = (GetFunctionImportUriInfo) resultsView;
+      }
+
+    }
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImpl.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImpl.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImpl.java
new file mode 100644
index 0000000..5ff10b0
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImpl.java
@@ -0,0 +1,434 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAFunction;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContext;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+import org.apache.olingo.odata2.processor.core.jpa.cud.JPACreateRequest;
+import org.apache.olingo.odata2.processor.core.jpa.cud.JPALink;
+import org.apache.olingo.odata2.processor.core.jpa.cud.JPAUpdateRequest;
+
+public class JPAProcessorImpl implements JPAProcessor {
+
+  ODataJPAContext oDataJPAContext;
+  EntityManager em;
+
+  public JPAProcessorImpl(final ODataJPAContext oDataJPAContext) {
+    this.oDataJPAContext = oDataJPAContext;
+    em = oDataJPAContext.getEntityManager();
+  }
+
+  /* Process Function Import Request */
+  @SuppressWarnings("unchecked")
+  @Override
+  public List<Object> process(final GetFunctionImportUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    JPAMethodContext jpaMethodContext = JPAMethodContext.createBuilder(
+        JPQLContextType.FUNCTION, uriParserResultView).build();
+
+    List<Object> resultObj = null;
+
+    try {
+
+      JPAFunction jpaFunction = jpaMethodContext.getJPAFunctionList()
+          .get(0);
+      Method method = jpaFunction.getFunction();
+      Object[] args = jpaFunction.getArguments();
+
+      if (uriParserResultView.getFunctionImport().getReturnType()
+          .getMultiplicity().equals(EdmMultiplicity.MANY)) {
+
+        resultObj = (List<Object>) method.invoke(
+            jpaMethodContext.getEnclosingObject(), args);
+      } else {
+        resultObj = new ArrayList<Object>();
+        Object result = method.invoke(
+            jpaMethodContext.getEnclosingObject(), args);
+        resultObj.add(result);
+      }
+
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalAccessException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (InvocationTargetException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getTargetException().getMessage()), e.getTargetException());
+    }
+
+    return resultObj;
+  }
+
+  /* Process Get Entity Set Request (Query) */
+  @SuppressWarnings("unchecked")
+  @Override
+  public <T> List<T> process(final GetEntitySetUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    if (uriParserResultView.getFunctionImport() != null) {
+      return (List<T>) process((GetFunctionImportUriInfo) uriParserResultView);
+    }
+    JPQLContextType contextType = null;
+    try {
+      if (!uriParserResultView.getStartEntitySet().getName()
+          .equals(uriParserResultView.getTargetEntitySet().getName())) {
+        contextType = JPQLContextType.JOIN;
+      } else {
+        contextType = JPQLContextType.SELECT;
+      }
+
+    } catch (EdmException e) {
+      ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.GENERAL, e);
+    }
+
+    JPQLContext jpqlContext = JPQLContext.createBuilder(contextType,
+        uriParserResultView).build();
+
+    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
+        .build();
+    Query query = null;
+    try {
+      query = em.createQuery(jpqlStatement.toString());
+      // $top/$skip with $inlinecount case handled in response builder to avoid multiple DB call
+      if (uriParserResultView.getSkip() != null && uriParserResultView.getInlineCount() == null) {
+        query.setFirstResult(uriParserResultView.getSkip());
+      }
+
+      if (uriParserResultView.getTop() != null && uriParserResultView.getInlineCount() == null) {
+        if (uriParserResultView.getTop() == 0) {
+          List<T> resultList = new ArrayList<T>();
+          return resultList;
+        } else {
+          query.setMaxResults(uriParserResultView.getTop());
+        }
+      }
+      return query.getResultList();
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+  }
+
+  /* Process Get Entity Request (Read) */
+  @Override
+  public <T> Object process(GetEntityUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    JPQLContextType contextType = null;
+    try {
+      if (uriParserResultView instanceof GetEntityUriInfo) {
+        uriParserResultView = ((GetEntityUriInfo) uriParserResultView);
+        if (!((GetEntityUriInfo) uriParserResultView).getStartEntitySet().getName()
+            .equals(((GetEntityUriInfo) uriParserResultView).getTargetEntitySet().getName())) {
+          contextType = JPQLContextType.JOIN_SINGLE;
+        } else {
+          contextType = JPQLContextType.SELECT_SINGLE;
+        }
+      }
+    } catch (EdmException e) {
+      ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.GENERAL, e);
+    }
+
+    return readEntity(uriParserResultView, contextType);
+  }
+
+  /* Process $count for Get Entity Set Request */
+  @Override
+  public long process(final GetEntitySetCountUriInfo resultsView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    JPQLContextType contextType = null;
+    try {
+      if (!resultsView.getStartEntitySet().getName()
+          .equals(resultsView.getTargetEntitySet().getName())) {
+        contextType = JPQLContextType.JOIN_COUNT;
+      } else {
+        contextType = JPQLContextType.SELECT_COUNT;
+      }
+    } catch (EdmException e) {
+      ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.GENERAL, e);
+    }
+
+    JPQLContext jpqlContext = JPQLContext.createBuilder(contextType,
+        resultsView).build();
+
+    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
+        .build();
+    Query query = null;
+    try {
+
+      query = em.createQuery(jpqlStatement.toString());
+      List<?> resultList = query.getResultList();
+      if (resultList != null && resultList.size() == 1) {
+        return Long.valueOf(resultList.get(0).toString());
+      }
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+    return 0;
+  }
+
+  /* Process $count for Get Entity Request */
+  @Override
+  public long process(final GetEntityCountUriInfo resultsView) throws ODataJPAModelException, ODataJPARuntimeException {
+
+    JPQLContextType contextType = null;
+    try {
+      if (!resultsView.getStartEntitySet().getName()
+          .equals(resultsView.getTargetEntitySet().getName())) {
+        contextType = JPQLContextType.JOIN_COUNT;
+      } else {
+        contextType = JPQLContextType.SELECT_COUNT;
+      }
+    } catch (EdmException e) {
+      ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.GENERAL, e);
+    }
+
+    JPQLContext jpqlContext = JPQLContext.createBuilder(contextType,
+        resultsView).build();
+
+    JPQLStatement jpqlStatement = JPQLStatement.createBuilder(jpqlContext)
+        .build();
+    Query query = null;
+    try {
+
+      query = em.createQuery(jpqlStatement.toString());
+      List<?> resultList = query.getResultList();
+      if (resultList != null && resultList.size() == 1) {
+        return Long.valueOf(resultList.get(0).toString());
+      }
+    } catch (IllegalArgumentException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+    }
+
+    return 0;
+  }
+
+  /* Process Create Entity Request */
+  @Override
+  public <T> List<T> process(final PostUriInfo createView, final InputStream content,
+      final String requestedContentType) throws ODataJPAModelException,
+      ODataJPARuntimeException {
+
+    JPACreateRequest jpaCreateRequest = new JPACreateRequest(em
+        .getEntityManagerFactory().getMetamodel());
+    List<T> createObjectList = jpaCreateRequest.process(createView, content,
+        requestedContentType);
+    try {
+      em.getTransaction().begin();
+      Object jpaEntity = createObjectList.get(0);
+
+      JPALink link = new JPALink(oDataJPAContext);
+      link.setSourceJPAEntity(jpaEntity);
+      link.create(createView, content, requestedContentType, requestedContentType);
+      em.persist(jpaEntity);
+      if (em.contains(jpaEntity)) {
+        em.getTransaction().commit();
+        return createObjectList;
+      }
+    } catch (Exception e) {
+      em.getTransaction().rollback();
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_CREATE_REQUEST, e);
+    }
+    return null;
+  }
+
+  /* Process Update Entity Request */
+  @Override
+  public <T> Object process(PutMergePatchUriInfo updateView,
+      final InputStream content, final String requestContentType)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    JPQLContextType contextType = null;
+    try {
+      if (updateView instanceof PutMergePatchUriInfo) {
+        updateView = ((PutMergePatchUriInfo) updateView);
+        if (!((PutMergePatchUriInfo) updateView).getStartEntitySet().getName()
+            .equals(((PutMergePatchUriInfo) updateView).getTargetEntitySet().getName())) {
+          contextType = JPQLContextType.JOIN_SINGLE;
+        } else {
+          contextType = JPQLContextType.SELECT_SINGLE;
+        }
+      }
+    } catch (EdmException e) {
+      ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.GENERAL, e);
+    }
+
+    JPAUpdateRequest jpaUpdateRequest = new JPAUpdateRequest();
+    Object updateObject = readEntity(updateView, contextType);
+    try {
+      em.getTransaction().begin();
+      jpaUpdateRequest.process(updateObject, updateView, content,
+          requestContentType);
+      em.flush();
+      em.getTransaction().commit();
+    } catch (Exception e) {
+      em.getTransaction().rollback();
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.ERROR_JPQL_UPDATE_REQUEST, e);
+    }
+    return updateObject;
+  }
+
+  /* Process Delete Entity Request */
+  @Override
+  public Object process(DeleteUriInfo uriParserResultView, final String contentType)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+    JPQLContextType contextType = null;
+    try {
+      if (uriParserResultView instanceof DeleteUriInfo) {
+        uriParserResultView = ((DeleteUriInfo) uriParserResultView);
+        if (!((DeleteUriInfo) uriParserResultView).getStartEntitySet().getName()
+            .equals(((DeleteUriInfo) uriParserResultView).getTargetEntitySet().getName())) {
+          contextType = JPQLContextType.JOIN_SINGLE;
+        } else {
+          contextType = JPQLContextType.SELECT_SINGLE;
+        }
+      }
+    } catch (EdmException e) {
+      ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.GENERAL, e);
+    }
+
+    // First read the entity with read operation.
+    Object selectedObject = readEntity(uriParserResultView, contextType);
+    // Read operation done. This object would be passed on to entity manager for delete
+    if (selectedObject != null) {
+      try {
+        em.getTransaction().begin();
+        em.remove(selectedObject);
+        em.flush();
+        em.getTransaction().commit();
+      } catch (Exception e) {
+        em.getTransaction().rollback();
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.ERROR_JPQL_DELETE_REQUEST, e);
+      }
+    }
+    return selectedObject;
+  }
+
+  /* Process Get Entity Link Request */
+  @Override
+  public Object process(final GetEntityLinkUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    return this.process((GetEntityUriInfo) uriParserResultView);
+  }
+
+  /* Process Get Entity Set Link Request */
+  @Override
+  public <T> List<T> process(final GetEntitySetLinksUriInfo uriParserResultView)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+    return this.process((GetEntitySetUriInfo) uriParserResultView);
+  }
+
+  @Override
+  public void process(final PostUriInfo uriInfo,
+      final InputStream content, final String requestContentType, final String contentType)
+      throws ODataJPARuntimeException, ODataJPAModelException {
+    JPALink link = new JPALink(oDataJPAContext);
+    link.create(uriInfo, content, requestContentType, contentType);
+    link.save();
+  }
+
+  /* Common method for Read and Delete */
+  private Object readEntity(final Object uriParserResultView, final JPQLContextType contextType)
+      throws ODataJPAModelException, ODataJPARuntimeException {
+
+    Object selectedObject = null;
+
+    if (uriParserResultView instanceof DeleteUriInfo || uriParserResultView instanceof GetEntityUriInfo || uriParserResultView instanceof PutMergePatchUriInfo) {
+
+      JPQLContext selectJPQLContext = JPQLContext.createBuilder(
+          contextType, uriParserResultView).build();
+
+      JPQLStatement selectJPQLStatement = JPQLStatement.createBuilder(
+          selectJPQLContext).build();
+      Query query = null;
+      try {
+        query = em.createQuery(selectJPQLStatement.toString());
+        if (!query.getResultList().isEmpty()) {
+          selectedObject = query.getResultList().get(0);
+        }
+      } catch (IllegalArgumentException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.ERROR_JPQL_QUERY_CREATE, e);
+      }
+    }
+    return selectedObject;
+  }
+
+  @Override
+  public void process(final PutMergePatchUriInfo putUriInfo,
+      final InputStream content, final String requestContentType, final String contentType)
+      throws ODataJPARuntimeException, ODataJPAModelException {
+    JPALink link = new JPALink(oDataJPAContext);
+    link.update(putUriInfo, content, requestContentType, contentType);
+    link.save();
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/EdmTypeConvertor.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/EdmTypeConvertor.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/EdmTypeConvertor.java
new file mode 100644
index 0000000..fb07fb7
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/EdmTypeConvertor.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.UUID;
+
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+public class EdmTypeConvertor {
+
+  public static Class<?> convertToJavaType(final EdmType edmType) throws ODataJPAModelException, ODataJPARuntimeException {
+    if (edmType instanceof EdmSimpleType) {
+        EdmSimpleType edmSimpleType = (EdmSimpleType) edmType;
+        if (edmSimpleType == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()) {
+          return String.class;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance()) {
+          return Long.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Int16.getEdmSimpleTypeInstance()) {
+          return Short.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance()) {
+          return Integer.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance()) {
+          return Double.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance()) {
+          return Float.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance()) {
+          return BigDecimal.class;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance()) {
+          return byte[].class;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Byte.getEdmSimpleTypeInstance()) {
+          return Byte.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Boolean.getEdmSimpleTypeInstance()) {
+          return Boolean.TYPE;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()) {
+          return Date.class;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()) {
+          return Calendar.class;
+        }
+        else if (edmSimpleType == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()) {
+          return UUID.class;
+        }
+    }
+    throw ODataJPAModelException.throwException(ODataJPAModelException.TYPE_NOT_SUPPORTED.addContent(edmType.toString()), null);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelService.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelService.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelService.java
new file mode 100644
index 0000000..69b94de
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/model/JPAEdmMappingModelService.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.model;
+
+import java.io.InputStream;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAAttributeMapType.JPAAttribute;
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAEdmMappingModel;
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAEmbeddableTypeMapType;
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAEntityTypeMapType;
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPAPersistenceUnitMapType;
+import org.apache.olingo.odata2.processor.api.jpa.model.mapping.JPARelationshipMapType.JPARelationship;
+
+public class JPAEdmMappingModelService implements JPAEdmMappingModelAccess {
+
+  boolean mappingModelExists = true;
+  private JPAEdmMappingModel mappingModel;
+  private String mappingModelName;
+
+  public JPAEdmMappingModelService(final ODataJPAContext ctx) {
+    mappingModelName = ctx.getJPAEdmMappingModel();
+    if (mappingModelName == null) {
+      mappingModelExists = false;
+    }
+  }
+
+  @Override
+  public void loadMappingModel() {
+
+    if (mappingModelExists) {
+      JAXBContext context;
+      try {
+        context = JAXBContext.newInstance(JPAEdmMappingModel.class);
+
+        Unmarshaller unmarshaller = context.createUnmarshaller();
+        InputStream is = loadMappingModelInputStream();
+        if (is == null) {
+          mappingModelExists = false;
+          return;
+        }
+
+        mappingModel = (JPAEdmMappingModel) unmarshaller.unmarshal(is);
+
+        if (mappingModel != null) {
+          mappingModelExists = true;
+        }
+
+      } catch (JAXBException e) {
+        mappingModelExists = false;
+        ODataJPAModelException.throwException(
+            ODataJPAModelException.GENERAL, e);
+      }
+    }
+  }
+
+  @Override
+  public boolean isMappingModelExists() {
+    return mappingModelExists;
+  }
+
+  @Override
+  public JPAEdmMappingModel getJPAEdmMappingModel() {
+    return mappingModel;
+  }
+
+  @Override
+  public String mapJPAPersistenceUnit(final String persistenceUnitName) {
+
+    JPAPersistenceUnitMapType persistenceUnit = mappingModel
+        .getPersistenceUnit();
+    if (persistenceUnit.getName().equals(persistenceUnitName)) {
+      return persistenceUnit.getEDMSchemaNamespace();
+    }
+
+    return null;
+  }
+
+  @Override
+  public String mapJPAEntityType(final String jpaEntityTypeName) {
+
+    JPAEntityTypeMapType jpaEntityTypeMap = searchJPAEntityTypeMapType(jpaEntityTypeName);
+    if (jpaEntityTypeMap != null) {
+      return jpaEntityTypeMap.getEDMEntityType();
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public String mapJPAEntitySet(final String jpaEntityTypeName) {
+    JPAEntityTypeMapType jpaEntityTypeMap = searchJPAEntityTypeMapType(jpaEntityTypeName);
+    if (jpaEntityTypeMap != null) {
+      return jpaEntityTypeMap.getEDMEntitySet();
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public String mapJPAAttribute(final String jpaEntityTypeName,
+      final String jpaAttributeName) {
+    JPAEntityTypeMapType jpaEntityTypeMap = searchJPAEntityTypeMapType(jpaEntityTypeName);
+    if (jpaEntityTypeMap != null
+        && jpaEntityTypeMap.getJPAAttributes() != null) {
+      // fixing attributes
+      // removal issue
+      // from mapping
+      for (JPAAttribute jpaAttribute : jpaEntityTypeMap
+          .getJPAAttributes().getJPAAttribute()) {
+        if (jpaAttribute.getName().equals(jpaAttributeName)) {
+          return jpaAttribute.getValue();
+        }
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public String mapJPARelationship(final String jpaEntityTypeName,
+      final String jpaRelationshipName) {
+    JPAEntityTypeMapType jpaEntityTypeMap = searchJPAEntityTypeMapType(jpaEntityTypeName);
+    if (jpaEntityTypeMap != null) {
+      for (JPARelationship jpaRealtionship : jpaEntityTypeMap
+          .getJPARelationships().getJPARelationship()) {
+        if (jpaRealtionship.getName().equals(jpaRelationshipName)) {
+          return jpaRealtionship.getValue();
+        }
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public String mapJPAEmbeddableType(final String jpaEmbeddableTypeName) {
+    JPAEmbeddableTypeMapType jpaEmbeddableType = searchJPAEmbeddableTypeMapType(jpaEmbeddableTypeName);
+    if (jpaEmbeddableType != null) {
+      return jpaEmbeddableType.getEDMComplexType();
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public String mapJPAEmbeddableTypeAttribute(final String jpaEmbeddableTypeName,
+      final String jpaAttributeName) {
+    JPAEmbeddableTypeMapType jpaEmbeddableType = searchJPAEmbeddableTypeMapType(jpaEmbeddableTypeName);
+    if (jpaEmbeddableType != null && jpaEmbeddableType.getJPAAttributes() != null) {
+      for (JPAAttribute jpaAttribute : jpaEmbeddableType
+          .getJPAAttributes().getJPAAttribute()) {
+        if (jpaAttribute.getName().equals(jpaAttributeName)) {
+          return jpaAttribute.getValue();
+        }
+      }
+    }
+    return null;
+  }
+
+  private JPAEntityTypeMapType searchJPAEntityTypeMapType(
+      final String jpaEntityTypeName) {
+    for (JPAEntityTypeMapType jpaEntityType : mappingModel
+        .getPersistenceUnit().getJPAEntityTypes().getJPAEntityType()) {
+      if (jpaEntityType.getName().equals(jpaEntityTypeName)) {
+        return jpaEntityType;
+      }
+    }
+
+    return null;
+  }
+
+  private JPAEmbeddableTypeMapType searchJPAEmbeddableTypeMapType(
+      final String jpaEmbeddableTypeName) {
+    for (JPAEmbeddableTypeMapType jpaEmbeddableType : mappingModel
+        .getPersistenceUnit().getJPAEmbeddableTypes()
+        .getJPAEmbeddableType()) {
+      if (jpaEmbeddableType.getName().equals(jpaEmbeddableTypeName)) {
+        return jpaEmbeddableType;
+      }
+    }
+
+    return null;
+  }
+
+  protected InputStream loadMappingModelInputStream() {
+    InputStream is = JPAEdmMappingModelService.class.getClassLoader()
+        .getResourceAsStream("../../" + mappingModelName);
+
+    return is;
+
+  }
+
+  @Override
+  public boolean checkExclusionOfJPAEntityType(final String jpaEntityTypeName) {
+    JPAEntityTypeMapType type = searchJPAEntityTypeMapType(jpaEntityTypeName);
+    if (type != null) {
+      return type.isExclude();
+    }
+    return false;
+  }
+
+  @Override
+  public boolean checkExclusionOfJPAAttributeType(final String jpaEntityTypeName,
+      final String jpaAttributeName) {
+    JPAEntityTypeMapType type = searchJPAEntityTypeMapType(jpaEntityTypeName);
+    if (type != null && type.getJPAAttributes() != null) {
+      for (JPAAttribute jpaAttribute : type.getJPAAttributes()
+          .getJPAAttribute()) {
+        if (jpaAttribute.getName().equals(jpaAttributeName)) {
+          return jpaAttribute.isExclude();
+        }
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public boolean checkExclusionOfJPAEmbeddableType(
+      final String jpaEmbeddableTypeName) {
+    JPAEmbeddableTypeMapType type = searchJPAEmbeddableTypeMapType(jpaEmbeddableTypeName);
+    if (type != null) {
+      return type.isExclude();
+    }
+    return false;
+  }
+
+  @Override
+  public boolean checkExclusionOfJPAEmbeddableAttributeType(
+      final String jpaEmbeddableTypeName, final String jpaAttributeName) {
+    JPAEmbeddableTypeMapType type = searchJPAEmbeddableTypeMapType(jpaEmbeddableTypeName);
+    if (type != null && type.getJPAAttributes() != null) {
+      for (JPAAttribute jpaAttribute : type.getJPAAttributes()
+          .getJPAAttribute()) {
+        if (jpaAttribute.getName().equals(jpaAttributeName)) {
+          return jpaAttribute.isExclude();
+        }
+      }
+    }
+    return false;
+  }
+}


[21/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmImpl.java
new file mode 100644
index 0000000..9023704
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmImpl.java
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmServiceMetadata;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+/**
+ * @author SAP AG
+ */
+public abstract class EdmImpl implements Edm {
+
+  private Map<String, EdmEntityContainer> edmEntityContainers;
+  private Map<FullQualifiedName, EdmEntityType> edmEntityTypes;
+  private Map<FullQualifiedName, EdmComplexType> edmComplexTypes;
+  private Map<FullQualifiedName, EdmAssociation> edmAssociations;
+
+  protected EdmServiceMetadata edmServiceMetadata;
+
+  public EdmImpl(final EdmServiceMetadata edmServiceMetadata) {
+    edmEntityContainers = new HashMap<String, EdmEntityContainer>();
+    edmEntityTypes = new HashMap<FullQualifiedName, EdmEntityType>();
+    edmComplexTypes = new HashMap<FullQualifiedName, EdmComplexType>();
+    edmAssociations = new HashMap<FullQualifiedName, EdmAssociation>();
+    this.edmServiceMetadata = edmServiceMetadata;
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer(final String name) throws EdmException {
+    if (edmEntityContainers.containsKey(name)) {
+      return edmEntityContainers.get(name);
+    }
+
+    EdmEntityContainer edmEntityContainer = null;
+
+    try {
+      edmEntityContainer = createEntityContainer(name);
+      if (edmEntityContainer != null) {
+        if (name == null && edmEntityContainers.containsKey(edmEntityContainer.getName())) {
+          //ensure that the same default entity container is stored in the HashMap under null and its name 
+          edmEntityContainer = edmEntityContainers.get(edmEntityContainer.getName());
+          edmEntityContainers.put(name, edmEntityContainer);
+        } else if (edmEntityContainers.containsKey(null) && edmEntityContainers.get(null) != null && name.equals(edmEntityContainers.get(null).getName())) {
+          //ensure that the same default entity container is stored in the HashMap under null and its name        
+          edmEntityContainer = edmEntityContainers.get(null);
+          edmEntityContainers.put(name, edmEntityContainer);
+        } else {
+          edmEntityContainers.put(name, edmEntityContainer);
+        }
+      }
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.COMMON, e);
+    }
+
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmEntityType getEntityType(final String namespace, final String name) throws EdmException {
+    FullQualifiedName fqName = new FullQualifiedName(namespace, name);
+    if (edmEntityTypes.containsKey(fqName)) {
+      return edmEntityTypes.get(fqName);
+    }
+
+    EdmEntityType edmEntityType = null;
+
+    try {
+      edmEntityType = createEntityType(fqName);
+      if (edmEntityType != null) {
+        edmEntityTypes.put(fqName, edmEntityType);
+      }
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.COMMON, e);
+    }
+
+    return edmEntityType;
+  }
+
+  @Override
+  public EdmComplexType getComplexType(final String namespace, final String name) throws EdmException {
+    FullQualifiedName fqName = new FullQualifiedName(namespace, name);
+    if (edmComplexTypes.containsKey(fqName)) {
+      return edmComplexTypes.get(fqName);
+    }
+
+    EdmComplexType edmComplexType = null;
+
+    try {
+      edmComplexType = createComplexType(fqName);
+      if (edmComplexType != null) {
+        edmComplexTypes.put(fqName, edmComplexType);
+      }
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.COMMON, e);
+    }
+
+    return edmComplexType;
+  }
+
+  @Override
+  public EdmAssociation getAssociation(final String namespace, final String name) throws EdmException {
+    FullQualifiedName fqName = new FullQualifiedName(namespace, name);
+    if (edmAssociations.containsKey(fqName)) {
+      return edmAssociations.get(fqName);
+    }
+
+    EdmAssociation edmAssociation = null;
+
+    try {
+      edmAssociation = createAssociation(fqName);
+      if (edmAssociation != null) {
+        edmAssociations.put(fqName, edmAssociation);
+      }
+    } catch (ODataException e) {
+      throw new EdmException(EdmException.COMMON, e);
+    }
+
+    return edmAssociation;
+  }
+
+  @Override
+  public EdmServiceMetadata getServiceMetadata() {
+    return edmServiceMetadata;
+  }
+
+  @Override
+  public EdmEntityContainer getDefaultEntityContainer() throws EdmException {
+    return getEntityContainer(null);
+  }
+
+  protected abstract EdmEntityContainer createEntityContainer(String name) throws ODataException;
+
+  protected abstract EdmEntityType createEntityType(FullQualifiedName fqName) throws ODataException;
+
+  protected abstract EdmComplexType createComplexType(FullQualifiedName fqName) throws ODataException;
+
+  protected abstract EdmAssociation createAssociation(FullQualifiedName fqName) throws ODataException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt16.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt16.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt16.java
new file mode 100644
index 0000000..b632179
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt16.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Int16.
+ * @author SAP AG
+ */
+public class EdmInt16 extends AbstractSimpleType {
+
+  private static final EdmInt16 instance = new EdmInt16();
+
+  public static EdmInt16 getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Short.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Short valueShort;
+    try {
+      valueShort = Short.parseShort(value);
+    } catch (final NumberFormatException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+    }
+
+    if (returnType.isAssignableFrom(Short.class)) {
+      return returnType.cast(valueShort);
+    } else if (returnType.isAssignableFrom(Byte.class)) {
+      if (valueShort >= Byte.MIN_VALUE && valueShort <= Byte.MAX_VALUE) {
+        return returnType.cast(valueShort.byteValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Integer.class)) {
+      return returnType.cast(valueShort.intValue());
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueShort.longValue());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Byte || value instanceof Short) {
+      return value.toString();
+    } else if (value instanceof Integer || value instanceof Long) {
+      if (((Number) value).longValue() >= Short.MIN_VALUE && ((Number) value).longValue() <= Short.MAX_VALUE) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt32.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt32.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt32.java
new file mode 100644
index 0000000..8d3b729
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt32.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Int32.
+ * @author SAP AG
+ */
+public class EdmInt32 extends AbstractSimpleType {
+
+  private static final EdmInt32 instance = new EdmInt32();
+
+  public static EdmInt32 getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16
+        || simpleType instanceof EdmInt32;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Integer.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Integer valueInteger;
+    try {
+      valueInteger = Integer.parseInt(value);
+    } catch (final NumberFormatException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+    }
+
+    if (returnType.isAssignableFrom(Integer.class)) {
+      return returnType.cast(valueInteger);
+    } else if (returnType.isAssignableFrom(Byte.class)) {
+      if (valueInteger >= Byte.MIN_VALUE && valueInteger <= Byte.MAX_VALUE) {
+        return returnType.cast(valueInteger.byteValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Short.class)) {
+      if (valueInteger >= Short.MIN_VALUE && valueInteger <= Short.MAX_VALUE) {
+        return returnType.cast(valueInteger.shortValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueInteger.longValue());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Byte || value instanceof Short || value instanceof Integer) {
+      return value.toString();
+    } else if (value instanceof Long) {
+      if ((Long) value >= Integer.MIN_VALUE && (Long) value <= Integer.MAX_VALUE) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt64.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt64.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt64.java
new file mode 100644
index 0000000..03b0825
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmInt64.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.math.BigInteger;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Int64.
+ * @author SAP AG
+ */
+public class EdmInt64 extends AbstractSimpleType {
+
+  private static final EdmInt64 instance = new EdmInt64();
+
+  public static EdmInt64 getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16
+        || simpleType instanceof EdmInt32
+        || simpleType instanceof EdmInt64;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Long.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Long valueLong;
+    try {
+      if (literalKind == EdmLiteralKind.URI) {
+        if (value.endsWith("L") || value.endsWith("l")) {
+          valueLong = Long.parseLong(value.substring(0, value.length() - 1));
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+        }
+      } else {
+        valueLong = Long.parseLong(value);
+      }
+    } catch (final NumberFormatException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+    }
+
+    if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueLong);
+    } else if (returnType.isAssignableFrom(Byte.class)) {
+      if (valueLong >= Byte.MIN_VALUE && valueLong <= Byte.MAX_VALUE) {
+        return returnType.cast(valueLong.byteValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Short.class)) {
+      if (valueLong >= Short.MIN_VALUE && valueLong <= Short.MAX_VALUE) {
+        return returnType.cast(valueLong.shortValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(Integer.class)) {
+      if (valueLong >= Integer.MIN_VALUE && valueLong <= Integer.MAX_VALUE) {
+        return returnType.cast(valueLong.intValue());
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+      }
+    } else if (returnType.isAssignableFrom(BigInteger.class)) {
+      return returnType.cast(BigInteger.valueOf(valueLong));
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long) {
+      return value.toString();
+    } else if (value instanceof BigInteger) {
+      if (((BigInteger) value).bitLength() < Long.SIZE) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return literal + "L";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmNull.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmNull.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmNull.java
new file mode 100644
index 0000000..8f84704
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmNull.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the simple type Null.
+ * @author SAP AG
+ */
+public class EdmNull extends AbstractSimpleType {
+
+  private static final EdmNull instance = new EdmNull();
+
+  public static EdmNull getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    return this == obj || obj == null;
+  }
+
+  @Override
+  public int hashCode() {
+    return 0;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return null;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    return null;
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    return null;
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return "null";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSByte.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSByte.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSByte.java
new file mode 100644
index 0000000..fffdeb9
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSByte.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type SByte.
+ * @author SAP AG
+ */
+public class EdmSByte extends AbstractSimpleType {
+
+  private static final EdmSByte instance = new EdmSByte();
+
+  public static EdmSByte getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmSByte;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Byte.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Byte valueByte;
+    try {
+      valueByte = Byte.parseByte(value);
+    } catch (final NumberFormatException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value), e);
+    }
+
+    if (returnType.isAssignableFrom(Byte.class)) {
+      return returnType.cast(valueByte);
+    } else if (returnType.isAssignableFrom(Short.class)) {
+      return returnType.cast(valueByte.shortValue());
+    } else if (returnType.isAssignableFrom(Integer.class)) {
+      return returnType.cast(valueByte.intValue());
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueByte.longValue());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Byte) {
+      return value.toString();
+    } else if (value instanceof Short || value instanceof Integer || value instanceof Long) {
+      if (((Number) value).longValue() >= Byte.MIN_VALUE && ((Number) value).longValue() <= Byte.MAX_VALUE) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java
new file mode 100644
index 0000000..08c8c9c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSimpleTypeFacadeImpl.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+
+/**
+ * @author SAP AG
+ */
+public class EdmSimpleTypeFacadeImpl implements EdmSimpleTypeFacade {
+
+  @Override
+  public EdmLiteral parseUriLiteral(final String uriLiteral) throws EdmLiteralException {
+    if (uriLiteral == null || "null".equals(uriLiteral)) {
+      return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Null), uriLiteral);
+    }
+
+    if ("true".equals(uriLiteral) || "false".equals(uriLiteral)) {
+      return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Boolean), uriLiteral);
+    }
+
+    if (uriLiteral.length() >= 2
+        && uriLiteral.startsWith("'") && uriLiteral.endsWith("'")) {
+      try {
+        final EdmSimpleType type = getEdmSimpleType(EdmSimpleTypeKind.String);
+        return new EdmLiteral(type, type.valueOfString(uriLiteral, EdmLiteralKind.URI, null, String.class));
+      } catch (EdmSimpleTypeException e) {
+        throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(uriLiteral), e);
+      }
+    }
+
+    if (uriLiteral.matches("-?\\p{Digit}+")) {
+      try {
+        final int i = getEdmSimpleType(EdmSimpleTypeKind.Int32).valueOfString(uriLiteral, EdmLiteralKind.URI, null, Integer.class);
+        if (i == 0 || i == 1) {
+          return new EdmLiteral(getInternalEdmSimpleTypeByString("Bit"), uriLiteral);
+        }
+        if (i >= 0 && i <= Byte.MAX_VALUE) {
+          return new EdmLiteral(getInternalEdmSimpleTypeByString("Uint7"), uriLiteral);
+        }
+        if (i >= Byte.MIN_VALUE && i < 0) {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.SByte), uriLiteral);
+        } else if (i > Byte.MAX_VALUE && i <= 255) {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Byte), uriLiteral);
+        } else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Int16), uriLiteral);
+        } else {
+          return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Int32), uriLiteral);
+        }
+      } catch (EdmSimpleTypeException e) {
+        throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(uriLiteral), e);
+      }
+    }
+
+    if (uriLiteral.endsWith("L") || uriLiteral.endsWith("l")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Int64, uriLiteral, 0, 1);
+    }
+    if (uriLiteral.endsWith("M") || uriLiteral.endsWith("m")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Decimal, uriLiteral, 0, 1);
+    }
+    if (uriLiteral.endsWith("D") || uriLiteral.endsWith("d")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Double, uriLiteral, 0, 1);
+    }
+    if (uriLiteral.equals("-INF") || uriLiteral.equals("INF") || uriLiteral.equals("NaN")) {
+      return new EdmLiteral(getEdmSimpleType(EdmSimpleTypeKind.Single), uriLiteral);
+    }
+    if (uriLiteral.endsWith("F") || uriLiteral.endsWith("f")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Single, uriLiteral, 0, 1);
+    }
+
+    if (uriLiteral.startsWith("datetime'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.DateTime, uriLiteral, 9, 1);
+    }
+    if (uriLiteral.startsWith("datetimeoffset'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.DateTimeOffset, uriLiteral, 15, 1);
+    }
+    if (uriLiteral.startsWith("guid'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Guid, uriLiteral, 5, 1);
+    }
+    if (uriLiteral.startsWith("time'")) {
+      return createEdmLiteral(EdmSimpleTypeKind.Time, uriLiteral, 5, 1);
+    }
+
+    if (uriLiteral.startsWith("X'") || uriLiteral.startsWith("binary'")) {
+      try {
+        final EdmSimpleType type = getEdmSimpleType(EdmSimpleTypeKind.Binary);
+        final byte[] value = type.valueOfString(uriLiteral, EdmLiteralKind.URI, null, byte[].class);
+        return new EdmLiteral(type, type.valueToString(value, EdmLiteralKind.DEFAULT, null));
+      } catch (EdmSimpleTypeException e) {
+        throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(uriLiteral), e);
+      }
+    }
+
+    throw new EdmLiteralException(EdmLiteralException.UNKNOWNLITERAL.addContent(uriLiteral));
+  }
+
+  private static EdmLiteral createEdmLiteral(final EdmSimpleTypeKind typeKind, final String literal, final int prefixLength, final int suffixLength) throws EdmLiteralException {
+    final EdmSimpleType type = getEdmSimpleType(typeKind);
+    if (type.validate(literal, EdmLiteralKind.URI, null)) {
+      return new EdmLiteral(type, literal.substring(prefixLength, literal.length() - suffixLength));
+    } else {
+      throw new EdmLiteralException(EdmLiteralException.LITERALFORMAT.addContent(literal));
+    }
+  }
+
+  @Override
+  public EdmSimpleType getEdmSimpleTypeInstance(final EdmSimpleTypeKind typeKind) {
+    return getEdmSimpleType(typeKind);
+  }
+
+  public static EdmSimpleType getEdmSimpleType(final EdmSimpleTypeKind typeKind) {
+
+    switch (typeKind) {
+    case Binary:
+      return EdmBinary.getInstance();
+    case Boolean:
+      return EdmBoolean.getInstance();
+    case Byte:
+      return EdmByte.getInstance();
+    case DateTime:
+      return EdmDateTime.getInstance();
+    case DateTimeOffset:
+      return EdmDateTimeOffset.getInstance();
+    case Decimal:
+      return EdmDecimal.getInstance();
+    case Double:
+      return EdmDouble.getInstance();
+    case Guid:
+      return EdmGuid.getInstance();
+    case Int16:
+      return EdmInt16.getInstance();
+    case Int32:
+      return EdmInt32.getInstance();
+    case Int64:
+      return EdmInt64.getInstance();
+    case SByte:
+      return EdmSByte.getInstance();
+    case Single:
+      return EdmSingle.getInstance();
+    case String:
+      return EdmString.getInstance();
+    case Time:
+      return EdmTime.getInstance();
+    case Null:
+      return EdmNull.getInstance();
+    default:
+      throw new ODataRuntimeException("Invalid Type " + typeKind);
+    }
+  }
+
+  public static EdmSimpleType getInternalEdmSimpleTypeByString(final String edmSimpleType) {
+    if ("Bit".equals(edmSimpleType)) {
+      return Bit.getInstance();
+    } else if ("Uint7".equals(edmSimpleType)) {
+      return Uint7.getInstance();
+    } else {
+      throw new ODataRuntimeException("Invalid internal Type " + edmSimpleType);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSingle.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSingle.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSingle.java
new file mode 100644
index 0000000..5e33fd6
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmSingle.java
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.math.BigDecimal;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type Single.
+ * @author SAP AG
+ */
+public class EdmSingle extends AbstractSimpleType {
+
+  // value-range limitations according to the CSDL document
+  private static final int MAX_PRECISION = 7;
+  private static final int MAX_SCALE = 38;
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "(?:\\+|-)?\\p{Digit}{1,7}(?:\\.\\p{Digit}{1,7})?(?:(?:E|e)(?:\\+|-)?\\p{Digit}{1,2})?(F|f)?");
+  private static final EdmSingle instance = new EdmSingle();
+
+  public static EdmSingle getInstance() {
+    return instance;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit
+        || simpleType instanceof Uint7
+        || simpleType instanceof EdmByte
+        || simpleType instanceof EdmSByte
+        || simpleType instanceof EdmInt16
+        || simpleType instanceof EdmInt32
+        || simpleType instanceof EdmInt64
+        || simpleType instanceof EdmSingle;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Float.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    String valueString = value;
+    Float result = null;
+    // Handle special values first.
+    if (value.equals("-INF")) {
+      result = Float.NEGATIVE_INFINITY;
+    } else if (value.equals("INF")) {
+      result = Float.POSITIVE_INFINITY;
+    } else if (value.equals("NaN")) {
+      result = Float.NaN;
+    } else {
+      // Now only "normal" numbers remain.
+      final Matcher matcher = PATTERN.matcher(value);
+      if (!matcher.matches()
+          || (literalKind == EdmLiteralKind.URI) == (matcher.group(1) == null)) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+
+      if (literalKind == EdmLiteralKind.URI) {
+        valueString = value.substring(0, value.length() - 1);
+      }
+
+      // The number format is checked above, so we don't have to catch NumberFormatException.
+      result = Float.valueOf(valueString);
+      // "Real" infinite values have been treated already above, so we can throw an exception
+      // if the conversion to a float results in an infinite value.
+      if (result.isInfinite()) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    }
+
+    if (returnType.isAssignableFrom(Float.class)) {
+      return returnType.cast(result);
+    } else if (returnType.isAssignableFrom(Double.class)) {
+      if (result.isInfinite() || result.isNaN()) {
+        return returnType.cast(result.doubleValue());
+      } else {
+        return returnType.cast(Double.valueOf(valueString));
+      }
+    } else if (result.isInfinite() || result.isNaN()) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType));
+    } else {
+      try {
+        final BigDecimal valueBigDecimal = new BigDecimal(valueString);
+        if (returnType.isAssignableFrom(BigDecimal.class)) {
+          return returnType.cast(valueBigDecimal);
+        } else if (returnType.isAssignableFrom(Long.class)) {
+          return returnType.cast(valueBigDecimal.longValueExact());
+        } else if (returnType.isAssignableFrom(Integer.class)) {
+          return returnType.cast(valueBigDecimal.intValueExact());
+        } else if (returnType.isAssignableFrom(Short.class)) {
+          return returnType.cast(valueBigDecimal.shortValueExact());
+        } else if (returnType.isAssignableFrom(Byte.class)) {
+          return returnType.cast(valueBigDecimal.byteValueExact());
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+        }
+
+      } catch (final ArithmeticException e) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE.addContent(value, returnType), e);
+      }
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    if (value instanceof Long || value instanceof Integer) {
+      if (Math.abs(((Number) value).longValue()) < Math.pow(10, MAX_PRECISION)) {
+        return value.toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else if (value instanceof Short || value instanceof Byte) {
+      return value.toString();
+    } else if (value instanceof Double) {
+      if (((Double) value).isInfinite()) {
+        return value.toString().toUpperCase(Locale.ROOT).substring(0, value.toString().length() - 5);
+      } else if (Float.isInfinite(((Double) value).floatValue())) {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      } else {
+        return Float.toString(((Double) value).floatValue());
+      }
+    } else if (value instanceof Float) {
+      final String result = value.toString();
+      return ((Float) value).isInfinite() ? result.toUpperCase(Locale.ROOT).substring(0, value.toString().length() - 5) : result;
+    } else if (value instanceof BigDecimal) {
+      if (((BigDecimal) value).precision() <= MAX_PRECISION && Math.abs(((BigDecimal) value).scale()) <= MAX_SCALE) {
+        return ((BigDecimal) value).toString();
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return literal.equals("-INF") || literal.equals("INF") || literal.equals("NaN") ?
+        literal : literal + "F";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmString.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmString.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmString.java
new file mode 100644
index 0000000..43eda7e
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmString.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the EDM simple type String.
+ * @author SAP AG
+ */
+public class EdmString extends AbstractSimpleType {
+
+  private static final Pattern PATTERN_ASCII = Pattern.compile("\\p{ASCII}*");
+  private static final EdmString instance = new EdmString();
+
+  public static EdmString getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return String.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    String result;
+    if (literalKind == EdmLiteralKind.URI) {
+      if (value.length() >= 2 && value.startsWith("'") && value.endsWith("'")) {
+        result = (value.substring(1, value.length() - 1)).replace("''", "'");
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      result = value;
+    }
+
+    if (facets != null
+        && (facets.isUnicode() != null && !facets.isUnicode() && !PATTERN_ASCII.matcher(result).matches()
+        || facets.getMaxLength() != null && facets.getMaxLength() < result.length())) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    if (returnType.isAssignableFrom(String.class)) {
+      return returnType.cast(result);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    final String result = value instanceof String ? (String) value : String.valueOf(value);
+
+    if (facets != null
+        && (facets.isUnicode() != null && !facets.isUnicode() && !PATTERN_ASCII.matcher(result).matches()
+        || facets.getMaxLength() != null && facets.getMaxLength() < result.length())) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets));
+    }
+
+    return result;
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) throws EdmSimpleTypeException {
+    final int length = literal.length();
+
+    StringBuilder uriLiteral = new StringBuilder(length + 2);
+    uriLiteral.append('\'');
+    for (int i = 0; i < length; i++) {
+      final char c = literal.charAt(i);
+      if (c == '\'') {
+        uriLiteral.append(c);
+      }
+      uriLiteral.append(c);
+    }
+    uriLiteral.append('\'');
+    return uriLiteral.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmTime.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmTime.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmTime.java
new file mode 100644
index 0000000..304aecb
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/EdmTime.java
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * 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.edm;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * <p>Implementation of the EDM simple type Time.</p>
+ * <p>Arguably, this type is intended to represent a time of day, not an instance in time.
+ * The time value is interpreted and formatted as local time.</p>
+ * <p>Formatting simply ignores the year, month, and day parts of time instances.
+ * Parsing returns a Calendar object where all unused fields have been cleared.</p>
+ * @author SAP AG
+ */
+public class EdmTime extends AbstractSimpleType {
+
+  private static final Pattern PATTERN = Pattern.compile(
+      "PT(?:(\\p{Digit}{1,2})H)?(?:(\\p{Digit}{1,4})M)?(?:(\\p{Digit}{1,5})(?:\\.(\\p{Digit}+?)0*)?S)?");
+  private static final EdmTime instance = new EdmTime();
+
+  public static EdmTime getInstance() {
+    return instance;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Calendar.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    Calendar valueCalendar;
+    if (literalKind == EdmLiteralKind.URI) {
+      if (value.length() > 6 && value.startsWith("time'") && value.endsWith("'")) {
+        valueCalendar = parseLiteral(value.substring(5, value.length() - 1), facets);
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(value));
+      }
+    } else {
+      valueCalendar = parseLiteral(value, facets);
+    }
+
+    if (returnType.isAssignableFrom(Calendar.class)) {
+      return returnType.cast(valueCalendar);
+    } else if (returnType.isAssignableFrom(Long.class)) {
+      return returnType.cast(valueCalendar.getTimeInMillis());
+    } else if (returnType.isAssignableFrom(Date.class)) {
+      return returnType.cast(valueCalendar.getTime());
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(returnType));
+    }
+  }
+
+  private Calendar parseLiteral(final String literal, final EdmFacets facets) throws EdmSimpleTypeException {
+    final Matcher matcher = PATTERN.matcher(literal);
+    if (!matcher.matches()
+        || (matcher.group(1) == null && matcher.group(2) == null && matcher.group(3) == null)) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(literal));
+    }
+
+    Calendar dateTimeValue = Calendar.getInstance();
+    dateTimeValue.clear();
+
+    if (matcher.group(1) != null) {
+      dateTimeValue.set(Calendar.HOUR_OF_DAY, Integer.parseInt(matcher.group(1)));
+    }
+    if (matcher.group(2) != null) {
+      dateTimeValue.set(Calendar.MINUTE, Integer.parseInt(matcher.group(2)));
+    }
+    if (matcher.group(3) != null) {
+      dateTimeValue.set(Calendar.SECOND, Integer.parseInt(matcher.group(3)));
+    }
+
+    if (matcher.group(4) != null) {
+      if (facets == null || facets.getPrecision() == null || facets.getPrecision() >= matcher.group(4).length()) {
+        if (matcher.group(4).length() <= 3) {
+          dateTimeValue.set(Calendar.MILLISECOND,
+              Short.parseShort(matcher.group(4) + "000".substring(0, 3 - matcher.group(4).length())));
+        } else {
+          throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(literal));
+        }
+      } else {
+        throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED.addContent(literal, facets));
+      }
+    }
+
+    if (dateTimeValue.get(Calendar.DAY_OF_YEAR) == 1) {
+      return dateTimeValue;
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT.addContent(literal));
+    }
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    Calendar dateTimeValue;
+    if (value instanceof Date) {
+      dateTimeValue = Calendar.getInstance();
+      dateTimeValue.clear();
+      dateTimeValue.setTime((Date) value);
+    } else if (value instanceof Calendar) {
+      dateTimeValue = (Calendar) ((Calendar) value).clone();
+    } else if (value instanceof Long) {
+      dateTimeValue = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+      dateTimeValue.clear();
+      dateTimeValue.setTimeInMillis((Long) value);
+    } else {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED.addContent(value.getClass()));
+    }
+
+    StringBuilder result = new StringBuilder(15); // 15 characters are enough for millisecond precision.
+    result.append('P');
+    result.append('T');
+    result.append(dateTimeValue.get(Calendar.HOUR_OF_DAY));
+    result.append('H');
+    result.append(dateTimeValue.get(Calendar.MINUTE));
+    result.append('M');
+    result.append(dateTimeValue.get(Calendar.SECOND));
+
+    try {
+      EdmDateTime.appendMilliseconds(result, dateTimeValue.get(Calendar.MILLISECOND), facets);
+    } catch (final IllegalArgumentException e) {
+      throw new EdmSimpleTypeException(EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED.addContent(value, facets), e);
+    }
+
+    result.append('S');
+
+    return result.toString();
+  }
+
+  @Override
+  public String toUriLiteral(final String literal) {
+    return "time'" + literal + "'";
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Uint7.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Uint7.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Uint7.java
new file mode 100644
index 0000000..3ffc348
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/Uint7.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.edm;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+
+/**
+ * Implementation of the internal simple type "unsigned 7-bit integer".
+ * @author SAP AG
+ */
+public class Uint7 extends AbstractSimpleType {
+
+  private static final Uint7 instance = new Uint7();
+
+  public static Uint7 getInstance() {
+    return instance;
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return SYSTEM_NAMESPACE;
+  }
+
+  @Override
+  public boolean isCompatible(final EdmSimpleType simpleType) {
+    return simpleType instanceof Bit || simpleType instanceof Uint7;
+  }
+
+  @Override
+  public Class<?> getDefaultType() {
+    return Byte.class;
+  }
+
+  @Override
+  protected <T> T internalValueOfString(final String value, final EdmLiteralKind literalKind, final EdmFacets facets, final Class<T> returnType) throws EdmSimpleTypeException {
+    return EdmSByte.getInstance().internalValueOfString(value, literalKind, facets, returnType);
+  }
+
+  @Override
+  protected <T> String internalValueToString(final T value, final EdmLiteralKind literalKind, final EdmFacets facets) throws EdmSimpleTypeException {
+    return EdmSByte.getInstance().internalValueToString(value, literalKind, facets);
+  }
+}


[20/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
new file mode 100644
index 0000000..8e3e3dd
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParser.java
@@ -0,0 +1,965 @@
+/*******************************************************************************
+ * 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.edm.parser;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmAction;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmContentKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.CustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.provider.DataServices;
+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.Facets;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.OnDelete;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraint;
+import org.apache.olingo.odata2.api.edm.provider.ReferentialConstraintRole;
+import org.apache.olingo.odata2.api.edm.provider.ReturnType;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.api.edm.provider.Using;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import java.util.HashSet;
+import java.util.Set;
+
+public class EdmParser {
+
+  private Map<String, Set<String>> inscopeMap = new HashMap<String, Set<String>>();
+  private Map<String, String> aliasNamespaceMap = new HashMap<String, String>();
+  private Map<String, String> xmlNamespaceMap;
+  private Map<String, String> mandatoryNamespaces;
+  private Map<FullQualifiedName, EntityType> entityTypesMap = new HashMap<FullQualifiedName, EntityType>();
+  private Map<FullQualifiedName, ComplexType> complexTypesMap = new HashMap<FullQualifiedName, ComplexType>();
+  private Map<FullQualifiedName, Association> associationsMap = new HashMap<FullQualifiedName, Association>();
+  private Map<FullQualifiedName, EntityContainer> containerMap = new HashMap<FullQualifiedName, EntityContainer>();
+  private List<NavigationProperty> navProperties = new ArrayList<NavigationProperty>();
+  private String currentHandledStartTagName;
+  private String currentNamespace;
+  private final String DEFAULT_NAMESPACE = "";
+
+  public DataServices readMetadata(final XMLStreamReader reader, final boolean validate)
+      throws EntityProviderException {
+    try {
+      initialize();
+      DataServices dataServices = new DataServices();
+      List<Schema> schemas = new ArrayList<Schema>();
+
+      while (reader.hasNext()
+          && !(reader.isEndElement() && Edm.NAMESPACE_EDMX_2007_06.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_DATA_SERVICES.equals(reader.getLocalName()))) {
+        reader.next();
+        if (reader.isStartElement()) {
+          extractNamespaces(reader);
+          if (EdmParserConstants.EDM_SCHEMA.equals(reader.getLocalName())) {
+            schemas.add(readSchema(reader));
+          } else if (EdmParserConstants.EDM_DATA_SERVICES.equals(reader
+              .getLocalName())) {
+            dataServices.setDataServiceVersion(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "DataServiceVersion"));
+          }
+        }
+      }
+      if (validate) {
+        validate();
+      }
+      dataServices.setSchemas(schemas);
+      reader.close();
+      return dataServices;
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+  }
+
+  private Schema readSchema(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_SCHEMA);
+
+    Schema schema = new Schema();
+    List<Using> usings = new ArrayList<Using>();
+    List<ComplexType> complexTypes = new ArrayList<ComplexType>();
+    List<EntityType> entityTypes = new ArrayList<EntityType>();
+    List<Association> associations = new ArrayList<Association>();
+    List<EntityContainer> entityContainers = new ArrayList<EntityContainer>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    schema.setNamespace(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_NAMESPACE));
+    this.inscopeMap.put(schema.getNamespace(), new HashSet<String>());
+    schema.setAlias(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_ALIAS));
+    schema.setAnnotationAttributes(readAnnotationAttribute(reader));
+    currentNamespace = schema.getNamespace();
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_SCHEMA.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_USING.equals(currentHandledStartTagName)) {
+          usings.add(readUsing(reader, schema.getNamespace()));
+        } else if (EdmParserConstants.EDM_ENTITY_TYPE.equals(currentHandledStartTagName)) {
+          entityTypes.add(readEntityType(reader));
+        } else if (EdmParserConstants.EDM_COMPLEX_TYPE.equals(currentHandledStartTagName)) {
+          complexTypes.add(readComplexType(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION.equals(currentHandledStartTagName)) {
+          associations.add(readAssociation(reader));
+        } else if (EdmParserConstants.EDM_ENTITY_CONTAINER.equals(currentHandledStartTagName)) {
+          entityContainers.add(readEntityContainer(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (schema.getAlias() != null) {
+      aliasNamespaceMap.put(schema.getAlias(), schema.getNamespace());
+    }
+    schema.setUsings(usings).setEntityTypes(entityTypes).setComplexTypes(complexTypes).setAssociations(associations).setEntityContainers(entityContainers).setAnnotationElements(annotationElements);
+    return schema;
+  }
+
+    private Using readUsing(final XMLStreamReader reader, final String schemaNamespace) 
+            throws XMLStreamException, EntityProviderException {
+        
+        reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_USING);
+
+        Using using = new Using();
+        using.setNamespace(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_NAMESPACE));
+        this.inscopeMap.get(schemaNamespace).add(using.getNamespace());
+        using.setAlias(reader.getAttributeValue(null, EdmParserConstants.EDM_SCHEMA_ALIAS));
+        using.setAnnotationAttributes(readAnnotationAttribute(reader));
+
+        List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+        while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI())
+                && EdmParserConstants.EDM_USING.equals(reader.getLocalName()))) {
+            
+            reader.next();
+            if (reader.isStartElement()) {
+                extractNamespaces(reader);
+                currentHandledStartTagName = reader.getLocalName();
+                annotationElements.add(readAnnotationElement(reader));
+            }
+        }
+        using.setAnnotationElements(annotationElements);
+
+        if (using.getAlias() != null) {
+            aliasNamespaceMap.put(using.getAlias(), using.getNamespace());
+        }
+
+        return using;
+    }
+  
+  private EntityContainer readEntityContainer(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_CONTAINER);
+    EntityContainer container = new EntityContainer();
+    List<EntitySet> entitySets = new ArrayList<EntitySet>();
+    List<AssociationSet> associationSets = new ArrayList<AssociationSet>();
+    List<FunctionImport> functionImports = new ArrayList<FunctionImport>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    container.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    if (reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "IsDefaultEntityContainer") != null) {
+      container.setDefaultEntityContainer("true".equalsIgnoreCase(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, "IsDefaultEntityContainer")));
+    }
+    container.setExtendz(reader.getAttributeValue(null, EdmParserConstants.EDM_CONTAINER_EXTENDZ));
+    container.setAnnotationAttributes(readAnnotationAttribute(reader));
+
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_CONTAINER.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ENTITY_SET.equals(currentHandledStartTagName)) {
+          entitySets.add(readEntitySet(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_SET.equals(currentHandledStartTagName)) {
+          associationSets.add(readAssociationSet(reader));
+        } else if (EdmParserConstants.EDM_FUNCTION_IMPORT.equals(currentHandledStartTagName)) {
+          functionImports.add(readFunctionImport(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    container.setEntitySets(entitySets).setAssociationSets(associationSets).setFunctionImports(functionImports).setAnnotationElements(annotationElements);
+
+    containerMap.put(new FullQualifiedName(currentNamespace, container.getName()), container);
+    return container;
+  }
+
+  private FunctionImport readFunctionImport(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_FUNCTION_IMPORT);
+    FunctionImport function = new FunctionImport();
+    List<FunctionImportParameter> functionParameters = new ArrayList<FunctionImportParameter>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    function.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    function.setHttpMethod(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.EDM_FUNCTION_IMPORT_HTTP_METHOD));
+    function.setEntitySet(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_SET));
+    ReturnType returnType = new ReturnType();
+    String returnTypeString = reader.getAttributeValue(null, EdmParserConstants.EDM_FUNCTION_IMPORT_RETURN);
+    if (returnTypeString != null) {
+      if (returnTypeString.startsWith("Collection") || returnTypeString.startsWith("collection")) {
+        returnType.setMultiplicity(EdmMultiplicity.MANY);
+        returnTypeString = returnTypeString.substring(returnTypeString.indexOf("(") + 1, returnTypeString.length() - 1);
+        if (function.getEntitySet() == null) {
+          //				throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("EntitySet");
+        }
+      }
+      FullQualifiedName fqName = extractFQName(returnTypeString);
+      returnType.setTypeName(fqName);
+      function.setReturnType(returnType);
+    }
+    function.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_FUNCTION_IMPORT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_FUNCTION_PARAMETER.equals(currentHandledStartTagName)) {
+          functionParameters.add(readFunctionImportParameter(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    function.setParameters(functionParameters).setAnnotationElements(annotationElements);
+    return function;
+  }
+
+  private FunctionImportParameter readFunctionImportParameter(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_FUNCTION_PARAMETER);
+    FunctionImportParameter functionParameter = new FunctionImportParameter();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    functionParameter.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String type = reader.getAttributeValue(null, EdmParserConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_TYPE).addContent(EdmParserConstants.EDM_FUNCTION_PARAMETER));
+    }
+    functionParameter.setType(EdmSimpleTypeKind.valueOf(extractFQName(type).getName()));
+    functionParameter.setFacets(readFacets(reader));
+    functionParameter.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_FUNCTION_IMPORT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    functionParameter.setAnnotationElements(annotationElements);
+    return functionParameter;
+  }
+
+  private AssociationSet readAssociationSet(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_SET);
+    AssociationSet associationSet = new AssociationSet();
+    List<AssociationSetEnd> ends = new ArrayList<AssociationSetEnd>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+
+    associationSet.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String association = reader.getAttributeValue(null, EdmParserConstants.EDM_ASSOCIATION);
+    if (association != null) {
+      associationSet.setAssociation(extractFQName(association));
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_ASSOCIATION).addContent(EdmParserConstants.EDM_ASSOCIATION_SET));
+    }
+    associationSet.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION_SET.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_END.equals(currentHandledStartTagName)) {
+          AssociationSetEnd associationSetEnd = new AssociationSetEnd();
+          associationSetEnd.setEntitySet(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_SET));
+          associationSetEnd.setRole(reader.getAttributeValue(null, EdmParserConstants.EDM_ROLE));
+          ends.add(associationSetEnd);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (ends.size() != 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Count of AssociationSet ends should be 2"));
+    } else {
+      associationSet.setEnd1(ends.get(0)).setEnd2(ends.get(1));
+    }
+    associationSet.setAnnotationElements(annotationElements);
+    return associationSet;
+  }
+
+  private EntitySet readEntitySet(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_SET);
+    EntitySet entitySet = new EntitySet();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    entitySet.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String entityType = reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE);
+    if (entityType != null) {
+      FullQualifiedName fqName = extractFQName(entityType);
+      entitySet.setEntityType(fqName);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_ENTITY_TYPE).addContent(EdmParserConstants.EDM_ENTITY_SET));
+    }
+    entitySet.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_SET.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    entitySet.setAnnotationElements(annotationElements);
+    return entitySet;
+  }
+
+  private Association readAssociation(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION);
+
+    Association association = new Association();
+    association.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    List<AssociationEnd> associationEnds = new ArrayList<AssociationEnd>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    association.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_END.equals(currentHandledStartTagName)) {
+          associationEnds.add(readAssociationEnd(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT.equals(currentHandledStartTagName)) {
+          association.setReferentialConstraint(readReferentialConstraint(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    if (associationEnds.size() < 2 && associationEnds.size() > 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Count of association ends should be 2"));
+    }
+
+    association.setEnd1(associationEnds.get(0)).setEnd2(associationEnds.get(1)).setAnnotationElements(annotationElements);
+    associationsMap.put(new FullQualifiedName(currentNamespace, association.getName()), association);
+    return association;
+  }
+
+  private ReferentialConstraint readReferentialConstraint(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT);
+    ReferentialConstraint refConstraint = new ReferentialConstraint();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    refConstraint.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION_CONSTRAINT.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL);
+          refConstraint.setPrincipal(readReferentialConstraintRole(reader));
+        } else if (EdmParserConstants.EDM_ASSOCIATION_DEPENDENT.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_DEPENDENT);
+          refConstraint.setDependent(readReferentialConstraintRole(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    refConstraint.setAnnotationElements(annotationElements);
+    return refConstraint;
+  }
+
+  private ReferentialConstraintRole readReferentialConstraintRole(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    ReferentialConstraintRole rcRole = new ReferentialConstraintRole();
+    rcRole.setRole(reader.getAttributeValue(null, EdmParserConstants.EDM_ROLE));
+    List<PropertyRef> propertyRefs = new ArrayList<PropertyRef>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    rcRole.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI())
+        && (EdmParserConstants.EDM_ASSOCIATION_PRINCIPAL.equals(reader.getLocalName()) || EdmParserConstants.EDM_ASSOCIATION_DEPENDENT.equals(reader.getLocalName())))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_PROPERTY_REF.equals(currentHandledStartTagName)) {
+          propertyRefs.add(readPropertyRef(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    rcRole.setPropertyRefs(propertyRefs).setAnnotationElements(annotationElements);
+    return rcRole;
+  }
+
+  private ComplexType readComplexType(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_COMPLEX_TYPE);
+
+    ComplexType complexType = new ComplexType();
+    List<Property> properties = new ArrayList<Property>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    complexType.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String baseType = reader.getAttributeValue(null, EdmParserConstants.EDM_BASE_TYPE);
+    if (baseType != null) {
+      complexType.setBaseType(extractFQName(baseType));
+    }
+    if (reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT) != null) {
+      complexType.setAbstract("true".equalsIgnoreCase(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT)));
+    }
+    complexType.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_COMPLEX_TYPE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_PROPERTY.equals(currentHandledStartTagName)) {
+          properties.add(readProperty(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    complexType.setProperties(properties).setAnnotationElements(annotationElements);
+    if (complexType.getName() != null) {
+      FullQualifiedName fqName = new FullQualifiedName(currentNamespace, complexType.getName());
+      complexTypesMap.put(fqName, complexType);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("Name"));
+    }
+    return complexType;
+
+  }
+
+  private EntityType readEntityType(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_TYPE);
+    EntityType entityType = new EntityType();
+    List<Property> properties = new ArrayList<Property>();
+    List<NavigationProperty> navProperties = new ArrayList<NavigationProperty>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    Key key = null;
+
+    entityType.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String hasStream = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_ENTITY_TYPE_HAS_STREAM);
+    if (hasStream != null) {
+      entityType.setHasStream("true".equalsIgnoreCase(hasStream));
+    }
+
+    if (reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT) != null) {
+      entityType.setAbstract("true".equalsIgnoreCase(reader.getAttributeValue(null, EdmParserConstants.EDM_ENTITY_TYPE_ABSTRACT)));
+    }
+    String baseType = reader.getAttributeValue(null, EdmParserConstants.EDM_BASE_TYPE);
+    if (baseType != null) {
+      entityType.setBaseType(extractFQName(baseType));
+    }
+    entityType.setCustomizableFeedMappings(readCustomizableFeedMappings(reader));
+    entityType.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_TYPE.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ENTITY_TYPE_KEY.equals(currentHandledStartTagName)) {
+          key = readEntityTypeKey(reader);
+        } else if (EdmParserConstants.EDM_PROPERTY.equals(currentHandledStartTagName)) {
+          properties.add(readProperty(reader));
+        } else if (EdmParserConstants.EDM_NAVIGATION_PROPERTY.equals(currentHandledStartTagName)) {
+          navProperties.add(readNavigationProperty(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+        extractNamespaces(reader);
+      }
+    }
+    entityType.setKey(key).setProperties(properties).setNavigationProperties(navProperties).setAnnotationElements(annotationElements);
+    if (entityType.getName() != null) {
+      FullQualifiedName fqName = new FullQualifiedName(currentNamespace, entityType.getName());
+      entityTypesMap.put(fqName, entityType);
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE.addContent("Name"));
+    }
+    return entityType;
+  }
+
+  private Key readEntityTypeKey(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ENTITY_TYPE_KEY);
+    List<PropertyRef> keys = new ArrayList<PropertyRef>();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    List<AnnotationAttribute> annotationAttributes = readAnnotationAttribute(reader);
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ENTITY_TYPE_KEY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_PROPERTY_REF.equals(currentHandledStartTagName)) {
+          reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_PROPERTY_REF);
+          keys.add(readPropertyRef(reader));
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    return new Key().setKeys(keys).setAnnotationElements(annotationElements).setAnnotationAttributes(annotationAttributes);
+  }
+
+  private PropertyRef readPropertyRef(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_PROPERTY_REF);
+    PropertyRef propertyRef = new PropertyRef();
+    propertyRef.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    propertyRef.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_PROPERTY_REF.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    return propertyRef.setAnnotationElements(annotationElements);
+  }
+
+  private NavigationProperty readNavigationProperty(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_NAVIGATION_PROPERTY);
+
+    NavigationProperty navProperty = new NavigationProperty();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    navProperty.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    String relationship = reader.getAttributeValue(null, EdmParserConstants.EDM_NAVIGATION_RELATIONSHIP);
+    if (relationship != null) {
+      FullQualifiedName fqName = extractFQName(relationship);
+      navProperty.setRelationship(fqName);
+
+    } else {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_NAVIGATION_RELATIONSHIP).addContent(EdmParserConstants.EDM_NAVIGATION_PROPERTY));
+    }
+
+    navProperty.setFromRole(reader.getAttributeValue(null, EdmParserConstants.EDM_NAVIGATION_FROM_ROLE));
+    navProperty.setToRole(reader.getAttributeValue(null, EdmParserConstants.EDM_NAVIGATION_TO_ROLE));
+    navProperty.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_NAVIGATION_PROPERTY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    navProperty.setAnnotationElements(annotationElements);
+    navProperties.add(navProperty);
+    return navProperty;
+  }
+
+  private Property readProperty(final XMLStreamReader reader) throws XMLStreamException, EntityProviderException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_PROPERTY);
+    Property property;
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    String type = reader.getAttributeValue(null, EdmParserConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_TYPE).addContent(EdmParserConstants.EDM_PROPERTY));
+    }
+    FullQualifiedName fqName = extractFQName(type);
+
+    if (EdmSimpleType.EDM_NAMESPACE.equals(fqName.getNamespace())) {
+      property = readSimpleProperty(reader, fqName);
+    } else {
+      property = readComplexProperty(reader, fqName);
+    }
+    property.setFacets(readFacets(reader));
+    property.setCustomizableFeedMappings(readCustomizableFeedMappings(reader));
+    property.setMimeType(reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_MIMETYPE));
+    property.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_PROPERTY.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        annotationElements.add(readAnnotationElement(reader));
+      }
+    }
+    property.setAnnotationElements(annotationElements);
+    return property;
+  }
+
+  private Property readComplexProperty(final XMLStreamReader reader, final FullQualifiedName fqName) throws XMLStreamException {
+    ComplexProperty property = new ComplexProperty();
+    property.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    property.setType(fqName);
+    return property;
+  }
+
+  private Property readSimpleProperty(final XMLStreamReader reader, final FullQualifiedName fqName) throws XMLStreamException {
+    SimpleProperty property = new SimpleProperty();
+    property.setName(reader.getAttributeValue(null, EdmParserConstants.EDM_NAME));
+    property.setType(EdmSimpleTypeKind.valueOf(fqName.getName()));
+    return property;
+  }
+
+  private Facets readFacets(final XMLStreamReader reader) throws XMLStreamException {
+    String isNullable = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_NULLABLE);
+    String maxLength = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_MAX_LENGTH);
+    String precision = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_PRECISION);
+    String scale = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_SCALE);
+    String isFixedLength = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_FIXED_LENGTH);
+    String isUnicode = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_UNICODE);
+    String concurrencyMode = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_CONCURRENCY_MODE);
+    String defaultValue = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_DEFAULT_VALUE);
+    String collation = reader.getAttributeValue(null, EdmParserConstants.EDM_PROPERTY_COLLATION);
+    if (isNullable != null || maxLength != null || precision != null || scale != null || isFixedLength != null || isUnicode != null
+        || concurrencyMode != null || defaultValue != null || collation != null) {
+      Facets facets = new Facets();
+      if (isNullable != null) {
+        facets.setNullable("true".equalsIgnoreCase(isNullable));
+      }
+      if (maxLength != null) {
+        if (EdmParserConstants.EDM_PROPERTY_MAX_LENGTH_MAX_VALUE.equals(maxLength)) {
+          facets.setMaxLength(Integer.MAX_VALUE);
+        } else {
+          facets.setMaxLength(Integer.parseInt(maxLength));
+        }
+      }
+      if (precision != null) {
+        facets.setPrecision(Integer.parseInt(precision));
+      }
+      if (scale != null) {
+        facets.setScale(Integer.parseInt(scale));
+      }
+      if (isFixedLength != null) {
+        facets.setFixedLength("true".equalsIgnoreCase(isFixedLength));
+      }
+      if (isUnicode != null) {
+        facets.setUnicode("true".equalsIgnoreCase(isUnicode));
+      }
+      for (int i = 0; i < EdmConcurrencyMode.values().length; i++) {
+        if (EdmConcurrencyMode.values()[i].name().equalsIgnoreCase(concurrencyMode)) {
+          facets.setConcurrencyMode(EdmConcurrencyMode.values()[i]);
+        }
+      }
+      facets.setDefaultValue(defaultValue);
+      facets.setCollation(collation);
+      return facets;
+    } else {
+      return null;
+    }
+  }
+
+  private CustomizableFeedMappings readCustomizableFeedMappings(final XMLStreamReader reader) {
+    String targetPath = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_TARGET_PATH);
+    String sourcePath = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_SOURCE_PATH);
+    String nsUri = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_NS_URI);
+    String nsPrefix = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_PREFIX);
+    String keepInContent = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_KEEP_IN_CONTENT);
+    String contentKind = reader.getAttributeValue(Edm.NAMESPACE_M_2007_08, EdmParserConstants.M_FC_CONTENT_KIND);
+
+    if (targetPath != null || sourcePath != null || nsUri != null || nsPrefix != null || keepInContent != null || contentKind != null) {
+      CustomizableFeedMappings feedMapping = new CustomizableFeedMappings();
+      if (keepInContent != null) {
+        feedMapping.setFcKeepInContent("true".equals(keepInContent));
+      }
+      for (int i = 0; i < EdmContentKind.values().length; i++) {
+        if (EdmContentKind.values()[i].name().equalsIgnoreCase(contentKind)) {
+          feedMapping.setFcContentKind(EdmContentKind.values()[i]);
+        }
+      }
+      feedMapping.setFcTargetPath(targetPath).setFcSourcePath(sourcePath).setFcNsUri(nsUri).setFcNsPrefix(nsPrefix);
+      return feedMapping;
+    } else {
+      return null;
+    }
+
+  }
+
+  private AssociationEnd readAssociationEnd(final XMLStreamReader reader) throws EntityProviderException, XMLStreamException {
+    reader.require(XMLStreamConstants.START_ELEMENT, Edm.NAMESPACE_EDM_2008_09, EdmParserConstants.EDM_ASSOCIATION_END);
+
+    AssociationEnd associationEnd = new AssociationEnd();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    associationEnd.setRole(reader.getAttributeValue(null, EdmParserConstants.EDM_ROLE));
+    associationEnd.setMultiplicity(EdmMultiplicity.fromLiteral(reader.getAttributeValue(null, EdmParserConstants.EDM_ASSOCIATION_MULTIPLICITY)));
+    String type = reader.getAttributeValue(null, EdmParserConstants.EDM_TYPE);
+    if (type == null) {
+      throw new EntityProviderException(EntityProviderException.MISSING_ATTRIBUTE
+          .addContent(EdmParserConstants.EDM_TYPE).addContent(EdmParserConstants.EDM_ASSOCIATION_END));
+    }
+    associationEnd.setType(extractFQName(type));
+    associationEnd.setAnnotationAttributes(readAnnotationAttribute(reader));
+    while (reader.hasNext() && !(reader.isEndElement() && Edm.NAMESPACE_EDM_2008_09.equals(reader.getNamespaceURI()) && EdmParserConstants.EDM_ASSOCIATION_END.equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        extractNamespaces(reader);
+        currentHandledStartTagName = reader.getLocalName();
+        if (EdmParserConstants.EDM_ASSOCIATION_ONDELETE.equals(currentHandledStartTagName)) {
+          OnDelete onDelete = new OnDelete();
+          for (int i = 0; i < EdmAction.values().length; i++) {
+            if (EdmAction.values()[i].name().equalsIgnoreCase(reader.getAttributeValue(null, EdmParserConstants.EDM_ONDELETE_ACTION))) {
+              onDelete.setAction(EdmAction.values()[i]);
+            }
+          }
+          associationEnd.setOnDelete(onDelete);
+        } else {
+          annotationElements.add(readAnnotationElement(reader));
+        }
+      }
+    }
+    associationEnd.setAnnotationElements(annotationElements);
+    return associationEnd;
+  }
+
+  private AnnotationElement readAnnotationElement(final XMLStreamReader reader) throws XMLStreamException {
+    AnnotationElement aElement = new AnnotationElement();
+    List<AnnotationElement> annotationElements = new ArrayList<AnnotationElement>();
+    List<AnnotationAttribute> annotationAttributes = new ArrayList<AnnotationAttribute>();
+    aElement.setName(reader.getLocalName());
+    String elementNamespace = reader.getNamespaceURI();
+    if (!Edm.NAMESPACE_EDM_2008_09.equals(elementNamespace)) {
+      aElement.setPrefix(reader.getPrefix());
+      aElement.setNamespace(elementNamespace);
+    }
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      AnnotationAttribute annotationAttribute = new AnnotationAttribute();
+      annotationAttribute.setText(reader.getAttributeValue(i));
+      annotationAttribute.setName(reader.getAttributeLocalName(i));
+      annotationAttribute.setPrefix(reader.getAttributePrefix(i));
+      String namespace = reader.getAttributeNamespace(i);
+      if (!DEFAULT_NAMESPACE.equals(namespace)) {
+        annotationAttribute.setNamespace(namespace);
+      }
+      annotationAttributes.add(annotationAttribute);
+    }
+    aElement.setAttributes(annotationAttributes);
+    while (reader.hasNext() && !(reader.isEndElement() && aElement.getName() != null && aElement.getName().equals(reader.getLocalName()))) {
+      reader.next();
+      if (reader.isStartElement()) {
+        annotationElements.add(readAnnotationElement(reader));
+      } else if (reader.isCharacters()) {
+        aElement.setText(reader.getText());
+      }
+    }
+    if (!annotationElements.isEmpty()) {
+      aElement.setChildElements(annotationElements);
+    }
+    return aElement;
+  }
+
+  private List<AnnotationAttribute> readAnnotationAttribute(final XMLStreamReader reader) {
+    List<AnnotationAttribute> annotationAttributes = new ArrayList<AnnotationAttribute>();
+    for (int i = 0; i < reader.getAttributeCount(); i++) {
+      if (!mandatoryNamespaces.containsValue(reader.getAttributeNamespace(i)) && !DEFAULT_NAMESPACE.equals(reader.getAttributeNamespace(i))) {
+        annotationAttributes.add(new AnnotationAttribute().setName(reader.getAttributeLocalName(i)).
+            setPrefix(reader.getAttributePrefix(i)).setNamespace(reader.getAttributeNamespace(i)).setText(reader.getAttributeValue(i)));
+      }
+    }
+    if (annotationAttributes.isEmpty()) {
+      return null;
+    }
+    return annotationAttributes;
+  }
+
+  private void checkAllMandatoryNamespacesAvailable() throws EntityProviderException {
+    if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_EDMX_2007_06)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_EDMX_2007_06));
+    } else if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_M_2007_08)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_EDMX_2007_06));
+    } else if (!xmlNamespaceMap.containsValue(Edm.NAMESPACE_EDM_2008_09)) {
+      throw new EntityProviderException(EntityProviderException.INVALID_NAMESPACE.addContent(Edm.NAMESPACE_EDMX_2007_06));
+    }
+  }
+
+  private void extractNamespaces(final XMLStreamReader reader) throws EntityProviderException {
+    int namespaceCount = reader.getNamespaceCount();
+    for (int i = 0; i < namespaceCount; i++) {
+      String namespacePrefix = reader.getNamespacePrefix(i);
+      String namespaceUri = reader.getNamespaceURI(i);
+      if (namespacePrefix == null || DEFAULT_NAMESPACE.equals(namespacePrefix)) {
+        namespacePrefix = Edm.PREFIX_EDM;
+      }
+      xmlNamespaceMap.put(namespacePrefix, namespaceUri);
+    }
+  }
+
+  private FullQualifiedName extractFQName(final String name)
+      throws EntityProviderException {
+    // Looking for the last dot
+    String[] names = name.split("\\" + Edm.DELIMITER + "(?=[^\\" + Edm.DELIMITER + "]+$)");
+    if (names.length != 2) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Attribute should specify a namespace qualified name or an alias qualified name"));
+    } else {
+      return new FullQualifiedName(names[0], names[1]);
+    }
+  }
+
+  private FullQualifiedName validateEntityTypeWithAlias(final FullQualifiedName aliasName) throws EntityProviderException {
+    String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
+    FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
+    if (!entityTypesMap.containsKey(fqName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid Type"));
+    }
+    return fqName;
+  }
+
+  private void validateEntityTypes() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, EntityType> entityTypes : entityTypesMap.entrySet()) {
+      if (entityTypes.getValue() != null && entityTypes.getKey() != null) {
+        EntityType entityType = entityTypes.getValue();
+        if (entityType.getBaseType() != null) {
+          FullQualifiedName baseTypeFQName = entityType.getBaseType();
+          EntityType baseEntityType;
+          if (!entityTypesMap.containsKey(baseTypeFQName)) {
+            FullQualifiedName fqName = validateEntityTypeWithAlias(baseTypeFQName);
+            baseEntityType = entityTypesMap.get(fqName);
+          } else {
+            baseEntityType = entityTypesMap.get(baseTypeFQName);
+          }
+          if (baseEntityType.getKey() == null) {
+            throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Missing key for EntityType " + baseEntityType.getName()));
+          }
+        } else if (entityType.getKey() == null) {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Missing key for EntityType " + entityType.getName()));
+        }
+      }
+    }
+  }
+
+  private FullQualifiedName validateComplexTypeWithAlias(final FullQualifiedName aliasName) throws EntityProviderException {
+    String namespace = aliasNamespaceMap.get(aliasName.getNamespace());
+    FullQualifiedName fqName = new FullQualifiedName(namespace, aliasName.getName());
+    if (!complexTypesMap.containsKey(fqName)) {
+      throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid BaseType").addContent(fqName));
+    }
+    return fqName;
+  }
+
+  private void validateComplexTypes() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, ComplexType> complexTypes : complexTypesMap.entrySet()) {
+      if (complexTypes.getValue() != null && complexTypes.getKey() != null) {
+        ComplexType complexType = complexTypes.getValue();
+        if (complexType.getBaseType() != null) {
+          FullQualifiedName baseTypeFQName = complexType.getBaseType();
+          if (!complexTypesMap.containsKey(baseTypeFQName)) {
+            validateComplexTypeWithAlias(baseTypeFQName);
+          }
+        }
+      }
+    }
+  }
+
+  private void validateRelationship() throws EntityProviderException {
+    for (NavigationProperty navProperty : navProperties) {
+      if (associationsMap.containsKey(navProperty.getRelationship())) {
+        Association assoc = associationsMap.get(navProperty.getRelationship());
+        if (!(assoc.getEnd1().getRole().equals(navProperty.getFromRole()) ^ assoc.getEnd1().getRole().equals(navProperty.getToRole())
+        && (assoc.getEnd2().getRole().equals(navProperty.getFromRole()) ^ assoc.getEnd2().getRole().equals(navProperty.getToRole())))) {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid end of association"));
+        }
+        if (!entityTypesMap.containsKey(assoc.getEnd1().getType())) {
+          validateEntityTypeWithAlias(assoc.getEnd1().getType());
+        }
+        if (!entityTypesMap.containsKey(assoc.getEnd2().getType())) {
+          validateEntityTypeWithAlias(assoc.getEnd2().getType());
+        }
+      } else {
+        throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid Relationship"));
+      }
+    }
+
+  }
+
+  private void validateAssociation() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, EntityContainer> container : containerMap.entrySet()) {
+      for (AssociationSet associationSet : container.getValue().getAssociationSets()) {
+        FullQualifiedName association = associationSet.getAssociation();
+        if (associationsMap.containsKey(association)) {
+          validateAssociationEnd(associationSet.getEnd1(), associationsMap.get(association));
+          validateAssociationEnd(associationSet.getEnd2(), associationsMap.get(association));
+          boolean end1 = false;
+          boolean end2 = false;
+          for (EntitySet entitySet : container.getValue().getEntitySets()) {
+            if (entitySet.getName().equals(associationSet.getEnd1().getEntitySet())) {
+              end1 = true;
+            }
+            if (entitySet.getName().equals(associationSet.getEnd2().getEntitySet())) {
+              end2 = true;
+            }
+          }
+          if (!(end1 && end2)) {
+            throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid AssociationSet"));
+          }
+        } else {
+          throw new EntityProviderException(EntityProviderException.ILLEGAL_ARGUMENT.addContent("Invalid AssociationSet"));
+        }
+      }
+    }
+
+  }
+
+  private void validateAssociationEnd(final AssociationSetEnd end, final Association association) throws EntityProviderException {
+    if (!(association.getEnd1().getRole().equals(end.getRole()) ^ association.getEnd2().getRole().equals(end.getRole()))) {
+      throw new EntityProviderException(EntityProviderException.COMMON.addContent("Invalid Association"));
+    }
+  }
+
+  private void validateEntitySet() throws EntityProviderException {
+    for (Map.Entry<FullQualifiedName, EntityContainer> container : containerMap.entrySet()) {
+      for (EntitySet entitySet : container.getValue().getEntitySets()) {
+        FullQualifiedName entityType = entitySet.getEntityType();
+        if (!(entityTypesMap.containsKey(entityType))) {
+          validateEntityTypeWithAlias(entityType);
+        }
+      }
+    }
+  }
+
+  private void validate() throws EntityProviderException {
+    checkAllMandatoryNamespacesAvailable();
+    validateEntityTypes();
+    validateComplexTypes();
+    validateRelationship();
+    validateEntitySet();
+    validateAssociation();
+  }
+
+  private void initialize() {
+    xmlNamespaceMap = new HashMap<String, String>();
+    mandatoryNamespaces = new HashMap<String, String>();
+    mandatoryNamespaces.put(Edm.PREFIX_EDMX, Edm.NAMESPACE_EDMX_2007_06);
+    mandatoryNamespaces.put(Edm.PREFIX_EDM, Edm.NAMESPACE_EDM_2008_09);
+    mandatoryNamespaces.put(Edm.PREFIX_M, Edm.NAMESPACE_M_2007_08);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java
new file mode 100644
index 0000000..c2a3ae8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmParserConstants.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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.edm.parser;
+
+public class EdmParserConstants {
+
+  public static final String EDM_DATA_SERVICES = "DataServices";
+  public static final String EDM_SCHEMA = "Schema";
+  public static final String EDM_SCHEMA_NAMESPACE = "Namespace";
+  public static final String EDM_SCHEMA_ALIAS = "Alias";
+  public static final String EDM_ENTITY_TYPE = "EntityType";
+  public static final String EDM_COMPLEX_TYPE = "ComplexType";
+  public static final String EDM_ASSOCIATION = "Association";
+  public static final String EDM_USING = "Using";
+
+  public static final String EDM_NAME = "Name";
+  public static final String EDM_TYPE = "Type";
+  public static final String EDM_ENTITY_TYPE_KEY = "Key";
+  public static final String EDM_ENTITY_TYPE_ABSTRACT = "Abstract";
+  public static final String EDM_BASE_TYPE = "BaseType";
+  public static final String EDM_PROPERTY_REF = "PropertyRef";
+
+  public static final String EDM_PROPERTY = "Property";
+  public static final String EDM_PROPERTY_NULLABLE = "Nullable";
+  public static final String EDM_PROPERTY_MAX_LENGTH = "MaxLength";
+  public static final String EDM_PROPERTY_MAX_LENGTH_MAX_VALUE = "Max";
+  public static final String EDM_PROPERTY_DEFAULT_VALUE = "DefaultValue";
+  public static final String EDM_PROPERTY_FIXED_LENGTH = "FixedLength";
+  public static final String EDM_PROPERTY_UNICODE = "Unicode";
+  public static final String EDM_PROPERTY_COLLATION = "Collation";
+  public static final String EDM_PROPERTY_PRECISION = "Precision";
+  public static final String EDM_PROPERTY_SCALE = "Scale";
+  public static final String EDM_PROPERTY_CONCURRENCY_MODE = "ConcurrencyMode";
+
+  public static final String EDM_NAVIGATION_PROPERTY = "NavigationProperty";
+  public static final String EDM_NAVIGATION_FROM_ROLE = "FromRole";
+  public static final String EDM_NAVIGATION_TO_ROLE = "ToRole";
+  public static final String EDM_NAVIGATION_RELATIONSHIP = "Relationship";
+
+  public static final String EDM_ASSOCIATION_CONSTRAINT = "ReferentialConstraint";
+  public static final String EDM_ASSOCIATION_END = "End";
+
+  public static final String EDM_ASSOCIATION_MULTIPLICITY = "Multiplicity";
+  public static final String EDM_ASSOCIATION_ONDELETE = "OnDelete";
+  public static final String EDM_ONDELETE_ACTION = "Action";
+
+  public static final String EDM_ENTITY_CONTAINER = "EntityContainer";
+  public static final String EDM_ENTITY_SET = "EntitySet";
+  public static final String EDM_ASSOCIATION_SET = "AssociationSet";
+  public static final String EDM_FUNCTION_IMPORT = "FunctionImport";
+  public static final String EDM_CONTAINER_EXTENDZ = "Extendz";
+
+  public static final String EDM_FUNCTION_IMPORT_HTTP_METHOD = "HttpMethod";
+  public static final String EDM_FUNCTION_IMPORT_RETURN = "ReturnType";
+  public static final String EDM_FUNCTION_PARAMETER = "Parameter";
+
+  public static final String M_ENTITY_TYPE_HAS_STREAM = "HasStream";
+  public static final String M_MIMETYPE = "MimeType";
+  public static final String M_FC_TARGET_PATH = "FC_TargetPath";
+  public static final String M_FC_SOURCE_PATH = "FC_SourcePath";
+  public static final String M_FC_NS_URI = "FC_NsUri";
+  public static final String M_FC_PREFIX = "FC_NsPrefix";
+  public static final String M_FC_KEEP_IN_CONTENT = "FC_KeepInContent";
+  public static final String M_FC_CONTENT_KIND = "FC_ContentKind";
+  public static final String EDM_ASSOCIATION_PRINCIPAL = "Principal";
+  public static final String EDM_ASSOCIATION_DEPENDENT = "Dependent";
+
+  public static final String EDM_ROLE = "Role";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java
new file mode 100644
index 0000000..2cb7ce8
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/parser/EdmxProvider.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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.edm.parser;
+
+import java.io.InputStream;
+import java.util.List;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+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.EntityContainerInfo;
+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.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.Schema;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+
+public class EdmxProvider extends EdmProvider {
+  private DataServices dataServices;
+
+  public EdmxProvider parse(final InputStream in, final boolean validate) throws EntityProviderException {
+    EdmParser parser = new EdmParser();
+    XMLStreamReader streamReader = createStreamReader(in);
+    dataServices = parser.readMetadata(streamReader, validate);
+    return this;
+  }
+
+  @Override
+  public EntityContainerInfo getEntityContainerInfo(final String name) throws ODataException {
+    if (name != null) {
+      for (Schema schema : dataServices.getSchemas()) {
+        for (EntityContainer container : schema.getEntityContainers()) {
+          if (container.getName().equals(name)) {
+            return container;
+          }
+        }
+      }
+    } else {
+      for (Schema schema : dataServices.getSchemas()) {
+        for (EntityContainer container : schema.getEntityContainers()) {
+          if (container.isDefaultEntityContainer()) {
+            return container;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EntityType getEntityType(final FullQualifiedName edmFQName) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+        for (EntityType entityType : schema.getEntityTypes()) {
+          if (entityType.getName().equals(edmFQName.getName())) {
+            return entityType;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public ComplexType getComplexType(final FullQualifiedName edmFQName) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+        for (ComplexType complexType : schema.getComplexTypes()) {
+          if (complexType.getName().equals(edmFQName.getName())) {
+            return complexType;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public Association getAssociation(final FullQualifiedName edmFQName) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      if (schema.getNamespace().equals(edmFQName.getNamespace())) {
+        for (Association association : schema.getAssociations()) {
+          if (association.getName().equals(edmFQName.getName())) {
+            return association;
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public EntitySet getEntitySet(final String entityContainer, final String name) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equals(entityContainer)) {
+          for (EntitySet entitySet : container.getEntitySets()) {
+            if (entitySet.getName().equals(name)) {
+              return entitySet;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public AssociationSet getAssociationSet(final String entityContainer, final FullQualifiedName association, final String sourceEntitySetName, final String sourceEntitySetRole) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equals(entityContainer)) {
+          for (AssociationSet associationSet : container.getAssociationSets()) {
+            if (associationSet.getAssociation().equals(association)
+                && ((associationSet.getEnd1().getEntitySet().equals(sourceEntitySetName) && associationSet.getEnd1().getRole().equals(sourceEntitySetRole))
+                || (associationSet.getEnd2().getEntitySet().equals(sourceEntitySetName) && associationSet.getEnd2().getRole().equals(sourceEntitySetRole)))) {
+              return associationSet;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public FunctionImport getFunctionImport(final String entityContainer, final String name) throws ODataException {
+    for (Schema schema : dataServices.getSchemas()) {
+      for (EntityContainer container : schema.getEntityContainers()) {
+        if (container.getName().equals(entityContainer)) {
+          for (FunctionImport function : container.getFunctionImports()) {
+            if (function.getName().equals(name)) {
+              return function;
+            }
+          }
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<Schema> getSchemas() throws ODataException {
+    return dataServices.getSchemas();
+  }
+
+  private XMLStreamReader createStreamReader(final InputStream in) throws EntityProviderException {
+    XMLInputFactory factory = XMLInputFactory.newInstance();
+    factory.setProperty(XMLInputFactory.IS_VALIDATING, false);
+    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+
+    XMLStreamReader streamReader;
+    try {
+      streamReader = factory.createXMLStreamReader(in);
+    } catch (XMLStreamException e) {
+      throw new EntityProviderException(EntityProviderException.EXCEPTION_OCCURRED.addContent(e.getClass().getSimpleName()), e);
+    }
+
+    return streamReader;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java
new file mode 100644
index 0000000..9c22cfd
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAnnotationsImplProv.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.EdmAnnotationElement;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationAttribute;
+import org.apache.olingo.odata2.api.edm.provider.AnnotationElement;
+
+public class EdmAnnotationsImplProv implements EdmAnnotations {
+
+  private List<AnnotationAttribute> annotationAttributes;
+  private List<? extends EdmAnnotationElement> annotationElements;
+
+  public EdmAnnotationsImplProv(final List<AnnotationAttribute> annotationAttributes, final List<AnnotationElement> annotationElements) {
+    this.annotationAttributes = annotationAttributes;
+    this.annotationElements = annotationElements;
+  }
+
+  @Override
+  public List<? extends EdmAnnotationElement> getAnnotationElements() {
+    return annotationElements;
+  }
+
+  @Override
+  public EdmAnnotationElement getAnnotationElement(final String name, final String namespace) {
+    if (annotationElements != null) {
+      Iterator<? extends EdmAnnotationElement> annotationElementIterator = annotationElements.iterator();
+
+      while (annotationElementIterator.hasNext()) {
+        EdmAnnotationElement annotationElement = annotationElementIterator.next();
+        if (annotationElement.getName().equals(name) && annotationElement.getNamespace().equals(namespace)) {
+          return annotationElement;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public List<? extends EdmAnnotationAttribute> getAnnotationAttributes() {
+    return annotationAttributes;
+  }
+
+  @Override
+  public EdmAnnotationAttribute getAnnotationAttribute(final String name, final String namespace) {
+    if (annotationElements != null) {
+      Iterator<? extends EdmAnnotationAttribute> annotationAttributesIterator = annotationAttributes.iterator();
+
+      while (annotationAttributesIterator.hasNext()) {
+        EdmAnnotationAttribute annotationAttribute = annotationAttributesIterator.next();
+        if (annotationAttribute.getName().equals(name) && annotationAttribute.getNamespace().equals(namespace)) {
+          return annotationAttribute;
+        }
+      }
+    }
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java
new file mode 100644
index 0000000..6030fa1
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationEndImplProv.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+
+public class EdmAssociationEndImplProv implements EdmAssociationEnd, EdmAnnotatable {
+
+  private EdmImplProv edm;
+  private AssociationEnd associationEnd;
+
+  public EdmAssociationEndImplProv(final EdmImplProv edm, final AssociationEnd associationEnd) throws EdmException {
+    this.edm = edm;
+    this.associationEnd = associationEnd;
+  }
+
+  @Override
+  public String getRole() {
+    return associationEnd.getRole();
+  }
+
+  @Override
+  public EdmEntityType getEntityType() throws EdmException {
+    final FullQualifiedName type = associationEnd.getType();
+    EdmEntityType entityType = edm.getEntityType(type.getNamespace(), type.getName());
+    if (entityType == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+    return entityType;
+  }
+
+  @Override
+  public EdmMultiplicity getMultiplicity() {
+    return associationEnd.getMultiplicity();
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(associationEnd.getAnnotationAttributes(), associationEnd.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java
new file mode 100644
index 0000000..3c102ca
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProv.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+
+public class EdmAssociationImplProv extends EdmNamedImplProv implements EdmAssociation, EdmAnnotatable {
+
+  private Association association;
+  private String namespace;
+
+  public EdmAssociationImplProv(final EdmImplProv edm, final Association association, final String namespace) throws EdmException {
+    super(edm, association.getName());
+    this.association = association;
+    this.namespace = namespace;
+  }
+
+  @Override
+  public String getNamespace() throws EdmException {
+    return namespace;
+  }
+
+  @Override
+  public EdmTypeKind getKind() {
+    return EdmTypeKind.ASSOCIATION;
+  }
+
+  @Override
+  public EdmAssociationEnd getEnd(final String role) throws EdmException {
+    AssociationEnd end = association.getEnd1();
+    if (end.getRole().equals(role)) {
+      return new EdmAssociationEndImplProv(edm, end);
+    }
+    end = association.getEnd2();
+    if (end.getRole().equals(role)) {
+      return new EdmAssociationEndImplProv(edm, end);
+    }
+
+    return null;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(association.getAnnotationAttributes(), association.getAnnotationElements());
+  }
+
+  public EdmMultiplicity getEndMultiplicity(final String role) {
+    if (association.getEnd1().getRole().equals(role)) {
+      return association.getEnd1().getMultiplicity();
+    }
+
+    if (association.getEnd2().getRole().equals(role)) {
+      return association.getEnd2().getMultiplicity();
+    }
+
+    return null;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java
new file mode 100644
index 0000000..4bbc1f7
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProv.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+
+public class EdmAssociationSetEndImplProv implements EdmAssociationSetEnd, EdmAnnotatable {
+
+  private EdmEntitySet entitySet;
+  private String role;
+  private AssociationSetEnd end;
+
+  public EdmAssociationSetEndImplProv(final AssociationSetEnd end, final EdmEntitySet entitySet) throws EdmException {
+    this.end = end;
+    this.entitySet = entitySet;
+    role = end.getRole();
+  }
+
+  @Override
+  public EdmEntitySet getEntitySet() throws EdmException {
+    return entitySet;
+  }
+
+  @Override
+  public String getRole() {
+    return role;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(end.getAnnotationAttributes(), end.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java
new file mode 100644
index 0000000..a831615
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProv.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+
+public class EdmAssociationSetImplProv extends EdmNamedImplProv implements EdmAssociationSet, EdmAnnotatable {
+
+  private AssociationSet associationSet;
+  private EdmEntityContainer edmEntityContainer;
+
+  public EdmAssociationSetImplProv(final EdmImplProv edm, final AssociationSet associationSet, final EdmEntityContainer edmEntityContainer) throws EdmException {
+    super(edm, associationSet.getName());
+    this.associationSet = associationSet;
+    this.edmEntityContainer = edmEntityContainer;
+  }
+
+  @Override
+  public EdmAssociation getAssociation() throws EdmException {
+    EdmAssociation association = edm.getAssociation(associationSet.getAssociation().getNamespace(), associationSet.getAssociation().getName());
+    if (association == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+    return association;
+  }
+
+  @Override
+  public EdmAssociationSetEnd getEnd(final String role) throws EdmException {
+    AssociationSetEnd end;
+
+    if (associationSet.getEnd1().getRole().equals(role)) {
+      end = associationSet.getEnd1();
+    } else if (associationSet.getEnd2().getRole().equals(role)) {
+      end = associationSet.getEnd2();
+    } else {
+      return null;
+    }
+
+    EdmEntitySet entitySet = edmEntityContainer.getEntitySet(end.getEntitySet());
+    if (entitySet == null) {
+      throw new EdmException(EdmException.COMMON);
+    }
+
+    return new EdmAssociationSetEndImplProv(end, entitySet);
+  }
+
+  @Override
+  public EdmEntityContainer getEntityContainer() throws EdmException {
+    return edmEntityContainer;
+  }
+
+  @Override
+  public EdmAnnotations getAnnotations() throws EdmException {
+    return new EdmAnnotationsImplProv(associationSet.getAnnotationAttributes(), associationSet.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java
new file mode 100644
index 0000000..70b48c6
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexPropertyImplProv.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+
+/**
+ * @author SAP AG
+ */
+public class EdmComplexPropertyImplProv extends EdmPropertyImplProv {
+
+  private ComplexProperty property;
+
+  public EdmComplexPropertyImplProv(final EdmImplProv edm, final ComplexProperty property) throws EdmException {
+    super(edm, property.getType(), property);
+    this.property = property;
+  }
+
+  @Override
+  public EdmType getType() throws EdmException {
+    if (edmType == null) {
+      edmType = edm.getComplexType(property.getType().getNamespace(), property.getType().getName());
+    }
+    if (edmType == null) {
+      throw new EdmException(EdmException.PROVIDERPROBLEM);
+    }
+    return edmType;
+  }
+
+  @Override
+  public boolean isSimple() {
+    return false;
+  }
+}


[09/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParserImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParserImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParserImpl.java
new file mode 100644
index 0000000..d81a412
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderByParserImpl.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.expression.SortOrder;
+
+public class OrderByParserImpl extends FilterParserImpl implements OrderByParser {
+  public OrderByParserImpl(final EdmEntityType resourceEntityType) {
+    super(resourceEntityType);
+  }
+
+  @Override
+  public OrderByExpression parseOrderByString(final String orderByExpression) throws ExpressionParserException, ExpressionParserInternalError {
+    curExpression = orderByExpression;
+    OrderByExpressionImpl orderCollection = new OrderByExpressionImpl(curExpression);
+
+    try {
+      tokenList = new Tokenizer(orderByExpression).tokenize(); //throws TokenizerMessage
+    } catch (TokenizerException tokenizerException) {
+      throw FilterParserExceptionImpl.createERROR_IN_TOKENIZER(tokenizerException, curExpression);
+    }
+
+    while (true) {
+      CommonExpression node = null;
+      try {
+        CommonExpression nodeLeft = readElement(null);
+        node = readElements(nodeLeft, 0);
+      } catch (ExpressionParserException expressionException) {
+        expressionException.setFilterTree(orderCollection);
+        throw expressionException;
+      }
+
+      OrderExpressionImpl orderNode = new OrderExpressionImpl(node);
+
+      //read the sort order
+      Token token = tokenList.lookToken();
+      if (token == null) {
+        orderNode.setSortOrder(SortOrder.asc);
+      } else if ((token.getKind() == TokenKind.LITERAL) && (token.getUriLiteral().equals("asc"))) {
+        orderNode.setSortOrder(SortOrder.asc);
+        tokenList.next();
+        token = tokenList.lookToken();
+      } else if ((token.getKind() == TokenKind.LITERAL) && (token.getUriLiteral().equals("desc"))) {
+        orderNode.setSortOrder(SortOrder.desc);
+        tokenList.next();
+        token = tokenList.lookToken();
+      } else if (token.getKind() == TokenKind.COMMA) {
+        orderNode.setSortOrder(SortOrder.asc);
+      } else {
+        // Tested with TestParserExceptions.TestOPMparseOrderByString CASE 1
+        throw FilterParserExceptionImpl.createINVALID_SORT_ORDER(token, curExpression);
+      }
+
+      orderCollection.addOrder(orderNode);
+
+      //ls_token may be a ',' or  empty.
+      if (token == null) {
+        break;
+      } else if (token.getKind() == TokenKind.COMMA) {
+        Token oldToken = token;
+        tokenList.next();
+        token = tokenList.lookToken();
+
+        if (token == null) {
+          // Tested with TestParserExceptions.TestOPMparseOrderByString CASE 2
+          throw FilterParserExceptionImpl.createEXPRESSION_EXPECTED_AFTER_POS(oldToken, curExpression);
+        }
+      } else { //e.g. in case $orderby=String asc a
+
+        throw FilterParserExceptionImpl.createCOMMA_OR_END_EXPECTED_AT_POS(token, curExpression);
+      }
+
+    }
+    return orderCollection;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderExpressionImpl.java
new file mode 100644
index 0000000..f07829f
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/OrderExpressionImpl.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.OrderExpression;
+import org.apache.olingo.odata2.api.uri.expression.SortOrder;
+
+/**
+ * @author SAP AG
+ */
+public class OrderExpressionImpl implements OrderExpression {
+
+  SortOrder orderType = SortOrder.asc;
+  CommonExpression expression;
+
+  OrderExpressionImpl(final CommonExpression expression) {
+    this.expression = expression;
+  }
+
+  @Override
+  public SortOrder getSortOrder() {
+    return orderType;
+  }
+
+  @Override
+  public CommonExpression getExpression() {
+    return expression;
+  }
+
+  void setSortOrder(final SortOrder orderType) {
+    this.orderType = orderType;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.ORDER;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return null;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    return this;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return "";
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    Object obj = expression.accept(visitor);
+    Object ret = visitor.visitOrder(this, obj, orderType);
+    return ret;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSet.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSet.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSet.java
new file mode 100644
index 0000000..410a590
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSet.java
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+
+/**
+ * Parameter set is a vector of 1 or more EDM types, it is used to store the possible 
+ * input and return types of a <i>OData filter operator</i> or <i>OData filter method</i>
+ * @see InfoMethod 
+ * @see InfoBinaryOperator 
+ * @see InfoUnaryOperator
+ * @author SAP AG 
+ */
+@SuppressWarnings("javadoc")
+public class ParameterSet {
+  private EdmType returnType = null;
+  public ArrayList<EdmSimpleType> types = new ArrayList<EdmSimpleType>();
+  private EdmSimpleType furtherType = null;
+
+  public ParameterSet(final EdmType returnType, final EdmSimpleType type1) {
+    this.returnType = returnType;
+    types.add(type1);
+  }
+
+  public ParameterSet(final EdmSimpleType returnType, final EdmSimpleType type1, final EdmSimpleType type2) {
+    this.returnType = returnType;
+    types.add(type1);
+    types.add(type2);
+  }
+
+  public ParameterSet(final EdmSimpleType returnType, final EdmSimpleType type1, final EdmSimpleType type2, final EdmSimpleType type3) {
+    this.returnType = returnType;
+    types.add(type1);
+    types.add(type2);
+    types.add(type3);
+  }
+
+  public EdmType getReturnType() {
+    return returnType;
+  }
+
+  public EdmSimpleType getFurtherType() {
+    return furtherType;
+  }
+
+  public ParameterSet setFurtherType(final EdmSimpleType furtherType) {
+    this.furtherType = furtherType;
+    return this;
+  }
+
+  /**
+   * Compares a list of EdmTypes with the EdmTypes stored in {@link #types}.
+   * The lists are compared sequentially, e.g index N of actualParameterTypes with index N of {@link #types}.
+   * If the input list contains more elements than stored in {@link #types} (which is allowed  when validating the <i>concat</i> method
+   * which takes a variable number of input parameters), the actual parameter type is compared against the {@link #furtherType}.
+   * @param actualParameterTypes
+   * @param allowPromotion
+   * @return true if equals
+   * @throws ExpressionParserInternalError
+   */
+  public boolean equals(final List<EdmType> actualParameterTypes, final boolean allowPromotion) throws ExpressionParserInternalError {
+    int actSize = actualParameterTypes.size();
+    int paramSize = types.size();
+
+    if (actSize < paramSize) {
+      return false;
+      //throw FilterParserInternalError.createINVALID_TYPE_COUNT(); //to few actual Parameters
+    }
+
+    //This may happen if the number of supplied actual method parameters is higher then than the number
+    //of allowed method parameters but this should be checked before, hence this is an internal error in the parser
+    if ((actSize > paramSize) && (furtherType == null)) {
+      return false;
+      //throw FilterParserInternalError.createINVALID_TYPE_COUNT();
+    }
+
+    for (int i = 0; i < actSize; i++) {
+      EdmType actType = actualParameterTypes.get(i);
+      if (actType == null) {
+        return false;
+      }
+
+      EdmSimpleType paramType = null;
+      if (i < paramSize) {
+        paramType = types.get(i);
+      } else {
+        paramType = furtherType; // for methods with variable amount of method parameters  
+      }
+
+      if (!actType.equals(paramType)) {
+        //this the parameter type does not fit and if it is not allowed to promoted the actual parameter then
+        //this parameter combination does not fit
+        if (!allowPromotion) {
+          return false;
+        }
+
+        //Its allowed to promoted the actual parameter!!!
+
+        //Promotion only allowed for simple types
+        if (actType.getKind() != EdmTypeKind.SIMPLE) {
+          return false; //Tested with TestParserExceptions.testAdditionalStuff CASE 8
+        }
+
+        //The type simply don't match          
+        if (!paramType.isCompatible((EdmSimpleType) actType)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSetCombination.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSetCombination.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSetCombination.java
new file mode 100644
index 0000000..a989055
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/ParameterSetCombination.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+public interface ParameterSetCombination {
+
+  void add(ParameterSet parameterSet);
+
+  ParameterSet validate(List<EdmType> actualParameterTypes) throws ExpressionParserInternalError;
+
+  void addFirst(ParameterSet parameterSet);
+
+  EdmType getReturnType();
+
+  public static class PSCflex implements ParameterSetCombination {
+    public List<ParameterSet> combinations = new ArrayList<ParameterSet>();
+
+    @Override
+    public void add(final ParameterSet parameterSet) {
+      combinations.add(parameterSet);
+    }
+
+    @Override
+    public EdmType getReturnType() {
+      int parameterCount = combinations.size();
+      if (parameterCount == 0) {
+        return null;
+      }
+
+      if (parameterCount == 1) {
+        return combinations.get(0).getReturnType();
+      }
+
+      //There are more than 1 possible return type, check if they are equal, if not return null.
+      EdmType returnType = combinations.get(0).getReturnType();
+      for (int i = 1; i < parameterCount; i++) {
+        if (returnType != combinations.get(i)) {
+          return null;
+        }
+      }
+
+      return returnType;
+
+    }
+
+    @Override
+    public void addFirst(final ParameterSet parameterSet) {
+      List<ParameterSet> oldCombinations = combinations;
+      combinations = new ArrayList<ParameterSet>();
+      combinations.add(parameterSet);
+      for (ParameterSet parameterSet1 : oldCombinations) {
+        combinations.add(parameterSet1);
+      }
+
+    }
+
+    @Override
+    public ParameterSet validate(final List<EdmType> actualParameterTypes) throws ExpressionParserInternalError {
+      if (combinations.size() == 0) {
+        return new ParameterSet(null, null);
+      }
+
+      //first check for exact parameter combination
+      for (ParameterSet parameterSet : combinations) {
+        boolean s = parameterSet.equals(actualParameterTypes, false);
+        if (s) {
+          return parameterSet;
+        }
+      }
+
+      //first check for parameter combination with promotion
+      for (ParameterSet parameterSet : combinations) {
+        boolean s = parameterSet.equals(actualParameterTypes, true);
+        if (s) {
+          return parameterSet;
+        }
+      }
+      return null;
+    }
+
+  }
+
+  public static class PSCReturnTypeEqLastParameter implements ParameterSetCombination {
+
+    @Override
+    public void add(final ParameterSet parameterSet) {
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public void addFirst(final ParameterSet parameterSet) {
+      throw new IllegalStateException();
+    }
+
+    @Override
+    public ParameterSet validate(final List<EdmType> actualParameterTypes) throws ExpressionParserInternalError {
+      EdmType xxx = actualParameterTypes.get(actualParameterTypes.size() - 1);
+      return new ParameterSet(xxx, null);
+      //return actualParameterTypes.get(actualParameterTypes.size() - 1);
+    }
+
+    @Override
+    public EdmType getReturnType() {
+      //If the return type is always the type of the last parameter of the actual parameters ( e.g. when using the method operator) 
+      //then the return type can not predicted.
+      return null;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/PropertyExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/PropertyExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/PropertyExpressionImpl.java
new file mode 100644
index 0000000..7e13237
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/PropertyExpressionImpl.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
+
+public class PropertyExpressionImpl implements PropertyExpression {
+  private String uriLiteral;
+  private EdmType edmType;
+  private EdmTyped edmProperty;
+  private EdmLiteral edmLiteral;
+
+  public PropertyExpressionImpl(final String uriLiteral, final EdmLiteral edmLiteral) {
+    this.uriLiteral = uriLiteral;
+
+    this.edmLiteral = edmLiteral;
+    if (edmLiteral != null) {
+      edmType = edmLiteral.getType();
+    }
+  }
+
+  public CommonExpression setEdmProperty(final EdmTyped edmProperty) {
+    //used EdmTyped because it may be a EdmProperty or a EdmNavigationProperty
+    this.edmProperty = edmProperty;
+    return this;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    this.edmType = edmType;
+    return this;
+  }
+
+  @Override
+  public String getPropertyName() {
+    if (edmProperty == null) {
+      return "";
+    }
+
+    try {
+      return edmProperty.getName();
+    } catch (EdmException e) {
+      return "";
+    }
+  }
+
+  public EdmLiteral getEdmLiteral() {
+    return edmLiteral;
+  }
+
+  @Override
+  public EdmTyped getEdmProperty() {
+    return edmProperty;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.PROPERTY;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return uriLiteral;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return edmType;
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) {
+    Object ret = visitor.visitProperty(this, uriLiteral, edmProperty);
+    return ret;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Token.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Token.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Token.java
new file mode 100644
index 0000000..e1f0354
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Token.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+/*1*/
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+
+public class Token {
+
+  private TokenKind kind;
+  private int position;
+  private String uriLiteral;
+  private EdmLiteral javaLiteral;
+
+  public Token(final TokenKind kind, final int position, final String uriLiteral, final EdmLiteral javaLiteral) {
+    this.kind = kind;
+    this.position = position;
+    this.uriLiteral = uriLiteral;
+    this.javaLiteral = javaLiteral;
+  }
+
+  public Token(final TokenKind kind, final int position, final String uriLiteral) {
+    this.kind = kind;
+    this.position = position;
+    this.uriLiteral = uriLiteral;
+    javaLiteral = null;
+  }
+
+  public TokenKind getKind() {
+    return kind;
+  }
+
+  public int getPosition() {
+    return position;
+  }
+
+  public EdmType getEdmType() {
+    if (javaLiteral == null) {
+      return null;
+    }
+    return javaLiteral.getType();
+  }
+
+  public String getUriLiteral() {
+    return uriLiteral;
+  }
+
+  public EdmLiteral getJavaLiteral() {
+    return javaLiteral;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenKind.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenKind.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenKind.java
new file mode 100644
index 0000000..fff6bb2
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenKind.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+/*1*/
+
+/**
+ * The token kind is used to categorize a single {@link Token}.
+ * The Expression parser ({@link FilterParserImpl}) uses this information 
+ * to build the expression tree.
+ */
+public enum TokenKind {
+  /**
+   * Indicates that the token is a whitespace character
+   */
+  WHITESPACE,
+
+  /**
+   * Indicates that the token is a '(' character
+   */
+  OPENPAREN,
+
+  /**
+   * Indicates that the token is a ')' character
+   */
+  CLOSEPAREN,
+
+  /**
+   * Indicates that the token is a ',' character
+   */
+  COMMA,
+
+  /**
+   * Indicates that the token is a typed literal. That may be a 
+   * Edm.String like 'TEST'
+   * Edm.Double like '1.1D' 
+   * or any other Edm.Simple Type
+   */
+  SIMPLE_TYPE,
+
+  /**
+   * Indicates that the token is a single symbol. That may be a
+   * '-', '=', '/', '?', '.' or a '*' character  
+   */
+  SYMBOL,
+
+  /**
+   * Indicates that the token is a set of alphanumeric characters starting
+   * with a letter
+   */
+  LITERAL, TYPED_LITERAL_TODO_CHECK, UNKNOWN
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenList.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenList.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenList.java
new file mode 100644
index 0000000..e08ba17
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenList.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+
+public class TokenList implements Iterator<Token> {
+  private ArrayList<Token> tokens = null;
+  int currentToken = 0;
+
+  public TokenList() {
+    tokens = new ArrayList<Token>();
+  }
+
+  /**
+   * Append StringValue Token to tokens parameter
+   * @param position Position of parsed token 
+   * @param kind Kind of parsed token
+   * @param uriLiteral String value of parsed token
+   */
+  public void appendToken(final int position, final TokenKind kind, final String uriLiteral) {
+    Token token = new Token(kind, position, uriLiteral);
+    tokens.add(token);
+    return;
+  }
+
+  /**
+   * Append CharValue Token to tokens parameter
+   * @param position Position of parsed token 
+   * @param kind Kind of parsed token
+   * @param charValue Char value of parsed token
+   */
+  public void appendToken(final int position, final TokenKind kind, final char charValue) {
+    Token token = new Token(kind, position, Character.toString(charValue));
+    tokens.add(token);
+    return;
+  }
+
+  /**
+   * Append UriLiteral Token to tokens parameter
+   * @param position Position of parsed token 
+   * @param kind Kind of parsed token
+   * @param javaLiteral EdmLiteral of parsed token containing type and value of UriLiteral 
+   */
+  public void appendEdmTypedToken(final int position, final TokenKind kind, final String uriLiteral, final EdmLiteral javaLiteral) {
+    Token token = new Token(kind, position, uriLiteral, javaLiteral);
+    tokens.add(token);
+    return;
+  }
+
+  public Token lookToken() {
+    if (currentToken >= tokens.size()) {
+      return null;
+    }
+
+    return tokens.get(currentToken);
+  }
+
+  public Token lookPrevToken() {
+    if (currentToken - 1 < 0) {
+      return null;
+    }
+
+    return tokens.get(currentToken - 1);
+  }
+
+  public boolean hasTokens() {
+    return (tokens.size() > 0);
+  }
+
+  public int tokenCount() {
+    int i = tokens.size();
+
+    return i;
+  }
+
+  public Token expectToken(final TokenKind comma) throws TokenizerExpectError {
+    Token actual = next();
+    if (actual == null) {
+      throw TokenizerExpectError.createNO_TOKEN_AVAILABLE(comma.toString());
+    }
+
+    if (comma != actual.getKind()) {
+      throw TokenizerExpectError.createINVALID_TOKENKIND_AT(comma, actual);
+    }
+    return actual;
+  }
+
+  public Token expectToken(final TokenKind comma, final boolean throwFilterExpression) throws ExpressionParserInternalError {
+    Token actual = next();
+    if (actual == null) {
+      throw ExpressionParserInternalError.createNO_TOKEN_AVAILABLE(comma.toString());
+    }
+
+    if (comma != actual.getKind()) {
+      if (throwFilterExpression) {
+        throw ExpressionParserInternalError.createINVALID_TOKENKIND_AT(comma, actual);
+      }
+    }
+    return actual;
+  }
+
+  public Token expectToken(final String literal) throws TokenizerExpectError {
+    Token actual = next();
+    if (actual == null) {
+      throw TokenizerExpectError.createNO_TOKEN_AVAILABLE(literal);
+    }
+
+    if (!literal.equals(actual.getUriLiteral())) {
+      throw TokenizerExpectError.createINVALID_TOKEN_AT(literal, actual);
+    }
+    return actual;
+  }
+
+  public Token expectToken(final String literal, final boolean throwInternal) throws ExpressionParserInternalError {
+    Token actual = next();
+    if (actual == null) {
+      throw ExpressionParserInternalError.createNO_TOKEN_AVAILABLE(literal);
+    }
+
+    if (!literal.equals(actual.getUriLiteral())) {
+      if (throwInternal) {
+        throw ExpressionParserInternalError.createINVALID_TOKEN_AT(literal, actual);
+      }
+    }
+    return actual;
+  }
+
+  public void skip() {
+    currentToken++;
+  }
+
+  @Override
+  public boolean hasNext() {
+    return (currentToken < tokens.size());
+  }
+
+  @Override
+  public Token next() {
+    if (currentToken >= tokens.size()) {
+      return null;
+    }
+
+    Token ret = tokens.get(currentToken);
+    currentToken++;
+    return ret;
+  }
+
+  @Override
+  public void remove() {
+    throw new IllegalArgumentException("Method not allowed");
+  }
+
+  public Token elementAt(final int index) {
+
+    return tokens.get(index);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Tokenizer.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Tokenizer.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Tokenizer.java
new file mode 100644
index 0000000..d449208
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/Tokenizer.java
@@ -0,0 +1,323 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeFacade;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+
+/**
+ * Expression tokenizer
+ * @author SAP AG
+ */
+public class Tokenizer {
+
+  //Pattern OTHER_LIT = Pattern.compile("^([[A-Za-z0-9]._~%!$&*+;:@-]+)");
+  private static final Pattern OTHER_LIT = Pattern.compile("(?:\\p{L}|\\p{Digit}|[-._~%!$&*+;:@])+");
+  private static final Pattern FUNK = Pattern.compile("^(startswith|endswith|substring|substring|substringof|indexof|replace|tolower|toupper|trim|concat|length|year|mounth|day|hour|minute|second|round|ceiling|floor)( *)\\(");
+  private static final Pattern AND_SUB1 = Pattern.compile("^(add|sub|mul|div|mod|not) ");
+  private static final Pattern AND_SUB = Pattern.compile("^(and|or|eq|ne|lt|gt|le|ge) ");
+  private static final Pattern prefix = Pattern.compile("^(X|binary|guid|datetime|datetimeoffset|time)'");
+  private boolean flagIncludeWhitespace = false;
+  private EdmSimpleTypeFacade typeDectector = null;
+
+  int curPosition;
+  final String expression;
+  final int expressionLength;
+  TokenList tokens;
+
+  public Tokenizer(final String expression) {
+    typeDectector = new EdmSimpleTypeFacadeImpl();
+    this.expression = expression;
+    expressionLength = expression.length();
+    tokens = new TokenList();
+  }
+
+  /**
+   * Inform the Tokenizer whether extra tokens for whitespace characters should be added to the token list or not.
+   * @param flagIncludeWhitespace True -> Whitespace token will be added to token list; False otherwise
+   * @return this
+   */
+  public Tokenizer setFlagWhiteSpace(final Boolean flagIncludeWhitespace) {
+    this.flagIncludeWhitespace = flagIncludeWhitespace;
+    return this;
+  }
+
+  /**
+   * Tokenizes an expression as defined per OData specification 
+   * @return Token list 
+   */
+  public TokenList tokenize() throws TokenizerException, ExpressionParserException {
+    curPosition = 0;
+    int oldPosition;
+    char curCharacter;
+    String token = "";
+
+    while (curPosition < expressionLength) {
+      oldPosition = curPosition;
+
+      curCharacter = expression.charAt(curPosition);
+      switch (curCharacter) {
+      case ' ':
+        //count whitespace and move pointer to next non-whitespace char
+        eatWhiteSpaces(curPosition, curCharacter);
+        break;
+
+      case '(':
+        tokens.appendToken(curPosition, TokenKind.OPENPAREN, curCharacter);
+        curPosition = curPosition + 1;
+
+        break;
+
+      case ')':
+        tokens.appendToken(curPosition, TokenKind.CLOSEPAREN, curCharacter);
+        curPosition = curPosition + 1;
+        break;
+
+      case '\'':
+        token = "";
+        readLiteral(curCharacter);
+
+        break;
+
+      case ',':
+        tokens.appendToken(oldPosition, TokenKind.COMMA, curCharacter);
+        curPosition = curPosition + 1;
+        break;
+
+      case '=':
+      case '/':
+      case '?':
+      case '.':
+      case '*':
+        curPosition = curPosition + 1;
+        tokens.appendToken(oldPosition, TokenKind.SYMBOL, curCharacter);
+        break;
+
+      default:
+        String rem_expr = expression.substring(curPosition); //remaining expression
+
+        boolean isBinary = checkForBinary(oldPosition, rem_expr);
+        if (isBinary) {
+          break;
+        }
+
+        //check for prefixes like X, binary, guid, datetime
+        boolean isPrefix = checkForPrefix(rem_expr);
+        if (isPrefix) {
+          break;
+        }
+
+        //check for math
+        boolean isMath = checkForMath(oldPosition, rem_expr);
+        if (isMath) {
+          break;
+        }
+
+        //check for function
+        boolean isFunction = checkForMethod(oldPosition, rem_expr);
+        if (isFunction) {
+          break;
+        }
+
+        boolean isBoolean = checkForBoolean(oldPosition, rem_expr);
+        if (isBoolean) {
+          break;
+        }
+
+        boolean isLiteral = checkForLiteral(oldPosition, curCharacter, rem_expr);
+        if (isLiteral) {
+          break;
+        }
+
+        token = new Character(curCharacter).toString();
+        throw TokenizerException.createUNKNOWN_CHARACTER(oldPosition, token, expression);
+      }
+    }
+    return tokens;
+  }
+
+  private boolean checkForLiteral(final int oldPosition, final char curCharacter, final String rem_expr) {
+    final Matcher matcher = OTHER_LIT.matcher(rem_expr);
+    boolean isLiteral = false;
+    if (matcher.lookingAt()) {
+      String token = matcher.group();
+      try {
+        EdmLiteral edmLiteral = typeDectector.parseUriLiteral(token);
+        curPosition = curPosition + token.length();
+        // It is a simple type.
+        tokens.appendEdmTypedToken(oldPosition, TokenKind.SIMPLE_TYPE, token, edmLiteral);
+        isLiteral = true;
+      } catch (EdmLiteralException e) {
+        // We treat it as normal untyped literal. 
+
+        // The '-' is checked here (and not in the switch statement) because it may be
+        // part of a negative number.
+        if (curCharacter == '-') {
+          curPosition = curPosition + 1;
+          tokens.appendToken(oldPosition, TokenKind.SYMBOL, curCharacter);
+          isLiteral = true;
+        } else {
+          curPosition = curPosition + token.length();
+          tokens.appendToken(oldPosition, TokenKind.LITERAL, token);
+          isLiteral = true;
+        }
+      }
+    }
+    return isLiteral;
+  }
+
+  private boolean checkForBoolean(final int oldPosition, final String rem_expr) {
+    boolean isBoolean = false;
+    if (rem_expr.equals("true") || rem_expr.equals("false")) {
+      curPosition = curPosition + rem_expr.length();
+      tokens.appendEdmTypedToken(oldPosition, TokenKind.SIMPLE_TYPE, rem_expr, new EdmLiteral(EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.Boolean), rem_expr));
+      isBoolean = true;
+    }
+    return isBoolean;
+  }
+
+  private void eatWhiteSpaces(final int oldPosition, char curCharacter) {
+    int lv_token_len;
+    String expression_sub;
+    while ((curCharacter == ' ') && (curPosition < expressionLength)) {
+      curPosition = curPosition + 1;
+      if (curPosition < expressionLength) {
+        curCharacter = expression.charAt(curPosition);
+      }
+    }
+
+    lv_token_len = curPosition - oldPosition;
+
+    if (flagIncludeWhitespace == true) {
+      expression_sub = expression.substring(oldPosition, oldPosition + lv_token_len);
+      tokens.appendEdmTypedToken(oldPosition, TokenKind.WHITESPACE, expression_sub, null);
+    }
+  }
+
+  private boolean checkForMethod(final int oldPosition, final String rem_expr) {
+    boolean isMethod = false;
+    Matcher matcher = FUNK.matcher(rem_expr);
+    if (matcher.find()) {
+      String token = matcher.group(1);
+      curPosition = curPosition + token.length();
+      tokens.appendToken(oldPosition, TokenKind.LITERAL, token);
+      isMethod = true;
+    }
+    return isMethod;
+  }
+
+  private boolean checkForMath(final int oldPosition, final String rem_expr) {
+    boolean isMath = false;
+    Matcher matcher1 = AND_SUB1.matcher(rem_expr);
+    if (matcher1.find()) {
+      String token = matcher1.group(1);
+      curPosition = curPosition + token.length();
+      tokens.appendToken(oldPosition, TokenKind.LITERAL, token);
+      isMath = true;
+    }
+    return isMath;
+  }
+
+  private boolean checkForBinary(final int oldPosition, final String rem_expr) {
+    boolean isBinary = false;
+    Matcher matcher1 = AND_SUB.matcher(rem_expr);
+    if (matcher1.find()) {
+      String token = matcher1.group(1);
+      curPosition = curPosition + token.length();
+      tokens.appendToken(oldPosition, TokenKind.LITERAL, token);
+      isBinary = true;
+    }
+    return isBinary;
+  }
+
+  private boolean checkForPrefix(final String rem_expr) throws ExpressionParserException, TokenizerException {
+    boolean isPrefix = false;
+    Matcher matcher = prefix.matcher(rem_expr);
+    String token = "";
+    char curCharacter;
+
+    if (matcher.find()) {
+      token = matcher.group(1);
+      curPosition = curPosition + token.length();
+      curCharacter = expression.charAt(curPosition); //"should  be '
+      readLiteral(curCharacter, token);
+      isPrefix = true;
+    }
+    return isPrefix;
+  }
+
+  private void readLiteral(final char curCharacter) throws ExpressionParserException, TokenizerException {
+    readLiteral(curCharacter, "");
+  }
+
+  /**
+   * Read up to single ' and move pointer to the following char and tries a type detection
+   * @param curCharacter
+   * @param token
+   * @throws ExpressionParserException
+   * @throws TokenizerException
+   */
+  private void readLiteral(char curCharacter, String token) throws ExpressionParserException, TokenizerException {
+    int offsetPos = -token.length();
+    int oldPosition = curPosition;
+    token = token + Character.toString(curCharacter);
+    curPosition = curPosition + 1;
+
+    boolean wasApostroph = false; //leading ' does not count
+    while (curPosition < expressionLength) {
+      curCharacter = expression.charAt(curPosition);
+
+      if (curCharacter != '\'') {
+        if (wasApostroph == true) {
+          break;
+        }
+
+        token = token + curCharacter;
+        wasApostroph = false;
+      } else {
+        if (wasApostroph) {
+          wasApostroph = false; //a double ' is a normal character '
+        } else {
+          wasApostroph = true;
+          token = token + curCharacter;
+        }
+      }
+      curPosition = curPosition + 1;
+    }
+
+    if (!wasApostroph) {
+      //Exception tested within TestPMparseFilterString
+      throw FilterParserExceptionImpl.createTOKEN_UNDETERMINATED_STRING(oldPosition, expression);
+    }
+
+    try {
+      EdmLiteral edmLiteral = typeDectector.parseUriLiteral(token);
+      tokens.appendEdmTypedToken(oldPosition + offsetPos, TokenKind.SIMPLE_TYPE, token, edmLiteral);
+    } catch (EdmLiteralException ex) {
+      throw TokenizerException.createTYPEDECTECTION_FAILED_ON_STRING(ex, oldPosition, token);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerException.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerException.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerException.java
new file mode 100644
index 0000000..695bc8a
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerException.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmLiteralException;
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+
+/**
+ * This exception is thrown if there is an error during tokenizing.<br>
+ * <b>This exception in not in the public API</b>, but may be added as cause for
+ * the {@link org.apache.olingo.odata2.api.uri.expression.ExpressionParserException} exception.  
+ * @author SAP AG
+ */
+public class TokenizerException extends ODataMessageException {
+  private static final long serialVersionUID = 77L;
+
+  public static final MessageReference TYPEDECTECTION_FAILED_ON_STRING = createMessageReference(TokenizerException.class, "TYPEDECTECTION_FAILED_ON_STRING");
+  public static final MessageReference UNKNOWN_CHARACTER = createMessageReference(TokenizerException.class, "UNKNOWN_CHARACTER");
+
+  private Token token;
+  private int position;
+
+  public Token getToken() {
+    return token;
+  }
+
+  public TokenizerException setToken(final Token token) {
+    this.token = token;
+    return this;
+  }
+
+  public int getPosition() {
+    return position;
+  }
+
+  public void setPosition(final int position) {
+    this.position = position;
+  }
+
+  public TokenizerException(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public TokenizerException(final MessageReference messageReference, final Throwable cause) {
+    super(messageReference, cause);
+  }
+
+  static public TokenizerException createTYPEDECTECTION_FAILED_ON_STRING(final EdmLiteralException ex, final int position, final String uriLiteral) {
+    MessageReference msgRef = TokenizerException.TYPEDECTECTION_FAILED_ON_STRING.create();
+
+    msgRef.addContent(uriLiteral);
+    msgRef.addContent(position);
+    Token token = new Token(TokenKind.UNKNOWN, position, uriLiteral);
+
+    return new TokenizerException(msgRef, ex).setToken(token);
+  }
+
+  /*
+  static public TokenizerException createTYPEDECTECTION_FAILED_ON_EDMTYPE(EdmLiteralException ex, int position, String uriLiteral)
+  {
+    MessageReference msgRef = TokenizerException.TYPEDECTECTION_FAILED_ON_EDMTYPE.create();
+
+    msgRef.addContent(uriLiteral);
+    msgRef.addContent(position);
+    Token token = new Token(TokenKind.UNKNOWN, position, uriLiteral);
+
+    return new TokenizerException(msgRef).setToken(token);
+  }
+  */
+  static public TokenizerException createUNKNOWN_CHARACTER(final int position, final String uriLiteral, final String expression) {
+    MessageReference msgRef = TokenizerException.UNKNOWN_CHARACTER.create();
+
+    msgRef.addContent(uriLiteral);
+    msgRef.addContent(position);
+    msgRef.addContent(expression);
+    Token token = new Token(TokenKind.UNKNOWN, position, uriLiteral);
+
+    return new TokenizerException(msgRef).setToken(token);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerExpectError.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerExpectError.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerExpectError.java
new file mode 100644
index 0000000..1b84b2c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerExpectError.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.exception.MessageReference;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+
+/**
+ * This exception is thrown if a token should be read
+ * from the top of the {@link TokenList} which does not match an 
+ * expected token. The cause for using this exception <b>MUST</b> indicate an internal error 
+ * in the {@link Tokenizer} or inside the {@link FilterParserImpl}.
+ * <br><br>
+ * <b>This exception in not in the public API</b>, but may be added as cause for
+ * the {@link ExpressionParserInternalError} exception. 
+ * @author SAP AG
+  */
+public class TokenizerExpectError extends ODataMessageException {
+
+  private static final long serialVersionUID = 1L;
+
+  public static final int parseStringpoken = 1;
+
+  //Invalid token detected at position &POSITION&
+  public static final MessageReference NO_TOKEN_AVAILABLE = createMessageReference(TokenizerExpectError.class, "NO_TOKEN_AVAILABLE");
+  public static final MessageReference INVALID_TOKEN_AT = createMessageReference(TokenizerExpectError.class, "INVALID_TOKEN_AT");
+  public static final MessageReference INVALID_TOKENKIND_AT = createMessageReference(TokenizerExpectError.class, "INVALID_TOKENKIND_AT");
+
+  private String token;
+  private Exception previous;
+  private int position;
+
+  public String getToken() {
+    return token;
+  }
+
+  public void setToken(final String token) {
+    this.token = token;
+  }
+
+  public Exception getPrevious() {
+    return previous;
+  }
+
+  public void setPrevious(final Exception previous) {
+    this.previous = previous;
+  }
+
+  public int getPosition() {
+    return position;
+  }
+
+  public void setPosition(final int position) {
+    this.position = position;
+  }
+
+  public TokenizerExpectError(final MessageReference messageReference) {
+    super(messageReference);
+  }
+
+  public static TokenizerExpectError createINVALID_TOKEN_AT(final String expectedToken, final Token actualToken) {
+    MessageReference msgRef = TokenizerExpectError.INVALID_TOKEN_AT.create();
+
+    msgRef.addContent(expectedToken);
+    msgRef.addContent(actualToken.getUriLiteral());
+    msgRef.addContent(actualToken.getPosition());
+
+    return new TokenizerExpectError(msgRef);
+  }
+
+  public static TokenizerExpectError createINVALID_TOKENKIND_AT(final TokenKind expectedTokenKind, final Token actualToken) {
+    MessageReference msgRef = TokenizerExpectError.INVALID_TOKEN_AT.create();
+
+    msgRef.addContent(expectedTokenKind.toString());
+    msgRef.addContent(actualToken.getKind().toString());
+    msgRef.addContent(actualToken.getUriLiteral());
+    msgRef.addContent(actualToken.getPosition());
+
+    return new TokenizerExpectError(msgRef);
+  }
+
+  public static TokenizerExpectError createNO_TOKEN_AVAILABLE(final String expectedToken) {
+    MessageReference msgRef = TokenizerExpectError.INVALID_TOKEN_AT.create();
+
+    msgRef.addContent(expectedToken);
+
+    return new TokenizerExpectError(msgRef);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerRTException.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerRTException.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerRTException.java
new file mode 100644
index 0000000..e230919
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/TokenizerRTException.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+/**
+ * Internal error. If used(thrown) the thrower
+ * @author SAP AG 
+ */
+public class TokenizerRTException extends Exception {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * 
+   */
+  public TokenizerRTException() {
+    super();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/UnaryExpressionImpl.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/UnaryExpressionImpl.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/UnaryExpressionImpl.java
new file mode 100644
index 0000000..06be49e
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/uri/expression/UnaryExpressionImpl.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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.uri.expression;
+
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.exception.ODataApplicationException;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionVisitor;
+import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.UnaryOperator;
+
+/**
+ * @author SAP AG
+ */
+public class UnaryExpressionImpl implements UnaryExpression {
+  private InfoUnaryOperator operatorInfo = null;
+  private CommonExpression operand = null;
+  private EdmType edmType = null;
+
+  public UnaryExpressionImpl(final InfoUnaryOperator operatorInfo, final CommonExpression operand) {
+    this.operatorInfo = operatorInfo;
+    this.operand = operand;
+  }
+
+  @Override
+  public ExpressionKind getKind() {
+    return ExpressionKind.UNARY;
+  }
+
+  @Override
+  public UnaryOperator getOperator() {
+    return operatorInfo.operator;
+  }
+
+  @Override
+  public CommonExpression getOperand() {
+    return operand;
+  }
+
+  @Override
+  public EdmType getEdmType() {
+    return edmType;
+  }
+
+  @Override
+  public CommonExpression setEdmType(final EdmType edmType) {
+    this.edmType = edmType;
+    return this;
+  }
+
+  @Override
+  public String getUriLiteral() {
+    return operatorInfo.getSyntax();
+  }
+
+  @Override
+  public Object accept(final ExpressionVisitor visitor) throws ExceptionVisitExpression, ODataApplicationException {
+    Object retOperand = operand.accept(visitor);
+
+    return visitor.visitUnary(this, operatorInfo.getOperator(), retOperand);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/resources/i18n.properties
----------------------------------------------------------------------
diff --git a/odata-core/src/main/resources/i18n.properties b/odata-core/src/main/resources/i18n.properties
new file mode 100644
index 0000000..1627223
--- /dev/null
+++ b/odata-core/src/main/resources/i18n.properties
@@ -0,0 +1,229 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# Fallback
+#
+##################################
+# CommonExceptions (Should these exist?)
+##################################
+org.apache.olingo.odata2.api.exception.ODataMessageException.COMMON=Common exception
+
+##################################
+# UriParserExceptions
+##################################
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.MATCHPROBLEM=Could not match segment: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.NOTFOUND=Could not find an entity set or function import for '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.CONTAINERNOTFOUND=Could not find container with name: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.ENTITYNOTFOUND=Could not find entity with name: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriNotMatchingException.PROPERTYNOTFOUND=Could not find property with name: '%1$s'.
+
+org.apache.olingo.odata2.api.uri.UriSyntaxException.URISYNTAX=Invalid URI syntax.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.ENTITYSETINSTEADOFENTITY=Must be an entity set instead of an entity: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.NOTEXT=An exception occurred.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.NOMEDIARESOURCE=The requested resource is no media resource.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.NONAVIGATIONPROPERTY=Property '%1$s' must be a navigation property. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MISSINGPARAMETER=Missing parameter.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MISSINGKEYPREDICATENAME=Missing key predicate name for key: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.DUPLICATEKEYNAMES=Duplicate key names: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.EMPTYSEGMENT=No empty segment allowed.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MUSTNOTBELASTSEGMENT='%1$s' must not be the last segment. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.MUSTBELASTSEGMENT='%1$s' must be the last segment.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDSEGMENT=Invalid segment: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDVALUE=Invalid value: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDNULLVALUE=Value for '%1$s' must not be null.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDNEGATIVEVALUE=Provided value '%1$s' must not be negative.  
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDRETURNTYPE=Invalid return type: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDPROPERTYTYPE=Invalid type for property: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDKEYPREDICATE=Invalid key predicate: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDSYSTEMQUERYOPTION=Invalid system query option: '%1$s'. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDFILTEREXPRESSION=Invalid filter expression: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INVALIDORDERBYEXPRESSION=Invalid order by expression: '%1$s'. 
+org.apache.olingo.odata2.api.uri.UriSyntaxException.LITERALFORMAT=Wrong literal format for literal: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.UNKNOWNLITERAL=Unknown literal: '%1$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INCOMPATIBLELITERAL=Format of '%1$s' is not compatible with '%2$s'.
+org.apache.olingo.odata2.api.uri.UriSyntaxException.INCOMPATIBLESYSTEMQUERYOPTION=System query option '%1$s' is not compatible with the return type.
+
+##################################
+# EDMExceptions
+##################################
+org.apache.olingo.odata2.api.edm.EdmLiteralException.NOTEXT=An exception occurred.
+org.apache.olingo.odata2.api.edm.EdmLiteralException.LITERALFORMAT=Wrong literal format for literal: '%1$s'.
+org.apache.olingo.odata2.api.edm.EdmLiteralException.UNKNOWNLITERAL=Unknown literal: '%1$s'.
+
+org.apache.olingo.odata2.api.edm.EdmException.COMMON=An exception occurred.
+org.apache.olingo.odata2.api.edm.EdmException.PROVIDERPROBLEM=A problem has been detected in the metadata provided by the EDM provider.
+
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.COMMON=An exception occurred.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_KIND_MISSING=The literal kind is missing.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_KIND_NOT_SUPPORTED=The literal kind '%1$s' is not supported.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_NULL_NOT_ALLOWED=The metadata do not allow a null literal.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_ILLEGAL_CONTENT=The literal '%1$s' is not formatted properly.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_FACETS_NOT_MATCHED=The metadata constraints '%2$s' do not match the literal '%1$s'.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.LITERAL_UNCONVERTIBLE_TO_VALUE_TYPE=The literal '%1$s' can not be converted into the type '%1$s'.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_TYPE_NOT_SUPPORTED=The type '%1$s' of the value object is not supported.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_NULL_NOT_ALLOWED=The metadata do not allow a null value.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_ILLEGAL_CONTENT=The value object '%1$s' can not be formatted properly due to its content.
+org.apache.olingo.odata2.api.edm.EdmSimpleTypeException.VALUE_FACETS_NOT_MATCHED=The metadata constraints '%2$s' do not allow to format the value '%1$s'.
+
+##################################
+# EPexceptions
+##################################
+org.apache.olingo.odata2.api.ep.EntityProviderException.COMMON=An exception occurred.
+org.apache.olingo.odata2.api.ep.EntityProviderException.EXCEPTION_OCCURRED=An exception of type '%1$s' occurred.
+org.apache.olingo.odata2.api.ep.EntityProviderException.ILLEGAL_ARGUMENT=Illegal argument for method call with message '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INLINECOUNT_INVALID=Invalid inline count found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_STATE=Invalid consuming state for parsing with message '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_INLINE_CONTENT=Invalid '%1$s' found for parsing of inline content.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_PROPERTY=Invalid property '%1$s' found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_NAMESPACE=Invalid or missing namespace for '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_PARENT_TAG=Invalid parent tag. Expected '%1$s' but found '%2$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_MAPPING=Invalid mapping value for property '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_ENTITYTYPE=Supplied entity type '%1$s' does not match the content entity type '%2$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_COMPLEX_TYPE=Supplied complex type '%1$s' does not match the content complex type '%2$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_CONTENT='%1$s' not expected in '%2$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.INVALID_PROPERTY_VALUE=Provided value for the property '%1$s' is not compatible with the property.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MISSING_ATTRIBUTE=Mandatory attribute '%1$s' at tag '%2$s' was not found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MISSING_PROPERTY=Property with name '%1$s' was not found.
+org.apache.olingo.odata2.api.ep.EntityProviderException.NOT_SET_CHARACTER_ENCODING=Mandatory character encoding is not set.
+org.apache.olingo.odata2.api.ep.EntityProviderException.DOUBLE_PROPERTY=Double occurrence of property with name '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.UNSUPPORTED_CHARACTER_ENCODING=The given character encoding '%1$s' is not supported.
+org.apache.olingo.odata2.api.ep.EntityProviderException.UNSUPPORTED_PROPERTY_TYPE=The given property type '%1$s' is not supported.
+org.apache.olingo.odata2.api.ep.EntityProviderException.EXPANDNOTSUPPORTED=Expand of the navigation property '%1$s' is not supported.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MEDIA_DATA_NOT_INITIAL=Resource is not a media resource but media metadata was provided.
+org.apache.olingo.odata2.api.ep.EntityProviderException.END_DOCUMENT_EXPECTED=End of document expected but was '%1$s'.
+org.apache.olingo.odata2.api.ep.EntityProviderException.MISSING_RESULTS_ARRAY=Mandatory results array not found.
+
+##################################
+# BatchParserexceptions
+##################################
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CHANGESET_BOUNDARY=The boundary of the ChangeSet should be different from that used by the Batch: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_BOUNDARY_DELIMITER=The boundary delimiter must begin with two hyphen characters: line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_BOUNDARY_DELIMITER=Missing boundary delimiter at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_CLOSE_DELIMITER=Missing close delimiter at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_QUERY_OPERATION_METHOD=Invalid method: a Query Operation cannot contain insert, update or delete requests at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CHANGESET_METHOD= Invalid method: a ChangeSet cannot contain retrieve requests at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_QUERY_PARAMETER=Invalid query parameters.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_URI=Invalid URI.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_BOUNDARY=Invalid boundary at line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.NO_MATCH_WITH_BOUNDARY_STRING=The boundary string does not match the boundary from the Content-Type header field '%1$s': line '%2$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_CONTENT_TYPE=No Content-Type field for MIME-header is present.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CONTENT_TYPE=Content-Type should be '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_PARAMETER_IN_CONTENT_TYPE=The Content-Type field for multipart entities requires boundary parameter.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_CONTENT_TRANSFER_ENCODING=The Content-Transfer-Encoding should be binary.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_ACCEPT_HEADER=Invalid Accept header: '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_ACCEPT_LANGUAGE_HEADER=Invalid Accept-Language: '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_HEADER=Invalid header: '%1$s' at line '%2$s'.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_BLANK_LINE=Expected empty line but was '%1$s': line '%2$s'  .
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_PATHINFO=PathInfo should not be null.
+org.apache.olingo.odata2.api.batch.BatchException.MISSING_METHOD=Missing method in request line '%1$s'.
+org.apache.olingo.odata2.api.batch.BatchException.INVALID_REQUEST_LINE=Invalid request line '%1$s' at line '%2$s'.
+org.apache.olingo.odata2.api.batch.BatchException.TRUNCATED_BODY=Body is truncated: line '%1$s'.
+
+##################################
+# HttpExceptions
+##################################
+org.apache.olingo.odata2.api.exception.ODataHttpException.COMMON=Common exception
+
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.COMMON=Bad Request.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.NOTSUPPORTED=The request is not supported by the processor.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.INVALID_HEADER=The request contains an invalid header parameter '%1$s' with value '%2$s'.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.INVALID_SYNTAX=The Data Services Request could not be understood due to malformed syntax.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.URLTOOSHORT=The URL is too short.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.VERSIONERROR=The Data Services Request version '%1$s' is not supported for the request payload.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.PARSEVERSIONERROR=The Data Services Request version '%1$s' cannot be parsed.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.BODY=The request body is malformed.
+org.apache.olingo.odata2.api.exception.ODataBadRequestException.AMBIGUOUS_XMETHOD=Ambiguous X-HTTP-Method and X-HTTP-Method-Override header.
+
+org.apache.olingo.odata2.api.exception.ODataForbiddenException.COMMON=Forbidden
+
+org.apache.olingo.odata2.api.exception.ODataNotFoundException.MATRIX=Matrix parameter '%1$s' with path segment '%2$s' not found!
+org.apache.olingo.odata2.api.exception.ODataNotFoundException.ENTITY=Requested entity could not be found.
+
+org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException.DISPATCH=The request dispatcher does not allow the HTTP method used for the request.
+
+org.apache.olingo.odata2.api.exception.ODataNotAcceptableException.COMMON=The request can not be accepted.
+org.apache.olingo.odata2.api.exception.ODataNotAcceptableException.NOT_SUPPORTED_CONTENT_TYPE=Content type '%1$s' is not supported.
+org.apache.olingo.odata2.api.exception.ODataNotAcceptableException.NOT_SUPPORTED_ACCEPT_HEADER=The accept header '%1$s' is not supported for this resource.
+
+org.apache.olingo.odata2.api.exception.ODataConflictException.COMMON=Conflict
+
+org.apache.olingo.odata2.api.exception.ODataPreconditionFailedException.COMMON=Precondition failed
+
+org.apache.olingo.odata2.api.exception.ODataUnsupportedMediaTypeException.NOT_SUPPORTED=Media type %1$s is not supported.
+org.apache.olingo.odata2.api.exception.ODataUnsupportedMediaTypeException.NOT_SUPPORTED_CONTENT_TYPE=Content type %1$s is not supported for this resource.
+org.apache.olingo.odata2.api.exception.ODataUnsupportedMediaTypeException.NOT_SUPPORTED_ACCEPT_HEADER=Accept header %1$s is not supported for this resource.
+
+org.apache.olingo.odata2.api.exception.ODataPreconditionRequiredException.COMMON=Precondition required
+
+org.apache.olingo.odata2.api.exception.ODataNotImplementedException.COMMON=Not implemented
+org.apache.olingo.odata2.api.exception.ODataNotImplementedException.TUNNELING=Method not recognized for X-HTTP-Method or X-HTTP-Method-Override header.
+
+org.apache.olingo.odata2.api.exception.ODataServiceUnavailableException.COMMON=Service Unavailable
+
+##################################
+# FilterParserExceptions
+##################################
+org.apache.olingo.odata2.api.uri.expression.ExceptionVisitExpression.COMMON=Error while traversing a ODATA expression tree.
+
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMON=Error while parsing a ODATA expression.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TRAILING_TOKEN_DETECTED_AFTER_PARSING=Invalid token "%1$s" detected after parsing at position %2$s in "%3$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.TOKEN_UNDETERMINATED_STRING=Unterminated string literal at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_TYPES_FOR_BINARY_OPERATOR=Operator "%1$s" incompatible with operand types "%2$s" and "%3$s" at position %4$s in "%5$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.MISSING_CLOSING_PHARENTHESIS=Missing closing parenthesis ")" for opening parenthesis "(" at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.ERROR_IN_TOKENIZER=Error while tokenizing a ODATA expression on token "%1$s" at position %2$s in "%3$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AFTER_POS=Expression expected after position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_END_EXPECTED_AT_POS=Comma or end of expression expected at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.EXPRESSION_EXPECTED_AT_POS=Expression expected at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.COMMA_OR_CLOSING_PHARENTHESIS_EXPECTED_AFTER_POS=")" or "," expected after position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_METHOD_CALL=Unknown function "%1$s" at position %2$s in "%3$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_EXACT=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires exact %4$s argument(s).
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_BETWEEN=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires between %4$s and %5$s arguments.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_X_OR_MORE=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires %4$s or more arguments.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_ARG_X_OR_LESS=No applicable method found for "%1$s" at position %2$s in "%3$s" with the specified arguments. Method "%1$s" requires maximal %4$s arguments.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.METHOD_WRONG_INPUT_TYPE=No applicable method found for "%1$s" at position %2$s in "%3$s" for the specified argument types.
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_STRUCTURAL_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.LEFT_SIDE_NOT_A_PROPERTY=Leftside of method operator at position %1$s is not a property in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.PROPERTY_NAME_NOT_FOUND_IN_TYPE=No property "%1$s" exists in type "%2$s" at position %3$s in "%4$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.INVALID_SORT_ORDER=Invalid sort order in OData orderby parser at position %1$s in "%2$s".
+org.apache.olingo.odata2.api.uri.expression.ExpressionParserException.TYPE_EXPECTED_AT=Expression of type "%1$s" expected at position %2$s in "%3$s" (actual type is "%4$s").
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_METHOD=Internal error in OData filter parser while parsing a method expression.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_PARSING_PARENTHESIS=Internal error in OData filter parser while parsing a parenthesis expression.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.ERROR_ACCESSING_EDM=Internal error in OData filter parser while accessing the EDM.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.INVALID_TYPE_COUNT=Internal error in OData filter parser while validating the allowed types.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.INVALID_TOKEN_AT    =Expect token '%1$s', but invalid token '%2$s' detected at position '%3$s'.
+org.apache.olingo.odata2.core.uri.expression.ExpressionParserInternalError.INVALID_TOKENKIND_AT=Expect tokenkind '%1$s', but invalid tokenkind '%2$s'(with value:'%3$s' detected at position '%4$s'.
+
+org.apache.olingo.odata2.core.uri.expression.TokenizerExpectError.NO_TOKEN_AVAILABLE       =Expect token %1$s, but no token left in token list.
+org.apache.olingo.odata2.core.uri.expression.TokenizerExpectError.INVALID_TOKEN_AT         =Expect token '%1$s', but invalid token '%2$s' detected at position '%3$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerExpectError.INVALID_TOKENKIND_AT     =Expect tokenkind '%1$s', but invalid tokenkind '%2$s'(with value:'%3$s' detected at position '%4$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerException.TYPEDECTECTION_FAILED_ON_STRING=Type detection error for string like token '%1$s' at position '%2$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerException.TYPEDECTECTION_FAILED_ON_EDMTYPE=Type detection error for edmType like token '%1$s' at position '%2$s'.
+org.apache.olingo.odata2.core.uri.expression.TokenizerException.UNKNOWN_CHARACTER=Unknown character '%1$s' at position '%2$s' detected in "%3$s".
+
+#########################################
+# For testing
+# (please keep this inside this file and keep the english text in other languages)
+#########################################
+org.apache.olingo.odata2.testutil.mock.SampleClassForInvalidMessageReferences.EXIST=Exist
+#keep DOES_NOT_EXIST out commented 
+#org.apache.olingo.odata2.testutil.mock.SampleClassForInvalidMessageReferences.DOES_NOT_EXIST=Does not exist
+#keep EXITS_BUT_EMPTY text empty
+org.apache.olingo.odata2.testutil.mock.SampleClassForInvalidMessageReferences.EXITS_BUT_EMPTY=
+
+
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/resources/i18n_de.properties
----------------------------------------------------------------------
diff --git a/odata-core/src/main/resources/i18n_de.properties b/odata-core/src/main/resources/i18n_de.properties
new file mode 100644
index 0000000..f34cea7
--- /dev/null
+++ b/odata-core/src/main/resources/i18n_de.properties
@@ -0,0 +1,23 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# German translations
+#
+org.apache.olingo.odata2.api.exception.ODataMessageException.COMMON=Allgemeiner Fehler
+
+org.apache.olingo.odata2.api.exception.ODataNotFoundException.ENTITY=Die angefragte Entit\u00e4t wurde nicht gefunden.

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/resources/i18n_de_DE.properties
----------------------------------------------------------------------
diff --git a/odata-core/src/main/resources/i18n_de_DE.properties b/odata-core/src/main/resources/i18n_de_DE.properties
new file mode 100644
index 0000000..ac6c760
--- /dev/null
+++ b/odata-core/src/main/resources/i18n_de_DE.properties
@@ -0,0 +1,21 @@
+#-------------------------------------------------------------------------------
+# 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.
+#-------------------------------------------------------------------------------
+# German translations
+#
+org.apache.olingo.odata2.api.exception.ODataMessageException.COMMON=Allgemeiner Fehler


[51/51] [partial] git commit: initial commit

Posted by fm...@apache.org.
initial commit


Project: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/commit/ff2b0a0e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/tree/ff2b0a0e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/diff/ff2b0a0e

Branch: refs/heads/master
Commit: ff2b0a0eee6d196fb217ed14d740ca3aac8b6d33
Parents: 
Author: Stephan Klevenz <st...@sap.com>
Authored: Fri Jul 26 13:20:03 2013 +0200
Committer: Stephan Klevenz <st...@sap.com>
Committed: Fri Jul 26 13:20:03 2013 +0200

----------------------------------------------------------------------
 .gitignore                                      |    9 +
 LICENSE                                         |  202 ++
 NOTICE                                          |    1 +
 README.md                                       |  113 +
 jpa-annotation/.gitignore                       |    8 +
 jpa-annotation/pom.xml                          |   43 +
 .../src/main/java/META-INF/MANIFEST.MF          |    3 +
 .../api/annotation/edm/Documentation.java       |   32 +
 .../odata2/api/annotation/edm/Facets.java       |   36 +
 .../api/annotation/edm/FunctionImport.java      |   52 +
 .../odata2/api/annotation/edm/Parameter.java    |   57 +
 .../odata2/api/annotation/edmx/HttpMethod.java  |   39 +
 jpa-api/.gitignore                              |    8 +
 jpa-api/pom.xml                                 |   51 +
 jpa-api/src/main/java/META-INF/MANIFEST.MF      |    3 +
 .../processor/api/jpa/ODataJPAContext.java      |  181 ++
 .../processor/api/jpa/ODataJPAProcessor.java    |   74 +
 .../api/jpa/ODataJPAServiceFactory.java         |  173 ++
 .../processor/api/jpa/access/JPAEdmBuilder.java |   74 +
 .../jpa/access/JPAEdmMappingModelAccess.java    |  199 ++
 .../processor/api/jpa/access/JPAFunction.java   |   85 +
 .../processor/api/jpa/access/JPAJoinClause.java |  152 ++
 .../api/jpa/access/JPAMethodContext.java        |  137 ++
 .../api/jpa/access/JPAMethodContextView.java    |   46 +
 .../processor/api/jpa/access/JPAProcessor.java  |  230 ++
 .../api/jpa/access/JPAProcessorExtension.java   |   45 +
 .../api/jpa/access/JPAProcessorOperation.java   |   27 +
 .../api/jpa/access/JPAProcessorRegistry.java    |   28 +
 .../processor/api/jpa/access/package-info.java  |   26 +
 .../api/jpa/exception/ODataJPAException.java    |   70 +
 .../jpa/exception/ODataJPAMessageService.java   |   49 +
 .../jpa/exception/ODataJPAModelException.java   |   97 +
 .../jpa/exception/ODataJPARuntimeException.java |  102 +
 .../api/jpa/exception/package-info.java         |   31 +
 .../api/jpa/factory/JPAAccessFactory.java       |   76 +
 .../api/jpa/factory/JPQLBuilderFactory.java     |   83 +
 .../api/jpa/factory/ODataJPAAccessFactory.java  |   90 +
 .../api/jpa/factory/ODataJPAFactory.java        |  109 +
 .../processor/api/jpa/factory/package-info.java |   33 +
 .../processor/api/jpa/jpql/JPQLContext.java     |  211 ++
 .../processor/api/jpa/jpql/JPQLContextType.java |   73 +
 .../processor/api/jpa/jpql/JPQLContextView.java |   54 +
 .../api/jpa/jpql/JPQLJoinContextView.java       |   45 +
 .../jpql/JPQLJoinSelectSingleContextView.java   |   47 +
 .../api/jpa/jpql/JPQLSelectContextView.java     |   62 +
 .../jpa/jpql/JPQLSelectSingleContextView.java   |   53 +
 .../processor/api/jpa/jpql/JPQLStatement.java   |  154 ++
 .../processor/api/jpa/jpql/package-info.java    |   27 +
 .../api/jpa/model/JPAEdmAssociationEndView.java |   98 +
 .../api/jpa/model/JPAEdmAssociationSetView.java |   69 +
 .../api/jpa/model/JPAEdmAssociationView.java    |  135 ++
 .../processor/api/jpa/model/JPAEdmBaseView.java |   92 +
 .../jpa/model/JPAEdmComplexPropertyView.java    |   46 +
 .../api/jpa/model/JPAEdmComplexTypeView.java    |  119 +
 .../jpa/model/JPAEdmEntityContainerView.java    |   75 +
 .../api/jpa/model/JPAEdmEntitySetView.java      |   66 +
 .../api/jpa/model/JPAEdmEntityTypeView.java     |   78 +
 .../api/jpa/model/JPAEdmExtension.java          |   63 +
 .../api/jpa/model/JPAEdmFunctionImportView.java |   52 +
 .../processor/api/jpa/model/JPAEdmKeyView.java  |   52 +
 .../processor/api/jpa/model/JPAEdmMapping.java  |   63 +
 .../api/jpa/model/JPAEdmModelView.java          |   45 +
 .../jpa/model/JPAEdmNavigationPropertyView.java |   74 +
 .../api/jpa/model/JPAEdmPropertyView.java       |  109 +
 .../JPAEdmReferentialConstraintRoleView.java    |  103 +
 .../model/JPAEdmReferentialConstraintView.java  |   70 +
 .../api/jpa/model/JPAEdmSchemaView.java         |  121 +
 .../jpa/model/mapping/JPAAttributeMapType.java  |  213 ++
 .../jpa/model/mapping/JPAEdmMappingModel.java   |   78 +
 .../mapping/JPAEdmMappingModelFactory.java      |   85 +
 .../model/mapping/JPAEmbeddableTypeMapType.java |  171 ++
 .../mapping/JPAEmbeddableTypesMapType.java      |   88 +
 .../jpa/model/mapping/JPAEntityTypeMapType.java |  227 ++
 .../model/mapping/JPAEntityTypesMapType.java    |   88 +
 .../mapping/JPAPersistenceUnitMapType.java      |  155 ++
 .../model/mapping/JPARelationshipMapType.java   |  176 ++
 .../api/jpa/model/mapping/package-info.java     |   27 +
 .../processor/api/jpa/model/package-info.java   |   27 +
 .../odata2/processor/api/jpa/package-info.java  |   33 +
 .../src/main/resources/JPAEDMMappingModel.xsd   |  147 ++
 jpa-core/.gitignore                             |    8 +
 jpa-core/pom.xml                                |  104 +
 jpa-core/src/main/java/META-INF/MANIFEST.MF     |    3 +
 .../processor/core/jpa/ODataEntityParser.java   |  161 ++
 .../core/jpa/ODataExpressionParser.java         |  364 +++
 .../processor/core/jpa/ODataJPAContextImpl.java |  135 ++
 .../core/jpa/ODataJPAProcessorDefault.java      |  212 ++
 .../core/jpa/ODataJPAResponseBuilder.java       |  721 ++++++
 .../core/jpa/access/data/JPAEntityParser.java   |  423 ++++
 .../core/jpa/access/data/JPAExpandCallBack.java |  175 ++
 .../jpa/access/data/JPAFunctionContext.java     |  200 ++
 .../core/jpa/access/data/JPAProcessorImpl.java  |  434 ++++
 .../core/jpa/access/model/EdmTypeConvertor.java |   79 +
 .../access/model/JPAEdmMappingModelService.java |  264 +++
 .../jpa/access/model/JPAEdmNameBuilder.java     |  545 +++++
 .../core/jpa/access/model/JPATypeConvertor.java |  109 +
 .../core/jpa/cud/JPACreateRequest.java          |  477 ++++
 .../odata2/processor/core/jpa/cud/JPALink.java  |  256 +++
 .../core/jpa/cud/JPAUpdateRequest.java          |  174 ++
 .../processor/core/jpa/cud/JPAWriteRequest.java |  187 ++
 .../core/jpa/edm/ODataJPAEdmProvider.java       |  302 +++
 .../ODataJPAMessageServiceDefault.java          |  125 +
 .../core/jpa/factory/ODataJPAFactoryImpl.java   |  246 ++
 .../core/jpa/jpql/JPQLJoinSelectContext.java    |  194 ++
 .../jpa/jpql/JPQLJoinSelectSingleContext.java   |  177 ++
 .../JPQLJoinSelectSingleStatementBuilder.java   |  115 +
 .../core/jpa/jpql/JPQLJoinStatementBuilder.java |  158 ++
 .../core/jpa/jpql/JPQLSelectContext.java        |  169 ++
 .../core/jpa/jpql/JPQLSelectSingleContext.java  |  113 +
 .../jpql/JPQLSelectSingleStatementBuilder.java  |   69 +
 .../jpa/jpql/JPQLSelectStatementBuilder.java    |   99 +
 .../core/jpa/model/JPAEdmAssociation.java       |  270 +++
 .../core/jpa/model/JPAEdmAssociationEnd.java    |  196 ++
 .../core/jpa/model/JPAEdmAssociationSet.java    |  139 ++
 .../core/jpa/model/JPAEdmBaseViewImpl.java      |   93 +
 .../core/jpa/model/JPAEdmComplexType.java       |  260 +++
 .../core/jpa/model/JPAEdmEntityContainer.java   |  161 ++
 .../core/jpa/model/JPAEdmEntitySet.java         |  115 +
 .../core/jpa/model/JPAEdmEntityType.java        |  242 ++
 .../core/jpa/model/JPAEdmFunctionImport.java    |  357 +++
 .../processor/core/jpa/model/JPAEdmKey.java     |  131 ++
 .../core/jpa/model/JPAEdmMappingImpl.java       |   51 +
 .../processor/core/jpa/model/JPAEdmModel.java   |   65 +
 .../jpa/model/JPAEdmNavigationProperty.java     |  102 +
 .../core/jpa/model/JPAEdmProperty.java          |  405 ++++
 .../jpa/model/JPAEdmReferentialConstraint.java  |  156 ++
 .../model/JPAEdmReferentialConstraintRole.java  |  279 +++
 .../processor/core/jpa/model/JPAEdmSchema.java  |  235 ++
 .../main/resources/jpaprocessor_msg.properties  |   61 +
 jpa-core/src/test/java/META-INF/MANIFEST.MF     |    3 +
 .../processor/core/jpa/JPAEntityParserTest.java |  652 ++++++
 .../core/jpa/ODataJPAContextImplTest.java       |  101 +
 .../core/jpa/ODataJPAProcessorDefaultTest.java  |  569 +++++
 .../core/jpa/ODataJPAResponseBuilderTest.java   |  675 ++++++
 .../jpa/access/data/JPAExpandCallBackTest.java  |  179 ++
 .../jpa/access/data/JPAFunctionContextTest.java |  157 ++
 .../jpa/access/data/JPAProcessorImplTest.java   |  464 ++++
 .../access/data/ODataExpressionParserTest.java  |  586 +++++
 .../core/jpa/access/data/TestUtil.java          |  391 ++++
 .../model/JPAEdmMappingModelServiceTest.java    |  201 ++
 .../jpa/access/model/JPAEdmNameBuilderTest.java |   93 +
 .../jpa/access/model/JPATypeConvertorTest.java  |  104 +
 .../core/jpa/common/ODataJPATestConstants.java  |   26 +
 .../core/jpa/cud/JPACreateRequestTest.java      |  375 +++
 .../processor/core/jpa/cud/JPATestUtil.java     |  554 +++++
 .../core/jpa/cud/JPAUpdateRequestTest.java      |   76 +
 .../core/jpa/cud/SalesOrderHeader.java          |   64 +
 .../core/jpa/cud/SalesOrderLineItem.java        |   38 +
 .../core/jpa/cud/SalesOrderLineItemKey.java     |   52 +
 .../edm/ODataJPAEdmProviderNegativeTest.java    |  220 ++
 .../core/jpa/edm/ODataJPAEdmProviderTest.java   |  456 ++++
 .../core/jpa/jpql/JPQLBuilderFactoryTest.java   |  414 ++++
 .../core/jpa/jpql/JPQLJoinContextTest.java      |  201 ++
 .../jpql/JPQLJoinSelectSingleContextTest.java   |  218 ++
 ...PQLJoinSelectSingleStatementBuilderTest.java |  134 ++
 .../jpa/jpql/JPQLJoinStatementBuilderTest.java  |  116 +
 .../jpa/jpql/JPQLSelectContextImplTest.java     |  454 ++++
 .../jpql/JPQLSelectSingleContextImplTest.java   |  216 ++
 .../JPQLSelectSingleStatementBuilderTest.java   |  127 ++
 .../jpql/JPQLSelectStatementBuilderTest.java    |  133 ++
 .../core/jpa/mock/ODataJPAContextMock.java      |   58 +
 .../core/jpa/mock/model/EdmSchemaMock.java      |  216 ++
 .../core/jpa/mock/model/JPAAttributeMock.java   |   63 +
 .../jpa/mock/model/JPACustomProcessorMock.java  |   75 +
 .../model/JPACustomProcessorNegativeMock.java   |   69 +
 .../core/jpa/mock/model/JPAEdmMockData.java     |   77 +
 .../core/jpa/mock/model/JPAEmbeddableMock.java  |  190 ++
 .../jpa/mock/model/JPAEmbeddableTypeMock.java   |  190 ++
 .../core/jpa/mock/model/JPAEntityTypeMock.java  |  252 +++
 .../core/jpa/mock/model/JPAJavaMemberMock.java  |   75 +
 .../core/jpa/mock/model/JPAManagedTypeMock.java |  190 ++
 .../core/jpa/mock/model/JPAMetaModelMock.java   |   60 +
 .../mock/model/JPASingularAttributeMock.java    |   94 +
 .../jpa/model/JPAEdmAssociationEndTest.java     |  185 ++
 .../jpa/model/JPAEdmAssociationSetTest.java     |  183 ++
 .../core/jpa/model/JPAEdmAssociationTest.java   |  438 ++++
 .../core/jpa/model/JPAEdmBaseViewImplTest.java  |   90 +
 .../core/jpa/model/JPAEdmComplexTypeTest.java   |  279 +++
 .../jpa/model/JPAEdmEntityContainerTest.java    |  238 ++
 .../core/jpa/model/JPAEdmEntitySetTest.java     |  228 ++
 .../core/jpa/model/JPAEdmEntityTypeTest.java    |  202 ++
 .../jpa/model/JPAEdmFunctionImportTest.java     |  627 ++++++
 .../processor/core/jpa/model/JPAEdmKeyTest.java |  188 ++
 .../core/jpa/model/JPAEdmModelTest.java         |  150 ++
 .../jpa/model/JPAEdmNavigationPropertyTest.java |  202 ++
 .../core/jpa/model/JPAEdmPropertyTest.java      |  403 ++++
 .../JPAEdmReferentialConstraintRoleTest.java    |  246 ++
 .../model/JPAEdmReferentialConstraintTest.java  |  187 ++
 .../core/jpa/model/JPAEdmSchemaTest.java        |  104 +
 .../core/jpa/model/JPAEdmTestModelView.java     |  394 ++++
 .../SalesOrderProcessingMappingModels.xml       |   62 +
 odata-api/pom.xml                               |   76 +
 .../apache/olingo/odata2/api/ODataCallback.java |   27 +
 .../olingo/odata2/api/ODataDebugCallback.java   |   35 +
 .../apache/olingo/odata2/api/ODataService.java  |  166 ++
 .../olingo/odata2/api/ODataServiceFactory.java  |   76 +
 .../olingo/odata2/api/ODataServiceVersion.java  |   89 +
 .../olingo/odata2/api/batch/BatchException.java |  113 +
 .../olingo/odata2/api/batch/BatchHandler.java   |   44 +
 .../olingo/odata2/api/batch/BatchPart.java      |   43 +
 .../odata2/api/batch/BatchResponsePart.java     |   84 +
 .../odata2/api/commons/HttpContentType.java     |   54 +
 .../olingo/odata2/api/commons/HttpHeaders.java  |  145 ++
 .../odata2/api/commons/HttpStatusCodes.java     |   87 +
 .../olingo/odata2/api/commons/InlineCount.java  |   27 +
 .../odata2/api/commons/ODataHttpHeaders.java    |   29 +
 .../odata2/api/commons/ODataHttpMethod.java     |   27 +
 .../olingo/odata2/api/commons/package-info.java |   22 +
 .../org/apache/olingo/odata2/api/edm/Edm.java   |  105 +
 .../apache/olingo/odata2/api/edm/EdmAction.java |   30 +
 .../olingo/odata2/api/edm/EdmAnnotatable.java   |   35 +
 .../odata2/api/edm/EdmAnnotationAttribute.java  |   56 +
 .../odata2/api/edm/EdmAnnotationElement.java    |   76 +
 .../olingo/odata2/api/edm/EdmAnnotations.java   |   62 +
 .../olingo/odata2/api/edm/EdmAssociation.java   |   37 +
 .../odata2/api/edm/EdmAssociationEnd.java       |   46 +
 .../odata2/api/edm/EdmAssociationSet.java       |   54 +
 .../odata2/api/edm/EdmAssociationSetEnd.java    |   44 +
 .../olingo/odata2/api/edm/EdmComplexType.java   |   32 +
 .../odata2/api/edm/EdmConcurrencyMode.java      |   30 +
 .../olingo/odata2/api/edm/EdmContentKind.java   |   31 +
 .../api/edm/EdmCustomizableFeedMappings.java    |   69 +
 .../olingo/odata2/api/edm/EdmElement.java       |   36 +
 .../odata2/api/edm/EdmEntityContainer.java      |   62 +
 .../olingo/odata2/api/edm/EdmEntitySet.java     |   53 +
 .../olingo/odata2/api/edm/EdmEntitySetInfo.java |   52 +
 .../olingo/odata2/api/edm/EdmEntityType.java    |   72 +
 .../olingo/odata2/api/edm/EdmException.java     |   52 +
 .../apache/olingo/odata2/api/edm/EdmFacets.java |   91 +
 .../odata2/api/edm/EdmFunctionImport.java       |   78 +
 .../olingo/odata2/api/edm/EdmLiteral.java       |   67 +
 .../odata2/api/edm/EdmLiteralException.java     |   51 +
 .../olingo/odata2/api/edm/EdmLiteralKind.java   |   29 +
 .../olingo/odata2/api/edm/EdmMappable.java      |   35 +
 .../olingo/odata2/api/edm/EdmMapping.java       |   48 +
 .../olingo/odata2/api/edm/EdmMultiplicity.java  |   64 +
 .../apache/olingo/odata2/api/edm/EdmNamed.java  |   33 +
 .../odata2/api/edm/EdmNavigationProperty.java   |   53 +
 .../olingo/odata2/api/edm/EdmParameter.java     |   29 +
 .../olingo/odata2/api/edm/EdmProperty.java      |   51 +
 .../odata2/api/edm/EdmServiceMetadata.java      |   51 +
 .../olingo/odata2/api/edm/EdmSimpleType.java    |  152 ++
 .../odata2/api/edm/EdmSimpleTypeException.java  |   62 +
 .../odata2/api/edm/EdmSimpleTypeFacade.java     |   46 +
 .../odata2/api/edm/EdmSimpleTypeKind.java       |   89 +
 .../odata2/api/edm/EdmStructuralType.java       |   54 +
 .../olingo/odata2/api/edm/EdmTargetPath.java    |   40 +
 .../apache/olingo/odata2/api/edm/EdmType.java   |   39 +
 .../olingo/odata2/api/edm/EdmTypeKind.java      |   29 +
 .../apache/olingo/odata2/api/edm/EdmTyped.java  |   43 +
 .../odata2/api/edm/FullQualifiedName.java       |   75 +
 .../olingo/odata2/api/edm/package-info.java     |   27 +
 .../api/edm/provider/AnnotationAttribute.java   |   94 +
 .../api/edm/provider/AnnotationElement.java     |  130 ++
 .../odata2/api/edm/provider/Association.java    |  155 ++
 .../odata2/api/edm/provider/AssociationEnd.java |  158 ++
 .../odata2/api/edm/provider/AssociationSet.java |  157 ++
 .../api/edm/provider/AssociationSetEnd.java     |  119 +
 .../api/edm/provider/ComplexProperty.java       |   98 +
 .../odata2/api/edm/provider/ComplexType.java    |  175 ++
 .../edm/provider/CustomizableFeedMappings.java  |  135 ++
 .../odata2/api/edm/provider/DataServices.java   |   65 +
 .../odata2/api/edm/provider/Documentation.java  |  101 +
 .../odata2/api/edm/provider/EdmProvider.java    |  117 +
 .../api/edm/provider/EdmProviderAccessor.java   |   33 +
 .../api/edm/provider/EdmProviderFactory.java    |   42 +
 .../api/edm/provider/EntityContainer.java       |  134 ++
 .../api/edm/provider/EntityContainerInfo.java   |  120 +
 .../odata2/api/edm/provider/EntitySet.java      |  139 ++
 .../odata2/api/edm/provider/EntityType.java     |  185 ++
 .../olingo/odata2/api/edm/provider/Facets.java  |  212 ++
 .../odata2/api/edm/provider/FunctionImport.java |  191 ++
 .../edm/provider/FunctionImportParameter.java   |  176 ++
 .../olingo/odata2/api/edm/provider/Key.java     |   83 +
 .../olingo/odata2/api/edm/provider/Mapping.java |   77 +
 .../api/edm/provider/NavigationProperty.java    |  175 ++
 .../odata2/api/edm/provider/OnDelete.java       |  103 +
 .../odata2/api/edm/provider/Property.java       |  175 ++
 .../odata2/api/edm/provider/PropertyRef.java    |   84 +
 .../api/edm/provider/ReferentialConstraint.java |  119 +
 .../edm/provider/ReferentialConstraintRole.java |  101 +
 .../odata2/api/edm/provider/ReturnType.java     |   76 +
 .../olingo/odata2/api/edm/provider/Schema.java  |  191 ++
 .../odata2/api/edm/provider/SimpleProperty.java |   98 +
 .../olingo/odata2/api/edm/provider/Using.java   |  119 +
 .../odata2/api/edm/provider/package-info.java   |  287 +++
 .../olingo/odata2/api/ep/EntityProvider.java    |  698 ++++++
 .../api/ep/EntityProviderBatchProperties.java   |   61 +
 .../odata2/api/ep/EntityProviderException.java  |   94 +
 .../api/ep/EntityProviderReadProperties.java    |  128 ++
 .../api/ep/EntityProviderWriteProperties.java   |  201 ++
 .../api/ep/callback/OnReadInlineContent.java    |   78 +
 .../api/ep/callback/OnWriteEntryContent.java    |   42 +
 .../api/ep/callback/OnWriteFeedContent.java     |   42 +
 .../odata2/api/ep/callback/ReadEntryResult.java |   66 +
 .../odata2/api/ep/callback/ReadFeedResult.java  |   66 +
 .../odata2/api/ep/callback/ReadResult.java      |   87 +
 .../api/ep/callback/TombstoneCallback.java      |   56 +
 .../ep/callback/TombstoneCallbackResult.java    |   66 +
 .../api/ep/callback/WriteCallbackContext.java   |  120 +
 .../ep/callback/WriteEntryCallbackContext.java  |   26 +
 .../ep/callback/WriteEntryCallbackResult.java   |   62 +
 .../ep/callback/WriteFeedCallbackContext.java   |   48 +
 .../ep/callback/WriteFeedCallbackResult.java    |   66 +
 .../odata2/api/ep/callback/package-info.java    |   27 +
 .../odata2/api/ep/entry/EntryMetadata.java      |   57 +
 .../odata2/api/ep/entry/MediaMetadata.java      |   54 +
 .../olingo/odata2/api/ep/entry/ODataEntry.java  |   69 +
 .../odata2/api/ep/entry/package-info.java       |   25 +
 .../olingo/odata2/api/ep/feed/FeedMetadata.java |   43 +
 .../olingo/odata2/api/ep/feed/ODataFeed.java    |   43 +
 .../olingo/odata2/api/ep/feed/package-info.java |   25 +
 .../olingo/odata2/api/ep/package-info.java      |   33 +
 .../odata2/api/exception/MessageReference.java  |  175 ++
 .../exception/ODataApplicationException.java    |  152 ++
 .../api/exception/ODataBadRequestException.java |   58 +
 .../api/exception/ODataConflictException.java   |   49 +
 .../odata2/api/exception/ODataException.java    |  117 +
 .../api/exception/ODataForbiddenException.java  |   48 +
 .../api/exception/ODataHttpException.java       |   55 +
 .../api/exception/ODataMessageException.java    |  114 +
 .../ODataMethodNotAllowedException.java         |   49 +
 .../exception/ODataNotAcceptableException.java  |   50 +
 .../api/exception/ODataNotFoundException.java   |   49 +
 .../exception/ODataNotImplementedException.java |   45 +
 .../ODataPreconditionFailedException.java       |   48 +
 .../ODataPreconditionRequiredException.java     |   48 +
 .../ODataServiceUnavailableException.java       |   49 +
 .../ODataUnsupportedMediaTypeException.java     |   53 +
 .../odata2/api/exception/package-info.java      |   60 +
 .../apache/olingo/odata2/api/package-info.java  |   71 +
 .../odata2/api/processor/ODataContext.java      |  235 ++
 .../api/processor/ODataErrorCallback.java       |   41 +
 .../odata2/api/processor/ODataErrorContext.java |  229 ++
 .../odata2/api/processor/ODataProcessor.java    |   43 +
 .../odata2/api/processor/ODataRequest.java      |  127 ++
 .../odata2/api/processor/ODataResponse.java     |  173 ++
 .../api/processor/ODataSingleProcessor.java     |  375 +++
 .../processor/feature/CustomContentType.java    |   42 +
 .../feature/ODataProcessorFeature.java          |   30 +
 .../api/processor/feature/package-info.java     |   24 +
 .../odata2/api/processor/package-info.java      |   40 +
 .../api/processor/part/BatchProcessor.java      |   59 +
 .../part/EntityComplexPropertyProcessor.java    |   56 +
 .../api/processor/part/EntityLinkProcessor.java |   74 +
 .../processor/part/EntityLinksProcessor.java    |   64 +
 .../processor/part/EntityMediaProcessor.java    |   64 +
 .../api/processor/part/EntityProcessor.java     |   76 +
 .../api/processor/part/EntitySetProcessor.java  |   66 +
 .../part/EntitySimplePropertyProcessor.java     |   54 +
 .../EntitySimplePropertyValueProcessor.java     |   66 +
 .../processor/part/FunctionImportProcessor.java |   39 +
 .../part/FunctionImportValueProcessor.java      |   39 +
 .../api/processor/part/MetadataProcessor.java   |   40 +
 .../part/ServiceDocumentProcessor.java          |   40 +
 .../odata2/api/processor/part/package-info.java |   22 +
 .../olingo/odata2/api/rt/RuntimeDelegate.java   |  188 ++
 .../olingo/odata2/api/rt/package-info.java      |   24 +
 .../odata2/api/servicedocument/Accept.java      |   41 +
 .../odata2/api/servicedocument/AtomInfo.java    |   50 +
 .../odata2/api/servicedocument/Categories.java  |   60 +
 .../odata2/api/servicedocument/Category.java    |   54 +
 .../odata2/api/servicedocument/Collection.java  |   71 +
 .../api/servicedocument/CommonAttributes.java   |   49 +
 .../api/servicedocument/ExtensionAttribute.java |   54 +
 .../api/servicedocument/ExtensionElement.java   |   71 +
 .../odata2/api/servicedocument/Fixed.java       |   29 +
 .../api/servicedocument/ServiceDocument.java    |   45 +
 .../servicedocument/ServiceDocumentParser.java  |   28 +
 .../ServiceDocumentParserException.java         |   31 +
 .../odata2/api/servicedocument/Title.java       |   31 +
 .../odata2/api/servicedocument/Workspace.java   |   57 +
 .../odata2/api/uri/ExpandSelectTreeNode.java    |   53 +
 .../olingo/odata2/api/uri/KeyPredicate.java     |   45 +
 .../api/uri/NavigationPropertySegment.java      |   44 +
 .../odata2/api/uri/NavigationSegment.java       |   53 +
 .../apache/olingo/odata2/api/uri/PathInfo.java  |   55 +
 .../olingo/odata2/api/uri/PathSegment.java      |   51 +
 .../olingo/odata2/api/uri/SelectItem.java       |   50 +
 .../apache/olingo/odata2/api/uri/UriInfo.java   |  245 ++
 .../odata2/api/uri/UriNotMatchingException.java |   53 +
 .../apache/olingo/odata2/api/uri/UriParser.java |  181 ++
 .../odata2/api/uri/UriSyntaxException.java      |   74 +
 .../api/uri/expression/BinaryExpression.java    |   48 +
 .../api/uri/expression/BinaryOperator.java      |   61 +
 .../api/uri/expression/CommonExpression.java    |   73 +
 .../expression/ExceptionVisitExpression.java    |   77 +
 .../api/uri/expression/ExpressionKind.java      |   78 +
 .../expression/ExpressionParserException.java   |  111 +
 .../api/uri/expression/ExpressionVisitor.java   |  150 ++
 .../api/uri/expression/FilterExpression.java    |   39 +
 .../api/uri/expression/LiteralExpression.java   |   39 +
 .../api/uri/expression/MemberExpression.java    |   51 +
 .../api/uri/expression/MethodExpression.java    |   54 +
 .../api/uri/expression/MethodOperator.java      |   52 +
 .../api/uri/expression/OrderByExpression.java   |   50 +
 .../api/uri/expression/OrderExpression.java     |   47 +
 .../api/uri/expression/PropertyExpression.java  |   49 +
 .../odata2/api/uri/expression/SortOrder.java    |   59 +
 .../api/uri/expression/UnaryExpression.java     |   47 +
 .../api/uri/expression/UnaryOperator.java       |   56 +
 .../odata2/api/uri/expression/Visitable.java    |   52 +
 .../odata2/api/uri/expression/package-info.java |   26 +
 .../odata2/api/uri/info/DeleteUriInfo.java      |  116 +
 .../api/uri/info/GetComplexPropertyUriInfo.java |  123 +
 .../api/uri/info/GetEntityCountUriInfo.java     |  123 +
 .../api/uri/info/GetEntityLinkCountUriInfo.java |  121 +
 .../api/uri/info/GetEntityLinkUriInfo.java      |  121 +
 .../api/uri/info/GetEntitySetCountUriInfo.java  |  125 +
 .../uri/info/GetEntitySetLinksCountUriInfo.java |  131 ++
 .../api/uri/info/GetEntitySetLinksUriInfo.java  |  144 ++
 .../api/uri/info/GetEntitySetUriInfo.java       |  163 ++
 .../odata2/api/uri/info/GetEntityUriInfo.java   |  140 ++
 .../api/uri/info/GetFunctionImportUriInfo.java  |   60 +
 .../api/uri/info/GetMediaResourceUriInfo.java   |  123 +
 .../odata2/api/uri/info/GetMetadataUriInfo.java |   37 +
 .../api/uri/info/GetServiceDocumentUriInfo.java |   43 +
 .../api/uri/info/GetSimplePropertyUriInfo.java  |  129 ++
 .../olingo/odata2/api/uri/info/PostUriInfo.java |   98 +
 .../api/uri/info/PutMergePatchUriInfo.java      |  124 +
 .../odata2/api/uri/info/package-info.java       |   24 +
 .../olingo/odata2/api/uri/package-info.java     |   26 +
 odata-core/pom.xml                              |  194 ++
 .../olingo/odata2/core/ContentNegotiator.java   |  141 ++
 .../apache/olingo/odata2/core/Dispatcher.java   |  304 +++
 .../olingo/odata2/core/ODataContextImpl.java    |  314 +++
 .../odata2/core/ODataExceptionWrapper.java      |  338 +++
 .../odata2/core/ODataPathSegmentImpl.java       |   60 +
 .../olingo/odata2/core/ODataRequestHandler.java |  456 ++++
 .../olingo/odata2/core/ODataRequestImpl.java    |  198 ++
 .../olingo/odata2/core/ODataResponseImpl.java   |  160 ++
 .../apache/olingo/odata2/core/PathInfoImpl.java |   73 +
 .../olingo/odata2/core/batch/AcceptParser.java  |  171 ++
 .../odata2/core/batch/BatchConstants.java       |   36 +
 .../odata2/core/batch/BatchHandlerImpl.java     |  177 ++
 .../olingo/odata2/core/batch/BatchPartImpl.java |   58 +
 .../odata2/core/batch/BatchRequestParser.java   |  563 +++++
 .../core/batch/BatchResponsePartImpl.java       |   63 +
 .../odata2/core/batch/BatchResponseWriter.java  |  136 ++
 .../olingo/odata2/core/commons/ContentType.java |  734 ++++++
 .../olingo/odata2/core/commons/Decoder.java     |   90 +
 .../olingo/odata2/core/commons/Encoder.java     |  149 ++
 .../olingo/odata2/core/debug/DebugInfo.java     |   42 +
 .../olingo/odata2/core/debug/DebugInfoBody.java |   93 +
 .../odata2/core/debug/DebugInfoException.java   |   94 +
 .../odata2/core/debug/DebugInfoRequest.java     |   73 +
 .../odata2/core/debug/DebugInfoResponse.java    |   77 +
 .../odata2/core/debug/DebugInfoRuntime.java     |  153 ++
 .../olingo/odata2/core/debug/DebugInfoUri.java  |  126 ++
 .../core/debug/ODataDebugResponseWrapper.java   |  139 ++
 .../odata2/core/edm/AbstractSimpleType.java     |  128 ++
 .../org/apache/olingo/odata2/core/edm/Bit.java  |   57 +
 .../olingo/odata2/core/edm/EdmBinary.java       |  151 ++
 .../olingo/odata2/core/edm/EdmBoolean.java      |   81 +
 .../apache/olingo/odata2/core/edm/EdmByte.java  |   91 +
 .../olingo/odata2/core/edm/EdmDateTime.java     |  236 ++
 .../odata2/core/edm/EdmDateTimeOffset.java      |  166 ++
 .../olingo/odata2/core/edm/EdmDecimal.java      |  199 ++
 .../olingo/odata2/core/edm/EdmDouble.java       |  164 ++
 .../apache/olingo/odata2/core/edm/EdmGuid.java  |   86 +
 .../apache/olingo/odata2/core/edm/EdmImpl.java  |  164 ++
 .../apache/olingo/odata2/core/edm/EdmInt16.java |   92 +
 .../apache/olingo/odata2/core/edm/EdmInt32.java |   97 +
 .../apache/olingo/odata2/core/edm/EdmInt64.java |  119 +
 .../apache/olingo/odata2/core/edm/EdmNull.java  |   66 +
 .../apache/olingo/odata2/core/edm/EdmSByte.java |   86 +
 .../core/edm/EdmSimpleTypeFacadeImpl.java       |  183 ++
 .../olingo/odata2/core/edm/EdmSingle.java       |  168 ++
 .../olingo/odata2/core/edm/EdmString.java       |  100 +
 .../apache/olingo/odata2/core/edm/EdmTime.java  |  159 ++
 .../apache/olingo/odata2/core/edm/Uint7.java    |   63 +
 .../odata2/core/edm/parser/EdmParser.java       |  965 ++++++++
 .../core/edm/parser/EdmParserConstants.java     |   86 +
 .../odata2/core/edm/parser/EdmxProvider.java    |  186 ++
 .../edm/provider/EdmAnnotationsImplProv.java    |   80 +
 .../edm/provider/EdmAssociationEndImplProv.java |   65 +
 .../edm/provider/EdmAssociationImplProv.java    |   83 +
 .../provider/EdmAssociationSetEndImplProv.java  |   54 +
 .../edm/provider/EdmAssociationSetImplProv.java |   82 +
 .../provider/EdmComplexPropertyImplProv.java    |   52 +
 .../edm/provider/EdmComplexTypeImplProv.java    |   43 +
 .../core/edm/provider/EdmElementImplProv.java   |   51 +
 .../provider/EdmEntityContainerImplProv.java    |  184 ++
 .../core/edm/provider/EdmEntitySetImplProv.java |   86 +
 .../edm/provider/EdmEntitySetInfoImplProv.java  |   78 +
 .../edm/provider/EdmEntityTypeImplProv.java     |  173 ++
 .../edm/provider/EdmFunctionImportImplProv.java |  142 ++
 .../odata2/core/edm/provider/EdmImplProv.java   |   85 +
 .../core/edm/provider/EdmNamedImplProv.java     |   57 +
 .../provider/EdmNavigationPropertyImplProv.java |   77 +
 .../core/edm/provider/EdmParameterImplProv.java |   56 +
 .../core/edm/provider/EdmPropertyImplProv.java  |   52 +
 .../provider/EdmServiceMetadataImplProv.java    |  163 ++
 .../edm/provider/EdmSimplePropertyImplProv.java |   50 +
 .../edm/provider/EdmStructuralTypeImplProv.java |  172 ++
 .../core/edm/provider/EdmTypedImplProv.java     |   70 +
 .../odata2/core/ep/AtomEntityProvider.java      |  394 ++++
 .../odata2/core/ep/BasicEntityProvider.java     |  296 +++
 .../core/ep/ContentTypeBasedEntityProvider.java |   73 +
 .../odata2/core/ep/JsonEntityProvider.java      |  327 +++
 .../odata2/core/ep/ProviderFacadeImpl.java      |  203 ++
 .../aggregator/EntityComplexPropertyInfo.java   |   90 +
 .../ep/aggregator/EntityInfoAggregator.java     |  451 ++++
 .../core/ep/aggregator/EntityPropertyInfo.java  |  101 +
 .../core/ep/aggregator/EntityTypeMapping.java   |  133 ++
 .../ep/aggregator/NavigationPropertyInfo.java   |   48 +
 .../consumer/AtomServiceDocumentConsumer.java   |  312 +++
 .../core/ep/consumer/JsonEntityConsumer.java    |  192 ++
 .../core/ep/consumer/JsonEntryConsumer.java     |  311 +++
 .../core/ep/consumer/JsonFeedConsumer.java      |  176 ++
 .../core/ep/consumer/JsonLinkConsumer.java      |  155 ++
 .../core/ep/consumer/JsonPropertyConsumer.java  |  190 ++
 .../consumer/JsonServiceDocumentConsumer.java   |  116 +
 .../core/ep/consumer/XmlEntityConsumer.java     |  239 ++
 .../core/ep/consumer/XmlEntryConsumer.java      |  684 ++++++
 .../core/ep/consumer/XmlFeedConsumer.java       |  181 ++
 .../core/ep/consumer/XmlLinkConsumer.java       |  112 +
 .../core/ep/consumer/XmlPropertyConsumer.java   |  168 ++
 .../odata2/core/ep/entry/EntryMetadataImpl.java |   88 +
 .../odata2/core/ep/entry/MediaMetadataImpl.java |   73 +
 .../odata2/core/ep/entry/ODataEntryImpl.java    |   89 +
 .../odata2/core/ep/feed/FeedMetadataImpl.java   |   56 +
 .../odata2/core/ep/feed/ODataFeedImpl.java      |   48 +
 .../ep/producer/AtomEntryEntityProducer.java    |  527 +++++
 .../core/ep/producer/AtomFeedProducer.java      |  219 ++
 .../producer/AtomServiceDocumentProducer.java   |  122 +
 .../producer/JsonCollectionEntityProducer.java  |   74 +
 .../ep/producer/JsonEntryEntityProducer.java    |  195 ++
 .../ep/producer/JsonErrorDocumentProducer.java  |   55 +
 .../ep/producer/JsonFeedEntityProducer.java     |   93 +
 .../ep/producer/JsonLinkEntityProducer.java     |   63 +
 .../ep/producer/JsonLinksEntityProducer.java    |   82 +
 .../ep/producer/JsonPropertyEntityProducer.java |  114 +
 .../producer/JsonServiceDocumentProducer.java   |   69 +
 .../core/ep/producer/TombstoneProducer.java     |  105 +
 .../producer/XmlCollectionEntityProducer.java   |   54 +
 .../ep/producer/XmlErrorDocumentProducer.java   |   71 +
 .../core/ep/producer/XmlLinkEntityProducer.java |   60 +
 .../ep/producer/XmlLinksEntityProducer.java     |   65 +
 .../core/ep/producer/XmlMetadataProducer.java   |  591 +++++
 .../ep/producer/XmlPropertyEntityProducer.java  |  211 ++
 .../odata2/core/ep/util/CircleStreamBuffer.java |  326 +++
 .../olingo/odata2/core/ep/util/FormatJson.java  |   53 +
 .../olingo/odata2/core/ep/util/FormatXml.java   |   94 +
 .../odata2/core/ep/util/JsonStreamWriter.java   |  175 ++
 .../olingo/odata2/core/ep/util/JsonUtils.java   |   72 +
 .../odata2/core/exception/MessageService.java   |  222 ++
 .../core/exception/ODataRuntimeException.java   |   47 +
 .../processor/ODataSingleProcessorService.java  |  247 ++
 .../apache/olingo/odata2/core/rest/MERGE.java   |   31 +
 .../core/rest/ODataExceptionMapperImpl.java     |  205 ++
 .../odata2/core/rest/ODataRedirectLocator.java  |   80 +
 .../odata2/core/rest/ODataRootLocator.java      |  133 ++
 .../odata2/core/rest/ODataSubLocator.java       |  171 ++
 .../apache/olingo/odata2/core/rest/PATCH.java   |   31 +
 .../olingo/odata2/core/rest/RestUtil.java       |  266 +++
 .../odata2/core/rest/SubLocatorParameter.java   |   96 +
 .../odata2/core/rest/app/ODataApplication.java  |   84 +
 .../odata2/core/rt/RuntimeDelegateImpl.java     |  105 +
 .../odata2/core/servicedocument/AcceptImpl.java |   50 +
 .../core/servicedocument/AtomInfoImpl.java      |   99 +
 .../core/servicedocument/CategoriesImpl.java    |   76 +
 .../core/servicedocument/CategoryImpl.java      |   72 +
 .../core/servicedocument/CollectionImpl.java    |  101 +
 .../servicedocument/CommonAttributesImpl.java   |   65 +
 .../servicedocument/ExtensionAttributeImpl.java |   72 +
 .../servicedocument/ExtensionElementImpl.java   |   98 +
 .../servicedocument/ServiceDocumentImpl.java    |   55 +
 .../odata2/core/servicedocument/TitleImpl.java  |   38 +
 .../core/servicedocument/WorkspaceImpl.java     |   77 +
 .../core/uri/ExpandSelectTreeCreator.java       |  194 ++
 .../core/uri/ExpandSelectTreeNodeImpl.java      |  163 ++
 .../odata2/core/uri/KeyPredicateImpl.java       |   61 +
 .../core/uri/NavigationPropertySegmentImpl.java |   55 +
 .../odata2/core/uri/NavigationSegmentImpl.java  |   72 +
 .../olingo/odata2/core/uri/SelectItemImpl.java  |   69 +
 .../odata2/core/uri/SystemQueryOption.java      |   26 +
 .../olingo/odata2/core/uri/UriInfoImpl.java     |  324 +++
 .../olingo/odata2/core/uri/UriParserImpl.java   |  843 +++++++
 .../apache/olingo/odata2/core/uri/UriType.java  |  128 ++
 .../uri/expression/ActualBinaryOperator.java    |   42 +
 .../uri/expression/BinaryExpressionImpl.java    |   96 +
 .../ExpressionParserInternalError.java          |  124 +
 .../uri/expression/FilterExpressionImpl.java    |   84 +
 .../core/uri/expression/FilterParser.java       |   57 +
 .../expression/FilterParserExceptionImpl.java   |  289 +++
 .../core/uri/expression/FilterParserImpl.java   |  856 +++++++
 .../core/uri/expression/InfoBinaryOperator.java |   65 +
 .../odata2/core/uri/expression/InfoMethod.java  |   90 +
 .../core/uri/expression/InfoUnaryOperator.java  |   82 +
 .../core/uri/expression/InputTypeValidator.java |   51 +
 .../odata2/core/uri/expression/JsonVisitor.java |  227 ++
 .../uri/expression/LiteralExpressionImpl.java   |   67 +
 .../uri/expression/MemberExpressionImpl.java    |  100 +
 .../uri/expression/MethodExpressionImpl.java    |  109 +
 .../uri/expression/OrderByExpressionImpl.java   |   97 +
 .../core/uri/expression/OrderByParser.java      |   57 +
 .../core/uri/expression/OrderByParserImpl.java  |   96 +
 .../uri/expression/OrderExpressionImpl.java     |   83 +
 .../core/uri/expression/ParameterSet.java       |  134 ++
 .../uri/expression/ParameterSetCombination.java |  131 ++
 .../uri/expression/PropertyExpressionImpl.java  |  100 +
 .../odata2/core/uri/expression/Token.java       |   69 +
 .../odata2/core/uri/expression/TokenKind.java   |   69 +
 .../odata2/core/uri/expression/TokenList.java   |  178 ++
 .../odata2/core/uri/expression/Tokenizer.java   |  323 +++
 .../core/uri/expression/TokenizerException.java |   98 +
 .../uri/expression/TokenizerExpectError.java    |  106 +
 .../uri/expression/TokenizerRTException.java    |   39 +
 .../uri/expression/UnaryExpressionImpl.java     |   81 +
 odata-core/src/main/resources/i18n.properties   |  229 ++
 .../src/main/resources/i18n_de.properties       |   23 +
 .../src/main/resources/i18n_de_DE.properties    |   21 +
 .../src/main/resources/i18n_en.properties       |  166 ++
 .../src/main/resources/i18n_en_US.properties    |   20 +
 odata-core/src/test/java/META-INF/MANIFEST.MF   |    3 +
 .../odata2/core/ContentNegotiatorTest.java      |  178 ++
 .../olingo/odata2/core/DispatcherTest.java      |  451 ++++
 .../odata2/core/ODataContextImplTest.java       |   79 +
 .../odata2/core/ODataExceptionWrapperTest.java  |  130 ++
 .../core/ODataRequestHandlerValidationTest.java |  682 ++++++
 .../olingo/odata2/core/ODataResponseTest.java   |  105 +
 .../olingo/odata2/core/PathSegmentTest.java     |   78 +
 .../odata2/core/batch/AcceptParserTest.java     |  152 ++
 .../core/batch/BatchRequestParserTest.java      |  593 +++++
 .../core/batch/BatchResponseWriterTest.java     |  153 ++
 .../odata2/core/commons/ContentTypeTest.java    |  928 ++++++++
 .../olingo/odata2/core/commons/DecoderTest.java |   91 +
 .../olingo/odata2/core/commons/EncoderTest.java |  108 +
 .../odata2/core/debug/DebugInfoBodyTest.java    |   86 +
 .../debug/ODataDebugResponseWrapperTest.java    |  299 +++
 .../olingo/odata2/core/edm/EdmImplTest.java     |  113 +
 .../core/edm/EdmSimpleTypeFacadeTest.java       |  389 ++++
 .../odata2/core/edm/EdmSimpleTypeTest.java      | 1383 ++++++++++++
 .../odata2/core/edm/parser/EdmParserTest.java   | 1491 ++++++++++++
 .../core/edm/parser/EdmxProviderTest.java       |  146 ++
 .../provider/EdmAnnotationsImplProvTest.java    |  116 +
 .../provider/EdmAssociationEndImplProvTest.java |   77 +
 .../provider/EdmAssociationImplProvTest.java    |   89 +
 .../EdmAssociationSetEndImplProvTest.java       |   80 +
 .../provider/EdmAssociationSetImplProvTest.java |  111 +
 .../provider/EdmComplexTypeImplProvTest.java    |  121 +
 .../EdmEntityContainerImplProvTest.java         |  149 ++
 .../provider/EdmEntitySetInfoImplProvTest.java  |   76 +
 .../core/edm/provider/EdmEntitySetProvTest.java |  143 ++
 .../edm/provider/EdmEntityTypeImplProvTest.java |  180 ++
 .../provider/EdmFunctionImportImplProvTest.java |  176 ++
 .../core/edm/provider/EdmImplProvTest.java      |   80 +
 .../core/edm/provider/EdmMappingTest.java       |   79 +
 .../core/edm/provider/EdmNamedImplProvTest.java |   42 +
 .../EdmNavigationPropertyImplProvTest.java      |   93 +
 .../edm/provider/EdmPropertyImplProvTest.java   |  128 ++
 .../EdmServiceMetadataImplProvTest.java         |  285 +++
 .../odata2/core/ep/AbstractProviderTest.java    |  212 ++
 .../core/ep/AbstractXmlProducerTestHelper.java  |   64 +
 .../odata2/core/ep/BasicProviderTest.java       |  203 ++
 .../odata2/core/ep/LoadXMLFactoryTest.java      |   49 +
 .../ep/ODataEntityProviderPropertiesTest.java   |   73 +
 .../olingo/odata2/core/ep/PerformanceTest.java  |  186 ++
 .../odata2/core/ep/ProviderFacadeImplTest.java  |  243 ++
 .../ep/aggregator/EntityInfoAggregatorTest.java |   79 +
 .../core/ep/consumer/AbstractConsumerTest.java  |  168 ++
 .../AtomServiceDocumentConsumerTest.java        |  266 +++
 .../core/ep/consumer/JsonEntryConsumerTest.java |  217 ++
 .../consumer/JsonEntryDeepInsertEntryTest.java  |  297 +++
 .../consumer/JsonEntryDeepInsertFeedTest.java   |  215 ++
 .../core/ep/consumer/JsonFeedConsumerTest.java  |  333 +++
 .../core/ep/consumer/JsonLinkConsumerTest.java  |  168 ++
 .../ep/consumer/JsonPropertyConsumerTest.java   |  533 +++++
 .../JsonServiceDocumentConsumerTest.java        |   70 +
 .../consumer/ServiceDocumentConsumerTest.java   |  115 +
 .../core/ep/consumer/XmlEntityConsumerTest.java | 2130 ++++++++++++++++++
 .../core/ep/consumer/XmlFeedConsumerTest.java   |  115 +
 .../core/ep/consumer/XmlLinkConsumerTest.java   |   98 +
 .../ep/consumer/XmlPropertyConsumerTest.java    |  388 ++++
 .../core/ep/producer/AtomEntryProducerTest.java |  644 ++++++
 .../core/ep/producer/AtomFeedProducerTest.java  |  198 ++
 .../AtomServiceDocumentProducerTest.java        |  188 ++
 .../producer/JsonEntryEntityProducerTest.java   |  538 +++++
 .../core/ep/producer/JsonErrorProducerTest.java |   77 +
 .../ep/producer/JsonFeedEntityProducerTest.java |  124 +
 .../ep/producer/JsonFunctionImportTest.java     |  158 ++
 .../ep/producer/JsonLinkEntityProducerTest.java |   79 +
 .../producer/JsonLinksEntityProducerTest.java   |  135 ++
 .../ep/producer/JsonPropertyProducerTest.java   |  166 ++
 .../JsonServiceDocumentProducerTest.java        |   84 +
 .../odata2/core/ep/producer/MyCallback.java     |  102 +
 .../producer/ServiceDocumentProducerTest.java   |   78 +
 .../core/ep/producer/TombstoneCallbackImpl.java |   45 +
 .../core/ep/producer/TombstoneProducerTest.java |  221 ++
 .../core/ep/producer/XmlErrorProducerTest.java  |  266 +++
 .../core/ep/producer/XmlExpandProducerTest.java |  430 ++++
 .../XmlFeedWithTombstonesProducerTest.java      |  164 ++
 .../core/ep/producer/XmlFunctionImportTest.java |  132 ++
 .../ep/producer/XmlLinkEntityProducerTest.java  |   76 +
 .../ep/producer/XmlLinksEntityProducerTest.java |   82 +
 .../ep/producer/XmlMetadataProducerTest.java    |  364 +++
 .../ep/producer/XmlPropertyProducerTest.java    |  170 ++
 .../core/ep/producer/XmlSelectProducerTest.java |  319 +++
 .../core/ep/util/CircleStreamBufferTest.java    |  242 ++
 .../core/ep/util/JsonStreamWriterTest.java      |   84 +
 .../core/exception/MessageReferenceTest.java    |   70 +
 .../core/exception/MessageServiceTest.java      |  113 +
 .../core/exception/ODataExceptionTest.java      |  121 +
 .../exception/ODataMessageTextVerifierTest.java |   56 +
 .../ODataSingleProcessorServiceTest.java        |  180 ++
 .../rest/ODataErrorHandlerCallbackImpl.java     |   64 +
 .../core/rest/ODataExceptionMapperImplTest.java |  444 ++++
 .../core/rest/ODataServiceFactoryImpl.java      |   51 +
 .../odata2/core/rt/RuntimeDelegateTest.java     |   35 +
 .../uri/ExpandSelectTreeCreatorImplTest.java    |  471 ++++
 .../odata2/core/uri/QueryOptionsEnumTest.java   |  336 +++
 .../olingo/odata2/core/uri/UriInfoTest.java     |  185 ++
 .../odata2/core/uri/UriParserFacadeTest.java    |   42 +
 .../olingo/odata2/core/uri/UriParserTest.java   |  904 ++++++++
 .../uri/expression/FilterParserImplTool.java    |   76 +
 .../core/uri/expression/FilterToJsonTest.java   |  230 ++
 .../odata2/core/uri/expression/ParserTool.java  |  589 +++++
 .../uri/expression/TestAbapCompatibility.java   |  414 ++++
 .../odata2/core/uri/expression/TestBase.java    |   81 +
 .../core/uri/expression/TestExceptionTexts.java |   55 +
 .../odata2/core/uri/expression/TestParser.java  |  493 ++++
 .../uri/expression/TestParserExceptions.java    |  418 ++++
 .../odata2/core/uri/expression/TestSpec.java    |  344 +++
 .../core/uri/expression/TestTokenizer.java      |  228 ++
 .../odata2/core/uri/expression/TokenTool.java   |  294 +++
 .../odata2/core/uri/expression/VisitorTool.java |  125 +
 .../src/test/resources/InvalidSvcDocJson2.txt   |    1 +
 odata-core/src/test/resources/JsonBuilding      |   17 +
 .../test/resources/JsonBuildingWithInlineRooms  |   37 +
 ...onBuildingWithInlineRoomsAndNextLinkAndCount |   39 +
 .../src/test/resources/JsonBuildingWithoutD     |   15 +
 odata-core/src/test/resources/JsonEmployee      |   48 +
 .../test/resources/JsonEmployeeWithInlineTeam   |   58 +
 .../resources/JsonInlineRoomWithInlineBuilding  |   75 +
 .../resources/JsonInvalidTeamDoubleNameProperty |   18 +
 odata-core/src/test/resources/JsonTeam          |   17 +
 odata-core/src/test/resources/JsonTeams         |   34 +
 .../src/test/resources/JsonTeamsWithCount       |   35 +
 .../test/resources/JsonTeamsWithCountWithoutD   |   34 +
 .../test/resources/JsonTeamsWithInlineEmployees |  151 ++
 odata-core/src/test/resources/JsonTeamsWithoutD |   33 +
 odata-core/src/test/resources/batchRequest.txt  |   51 +
 .../src/test/resources/batchWithContent.txt     |    1 +
 odata-core/src/test/resources/batchWithPost.txt |   38 +
 .../src/test/resources/double_expanded_team.xml |  264 +++
 .../src/test/resources/employee_empty_room.xml  |   52 +
 .../src/test/resources/expandedBuilding.xml     |   60 +
 odata-core/src/test/resources/expanded_team.xml |  146 ++
 .../src/test/resources/feed_employees.xml       |  247 ++
 .../src/test/resources/feed_employees_full.xml  |  249 ++
 .../src/test/resources/feed_with_delta_link.xml |   69 +
 .../src/test/resources/i18n_test_SAP.properties |   25 +
 .../src/test/resources/invalidSvcDocJson.txt    |    1 +
 .../src/test/resources/invalidSvcExample.xml    |   34 +
 odata-core/src/test/resources/refScenario.edmx  |  236 ++
 .../src/test/resources/serviceDocExample.xml    |   69 +
 .../src/test/resources/serviceDocument.xml      |   43 +
 .../src/test/resources/svcAtomExample.xml       |   52 +
 odata-core/src/test/resources/svcDocJson.txt    |    1 +
 .../src/test/resources/svcDocWithoutTitle.xml   |   42 +
 odata-core/src/test/resources/svcExample.xml    |   76 +
 odata-fit/pom.xml                               |  212 ++
 .../odata2/fit/basic/AbstractBasicTest.java     |   86 +
 .../odata2/fit/basic/AcceptHeaderTypeTest.java  |  169 ++
 .../olingo/odata2/fit/basic/BasicBatchTest.java |  229 ++
 .../olingo/odata2/fit/basic/BasicHttpTest.java  |  267 +++
 .../ContentNegotiationDollarFormatTest.java     |  100 +
 .../olingo/odata2/fit/basic/ContextTest.java    |  207 ++
 .../odata2/fit/basic/ErrorResponseTest.java     |   60 +
 .../olingo/odata2/fit/basic/ExceptionsTest.java |   63 +
 .../olingo/odata2/fit/basic/FitLoadTest.java    |   84 +
 .../fit/basic/HttpExceptionResponseTest.java    |  157 ++
 .../fit/basic/LanguageNegotiationTest.java      |  133 ++
 .../olingo/odata2/fit/basic/MetadataTest.java   |   61 +
 .../fit/basic/RequestContentTypeTest.java       |  166 ++
 .../odata2/fit/basic/ServiceResolutionTest.java |  269 +++
 .../olingo/odata2/fit/basic/UrlRewriteTest.java |  170 ++
 .../odata2/fit/basic/issues/TestIssue105.java   |   79 +
 .../olingo/odata2/fit/mapping/MapFactory.java   |   43 +
 .../olingo/odata2/fit/mapping/MapProcessor.java |  131 ++
 .../olingo/odata2/fit/mapping/MapProvider.java  |  145 ++
 .../olingo/odata2/fit/mapping/MappingTest.java  |  129 ++
 .../odata2/fit/ref/AbstractRefJsonTest.java     |   38 +
 .../olingo/odata2/fit/ref/AbstractRefTest.java  |  204 ++
 .../odata2/fit/ref/AbstractRefXmlTest.java      |   90 +
 .../apache/olingo/odata2/fit/ref/BatchTest.java |   98 +
 .../odata2/fit/ref/ContentNegotiationTest.java  |  147 ++
 .../odata2/fit/ref/DataServiceVersionTest.java  |  122 +
 .../odata2/fit/ref/EntryJsonChangeTest.java     |  120 +
 .../fit/ref/EntryJsonCreateInlineTest.java      |  342 +++
 .../odata2/fit/ref/EntryJsonCreateTest.java     |  108 +
 .../odata2/fit/ref/EntryJsonReadOnlyTest.java   |  155 ++
 .../odata2/fit/ref/EntryXmlChangeTest.java      |  280 +++
 .../odata2/fit/ref/EntryXmlCreateTest.java      |   81 +
 .../odata2/fit/ref/EntryXmlReadOnlyTest.java    |  208 ++
 .../odata2/fit/ref/FeedJsonReadOnlyTest.java    |  154 ++
 .../odata2/fit/ref/FeedXmlReadOnlyTest.java     |  266 +++
 .../odata2/fit/ref/FunctionImportJsonTest.java  |   82 +
 .../odata2/fit/ref/FunctionImportXmlTest.java   |  106 +
 .../odata2/fit/ref/LinksJsonChangeTest.java     |   49 +
 .../odata2/fit/ref/LinksJsonReadOnlyTest.java   |   51 +
 .../odata2/fit/ref/LinksXmlChangeTest.java      |   66 +
 .../odata2/fit/ref/LinksXmlReadOnlyTest.java    |   68 +
 .../olingo/odata2/fit/ref/MetadataTest.java     |  210 ++
 .../olingo/odata2/fit/ref/MiscChangeTest.java   |  116 +
 .../olingo/odata2/fit/ref/MiscReadOnlyTest.java |   99 +
 .../odata2/fit/ref/PropertyJsonChangeTest.java  |   57 +
 .../fit/ref/PropertyJsonReadOnlyTest.java       |   57 +
 .../odata2/fit/ref/PropertyXmlChangeTest.java   |   80 +
 .../odata2/fit/ref/PropertyXmlReadOnlyTest.java |  112 +
 .../olingo/odata2/fit/ref/ServiceJsonTest.java  |   72 +
 .../olingo/odata2/fit/ref/ServiceXmlTest.java   |  122 +
 .../AbstractContentNegotiationTest.java         |  689 ++++++
 .../ContentNegotiationGetRequestTest.java       |  418 ++++
 .../ContentNegotiationPostRequestTest.java      |  247 ++
 .../src/test/resources/batchWithContentId.batch |   56 +
 odata-fit/src/test/resources/changeset.batch    |   37 +
 odata-fit/src/test/resources/error.batch        |   17 +
 odata-fit/src/test/resources/i18n.properties    |   22 +
 odata-fit/src/test/resources/i18n_it.properties |   22 +
 .../resources/room_w_four_inlined_employees.xml |  219 ++
 odata-fit/src/test/resources/simple.batch       |    8 +
 odata-ref/pom.xml                               |  107 +
 .../odata2/ref/edm/ScenarioEdmProvider.java     |  491 ++++
 .../olingo/odata2/ref/model/Building.java       |   82 +
 .../apache/olingo/odata2/ref/model/City.java    |   55 +
 .../olingo/odata2/ref/model/DataContainer.java  |  289 +++
 .../olingo/odata2/ref/model/Employee.java       |  182 ++
 .../olingo/odata2/ref/model/Location.java       |   54 +
 .../apache/olingo/odata2/ref/model/Manager.java |   38 +
 .../olingo/odata2/ref/model/ModelException.java |   32 +
 .../apache/olingo/odata2/ref/model/Photo.java   |  149 ++
 .../apache/olingo/odata2/ref/model/Room.java    |   95 +
 .../apache/olingo/odata2/ref/model/Team.java    |   77 +
 .../odata2/ref/processor/ListsDataSource.java   |  186 ++
 .../odata2/ref/processor/ListsProcessor.java    | 1684 ++++++++++++++
 .../ref/processor/ScenarioDataSource.java       |  605 +++++
 .../ref/processor/ScenarioErrorCallback.java    |   48 +
 .../ref/processor/ScenarioServiceFactory.java   |   59 +
 odata-ref/src/main/resources/female_6_BaySu.jpg |  Bin 0 -> 2418 bytes
 odata-ref/src/main/resources/male_1_WinterW.jpg |  Bin 0 -> 2723 bytes
 odata-ref/src/main/resources/male_2_FallF.jpg   |  Bin 0 -> 2515 bytes
 odata-ref/src/main/resources/male_3_SmithJo.jpg |  Bin 0 -> 2659 bytes
 odata-ref/src/main/resources/male_4_BurkeP.jpg  |  Bin 0 -> 2741 bytes
 odata-ref/src/main/resources/male_5_FieldJ.jpg  |  Bin 0 -> 2256 bytes
 .../olingo/odata2/ref/model/BuildingTest.java   |   72 +
 .../odata2/ref/model/DataContainerTest.java     |   85 +
 .../olingo/odata2/ref/model/EmployeeTest.java   |  156 ++
 .../olingo/odata2/ref/model/ManagerTest.java    |  101 +
 .../olingo/odata2/ref/model/RoomTest.java       |   83 +
 .../olingo/odata2/ref/model/TeamTest.java       |   71 +
 .../olingo/odata2/ref/read/EntitySetTest.java   |  157 ++
 .../olingo/odata2/ref/read/EntityTest.java      |  173 ++
 odata-testutil/pom.xml                          |  109 +
 .../testutil/TestUtilRuntimeException.java      |   42 +
 .../odata2/testutil/fit/AbstractFitTest.java    |   81 +
 .../olingo/odata2/testutil/fit/BaseTest.java    |  113 +
 .../odata2/testutil/fit/FitErrorCallback.java   |   47 +
 .../testutil/fit/FitStaticServiceFactory.java   |   90 +
 .../testutil/fit/Log4JConfigurationTest.java    |   35 +
 .../odata2/testutil/helper/ClassHelper.java     |  159 ++
 .../odata2/testutil/helper/HttpMerge.java       |   53 +
 .../helper/HttpSomethingUnsupported.java        |   53 +
 .../helper/ODataMessageTextVerifier.java        |  135 ++
 .../odata2/testutil/helper/ProcessLocker.java   |   96 +
 .../odata2/testutil/helper/StringHelper.java    |  117 +
 .../odata2/testutil/helper/XMLUnitHelper.java   |   56 +
 .../olingo/odata2/testutil/mock/EdmMock.java    |  338 +++
 .../odata2/testutil/mock/EdmTestProvider.java   |  522 +++++
 .../olingo/odata2/testutil/mock/MockFacade.java |   49 +
 .../SampleClassForInvalidMessageReferences.java |   42 +
 .../olingo/odata2/testutil/mock/TecEdmInfo.java |   50 +
 .../mock/TechnicalScenarioEdmProvider.java      |  300 +++
 .../testutil/server/ServerRuntimeException.java |   32 +
 .../odata2/testutil/server/TestServer.java      |  137 ++
 odata-testutil/src/main/resources/log4j.xml     |   39 +
 odata-web/pom.xml                               |  127 ++
 odata-web/src/main/resources/log4j.xml          |   41 +
 odata-web/src/main/version/version.html         |    9 +
 odata-web/src/main/webapp/WEB-INF/web.xml       |   48 +
 odata-web/src/main/webapp/index.jsp             |   93 +
 pom.xml                                         |  306 +++
 src/eclipse/codetemplates.xml                   |   10 +
 src/eclipse/eclipse-cleanup-profile.xml         |   80 +
 src/eclipse/eclipse-codestyle-formatter.xml     | 1637 ++++++++++++++
 src/eclipse/eclipse-codetemplates.xml           |    6 +
 src/eclipse/org.eclipse.jdt.core.prefs          |  291 +++
 src/etc/header.txt                              |    1 +
 src/git/hooks/pre-commit                        |   39 +
 890 files changed, 127109 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9c201f5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.pmd
+.project
+.classpath
+.settings
+target
+bin
+*.bak
+classes
+.DS_Store

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   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.

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/NOTICE
----------------------------------------------------------------------
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..501a6bb
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1 @@
+	
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..bce07c3
--- /dev/null
+++ b/README.md
@@ -0,0 +1,113 @@
+OData Library (Java)
+====================
+
+Introduction
+------------
+
+### What is it about? ###
+
+The [Open Data Protocol (OData)](http://odata.org) is a Web protocol for querying and updating data that provides a way to unlock your data and free it from silos that exist in applications today. OData does this by applying and building upon Web technologies such as HTTP, Atom Publishing Protocol (AtomPub) and JSON to provide access to information from a variety of applications, services, and stores.
+
+The OData Library (Java) is a library which enables developers to implement OData producers and OData consumers and adheres to the following principles:
+
+- Provide an OData 2.0 specification compliant OData Library (Java) 
+- Enhancements shall be possible in a compatible manner 
+- Clear separation between Core and API 
+- Option to build extensions on top
+
+### Some more Background ###
+
+The basic idea behind this project is to have a code base that can continue development to support future OData 4.0 standard. OData 4.0 is expected to be release by OAISI in 2013. For that the code is modular and has following components:
+
+- URI parser: currently a OData 2.0 parser
+- Dispatcher: is handling OData 2.0 URI types
+- Processor interfaces: to support server side implementations
+- EDM model API: OData 2.0 compliant, supports lazy and partial loading of metadata
+- Entity provider: for JSON and Atom default formats and extendible to support future formats
+
+The support of OData 2.0 is just mandatory because of there is already a wide adoption of this standard version. It is also an option to extend the OData 2.0 library to support features of OData 3.0 if required. Contributions to this are welcome.
+
+For OData 4.0 development could happen in a new branch and we target that OData 2.0 (3.0) and OData 4.0 can exist in parallel. 
+
+Maven
+-----
+
+The project build with Maven. To consume sources execute 
+
+    mvn eclipse:eclipse
+
+and import generated projects into Eclipse. 
+
+To consume libraries with Maven add following dependencies to your pom.xml:
+
+    $odata.lib.version=0.6.0
+
+    <dependency>
+      <groupId>com.sap.odata</groupId>
+      <artifactId>com.sap.core.odata.api</artifactId>
+      <version>${odata.lib.version}</version> 
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.sap.odata</groupId>
+      <artifactId>com.sap.core.odata.core</artifactId>
+      <version>${odata.lib.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+
+For advanced JPA processor usage these additional dependencies are required:
+
+    <dependency>
+      <groupId>com.sap.odata</groupId>
+      <artifactId>com.sap.core.odata.processor.api</artifactId>
+      <version>${odata.lib.version}</version> 
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.sap.odata</groupId>
+      <artifactId>com.sap.core.odata.api.annotation</artifactId>
+      <version>${odata.lib.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.sap.odata</groupId>
+      <artifactId>com.sap.core.odata.processor.core</artifactId>
+      <version>${odata.lib.version}</version>
+      <scope>runtime</scope>
+    </dependency>
+
+
+Build artifacts are already available at Maven Central.
+
+Additional Information
+----------------------
+
+### License ###
+
+This project is copyrighted by [SAP AG](http://www.sap.com/) and made available under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). Please also confer to the text files "LICENSE" and "NOTICE" included with the project sources.
+
+
+### Contributions ###
+
+Contributions to this project are very welcome, but can only be accepted if the contributions themselves are given to the project under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0.html). Contributions other than those given under Apache License 2.0 will be rejected.
+
+
+Version History
+---------------
+
+0.7.0-SNAPSHOT advanced $batch (content id handling) <br/>
+0.6.0  Support of tumbestones and $batch
+0.5.0  Service Document parsing / performance optimization<br/>
+0.4.1  JPA processor support  
+0.4.0  Advanced Read / Write and JSON support  
+0.3.0  Advanced Read / Basic Write  
+0.2.0  Basic Read / Write  
+0.1.0  Basic Read
+
+Roadmap
+-------
+
+1. $batch
+2. Conditional Handling  
+3. Client Support
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/.gitignore
----------------------------------------------------------------------
diff --git a/jpa-annotation/.gitignore b/jpa-annotation/.gitignore
new file mode 100644
index 0000000..8b3fd61
--- /dev/null
+++ b/jpa-annotation/.gitignore
@@ -0,0 +1,8 @@
+.project
+.classpath
+.settings
+target
+bin
+*.bak
+classes
+.DS_Store

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/pom.xml
----------------------------------------------------------------------
diff --git a/jpa-annotation/pom.xml b/jpa-annotation/pom.xml
new file mode 100644
index 0000000..b8899af
--- /dev/null
+++ b/jpa-annotation/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+         or more contributor license agreements.  See the NOTICE file
+         distributed with this work for additional information
+         regarding copyright ownership.  The ASF licenses this file
+         to you under the Apache License, Version 2.0 (the
+         "License"); you may not use this file except in compliance
+         with the License.  You may obtain a copy of the License at
+  
+           http://www.apache.org/licenses/LICENSE-2.0
+  
+         Unless required by applicable law or agreed to in writing,
+         software distributed under the License is distributed on an
+         "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+         KIND, either express or implied.  See the License for the
+         specific language governing permissions and limitations
+         under the License.
+-->
+<project
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+	xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+	<modelVersion>4.0.0</modelVersion>
+	
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>org.apache.olingo.odata2.parent</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+		<relativePath>..</relativePath>
+	</parent>
+
+	<artifactId>org.apache.olingo.odata2.api.annotation</artifactId>
+
+	<dependencies>
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>3.8.1</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/jpa-annotation/src/main/java/META-INF/MANIFEST.MF b/jpa-annotation/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/jpa-annotation/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Documentation.java
----------------------------------------------------------------------
diff --git a/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Documentation.java b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Documentation.java
new file mode 100644
index 0000000..f37c766
--- /dev/null
+++ b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Documentation.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.api.annotation.edm;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface Documentation {
+  String summary() default "";
+
+  String longDescription() default "";
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Facets.java
----------------------------------------------------------------------
diff --git a/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Facets.java b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Facets.java
new file mode 100644
index 0000000..d59a3de
--- /dev/null
+++ b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Facets.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.api.annotation.edm;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface Facets {
+  int maxLength() default 0;
+
+  int scale() default -1;
+
+  int precision() default 0;
+
+  boolean nullable() default false;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/FunctionImport.java
----------------------------------------------------------------------
diff --git a/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/FunctionImport.java b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/FunctionImport.java
new file mode 100644
index 0000000..5101cc3
--- /dev/null
+++ b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/FunctionImport.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.api.annotation.edm;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.olingo.odata2.api.annotation.edmx.HttpMethod;
+import org.apache.olingo.odata2.api.annotation.edmx.HttpMethod.Name;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface FunctionImport {
+
+  enum ReturnType {
+    SCALAR, ENTITY_TYPE, COMPLEX_TYPE, NONE
+  }
+
+  enum Multiplicity {
+    MANY, ONE
+  }
+
+  String name() default "";
+
+  String entitySet() default "";
+
+  ReturnType returnType();
+
+  Multiplicity multiplicity() default Multiplicity.ONE;
+
+  HttpMethod httpMethod() default @HttpMethod(name = Name.GET);
+
+  Documentation documentation() default @Documentation;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Parameter.java
----------------------------------------------------------------------
diff --git a/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Parameter.java b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Parameter.java
new file mode 100644
index 0000000..ee685e4
--- /dev/null
+++ b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edm/Parameter.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * 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.api.annotation.edm;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface Parameter {
+  enum Mode {
+    IN {
+      @Override
+      public String toString() {
+        return new String("In");
+      }
+    },
+    OUT {
+      @Override
+      public String toString() {
+        return new String("Out");
+      }
+    },
+    INOUT {
+      @Override
+      public String toString() {
+        return new String("InOut");
+      }
+    }
+  };
+
+  String name();
+
+  Mode mode() default Mode.IN;
+
+  Facets facets() default @Facets;
+
+  Documentation documentation() default @Documentation;
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edmx/HttpMethod.java
----------------------------------------------------------------------
diff --git a/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edmx/HttpMethod.java b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edmx/HttpMethod.java
new file mode 100644
index 0000000..9e8321a
--- /dev/null
+++ b/jpa-annotation/src/main/java/org/apache/olingo/odata2/api/annotation/edmx/HttpMethod.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * 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.api.annotation.edmx;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface HttpMethod {
+  enum Name {
+    POST,
+    PUT,
+    GET,
+    MERGE,
+    DELETE,
+    PATCH
+  };
+
+  Name name();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/.gitignore
----------------------------------------------------------------------
diff --git a/jpa-api/.gitignore b/jpa-api/.gitignore
new file mode 100644
index 0000000..fe5d89b
--- /dev/null
+++ b/jpa-api/.gitignore
@@ -0,0 +1,8 @@
+.project
+.classpath
+.settings
+target
+bin
+*.bak
+classes
+.DS_Store
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/pom.xml
----------------------------------------------------------------------
diff --git a/jpa-api/pom.xml b/jpa-api/pom.xml
new file mode 100644
index 0000000..1d98843
--- /dev/null
+++ b/jpa-api/pom.xml
@@ -0,0 +1,51 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>org.apache.olingo.odata2.parent</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+		<relativePath>../</relativePath>
+	</parent>
+
+	<artifactId>org.apache.olingo.odata2.processor.api</artifactId>
+	<packaging>jar</packaging>
+
+	<dependencies>
+		<!-- JPA Support -->
+		<dependency>
+			<groupId>org.eclipse.persistence</groupId>
+			<artifactId>javax.persistence</artifactId>
+			<version>${version.javax.persistence}</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- OData Java Library -->
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.api</artifactId>
+			<version>${project.version}</version>
+			<scope>provided</scope>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/java/META-INF/MANIFEST.MF b/jpa-api/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/jpa-api/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+


[07/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
new file mode 100644
index 0000000..4658cf0
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataRequestHandlerValidationTest.java
@@ -0,0 +1,682 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+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.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.part.BatchProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityComplexPropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.MetadataProcessor;
+import org.apache.olingo.odata2.api.processor.part.ServiceDocumentProcessor;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.core.uri.UriType;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+import org.apache.olingo.odata2.testutil.mock.MockFacade;
+
+/**
+ * Tests for the validation of HTTP method, URI path, query options,
+ * and request-body content type.
+ * @author SAP AG
+ */
+public class ODataRequestHandlerValidationTest extends BaseTest {
+
+  private Edm edm = null;
+
+  @Before
+  public void setEdm() throws ODataException {
+    edm = MockFacade.getMockEdm();
+  }
+
+  private List<String> createPathSegments(final UriType uriType, final boolean moreNavigation, final boolean isValue) {
+    List<String> segments = new ArrayList<String>();
+
+    if (uriType == UriType.URI1 || uriType == UriType.URI15) {
+      if (moreNavigation) {
+        segments.add("Managers('1')");
+        segments.add("nm_Employees");
+      } else {
+        segments.add("Employees");
+      }
+    } else if (uriType == UriType.URI2 || uriType == UriType.URI3
+        || uriType == UriType.URI4 || uriType == UriType.URI5
+        || uriType == UriType.URI16 || uriType == UriType.URI17) {
+      if (moreNavigation) {
+        segments.add("Managers('1')");
+        segments.add("nm_Employees('1')");
+      } else {
+        segments.add("Employees('1')");
+      }
+    } else if (uriType == UriType.URI6A || uriType == UriType.URI7A || uriType == UriType.URI50A) {
+      segments.add("Managers('1')");
+      if (moreNavigation) {
+        segments.add("nm_Employees('1')");
+        segments.add("ne_Manager");
+      }
+      if (uriType == UriType.URI7A || uriType == UriType.URI50A) {
+        segments.add("$links");
+      }
+      segments.add("nm_Employees('1')");
+    } else if (uriType == UriType.URI6B || uriType == UriType.URI7B || uriType == UriType.URI50B) {
+      segments.add("Managers('1')");
+      if (moreNavigation) {
+        segments.add("nm_Employees('1')");
+        segments.add("ne_Manager");
+      }
+      if (uriType == UriType.URI7B || uriType == UriType.URI50B) {
+        segments.add("$links");
+      }
+      segments.add("nm_Employees");
+    } else if (uriType == UriType.URI8) {
+      segments.add("$metadata");
+    } else if (uriType == UriType.URI9) {
+      segments.add("$batch");
+    } else if (uriType == UriType.URI10) {
+      segments.add("OldestEmployee");
+    } else if (uriType == UriType.URI11) {
+      segments.add("AllLocations");
+    } else if (uriType == UriType.URI12) {
+      segments.add("MostCommonLocation");
+    } else if (uriType == UriType.URI13) {
+      segments.add("AllUsedRoomIds");
+    } else if (uriType == UriType.URI14) {
+      segments.add("MaximalAge");
+    }
+
+    if (uriType == UriType.URI3 || uriType == UriType.URI4) {
+      segments.add("Location");
+    }
+    if (uriType == UriType.URI4) {
+      segments.add("Country");
+    } else if (uriType == UriType.URI5) {
+      segments.add("EmployeeName");
+    }
+
+    if (uriType == UriType.URI15 || uriType == UriType.URI16
+        || uriType == UriType.URI50A || uriType == UriType.URI50B) {
+      segments.add("$count");
+    }
+
+    if (uriType == UriType.URI17 || isValue) {
+      segments.add("$value");
+    }
+
+    // self-test
+    try {
+      final UriInfoImpl uriInfo = (UriInfoImpl) UriParser.parse(edm,
+          MockFacade.getPathSegmentsAsODataPathSegmentMock(segments),
+          Collections.<String, String> emptyMap());
+      assertEquals(uriType, uriInfo.getUriType());
+      assertEquals(uriType == UriType.URI17 || isValue, uriInfo.isValue());
+    } catch (final ODataException e) {
+      fail();
+    }
+
+    return segments;
+  }
+
+  private static Map<String, String> createOptions(
+      final boolean format,
+      final boolean filter, final boolean inlineCount, final boolean orderBy,
+      final boolean skipToken, final boolean skip, final boolean top,
+      final boolean expand, final boolean select) {
+
+    Map<String, String> map = new HashMap<String, String>();
+
+    if (format) {
+      map.put("$format", ODataFormat.XML.toString());
+    }
+    if (filter) {
+      map.put("$filter", "true");
+    }
+    if (inlineCount) {
+      map.put("$inlinecount", "none");
+    }
+    if (orderBy) {
+      map.put("$orderby", "Age");
+    }
+    if (skipToken) {
+      map.put("$skiptoken", "x");
+    }
+    if (skip) {
+      map.put("$skip", "0");
+    }
+    if (top) {
+      map.put("$top", "0");
+    }
+    if (expand) {
+      map.put("$expand", "ne_Team");
+    }
+    if (select) {
+      map.put("$select", "Age");
+    }
+
+    return map;
+  }
+
+  private ODataRequest mockODataRequest(
+      final ODataHttpMethod method,
+      final List<String> pathSegments,
+      final Map<String, String> queryParameters,
+      final String requestContentType) throws ODataException {
+    ODataRequest request = mock(ODataRequest.class);
+    when(request.getMethod()).thenReturn(method);
+    PathInfo pathInfo = mock(PathInfo.class);
+    List<PathSegment> segments = new ArrayList<PathSegment>();
+    for (final String pathSegment : pathSegments) {
+      PathSegment segment = mock(PathSegment.class);
+      when(segment.getPath()).thenReturn(pathSegment);
+      segments.add(segment);
+    }
+    when(pathInfo.getODataSegments()).thenReturn(segments);
+    when(request.getPathInfo()).thenReturn(pathInfo);
+    when(request.getQueryParameters())
+        .thenReturn(queryParameters == null ? new HashMap<String, String>() : queryParameters);
+    when(request.getContentType()).thenReturn(requestContentType);
+    return request;
+  }
+
+  private ODataService mockODataService(final ODataServiceFactory serviceFactory) throws ODataException {
+    ODataService service = DispatcherTest.getMockService();
+    when(service.getEntityDataModel()).thenReturn(edm);
+    when(service.getProcessor()).thenReturn(mock(ODataProcessor.class));
+    when(serviceFactory.createService(any(ODataContext.class))).thenReturn(service);
+
+    when(service.getSupportedContentTypes(BatchProcessor.class)).thenReturn(
+        Arrays.asList(HttpContentType.MULTIPART_MIXED));
+
+    when(service.getSupportedContentTypes(EntityProcessor.class)).thenReturn(Arrays.asList(
+        HttpContentType.APPLICATION_ATOM_XML_ENTRY_UTF8,
+        HttpContentType.APPLICATION_ATOM_XML_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8_VERBOSE,
+        HttpContentType.APPLICATION_XML_UTF8));
+
+    final List<String> jsonAndXml = Arrays.asList(
+        HttpContentType.APPLICATION_JSON_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8_VERBOSE,
+        HttpContentType.APPLICATION_XML_UTF8);
+    when(service.getSupportedContentTypes(FunctionImportProcessor.class)).thenReturn(jsonAndXml);
+    when(service.getSupportedContentTypes(EntityLinkProcessor.class)).thenReturn(jsonAndXml);
+    when(service.getSupportedContentTypes(EntityLinksProcessor.class)).thenReturn(jsonAndXml);
+    when(service.getSupportedContentTypes(EntitySimplePropertyProcessor.class)).thenReturn(jsonAndXml);
+    when(service.getSupportedContentTypes(EntityComplexPropertyProcessor.class)).thenReturn(jsonAndXml);
+
+    final List<String> wildcard = Arrays.asList(HttpContentType.WILDCARD);
+    when(service.getSupportedContentTypes(EntityMediaProcessor.class)).thenReturn(wildcard);
+    when(service.getSupportedContentTypes(EntitySimplePropertyValueProcessor.class)).thenReturn(wildcard);
+    when(service.getSupportedContentTypes(FunctionImportValueProcessor.class)).thenReturn(wildcard);
+
+    when(service.getSupportedContentTypes(EntitySetProcessor.class)).thenReturn(Arrays.asList(
+        HttpContentType.APPLICATION_ATOM_XML_FEED_UTF8,
+        HttpContentType.APPLICATION_ATOM_XML_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8_VERBOSE,
+        HttpContentType.APPLICATION_XML_UTF8));
+
+    when(service.getSupportedContentTypes(MetadataProcessor.class)).thenReturn(Arrays.asList(
+        HttpContentType.APPLICATION_XML_UTF8));
+
+    when(service.getSupportedContentTypes(ServiceDocumentProcessor.class)).thenReturn(Arrays.asList(
+        HttpContentType.APPLICATION_ATOM_SVC_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8,
+        HttpContentType.APPLICATION_JSON_UTF8_VERBOSE,
+        HttpContentType.APPLICATION_XML_UTF8));
+
+    return service;
+  }
+
+  private ODataResponse executeRequest(final ODataHttpMethod method,
+      final List<String> pathSegments,
+      final Map<String, String> queryParameters,
+      final String requestContentType) throws ODataException {
+    ODataServiceFactory serviceFactory = mock(ODataServiceFactory.class);
+    final ODataService service = mockODataService(serviceFactory);
+    when(serviceFactory.createService(any(ODataContext.class))).thenReturn(service);
+
+    final ODataRequest request = mockODataRequest(method, pathSegments, queryParameters, requestContentType);
+    final ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
+
+    return new ODataRequestHandler(serviceFactory, service, context).handle(request);
+  }
+
+  private void executeAndValidateRequest(final ODataHttpMethod method,
+      final List<String> pathSegments,
+      final Map<String, String> queryParameters,
+      final String requestContentType,
+      final HttpStatusCodes expectedStatusCode) throws ODataException {
+
+    final ODataResponse response = executeRequest(method, pathSegments, queryParameters, requestContentType);
+    assertNotNull(response);
+    assertEquals(expectedStatusCode == null ? HttpStatusCodes.PAYMENT_REQUIRED : expectedStatusCode,
+        response.getStatus());
+  }
+
+  private void checkValueContentType(final ODataHttpMethod method, final UriType uriType, final String requestContentType) throws Exception {
+    executeAndValidateRequest(method, createPathSegments(uriType, false, true), null, requestContentType, null);
+  }
+
+  private void wrongRequest(final ODataHttpMethod method, final List<String> pathSegments, final Map<String, String> queryParameters) throws ODataException {
+    executeAndValidateRequest(method, pathSegments, queryParameters, null, HttpStatusCodes.METHOD_NOT_ALLOWED);
+  }
+
+  private void wrongOptions(final ODataHttpMethod method, final UriType uriType,
+      final boolean format,
+      final boolean filter, final boolean inlineCount, final boolean orderBy,
+      final boolean skipToken, final boolean skip, final boolean top,
+      final boolean expand, final boolean select) throws ODataException {
+    wrongRequest(method,
+        createPathSegments(uriType, false, false),
+        createOptions(format, filter, inlineCount, orderBy, skipToken, skip, top, expand, select));
+  }
+
+  private void wrongFunctionHttpMethod(final ODataHttpMethod method, final UriType uriType) throws ODataException {
+    wrongRequest(method,
+        uriType == UriType.URI1 ? Arrays.asList("EmployeeSearch") : createPathSegments(uriType, false, false),
+        null);
+  }
+
+  private void wrongProperty(final ODataHttpMethod method, final boolean ofComplex, final Boolean key) throws ODataException {
+    EdmProperty property = (EdmProperty) (ofComplex ?
+        edm.getComplexType("RefScenario", "c_Location").getProperty("Country") :
+        edm.getEntityType("RefScenario", "Employee").getProperty("Age"));
+    EdmFacets facets = mock(EdmFacets.class);
+    when(facets.isNullable()).thenReturn(false);
+    when(property.getFacets()).thenReturn(facets);
+
+    List<String> pathSegments;
+    if (ofComplex) {
+      pathSegments = createPathSegments(UriType.URI4, false, true);
+    } else {
+      pathSegments = createPathSegments(UriType.URI2, false, false);
+      pathSegments.add(key ? "EmployeeId" : "Age");
+      pathSegments.add("$value");
+    }
+
+    wrongRequest(method, pathSegments, null);
+  }
+
+  private void wrongNavigationPath(final ODataHttpMethod method, final UriType uriType, final HttpStatusCodes expectedStatusCode) throws ODataException {
+    executeAndValidateRequest(method, createPathSegments(uriType, true, false), null, null, expectedStatusCode);
+  }
+
+  private void wrongRequestContentType(final ODataHttpMethod method, final UriType uriType, final ContentType requestContentType) throws ODataException {
+    wrongRequestContentType(method, uriType, false, requestContentType);
+  }
+
+  private void wrongRequestContentType(final ODataHttpMethod method, final UriType uriType, final boolean isValue, final ContentType requestContentType) throws ODataException {
+    wrongRequestContentType(method, uriType, isValue, requestContentType.toContentTypeString());
+  }
+
+  private void wrongRequestContentType(final ODataHttpMethod method, final UriType uriType, final boolean isValue, final String requestContentType) throws ODataException {
+    executeAndValidateRequest(method, createPathSegments(uriType, false, isValue), null, requestContentType, HttpStatusCodes.UNSUPPORTED_MEDIA_TYPE);
+  }
+
+  @Test
+  public void dataServiceVersion() throws Exception {
+    ODataServiceFactory serviceFactory = mock(ODataServiceFactory.class);
+    final ODataService service = mockODataService(serviceFactory);
+    when(serviceFactory.createService(any(ODataContext.class))).thenReturn(service);
+
+    ODataRequest request = mockODataRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI0, false, false), null, null);
+    ODataContextImpl context = new ODataContextImpl(request, serviceFactory);
+
+    final ODataRequestHandler handler = new ODataRequestHandler(serviceFactory, service, context);
+
+    when(request.getRequestHeaderValue(ODataHttpHeaders.DATASERVICEVERSION)).thenReturn("1.0");
+    ODataResponse response = handler.handle(request);
+    assertEquals(HttpStatusCodes.PAYMENT_REQUIRED, response.getStatus());
+
+    when(request.getRequestHeaderValue(ODataHttpHeaders.DATASERVICEVERSION)).thenReturn("2.0");
+    response = handler.handle(request);
+    assertEquals(HttpStatusCodes.PAYMENT_REQUIRED, response.getStatus());
+
+    when(request.getRequestHeaderValue(ODataHttpHeaders.DATASERVICEVERSION)).thenReturn("3.0");
+    response = handler.handle(request);
+    assertEquals(HttpStatusCodes.BAD_REQUEST, response.getStatus());
+
+    when(request.getRequestHeaderValue(ODataHttpHeaders.DATASERVICEVERSION)).thenReturn("4.2");
+    response = handler.handle(request);
+    assertEquals(HttpStatusCodes.BAD_REQUEST, response.getStatus());
+
+    when(request.getRequestHeaderValue(ODataHttpHeaders.DATASERVICEVERSION)).thenReturn("42");
+    response = handler.handle(request);
+    assertEquals(HttpStatusCodes.BAD_REQUEST, response.getStatus());
+
+    when(request.getRequestHeaderValue(ODataHttpHeaders.DATASERVICEVERSION)).thenReturn("test.2.0");
+    response = handler.handle(request);
+    assertEquals(HttpStatusCodes.BAD_REQUEST, response.getStatus());
+  }
+
+  @Test
+  public void allowedMethods() throws Exception {
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI0, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI1, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI1, false, false), null, HttpContentType.APPLICATION_JSON, null);
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI2, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI3, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI3, false, false), null, HttpContentType.APPLICATION_JSON, null);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI3, false, false), null, HttpContentType.APPLICATION_JSON, null);
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI4, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI9, false, false), null, HttpContentType.MULTIPART_MIXED, null);
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI15, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.GET, createPathSegments(UriType.URI17, false, false), null, null, null);
+  }
+
+  @Test
+  public void notAllowedMethod() throws Exception {
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI0, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI1, false, false), null);
+    wrongRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI2, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI3, false, false), null);
+    wrongRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI4, false, false), null);
+    wrongRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI5, false, false), null);
+    wrongRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI6A, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI6B, false, false), null);
+    wrongRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI7A, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI7B, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI8, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI9, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI15, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI16, false, false), null);
+    wrongRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI17, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI50A, false, false), null);
+    wrongRequest(ODataHttpMethod.DELETE, createPathSegments(UriType.URI50B, false, false), null);
+  }
+
+  @Test
+  public void notAllowedOptions() throws Exception {
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, true, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, true, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, false, true, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, false, false, true, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, false, false, false, true, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, false, false, false, false, true, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, false, false, false, false, false, true, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI1, false, false, false, false, false, false, false, false, true);
+
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI2, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI2, false, false, false, false, false, false, false, true, false);
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI2, false, false, false, false, false, false, false, false, true);
+    wrongOptions(ODataHttpMethod.PATCH, UriType.URI2, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.PATCH, UriType.URI2, false, false, false, false, false, false, false, true, false);
+    wrongOptions(ODataHttpMethod.PATCH, UriType.URI2, false, false, false, false, false, false, false, false, true);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI2, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI2, false, true, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI2, false, false, false, false, false, false, false, true, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI2, false, false, false, false, false, false, false, false, true);
+
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI3, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.PATCH, UriType.URI3, true, false, false, false, false, false, false, false, false);
+
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI4, true, false, false, false, false, false, false, false, false);
+
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI5, true, false, false, false, false, false, false, false, false);
+
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, true, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, true, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, false, true, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, false, false, true, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, false, false, false, true, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, false, false, false, false, true, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, false, false, false, false, false, true, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI6B, false, false, false, false, false, false, false, false, true);
+
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI7A, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI7A, false, true, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI7A, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI7A, false, true, false, false, false, false, false, false, false);
+
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, true, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, false, true, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, false, false, true, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, false, false, false, true, false, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, false, false, false, false, true, false, false, false);
+    wrongOptions(ODataHttpMethod.POST, UriType.URI7B, false, false, false, false, false, false, true, false, false);
+
+    wrongOptions(ODataHttpMethod.PUT, UriType.URI17, false, true, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI17, true, false, false, false, false, false, false, false, false);
+    wrongOptions(ODataHttpMethod.DELETE, UriType.URI17, false, true, false, false, false, false, false, false, false);
+  }
+
+  @Test
+  public void functionImportWrongHttpMethod() throws Exception {
+    wrongFunctionHttpMethod(ODataHttpMethod.POST, UriType.URI1);
+    wrongFunctionHttpMethod(ODataHttpMethod.PUT, UriType.URI10);
+    wrongFunctionHttpMethod(ODataHttpMethod.POST, UriType.URI11);
+    wrongFunctionHttpMethod(ODataHttpMethod.PATCH, UriType.URI12);
+    wrongFunctionHttpMethod(ODataHttpMethod.POST, UriType.URI13);
+    wrongFunctionHttpMethod(ODataHttpMethod.PUT, UriType.URI14);
+  }
+
+  @Test
+  public void wrongProperty() throws Exception {
+    wrongProperty(ODataHttpMethod.DELETE, true, false);
+
+    wrongProperty(ODataHttpMethod.PUT, false, true);
+    wrongProperty(ODataHttpMethod.PATCH, false, true);
+    wrongProperty(ODataHttpMethod.DELETE, false, true);
+    wrongProperty(ODataHttpMethod.DELETE, false, false);
+  }
+
+  @Test
+  public void wrongNavigationPath() throws Exception {
+    wrongNavigationPath(ODataHttpMethod.PUT, UriType.URI3, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.PATCH, UriType.URI3, HttpStatusCodes.BAD_REQUEST);
+
+    wrongNavigationPath(ODataHttpMethod.PUT, UriType.URI4, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.PATCH, UriType.URI4, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.DELETE, UriType.URI4, HttpStatusCodes.METHOD_NOT_ALLOWED);
+
+    wrongNavigationPath(ODataHttpMethod.PUT, UriType.URI5, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.PATCH, UriType.URI5, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.DELETE, UriType.URI5, HttpStatusCodes.METHOD_NOT_ALLOWED);
+
+    wrongNavigationPath(ODataHttpMethod.PUT, UriType.URI7A, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.PATCH, UriType.URI7A, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.DELETE, UriType.URI7A, HttpStatusCodes.BAD_REQUEST);
+
+    wrongNavigationPath(ODataHttpMethod.POST, UriType.URI6B, HttpStatusCodes.BAD_REQUEST);
+
+    wrongNavigationPath(ODataHttpMethod.POST, UriType.URI7B, HttpStatusCodes.BAD_REQUEST);
+
+    wrongNavigationPath(ODataHttpMethod.PUT, UriType.URI17, HttpStatusCodes.BAD_REQUEST);
+    wrongNavigationPath(ODataHttpMethod.DELETE, UriType.URI17, HttpStatusCodes.BAD_REQUEST);
+  }
+
+  @Test
+  public void requestContentType() throws Exception {
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI2, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI2, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI2, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI3, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI3, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI3, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI4, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI4, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI4, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI5, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI5, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI5, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI6A, false, false), null, HttpContentType.APPLICATION_XML, HttpStatusCodes.BAD_REQUEST);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI6A, false, false), null, HttpContentType.APPLICATION_XML, HttpStatusCodes.BAD_REQUEST);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI6A, false, false), null, HttpContentType.APPLICATION_XML, HttpStatusCodes.BAD_REQUEST);
+
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI6B, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI7A, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.PATCH, createPathSegments(UriType.URI7A, false, false), null, HttpContentType.APPLICATION_XML, null);
+    executeAndValidateRequest(ODataHttpMethod.MERGE, createPathSegments(UriType.URI7A, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI7B, false, false), null, HttpContentType.APPLICATION_XML, null);
+
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI9, false, false), null, HttpContentType.MULTIPART_MIXED, null);
+  }
+
+  @Test
+  public void requestContentTypeMediaResource() throws Exception {
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI1, false, false), null, "image/jpeg", null);
+
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI17, false, true), null, "image/jpeg", null);
+  }
+
+  @Test
+  public void requestContentTypeFunctionImport() throws Exception {
+    EdmFunctionImport function = edm.getDefaultEntityContainer().getFunctionImport("MaximalAge");
+    when(function.getHttpMethod()).thenReturn(ODataHttpMethod.PUT.name());
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI14, false, false), null, null, null);
+    executeAndValidateRequest(ODataHttpMethod.PUT, createPathSegments(UriType.URI14, false, false), null, HttpContentType.WILDCARD, null);
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI14, null);
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI14, HttpContentType.WILDCARD);
+
+    function = edm.getDefaultEntityContainer().getFunctionImport("OldestEmployee");
+    when(function.getHttpMethod()).thenReturn(ODataHttpMethod.POST.name());
+    executeAndValidateRequest(ODataHttpMethod.POST, createPathSegments(UriType.URI10, false, false), null, null, null);
+  }
+
+  @Test
+  public void requestValueContentType() throws Exception {
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI4, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.DELETE, UriType.URI4, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.PATCH, UriType.URI4, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.MERGE, UriType.URI4, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI4, HttpContentType.TEXT_PLAIN_UTF8);
+    checkValueContentType(ODataHttpMethod.DELETE, UriType.URI4, HttpContentType.TEXT_PLAIN_UTF8);
+    checkValueContentType(ODataHttpMethod.PATCH, UriType.URI4, HttpContentType.TEXT_PLAIN_UTF8);
+    checkValueContentType(ODataHttpMethod.MERGE, UriType.URI4, HttpContentType.TEXT_PLAIN_UTF8);
+
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI5, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.DELETE, UriType.URI5, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.PATCH, UriType.URI5, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.MERGE, UriType.URI5, HttpContentType.TEXT_PLAIN);
+
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI17, HttpContentType.TEXT_PLAIN);
+    checkValueContentType(ODataHttpMethod.DELETE, UriType.URI17, HttpContentType.TEXT_PLAIN);
+  }
+
+  @Test
+  public void requestBinaryValueContentType() throws Exception {
+    EdmProperty property = (EdmProperty) edm.getEntityType("RefScenario", "Employee").getProperty("EmployeeName");
+    when(property.getType()).thenReturn(EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance());
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI5, HttpContentType.TEXT_PLAIN);
+    when(property.getMimeType()).thenReturn("image/png");
+    checkValueContentType(ODataHttpMethod.PUT, UriType.URI5, "image/png");
+  }
+
+  @Test
+  public void wrongRequestContentType() throws Exception {
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI1, ContentType.WILDCARD);
+
+    wrongRequestContentType(ODataHttpMethod.PUT, UriType.URI2, ContentType.APPLICATION_ATOM_SVC);
+    wrongRequestContentType(ODataHttpMethod.PUT, UriType.URI2, ContentType.APPLICATION_ATOM_SVC_CS_UTF_8);
+    wrongRequestContentType(ODataHttpMethod.PUT, UriType.URI2, ContentType.APPLICATION_ATOM_SVC);
+    wrongRequestContentType(ODataHttpMethod.PUT, UriType.URI2, ContentType.APPLICATION_ATOM_SVC_CS_UTF_8);
+
+    ODataHttpMethod[] methodsToTest = { ODataHttpMethod.PUT, ODataHttpMethod.PATCH, ODataHttpMethod.MERGE };
+
+    for (ODataHttpMethod oDataHttpMethod : methodsToTest) {
+      wrongRequestContentType(oDataHttpMethod, UriType.URI2, ContentType.create("image/jpeg"));
+
+      wrongRequestContentType(oDataHttpMethod, UriType.URI3, ContentType.TEXT_PLAIN);
+
+      wrongRequestContentType(oDataHttpMethod, UriType.URI4, false, ContentType.TEXT_PLAIN);
+
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_ATOM_SVC);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_ATOM_SVC_CS_UTF_8);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_XML);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_XML_CS_UTF_8);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_ATOM_XML);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_ATOM_XML_CS_UTF_8);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_JSON);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.APPLICATION_JSON_CS_UTF_8);
+      wrongRequestContentType(oDataHttpMethod, UriType.URI5, true, ContentType.create("image/jpeg"));
+
+      wrongRequestContentType(oDataHttpMethod, UriType.URI6A, ContentType.APPLICATION_ATOM_SVC);
+
+      wrongRequestContentType(oDataHttpMethod, UriType.URI7A, ContentType.APPLICATION_ATOM_SVC);
+    }
+
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI7B, ContentType.APPLICATION_ATOM_SVC);
+
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI9, ContentType.APPLICATION_OCTET_STREAM);
+  }
+
+  @Test
+  public void unsupportedRequestContentTypeNoMediaResource() throws Exception {
+    EdmEntityType entityType = edm.getDefaultEntityContainer().getEntitySet("Employees").getEntityType();
+    when(entityType.hasStream()).thenReturn(false);
+
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI1, ContentType.APPLICATION_ATOM_SVC);
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI1, ContentType.APPLICATION_ATOM_SVC_CS_UTF_8);
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI1, ContentType.APPLICATION_OCTET_STREAM);
+    wrongRequestContentType(ODataHttpMethod.POST, UriType.URI6B, ContentType.APPLICATION_ATOM_SVC);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataResponseTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataResponseTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataResponseTest.java
new file mode 100644
index 0000000..197d74c
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/ODataResponseTest.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.HttpContentType;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class ODataResponseTest extends BaseTest {
+
+  @Test
+  public void buildStatusResponseTest() {
+    ODataResponse response = ODataResponse.status(HttpStatusCodes.FOUND).build();
+    assertEquals(HttpStatusCodes.FOUND, response.getStatus());
+  }
+
+  @Test
+  public void buildEntityResponseTest() {
+    ODataResponse response = ODataResponse.entity("abc").build();
+    assertNull(response.getStatus());
+    assertEquals("abc", response.getEntity());
+  }
+
+  @Test
+  public void buildHeaderResponseTest() {
+    ODataResponse response = ODataResponse
+        .header("abc", "123")
+        .header("def", "456")
+        .header("ghi", null)
+        .build();
+    assertNull(response.getStatus());
+    assertEquals("123", response.getHeader("abc"));
+    assertEquals("456", response.getHeader("def"));
+    assertNull(response.getHeader("ghi"));
+  }
+
+  @Test
+  public void contentHeader() {
+    final ODataResponse response = ODataResponse.contentHeader(HttpContentType.APPLICATION_OCTET_STREAM).build();
+    assertNull(response.getStatus());
+    assertEquals(HttpContentType.APPLICATION_OCTET_STREAM, response.getContentHeader());
+    assertTrue(response.containsHeader(HttpHeaders.CONTENT_TYPE));
+    assertEquals(HttpContentType.APPLICATION_OCTET_STREAM, response.getHeader(HttpHeaders.CONTENT_TYPE));
+    assertFalse(response.containsHeader(HttpHeaders.CONTENT_LENGTH));
+    assertEquals(new HashSet<String>(Arrays.asList(HttpHeaders.CONTENT_TYPE)), response.getHeaderNames());
+  }
+
+  @Test
+  public void completeResponse() {
+    final ODataResponse response = ODataResponse.newBuilder()
+        .status(HttpStatusCodes.OK)
+        .header("def", "456")
+        .eTag("x")
+        .contentHeader(HttpContentType.TEXT_PLAIN)
+        .idLiteral("id")
+        .entity("body")
+        .build();
+    assertEquals(HttpStatusCodes.OK, response.getStatus());
+    assertEquals("456", response.getHeader("def"));
+    assertEquals("x", response.getETag());
+    assertEquals(HttpContentType.TEXT_PLAIN, response.getContentHeader());
+    assertEquals("id", response.getIdLiteral());
+    assertEquals(4, response.getHeaderNames().size());
+    assertEquals("body", response.getEntity());
+
+    final ODataResponse responseCopy = ODataResponse.fromResponse(response).build();
+    assertEquals(HttpStatusCodes.OK, responseCopy.getStatus());
+    assertEquals("456", responseCopy.getHeader("def"));
+    assertEquals("x", responseCopy.getETag());
+    assertEquals(HttpContentType.TEXT_PLAIN, response.getContentHeader());
+    assertEquals("id", responseCopy.getIdLiteral());
+    assertEquals("body", responseCopy.getEntity());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/PathSegmentTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/PathSegmentTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/PathSegmentTest.java
new file mode 100644
index 0000000..cba2439
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/PathSegmentTest.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * 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;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class PathSegmentTest extends BaseTest {
+
+  PathSegment segment;
+  PathSegment segmentNoMatrix;
+
+  @Before
+  public void before() {
+    Map<String, List<String>> map = new HashMap<String, List<String>>();
+    map.put("a", Arrays.asList("1"));
+    map.put("b", Arrays.asList("2"));
+    map.put("c", Arrays.asList("3"));
+    map.put("m", Arrays.asList("x", "y", "z"));
+
+    segment = new ODataPathSegmentImpl("segment", map);
+    segmentNoMatrix = new ODataPathSegmentImpl("segment", null);
+  }
+
+  @Test
+  public void testPathSegement() {
+    assertEquals("segment", segment.getPath());
+
+    assertEquals("1", segment.getMatrixParameters().get("a").get(0));
+    assertEquals("2", segment.getMatrixParameters().get("b").get(0));
+    assertEquals("3", segment.getMatrixParameters().get("c").get(0));
+
+    assertEquals("x", segment.getMatrixParameters().get("m").get(0));
+    assertEquals("y", segment.getMatrixParameters().get("m").get(1));
+    assertEquals("z", segment.getMatrixParameters().get("m").get(2));
+  }
+
+  @Test(expected = UnsupportedOperationException.class)
+  public void readonlyMatrixParameter() {
+    segment.getMatrixParameters().get("m").clear();
+  }
+
+  @Test
+  public void noMatrixParameter() {
+    assertEquals("segment", segmentNoMatrix.getPath());
+    assertTrue(segmentNoMatrix.getMatrixParameters().isEmpty());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
new file mode 100644
index 0000000..88b3c11
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/AcceptParserTest.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+
+public class AcceptParserTest {
+  private static final String TAB = "\t";
+
+  @Test
+  public void testAcceptHeader() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+    assertNotNull(acceptHeaders);
+    assertEquals(4, acceptHeaders.size());
+    assertEquals("text/html", acceptHeaders.get(0));
+    assertEquals("application/xhtml+xml", acceptHeaders.get(1));
+    assertEquals("application/xml", acceptHeaders.get(2));
+    assertEquals("*/*", acceptHeaders.get(3));
+  }
+
+  @Test
+  public void testAcceptHeaderWithParameter() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;odata=verbose;q=1.0, */*;q=0.1");
+    assertNotNull(acceptHeaders);
+    assertEquals(2, acceptHeaders.size());
+    assertEquals("application/json;odata=verbose", acceptHeaders.get(0));
+    ;
+    assertEquals("*/*", acceptHeaders.get(1));
+  }
+
+  @Test
+  public void testAcceptHeaderWithParameterAndLws() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;  odata=verbose;q=1.0, */*;q=0.1");
+    assertNotNull(acceptHeaders);
+    assertEquals(2, acceptHeaders.size());
+    assertEquals("application/json;  odata=verbose", acceptHeaders.get(0));
+    ;
+    assertEquals("*/*", acceptHeaders.get(1));
+  }
+
+  @Test
+  public void testAcceptHeaderWithTabulator() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/json;\todata=verbose;q=1.0, */*;q=0.1");
+    assertNotNull(acceptHeaders);
+    assertEquals(2, acceptHeaders.size());
+    assertEquals("application/json;" + TAB + "odata=verbose", acceptHeaders.get(0));
+    ;
+    assertEquals("*/*", acceptHeaders.get(1));
+  }
+
+  @Test
+  public void testAcceptHeaderWithTwoParameters() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/xml;another=test ; param=alskdf, */*;q=0.1");
+    assertNotNull(acceptHeaders);
+    assertEquals(2, acceptHeaders.size());
+    assertEquals("application/xml;another=test ; param=alskdf", acceptHeaders.get(0));
+    ;
+    assertEquals("*/*", acceptHeaders.get(1));
+  }
+
+  @Test
+  public void testAcceptHeader2() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("text/html;level=1, application/*, */*;q=0.1");
+    assertNotNull(acceptHeaders);
+    assertEquals(3, acceptHeaders.size());
+    assertEquals("text/html;level=1", acceptHeaders.get(0));
+    assertEquals("application/*", acceptHeaders.get(1));
+    assertEquals("*/*", acceptHeaders.get(2));
+  }
+
+  @Test
+  public void testMoreSpecificMediaType() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/*, application/xml");
+    assertNotNull(acceptHeaders);
+    assertEquals(2, acceptHeaders.size());
+    assertEquals("application/xml", acceptHeaders.get(0));
+    assertEquals("application/*", acceptHeaders.get(1));
+  }
+
+  @Test
+  public void testQualityParameter() throws BatchException {
+    List<String> acceptHeaders = AcceptParser.parseAcceptHeaders("application/*, */*; q=0.012");
+    assertNotNull(acceptHeaders);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidAcceptHeader() throws BatchException {
+    AcceptParser.parseAcceptHeaders("appi cation/*, */*;q=0.1");
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidQualityParameter() throws BatchException {
+    AcceptParser.parseAcceptHeaders("appication/*, */*;q=0,9");
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidQualityParameter2() throws BatchException {
+    AcceptParser.parseAcceptHeaders("appication/*, */*;q=1.0001");
+  }
+
+  @Test
+  public void testAcceptLanguages() throws BatchException {
+    List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("en-US,en;q=0.7,en-UK;q=0.9");
+    assertNotNull(acceptLanguageHeaders);
+    assertEquals(3, acceptLanguageHeaders.size());
+    assertEquals("en-US", acceptLanguageHeaders.get(0));
+    assertEquals("en-UK", acceptLanguageHeaders.get(1));
+    assertEquals("en", acceptLanguageHeaders.get(2));
+  }
+
+  @Test
+  public void testAllAcceptLanguages() throws BatchException {
+    List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("*");
+    assertNotNull(acceptLanguageHeaders);
+    assertEquals(1, acceptLanguageHeaders.size());
+  }
+
+  @Test
+  public void testLongAcceptLanguageValue() throws BatchException {
+    List<String> acceptLanguageHeaders = AcceptParser.parseAcceptableLanguages("english");
+    assertNotNull(acceptLanguageHeaders);
+    assertEquals("english", acceptLanguageHeaders.get(0));
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidAcceptLanguageValue() throws BatchException {
+    AcceptParser.parseAcceptableLanguages("en_US");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
new file mode 100644
index 0000000..edf5f3e
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchRequestParserTest.java
@@ -0,0 +1,593 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchPart;
+import org.apache.olingo.odata2.api.commons.HttpHeaders;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
+import org.apache.olingo.odata2.api.processor.ODataRequest;
+import org.apache.olingo.odata2.core.ODataPathSegmentImpl;
+import org.apache.olingo.odata2.core.PathInfoImpl;
+import org.apache.olingo.odata2.testutil.helper.StringHelper;
+
+/**
+ * @author SAP AG
+ */
+public class BatchRequestParserTest {
+
+  private static final String CONTENT_ID_REFERENCE = "NewEmployee";
+  private static final String PUT_MIME_HEADER_CONTENT_ID = "BBB_MIMEPART1";
+  private static final String PUT_REQUEST_HEADER_CONTENT_ID = "BBB_REQUEST1";
+  private static final String SERVICE_ROOT = "http://localhost/odata/";
+  private static EntityProviderBatchProperties batchProperties;
+  private static final String contentType = "multipart/mixed;boundary=batch_8194-cf13-1f56";
+  private static final String MIME_HEADERS = "Content-Type: application/http" + "\r\n"
+      + "Content-Transfer-Encoding: binary" + "\r\n";
+  private static final String GET_REQUEST = MIME_HEADERS + "\n"
+      + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
+      + "\n"
+      + "\n";
+
+  @BeforeClass
+  public static void setProperties() throws URISyntaxException {
+    PathInfoImpl pathInfo = new PathInfoImpl();
+    pathInfo.setServiceRoot(new URI(SERVICE_ROOT));
+    batchProperties = EntityProviderBatchProperties.init().pathInfo(pathInfo).build();
+
+  }
+
+  @Test
+  public void test() throws IOException, BatchException, URISyntaxException {
+    String fileName = "/batchWithPost.txt";
+    InputStream in = ClassLoader.class.getResourceAsStream(fileName);
+    if (in == null) {
+      throw new IOException("Requested file '" + fileName + "' was not found.");
+    }
+
+    BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
+    List<BatchPart> batchParts = parser.parse(in);
+    assertNotNull(batchParts);
+    assertEquals(false, batchParts.isEmpty());
+    for (BatchPart object : batchParts) {
+      if (!object.isChangeSet()) {
+        assertEquals(1, object.getRequests().size());
+        ODataRequest retrieveRequest = object.getRequests().get(0);
+        assertEquals(ODataHttpMethod.GET, retrieveRequest.getMethod());
+        if (!retrieveRequest.getAcceptableLanguages().isEmpty()) {
+          assertEquals(3, retrieveRequest.getAcceptableLanguages().size());
+        }
+        assertEquals(new URI(SERVICE_ROOT), retrieveRequest.getPathInfo().getServiceRoot());
+        ODataPathSegmentImpl pathSegment = new ODataPathSegmentImpl("Employees('2')", null);
+        assertEquals(pathSegment.getPath(), retrieveRequest.getPathInfo().getODataSegments().get(0).getPath());
+        if (retrieveRequest.getQueryParameters().get("$format") != null) {
+          assertEquals("json", retrieveRequest.getQueryParameters().get("$format"));
+        }
+        assertEquals(SERVICE_ROOT + "Employees('2')/EmployeeName?$format=json", retrieveRequest.getPathInfo().getRequestUri().toASCIIString());
+      } else {
+        List<ODataRequest> requests = object.getRequests();
+        for (ODataRequest request : requests) {
+
+          assertEquals(ODataHttpMethod.PUT, request.getMethod());
+          assertEquals("100000", request.getRequestHeaderValue(HttpHeaders.CONTENT_LENGTH.toLowerCase()));
+          assertEquals("application/json;odata=verbose", request.getContentType());
+          assertEquals(3, request.getAcceptHeaders().size());
+          assertNotNull(request.getAcceptableLanguages());
+          assertTrue(request.getAcceptableLanguages().isEmpty());
+          assertEquals("*/*", request.getAcceptHeaders().get(2));
+          assertEquals("application/atomsvc+xml", request.getAcceptHeaders().get(0));
+          assertEquals(new URI(SERVICE_ROOT + "Employees('2')/EmployeeName").toASCIIString(), request.getPathInfo().getRequestUri().toASCIIString());
+
+          ODataPathSegmentImpl pathSegment = new ODataPathSegmentImpl("Employees('2')", null);
+          assertEquals(pathSegment.getPath(), request.getPathInfo().getODataSegments().get(0).getPath());
+          ODataPathSegmentImpl pathSegment2 = new ODataPathSegmentImpl("EmployeeName", null);
+          assertEquals(pathSegment2.getPath(), request.getPathInfo().getODataSegments().get(1).getPath());
+
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testImageInContent() throws IOException, BatchException, URISyntaxException {
+    String fileName = "/batchWithContent.txt";
+    InputStream contentInputStream = ClassLoader.class.getResourceAsStream(fileName);
+    if (contentInputStream == null) {
+      throw new IOException("Requested file '" + fileName + "' was not found.");
+    }
+    String content = StringHelper.inputStreamToString(contentInputStream);
+    String batch = "\r\n"
+        + "--batch_8194-cf13-1f56" + "\r" + "\n"
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\r\n"
+        + "\r\n"
+        + "--changeset_f980-1cb6-94dd" + "\r\n"
+        + "content-type:     Application/http" + "\r\n"
+        + "content-transfer-encoding: Binary" + "\r\n"
+        + "Content-ID: 1" + "\r\n"
+        + "\r\n"
+        + "POST Employees HTTP/1.1" + "\r\n"
+        + "Content-length: 100000" + "\r\n"
+        + "Content-type: application/octet-stream" + "\r\n"
+        + "\r\n"
+        + content + "\r\n"
+        + "\r\n"
+        + "--changeset_f980-1cb6-94dd--" + "\r\n"
+        + "\r\n"
+        + "--batch_8194-cf13-1f56" + "\r\n"
+        + MIME_HEADERS
+        + "\r\n"
+        + "GET Employees?$filter=Age%20gt%2040 HTTP/1.1" + "\r\n"
+        + "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + "\r\n"
+        + "MaxDataServiceVersion: 2.0" + "\r\n"
+        + "\r\n"
+        + "\r\n"
+        + "--batch_8194-cf13-1f56--";
+    List<BatchPart> batchParts = parse(batch);
+    for (BatchPart object : batchParts) {
+      if (!object.isChangeSet()) {
+        assertEquals(1, object.getRequests().size());
+        ODataRequest retrieveRequest = object.getRequests().get(0);
+        assertEquals(ODataHttpMethod.GET, retrieveRequest.getMethod());
+        assertEquals("Age gt 40", retrieveRequest.getQueryParameters().get("$filter"));
+        assertEquals(new URI("http://localhost/odata/Employees?$filter=Age%20gt%2040"), retrieveRequest.getPathInfo().getRequestUri());
+      } else {
+        List<ODataRequest> requests = object.getRequests();
+        for (ODataRequest request : requests) {
+          assertEquals(ODataHttpMethod.POST, request.getMethod());
+          assertEquals("100000", request.getRequestHeaderValue(HttpHeaders.CONTENT_LENGTH.toLowerCase()));
+          assertEquals("1", request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase()));
+          assertEquals("application/octet-stream", request.getContentType());
+          InputStream body = request.getBody();
+          assertEquals(content, StringHelper.inputStreamToString(body));
+
+        }
+
+      }
+    }
+  }
+
+  @Test
+  public void testPostWithoutBody() throws IOException, BatchException, URISyntaxException {
+    String fileName = "/batchWithContent.txt";
+    InputStream contentInputStream = ClassLoader.class.getResourceAsStream(fileName);
+    if (contentInputStream == null) {
+      throw new IOException("Requested file '" + fileName + "' was not found.");
+    }
+    StringHelper.inputStreamToString(contentInputStream);
+    String batch = "\r\n"
+        + "--batch_8194-cf13-1f56" + "\r" + "\n"
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\r\n"
+        + "\r\n"
+        + "--changeset_f980-1cb6-94dd" + "\r\n"
+        + MIME_HEADERS
+        + "\r\n"
+        + "POST Employees('2') HTTP/1.1" + "\r\n"
+        + "Content-Length: 100" + "\r\n"
+        + "Content-Type: application/octet-stream" + "\r\n"
+        + "\r\n"
+        + "\r\n"
+        + "--changeset_f980-1cb6-94dd--" + "\r\n"
+        + "\r\n"
+        + "--batch_8194-cf13-1f56--";
+    List<BatchPart> batchParts = parse(batch);
+    for (BatchPart object : batchParts) {
+      if (object.isChangeSet()) {
+        List<ODataRequest> requests = object.getRequests();
+        for (ODataRequest request : requests) {
+          assertEquals(ODataHttpMethod.POST, request.getMethod());
+          assertEquals("100", request.getRequestHeaderValue(HttpHeaders.CONTENT_LENGTH.toLowerCase()));
+          assertEquals("application/octet-stream", request.getContentType());
+          assertNotNull(request.getBody());
+        }
+      }
+    }
+  }
+
+  @Test
+  public void testBoundaryParameterWithQuotas() throws BatchException {
+    String contentType = "multipart/mixed; boundary=\"batch_1.2+34:2j)0?\"";
+
+    String batch = "--batch_1.2+34:2j)0?" + "\n"
+        + GET_REQUEST
+        + "--batch_1.2+34:2j)0?--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
+    List<BatchPart> batchParts = parser.parse(in);
+    assertNotNull(batchParts);
+    assertEquals(false, batchParts.isEmpty());
+  }
+
+  @Test(expected = BatchException.class)
+  public void testBatchWithInvalidContentType() throws BatchException {
+    String invalidContentType = "multipart;boundary=batch_1740-bb84-2f7f";
+
+    String batch = "--batch_1740-bb84-2f7f" + "\n"
+        + GET_REQUEST
+        + "--batch_1740-bb84-2f7f--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(invalidContentType, batchProperties);
+    parser.parse(in);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testBatchWithoutBoundaryParameter() throws BatchException {
+    String invalidContentType = "multipart/mixed";
+    String batch = "--batch_1740-bb84-2f7f" + "\n"
+        + GET_REQUEST
+        + "--batch_1740-bb84-2f7f--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(invalidContentType, batchProperties);
+    parser.parse(in);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testBoundaryParameterWithoutQuota() throws BatchException {
+    String invalidContentType = "multipart;boundary=batch_1740-bb:84-2f7f";
+    String batch = "--batch_1740-bb:84-2f7f" + "\n"
+        + GET_REQUEST
+        + "--batch_1740-bb:84-2f7f--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(invalidContentType, batchProperties);
+    parser.parse(in);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testWrongBoundaryString() throws BatchException {
+    String batch = "--batch_8194-cf13-1f5" + "\n"
+        + GET_REQUEST
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testBoundaryWithoutHyphen() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + GET_REQUEST
+        + "batch_8194-cf13-1f56" + "\n"
+        + GET_REQUEST
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testNoBoundaryString() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + GET_REQUEST
+        //+ no boundary string
+        + GET_REQUEST
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testBatchBoundaryEqualsChangeSetBoundary() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Type: multipart/mixed;boundary=batch_8194-cf13-1f56" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "PUT Employees('2')/EmployeeName HTTP/1.1" + "\n"
+        + "Accept: application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.1" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "MaxDataServiceVersion: 2.0" + "\n"
+        + "\n"
+        + "{\"EmployeeName\":\"Frederic Fall MODIFIED\"}" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testNoContentType() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Transfer-Encoding: binary" + "\n"
+        + "\n"
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testMimeHeaderContentType() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Type: text/plain" + "\n"
+        + "Content-Transfer-Encoding: binary" + "\n"
+        + "\n"
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testMimeHeaderEncoding() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Type: application/http" + "\n"
+        + "Content-Transfer-Encoding: 8bit" + "\n"
+        + "\n"
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testMimeHeaderContentId() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "Content-ID: 1" + "\n"
+        + "\n"
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidMethodForBatch() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "POST Employees('1')/EmployeeName HTTP/1.1" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testNoMethod() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + /*GET*/"Employees('1')/EmployeeName HTTP/1.1" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidMethodForChangeset() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\n"
+        + "\n"
+        + "--changeset_f980-1cb6-94dd" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "MaxDataServiceVersion: 2.0" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testInvalidChangeSetBoundary() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Type: multipart/mixed;boundary=changeset_f980-1cb6-94dd" + "\n"
+        + "\n"
+        + "--changeset_f980-1cb6-94d"/*+"d"*/+ "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "POST Employees('2') HTTP/1.1" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "MaxDataServiceVersion: 2.0" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testNoCloseDelimiter() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + GET_REQUEST;
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testNoCloseDelimiter2() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "GET Employees('1')/EmployeeName HTTP/1.1" + "\n"
+    /*--batch_8194-cf13-1f56--*/;
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test(expected = BatchException.class)
+  public void testNoCloseDelimiter3() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n" + GET_REQUEST + "--batch_8194-cf13-1f56-"/*no hash*/;
+    parseInvalidBatchBody(batch);
+  }
+
+  @Test
+  public void testAcceptHeaders() throws BatchException, URISyntaxException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
+        + "Content-Length: 100000" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "Accept: application/xml;q=0.3, application/atomsvc+xml;q=0.8, application/json;odata=verbose;q=0.5, */*;q=0.001" + "\n"
+        + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    List<BatchPart> batchParts = parse(batch);
+    for (BatchPart multipart : batchParts) {
+      if (!multipart.isChangeSet()) {
+        assertEquals(1, multipart.getRequests().size());
+        ODataRequest retrieveRequest = multipart.getRequests().get(0);
+        assertEquals(ODataHttpMethod.GET, retrieveRequest.getMethod());
+        assertNotNull(retrieveRequest.getAcceptHeaders());
+        assertEquals(4, retrieveRequest.getAcceptHeaders().size());
+        assertEquals("application/atomsvc+xml", retrieveRequest.getAcceptHeaders().get(0));
+        assertEquals("*/*", retrieveRequest.getAcceptHeaders().get(3));
+      }
+
+    }
+  }
+
+  @Test
+  public void testAcceptHeaders2() throws BatchException, URISyntaxException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
+        + "Content-Length: 100000" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "Accept: */*;q=0.5, application/json;odata=verbose;q=1.0,application/atom+xml" + "\n"
+        + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    List<BatchPart> batchParts = parse(batch);
+    for (BatchPart multipart : batchParts) {
+      if (!multipart.isChangeSet()) {
+        assertEquals(1, multipart.getRequests().size());
+        ODataRequest retrieveRequest = multipart.getRequests().get(0);
+        assertEquals(ODataHttpMethod.GET, retrieveRequest.getMethod());
+        assertNotNull(retrieveRequest.getAcceptHeaders());
+        assertEquals(3, retrieveRequest.getAcceptHeaders().size());
+        assertEquals("application/json;odata=verbose", retrieveRequest.getAcceptHeaders().get(0));
+        assertEquals("application/atom+xml", retrieveRequest.getAcceptHeaders().get(1));
+        assertEquals("*/*", retrieveRequest.getAcceptHeaders().get(2));
+      }
+
+    }
+  }
+
+  @Test
+  public void testAcceptHeaders3() throws BatchException, URISyntaxException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "GET Employees('2')/EmployeeName HTTP/1.1" + "\n"
+        + "Content-Length: 100000" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "accept: */*,application/atom+xml,application/atomsvc+xml,application/xml" + "\n"
+        + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    List<BatchPart> batchParts = parse(batch);
+    for (BatchPart multipart : batchParts) {
+      if (!multipart.isChangeSet()) {
+        assertEquals(1, multipart.getRequests().size());
+        ODataRequest retrieveRequest = multipart.getRequests().get(0);
+        assertEquals(ODataHttpMethod.GET, retrieveRequest.getMethod());
+        assertNotNull(retrieveRequest.getAcceptHeaders());
+        assertEquals(4, retrieveRequest.getAcceptHeaders().size());
+
+        assertEquals("application/atom+xml", retrieveRequest.getAcceptHeaders().get(0));
+        assertEquals("application/atomsvc+xml", retrieveRequest.getAcceptHeaders().get(1));
+
+        assertEquals("application/xml", retrieveRequest.getAcceptHeaders().get(2));
+      }
+
+    }
+  }
+
+  @Test
+  public void testContentId() throws BatchException {
+    String batch = "--batch_8194-cf13-1f56" + "\n"
+        + MIME_HEADERS
+        + "\n"
+        + "GET Employees HTTP/1.1" + "\n"
+        + "accept: */*,application/atom+xml,application/atomsvc+xml,application/xml" + "\n"
+        + "Content-Id: BBB" + "\n"
+        + "\n" + "\n"
+        + "--batch_8194-cf13-1f56" + "\n"
+        + "Content-Type: multipart/mixed; boundary=changeset_f980-1cb6-94dd" + "\n"
+        + "\n"
+        + "--changeset_f980-1cb6-94dd" + "\n"
+        + MIME_HEADERS
+        + "Content-Id: " + CONTENT_ID_REFERENCE + "\n"
+        + "\n"
+        + "POST Employees HTTP/1.1" + "\n"
+        + "Content-type: application/octet-stream" + "\n"
+        + "\n"
+        + "/9j/4AAQSkZJRgABAQEBLAEsAAD/4RM0RXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAA" + "\n"
+        + "\n"
+        + "--changeset_f980-1cb6-94dd" + "\n"
+        + MIME_HEADERS
+        + "Content-ID: " + PUT_MIME_HEADER_CONTENT_ID + "\n"
+        + "\n"
+        + "PUT $" + CONTENT_ID_REFERENCE + "/EmployeeName HTTP/1.1" + "\n"
+        + "Content-Type: application/json;odata=verbose" + "\n"
+        + "Content-Id:" + PUT_REQUEST_HEADER_CONTENT_ID + "\n"
+        + "\n"
+        + "{\"EmployeeName\":\"Peter Fall\"}" + "\n"
+        + "--changeset_f980-1cb6-94dd--" + "\n"
+        + "\n"
+        + "--batch_8194-cf13-1f56--";
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
+    List<BatchPart> batchParts = parser.parse(in);
+    assertNotNull(batchParts);
+    for (BatchPart multipart : batchParts) {
+      if (!multipart.isChangeSet()) {
+        assertEquals(1, multipart.getRequests().size());
+        ODataRequest retrieveRequest = multipart.getRequests().get(0);
+        assertEquals("BBB", retrieveRequest.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase()));
+      } else {
+        for (ODataRequest request : multipart.getRequests()) {
+          if (ODataHttpMethod.POST.equals(request.getMethod())) {
+            assertEquals(CONTENT_ID_REFERENCE, request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase()));
+          } else if (ODataHttpMethod.PUT.equals(request.getMethod())) {
+            assertEquals(PUT_MIME_HEADER_CONTENT_ID, request.getRequestHeaderValue(BatchConstants.MIME_HEADER_CONTENT_ID.toLowerCase()));
+            assertEquals(PUT_REQUEST_HEADER_CONTENT_ID, request.getRequestHeaderValue(BatchConstants.REQUEST_HEADER_CONTENT_ID.toLowerCase()));
+            assertNull(request.getPathInfo().getRequestUri());
+            assertEquals("$" + CONTENT_ID_REFERENCE, request.getPathInfo().getODataSegments().get(0).getPath());
+          }
+        }
+      }
+    }
+  }
+
+  private List<BatchPart> parse(final String batch) throws BatchException {
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
+    List<BatchPart> batchParts = parser.parse(in);
+    assertNotNull(batchParts);
+    assertEquals(false, batchParts.isEmpty());
+    return batchParts;
+  }
+
+  private void parseInvalidBatchBody(final String batch) throws BatchException {
+    InputStream in = new ByteArrayInputStream(batch.getBytes());
+    BatchRequestParser parser = new BatchRequestParser(contentType, batchProperties);
+    parser.parse(in);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
new file mode 100644
index 0000000..f236226
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/batch/BatchResponseWriterTest.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ *        or more contributor license agreements.  See the NOTICE file
+ *        distributed with this work for additional information
+ *        regarding copyright ownership.  The ASF licenses this file
+ *        to you under the Apache License, Version 2.0 (the
+ *        "License"); you may not use this file except in compliance
+ *        with the License.  You may obtain a copy of the License at
+ * 
+ *          http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ *        Unless required by applicable law or agreed to in writing,
+ *        software distributed under the License is distributed on an
+ *        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *        KIND, either express or implied.  See the License for the
+ *        specific language governing permissions and limitations
+ *        under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.core.batch;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.batch.BatchException;
+import org.apache.olingo.odata2.api.batch.BatchResponsePart;
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+
+public class BatchResponseWriterTest {
+
+  @Test
+  public void testBatchResponse() throws BatchException, IOException {
+    List<BatchResponsePart> parts = new ArrayList<BatchResponsePart>();
+    ODataResponse response = ODataResponse.entity("Walter Winter")
+        .status(HttpStatusCodes.OK)
+        .contentHeader("application/json")
+        .build();
+    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+    responses.add(response);
+    parts.add(BatchResponsePart.responses(responses).changeSet(false).build());
+
+    ODataResponse changeSetResponse = ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
+    responses = new ArrayList<ODataResponse>(1);
+    responses.add(changeSetResponse);
+    parts.add(BatchResponsePart.responses(responses).changeSet(true).build());
+
+    BatchResponseWriter writer = new BatchResponseWriter();
+    ODataResponse batchResponse = writer.writeResponse(parts);
+
+    assertEquals(202, batchResponse.getStatus().getStatusCode());
+    assertNotNull(batchResponse.getEntity());
+    String body = (String) batchResponse.getEntity();
+
+    assertTrue(body.contains("--batch"));
+    assertTrue(body.contains("--changeset"));
+    assertTrue(body.contains("HTTP/1.1 200 OK"));
+    assertTrue(body.contains("Content-Type: application/http"));
+    assertTrue(body.contains("Content-Transfer-Encoding: binary"));
+    assertTrue(body.contains("Walter Winter"));
+    assertTrue(body.contains("multipart/mixed; boundary=changeset"));
+    assertTrue(body.contains("HTTP/1.1 204 No Content"));
+
+  }
+
+  @Test
+  public void testResponse() throws BatchException, IOException {
+    List<BatchResponsePart> parts = new ArrayList<BatchResponsePart>();
+    ODataResponse response = ODataResponse.entity("Walter Winter").status(HttpStatusCodes.OK).contentHeader("application/json").build();
+    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+    responses.add(response);
+    parts.add(BatchResponsePart.responses(responses).changeSet(false).build());
+    BatchResponseWriter writer = new BatchResponseWriter();
+    ODataResponse batchResponse = writer.writeResponse(parts);
+
+    assertEquals(202, batchResponse.getStatus().getStatusCode());
+    assertNotNull(batchResponse.getEntity());
+    String body = (String) batchResponse.getEntity();
+
+    assertTrue(body.contains("--batch"));
+    assertFalse(body.contains("--changeset"));
+    assertTrue(body.contains("HTTP/1.1 200 OK" + "\r\n"));
+    assertTrue(body.contains("Content-Type: application/http" + "\r\n"));
+    assertTrue(body.contains("Content-Transfer-Encoding: binary" + "\r\n"));
+    assertTrue(body.contains("Walter Winter"));
+    assertFalse(body.contains("multipart/mixed; boundary=changeset"));
+
+  }
+
+  @Test
+  public void testChangeSetResponse() throws BatchException, IOException {
+    List<BatchResponsePart> parts = new ArrayList<BatchResponsePart>();
+    ODataResponse changeSetResponse = ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
+    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+    responses.add(changeSetResponse);
+    parts.add(BatchResponsePart.responses(responses).changeSet(true).build());
+
+    BatchResponseWriter writer = new BatchResponseWriter();
+    ODataResponse batchResponse = writer.writeResponse(parts);
+
+    assertEquals(202, batchResponse.getStatus().getStatusCode());
+    assertNotNull(batchResponse.getEntity());
+    String body = (String) batchResponse.getEntity();
+    assertTrue(body.contains("--batch"));
+    assertTrue(body.contains("--changeset"));
+    assertTrue(body.indexOf("--changeset") != body.lastIndexOf("--changeset"));
+    assertFalse(body.contains("HTTP/1.1 200 OK" + "\r\n"));
+    assertTrue(body.contains("Content-Type: application/http" + "\r\n"));
+    assertTrue(body.contains("Content-Transfer-Encoding: binary" + "\r\n"));
+    assertTrue(body.contains("HTTP/1.1 204 No Content" + "\r\n"));
+    assertTrue(body.contains("Content-Type: multipart/mixed; boundary=changeset"));
+
+  }
+
+  @Test
+  public void testContentIdEchoing() throws BatchException, IOException {
+    List<BatchResponsePart> parts = new ArrayList<BatchResponsePart>();
+    ODataResponse response = ODataResponse.entity("Walter Winter")
+        .status(HttpStatusCodes.OK)
+        .contentHeader("application/json")
+        .header(BatchConstants.MIME_HEADER_CONTENT_ID, "mimeHeaderContentId123")
+        .header(BatchConstants.REQUEST_HEADER_CONTENT_ID, "requestHeaderContentId123")
+        .build();
+    List<ODataResponse> responses = new ArrayList<ODataResponse>(1);
+    responses.add(response);
+    parts.add(BatchResponsePart.responses(responses).changeSet(false).build());
+    BatchResponseWriter writer = new BatchResponseWriter();
+    ODataResponse batchResponse = writer.writeResponse(parts);
+
+    assertEquals(202, batchResponse.getStatus().getStatusCode());
+    assertNotNull(batchResponse.getEntity());
+    String body = (String) batchResponse.getEntity();
+
+    String mimeHeader = "Content-Type: application/http" + "\r\n"
+        + "Content-Transfer-Encoding: binary" + "\r\n"
+        + "Content-Id: mimeHeaderContentId123" + "\r\n";
+
+    String requestHeader = "Content-Id: requestHeaderContentId123" + "\r\n"
+        + "Content-Type: application/json" + "\r\n"
+        + "Content-Length: 13" + "\r\n";
+
+    assertTrue(body.contains(mimeHeader));
+    assertTrue(body.contains(requestHeader));
+  }
+
+}


[03/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProvTest.java
new file mode 100644
index 0000000..f6d7f62
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationImplProvTest.java
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmAssociationImplProvTest extends BaseTest {
+
+  private static EdmAssociationImplProv associationProv;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    AssociationEnd end1 = new AssociationEnd().setRole("end1Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+    AssociationEnd end2 = new AssociationEnd().setRole("end2Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+
+    List<PropertyRef> propRef = new ArrayList<PropertyRef>();
+    propRef.add(new PropertyRef().setName("prop1"));
+    List<PropertyRef> propRef2 = new ArrayList<PropertyRef>();
+    propRef2.add(new PropertyRef().setName("prop2"));
+
+    Association association = new Association().setName("association").setEnd1(end1).setEnd2(end2);
+
+    associationProv = new EdmAssociationImplProv(edmImplProv, association, "namespace");
+  }
+
+  @Test
+  public void testAssociation() throws Exception {
+    EdmAssociation association = associationProv;
+
+    assertEquals(EdmTypeKind.ASSOCIATION, association.getKind());
+    assertEquals("end1Role", association.getEnd("end1Role").getRole());
+    assertEquals("end2Role", association.getEnd("end2Role").getRole());
+    assertEquals("namespace", association.getNamespace());
+    assertEquals(null, association.getEnd("endWrongRole"));
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = associationProv;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProvTest.java
new file mode 100644
index 0000000..d276aa8
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetEndImplProvTest.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmAssociationSetEndImplProvTest extends BaseTest {
+  private static EdmAssociationSetEnd edmAssociationSetEnd;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    EntityContainerInfo entityContainer = new EntityContainerInfo().setName("Container");
+    EdmEntityContainer edmEntityContainer = new EdmEntityContainerImplProv(edmImplProv, entityContainer);
+
+    //    AssociationEnd end1 = new AssociationEnd().setRole("end1Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+    //    AssociationEnd end2 = new AssociationEnd().setRole("end2Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+    //    Association association = new Association().setName("association").setEnd1(end1).setEnd2(end2);
+    //    FullQualifiedName assocName = new FullQualifiedName("namespace", "association");
+    //    when(edmProvider.getAssociation(assocName)).thenReturn(association);
+
+    AssociationSetEnd associationSetEnd = new AssociationSetEnd().setRole("end1Role").setEntitySet("entitySetRole1");
+    EntitySet entitySet = new EntitySet().setName("entitySetRole1");
+    when(edmProvider.getEntitySet("Container", "entitySetRole1")).thenReturn(entitySet);
+
+    edmAssociationSetEnd = new EdmAssociationSetEndImplProv(associationSetEnd, edmEntityContainer.getEntitySet("entitySetRole1"));
+  }
+
+  @Test
+  public void testAssociationSetEnd() throws Exception {
+    EdmAssociationSetEnd setEnd = edmAssociationSetEnd;
+
+    assertEquals("end1Role", setEnd.getRole());
+    assertEquals("entitySetRole1", setEnd.getEntitySet().getName());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = (EdmAnnotatable) edmAssociationSetEnd;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProvTest.java
new file mode 100644
index 0000000..1f03fde
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmAssociationSetImplProvTest.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociationSet;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmAssociationSetImplProvTest extends BaseTest {
+
+  private static EdmAssociationSet edmAssociationSet;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    EntityContainerInfo entityContainer = new EntityContainerInfo().setName("Container");
+    EdmEntityContainer edmEntityContainer = new EdmEntityContainerImplProv(edmImplProv, entityContainer);
+
+    AssociationEnd end1 = new AssociationEnd().setRole("end1Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+    AssociationEnd end2 = new AssociationEnd().setRole("end2Role").setMultiplicity(EdmMultiplicity.ONE).setType(EdmSimpleTypeKind.String.getFullQualifiedName());
+    Association association = new Association().setName("association").setEnd1(end1).setEnd2(end2);
+    FullQualifiedName assocName = new FullQualifiedName("namespace", "association");
+    when(edmProvider.getAssociation(assocName)).thenReturn(association);
+
+    AssociationSetEnd endSet1 = new AssociationSetEnd().setRole("end1Role").setEntitySet("entitySetRole1");
+    when(edmProvider.getEntitySet("Container", "entitySetRole1")).thenReturn(new EntitySet().setName("entitySetRole1"));
+    AssociationSetEnd endSet2 = new AssociationSetEnd().setRole("end2Role");
+
+    AssociationSet associationSet = new AssociationSet().setName("associationSetName").setAssociation(assocName).setEnd1(endSet1).setEnd2(endSet2);
+
+    edmAssociationSet = new EdmAssociationSetImplProv(edmImplProv, associationSet, edmEntityContainer);
+  }
+
+  @Test
+  public void testAssociationSet() throws Exception {
+    EdmAssociationSet associationSet = edmAssociationSet;
+
+    assertEquals("associationSetName", associationSet.getName());
+
+    assertEquals("end1Role", associationSet.getEnd("end1Role").getRole());
+    assertEquals(null, associationSet.getEnd("endWrongRole"));
+  }
+
+  @Test(expected = EdmException.class)
+  public void testAssociationSetNoEntity() throws Exception {
+    EdmAssociationSet associationSet = edmAssociationSet;
+    associationSet.getEnd("end2Role");
+  }
+
+  @Test
+  public void testAssociationExists() throws Exception {
+    EdmAssociationSet associationSet = edmAssociationSet;
+    assertNotNull(associationSet.getAssociation());
+  }
+
+  @Test
+  public void testEntityContainer() throws Exception {
+    EdmAssociationSet associationSet = edmAssociationSet;
+    assertNotNull(associationSet.getEntityContainer());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = (EdmAnnotatable) edmAssociationSet;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProvTest.java
new file mode 100644
index 0000000..669b6d5
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmComplexTypeImplProvTest.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmComplexType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmComplexTypeImplProvTest extends BaseTest {
+  private static EdmComplexTypeImplProv edmComplexType;
+  private static EdmComplexTypeImplProv edmComplexTypeWithBaseType;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    ComplexType fooComplexType = new ComplexType().setName("fooComplexType");
+
+    List<Property> keyPropertysFoo = new ArrayList<Property>();
+    keyPropertysFoo.add(new SimpleProperty().setName("Name").setType(EdmSimpleTypeKind.String));
+    keyPropertysFoo.add(new SimpleProperty().setName("Address").setType(EdmSimpleTypeKind.String));
+    fooComplexType.setProperties(keyPropertysFoo);
+
+    edmComplexType = new EdmComplexTypeImplProv(edmImplProv, fooComplexType, "namespace");
+
+    FullQualifiedName barBaseTypeName = new FullQualifiedName("namespace", "barBase");
+    ComplexType barBase = new ComplexType().setName("barBase");
+    when(edmProvider.getComplexType(barBaseTypeName)).thenReturn(barBase);
+
+    List<Property> propertysBarBase = new ArrayList<Property>();
+    propertysBarBase.add(new SimpleProperty().setName("Name").setType(EdmSimpleTypeKind.String));
+    propertysBarBase.add(new SimpleProperty().setName("Address").setType(EdmSimpleTypeKind.String));
+    barBase.setProperties(propertysBarBase);
+
+    ComplexType barComplexType = new ComplexType().setName("barComplexType").setBaseType(barBaseTypeName);
+    edmComplexTypeWithBaseType = new EdmComplexTypeImplProv(edmImplProv, barComplexType, "namespace");
+
+  }
+
+  @Test
+  public void getPropertiesNames() throws Exception {
+    List<String> properties = edmComplexType.getPropertyNames();
+    assertNotNull(properties);
+    assertTrue(properties.contains("Name"));
+    assertTrue(properties.contains("Address"));
+  }
+
+  @Test
+  public void getPropertiesWithBaseType() throws Exception {
+    List<String> properties = edmComplexTypeWithBaseType.getPropertyNames();
+    assertNotNull(properties);
+    assertTrue(properties.contains("Name"));
+    assertTrue(properties.contains("Address"));
+  }
+
+  @Test
+  public void getBaseType() throws Exception {
+    EdmComplexType baseType = edmComplexTypeWithBaseType.getBaseType();
+    assertNotNull(baseType);
+    assertEquals("barBase", baseType.getName());
+    assertEquals("namespace", baseType.getNamespace());
+  }
+
+  @Test
+  public void getProperty() throws Exception {
+    EdmTyped property = edmComplexType.getProperty("Name");
+    assertNotNull(property);
+    assertEquals("Name", property.getName());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = edmComplexType;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProvTest.java
new file mode 100644
index 0000000..6c0608c
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityContainerImplProvTest.java
@@ -0,0 +1,149 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmEntityContainerImplProvTest extends BaseTest {
+
+  private static EdmEntityContainerImplProv edmEntityContainer;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+    when(edmProvider.getEntityContainerInfo("Container")).thenReturn(new EntityContainerInfo().setName("Container"));
+
+    EntityContainerInfo entityContainer = new EntityContainerInfo().setName("Container1").setExtendz("Container");
+
+    EntitySet entitySetFooFromParent = new EntitySet().setName("fooFromParent");
+    when(edmProvider.getEntitySet("Container", "fooFromParent")).thenReturn(entitySetFooFromParent);
+
+    EntitySet entitySetFoo = new EntitySet().setName("foo");
+    when(edmProvider.getEntitySet("Container1", "foo")).thenReturn(entitySetFoo);
+
+    EntitySet entitySetBar = new EntitySet().setName("foo");
+    when(edmProvider.getEntitySet("Container1", "foo")).thenReturn(entitySetBar);
+
+    AssociationSet associationSet = new AssociationSet().setName("4711");
+    FullQualifiedName assocFQName = new FullQualifiedName("AssocNs", "AssocName");
+    when(edmProvider.getAssociationSet("Container1", assocFQName, "foo", "fromRole")).thenReturn(associationSet);
+
+    FunctionImport functionImportFoo = new FunctionImport().setName("foo");
+    when(edmProvider.getFunctionImport("Container1", "foo")).thenReturn(functionImportFoo);
+
+    FunctionImport functionImportBar = new FunctionImport().setName("foo");
+    when(edmProvider.getFunctionImport("Container1", "foo")).thenReturn(functionImportBar);
+
+    edmEntityContainer = new EdmEntityContainerImplProv(edmImplProv, entityContainer);
+  }
+
+  @Test
+  public void testEntityContainerName() throws EdmException {
+    assertEquals("Container1", edmEntityContainer.getName());
+  }
+
+  @Test
+  public void testEntityContainerInheritance() throws EdmException {
+    assertEquals("fooFromParent", edmEntityContainer.getEntitySet("fooFromParent").getName());
+
+    EdmEntitySet sourceEntitySet = mock(EdmEntitySet.class);
+    when(sourceEntitySet.getName()).thenReturn("foo");
+
+    EdmAssociation edmAssociation = mock(EdmAssociation.class);
+    when(edmAssociation.getNamespace()).thenReturn("AssocNs");
+    when(edmAssociation.getName()).thenReturn("AssocName");
+
+    EdmNavigationProperty edmNavigationProperty = mock(EdmNavigationProperty.class);
+    when(edmNavigationProperty.getRelationship()).thenReturn(edmAssociation);
+    when(edmNavigationProperty.getFromRole()).thenReturn("wrongRole");
+
+    boolean failed = false;
+    try {
+      edmEntityContainer.getAssociationSet(sourceEntitySet, edmNavigationProperty);
+    } catch (EdmException e) {
+      failed = true;
+    }
+
+    assertTrue(failed);
+  }
+
+  @Test
+  public void testEntitySetCache() throws EdmException {
+    assertEquals(edmEntityContainer.getEntitySet("foo"), edmEntityContainer.getEntitySet("foo"));
+    assertNotSame(edmEntityContainer.getEntitySet("foo"), edmEntityContainer.getEntitySet("bar"));
+  }
+
+  @Test
+  public void testAssociationSetCache() throws EdmException {
+    EdmEntitySet sourceEntitySet = mock(EdmEntitySet.class);
+    when(sourceEntitySet.getName()).thenReturn("foo");
+
+    EdmAssociation edmAssociation = mock(EdmAssociation.class);
+    when(edmAssociation.getNamespace()).thenReturn("AssocNs");
+    when(edmAssociation.getName()).thenReturn("AssocName");
+
+    EdmNavigationProperty edmNavigationProperty = mock(EdmNavigationProperty.class);
+    when(edmNavigationProperty.getRelationship()).thenReturn(edmAssociation);
+    when(edmNavigationProperty.getFromRole()).thenReturn("fromRole");
+
+    assertNotNull(edmEntityContainer.getAssociationSet(sourceEntitySet, edmNavigationProperty));
+    assertEquals(edmEntityContainer.getAssociationSet(sourceEntitySet, edmNavigationProperty), edmEntityContainer.getAssociationSet(sourceEntitySet, edmNavigationProperty));
+  }
+
+  @Test
+  public void testFunctionImportCache() throws EdmException {
+    assertEquals(edmEntityContainer.getFunctionImport("foo"), edmEntityContainer.getFunctionImport("foo"));
+    assertNotSame(edmEntityContainer.getFunctionImport("foo"), edmEntityContainer.getFunctionImport("bar"));
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = edmEntityContainer;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProvTest.java
new file mode 100644
index 0000000..ad601e6
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetInfoImplProvTest.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.net.URI;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmEntitySetInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmEntitySetInfoImplProvTest extends BaseTest {
+
+  @Test
+  public void entityWithDefaultContainer() throws Exception {
+    String entitySetName = "Employees";
+    URI entitySetUri = new URI(entitySetName);
+    String entityContainerName = "Container";
+
+    EntitySet entitySet = new EntitySet();
+    entitySet.setName(entitySetName);
+
+    EntityContainerInfo entityContainerInfo = new EntityContainerInfo();
+    entityContainerInfo.setName(entityContainerName).setDefaultEntityContainer(true);
+
+    EdmEntitySetInfo info = new EdmEntitySetInfoImplProv(entitySet, entityContainerInfo);
+
+    assertEquals(entitySetName, info.getEntitySetName());
+    assertEquals(entitySetUri.toASCIIString(), info.getEntitySetUri().toASCIIString());
+    assertEquals(entityContainerName, info.getEntityContainerName());
+    assertTrue(info.isDefaultEntityContainer());
+  }
+
+  @Test
+  public void entityWithoutDefaultContainer() throws Exception {
+    String entitySetName = "Employees";
+    String entityContainerName = "Container";
+    URI entitySetUri = new URI(entityContainerName + "." + entitySetName);
+
+    EntitySet entitySet = new EntitySet();
+    entitySet.setName(entitySetName);
+
+    EntityContainerInfo entityContainerInfo = new EntityContainerInfo();
+    entityContainerInfo.setName(entityContainerName).setDefaultEntityContainer(false);
+
+    EdmEntitySetInfo info = new EdmEntitySetInfoImplProv(entitySet, entityContainerInfo);
+
+    assertEquals(entitySetName, info.getEntitySetName());
+    assertEquals(entitySetUri.toASCIIString(), info.getEntitySetUri().toASCIIString());
+    assertEquals(entityContainerName, info.getEntityContainerName());
+    assertFalse(info.isDefaultEntityContainer());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetProvTest.java
new file mode 100644
index 0000000..704289a
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntitySetProvTest.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSet;
+import org.apache.olingo.odata2.api.edm.provider.AssociationSetEnd;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+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.NavigationProperty;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ *
+ */
+public class EdmEntitySetProvTest extends BaseTest {
+
+  private static EdmEntitySetImplProv edmEntitySetFoo;
+  private static EdmEntitySetImplProv edmEnitiySetBar;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    EntityContainerInfo entityContainer = new EntityContainerInfo().setName("Container");
+    when(edmProvider.getEntityContainerInfo("Container")).thenReturn(entityContainer);
+    EdmEntityContainerImplProv edmEntityContainer = new EdmEntityContainerImplProv(edmImplProv, entityContainer);
+
+    EntitySet entitySetFoo = new EntitySet().setName("foo");
+    when(edmProvider.getEntitySet("Container", "foo")).thenReturn(entitySetFoo);
+
+    List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
+    FullQualifiedName fooBarAssocName = new FullQualifiedName("namespace", "fooBarAssoc");
+    navigationProperties.add(new NavigationProperty().setName("fooBarNav").setFromRole("fromFoo").setRelationship(fooBarAssocName).setToRole("toBar"));
+
+    EntityType fooEntityType = new EntityType().setName("fooEntityType").setNavigationProperties(navigationProperties);
+    FullQualifiedName fooEntityTypeFullName = new FullQualifiedName("namespace", "fooEntityType");
+    entitySetFoo.setEntityType(fooEntityTypeFullName);
+    when(edmProvider.getEntityType(fooEntityTypeFullName)).thenReturn(fooEntityType);
+
+    EntitySet entitySetBar = new EntitySet().setName("bar");
+    when(edmProvider.getEntitySet("Container", "bar")).thenReturn(entitySetBar);
+
+    EntityType barEntityType = new EntityType().setName("barEntityType");
+    FullQualifiedName barEntityTypeFullName = new FullQualifiedName("namespace", "barEntityType");
+    entitySetBar.setEntityType(barEntityTypeFullName);
+    when(edmProvider.getEntityType(barEntityTypeFullName)).thenReturn(barEntityType);
+
+    AssociationEnd fooEnd = new AssociationEnd().setRole("fromFoo");
+    AssociationEnd barEnd = new AssociationEnd().setRole("toBar");
+
+    Association fooBarAssoc = new Association().setName("fooBarAssoc").setEnd1(fooEnd).setEnd2(barEnd);
+    when(edmProvider.getAssociation(fooBarAssocName)).thenReturn(fooBarAssoc);
+
+    AssociationSet associationSet = new AssociationSet().setName("fooBarRelation").setEnd1(new AssociationSetEnd().setRole("fromFoo").setEntitySet("foo")).setEnd2(new AssociationSetEnd().setRole("toBar").setEntitySet("bar"));
+    FullQualifiedName assocFQName = new FullQualifiedName("namespace", "fooBarAssoc");
+    when(edmProvider.getAssociationSet("Container", assocFQName, "foo", "fromFoo")).thenReturn(associationSet);
+
+    edmEntitySetFoo = new EdmEntitySetImplProv(edmImplProv, entitySetFoo, edmEntityContainer);
+    edmEnitiySetBar = new EdmEntitySetImplProv(edmImplProv, entitySetBar, edmEntityContainer);
+  }
+
+  @Test
+  public void testEntitySet1() throws Exception {
+    assertEquals("foo", edmEntitySetFoo.getName());
+    assertEquals("Container", edmEntitySetFoo.getEntityContainer().getName());
+  }
+
+  @Test
+  public void testEntitySet2() throws Exception {
+    assertEquals("bar", edmEnitiySetBar.getName());
+    assertEquals("Container", edmEnitiySetBar.getEntityContainer().getName());
+  }
+
+  @Test
+  public void testEntitySetNavigation() throws Exception {
+    List<String> navPropertyyNames = edmEntitySetFoo.getEntityType().getNavigationPropertyNames();
+    assertTrue(navPropertyyNames.contains("fooBarNav"));
+    EdmTyped navProperty = edmEntitySetFoo.getEntityType().getProperty("fooBarNav");
+    assertNotNull(navProperty);
+
+    EdmEntitySet relatedEntitySet = edmEntitySetFoo.getRelatedEntitySet((EdmNavigationProperty) navProperty);
+
+    assertEquals(edmEnitiySetBar.getName(), relatedEntitySet.getName());
+  }
+
+  @Test
+  public void testEntitySetType() throws Exception {
+    assertEquals("fooEntityType", edmEntitySetFoo.getEntityType().getName());
+    assertEquals(edmEntitySetFoo.getEntityType().getName(), edmProvider.getEntityType(new FullQualifiedName("namespace", "fooEntityType")).getName());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = edmEntitySetFoo;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProvTest.java
new file mode 100644
index 0000000..44172ff
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmEntityTypeImplProvTest.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Key;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.Property;
+import org.apache.olingo.odata2.api.edm.provider.PropertyRef;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmEntityTypeImplProvTest extends BaseTest {
+
+  private static EdmEntityTypeImplProv edmEntityType;
+  private static EdmEntityTypeImplProv edmEntityTypeWithBaseType;
+  private static EdmProvider edmProvider;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    List<NavigationProperty> navigationProperties = new ArrayList<NavigationProperty>();
+    FullQualifiedName fooBarAssocName = new FullQualifiedName("namespace", "fooBarAssoc");
+    navigationProperties.add(new NavigationProperty().setName("fooBarNav").setFromRole("fromFoo").setRelationship(fooBarAssocName).setToRole("toBar"));
+
+    EntityType fooEntityType = new EntityType().setName("fooEntityType").setNavigationProperties(navigationProperties);
+    FullQualifiedName fooEntityTypeFullName = new FullQualifiedName("namespace", "fooEntityType");
+    when(edmProvider.getEntityType(fooEntityTypeFullName)).thenReturn(fooEntityType);
+
+    List<Property> keyPropertysFoo = new ArrayList<Property>();
+    Property keyPropFoo = new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.String);
+    keyPropertysFoo.add(keyPropFoo);
+    fooEntityType.setProperties(keyPropertysFoo);
+
+    PropertyRef refToKeyFoo = new PropertyRef().setName("Id");
+    List<PropertyRef> propRefKeysFoo = new ArrayList<PropertyRef>();
+    propRefKeysFoo.add(refToKeyFoo);
+
+    Key fooTypeKey = new Key().setKeys(propRefKeysFoo);
+    fooEntityType.setKey(fooTypeKey);
+
+    edmEntityType = new EdmEntityTypeImplProv(edmImplProv, fooEntityType, "namespace");
+
+    FullQualifiedName barBaseTypeName = new FullQualifiedName("namespace", "barBase");
+    EntityType barBase = new EntityType().setName("barBase");
+    when(edmProvider.getEntityType(barBaseTypeName)).thenReturn(barBase);
+
+    List<NavigationProperty> navigationPropertiesBarBase = new ArrayList<NavigationProperty>();
+    navigationPropertiesBarBase.add(new NavigationProperty().setName("barBaseNav"));
+    barBase.setNavigationProperties(navigationPropertiesBarBase);
+
+    List<Property> keyPropertysBarBase = new ArrayList<Property>();
+    Property keyPropBarBase = new SimpleProperty().setName("Id").setType(EdmSimpleTypeKind.String);
+    keyPropertysBarBase.add(keyPropBarBase);
+    barBase.setProperties(keyPropertysBarBase);
+
+    PropertyRef refToKeyBarBase = new PropertyRef().setName("Id");
+    List<PropertyRef> propRefKeysBarBase = new ArrayList<PropertyRef>();
+    propRefKeysBarBase.add(refToKeyBarBase);
+
+    Key barBaseTypeKey = new Key().setKeys(propRefKeysBarBase);
+    barBase.setKey(barBaseTypeKey);
+
+    EntityType barEntityType = new EntityType().setName("barEntityType").setBaseType(barBaseTypeName);
+    FullQualifiedName barEntityTypeFullName = new FullQualifiedName("namespace", "barEntityType");
+    when(edmProvider.getEntityType(barEntityTypeFullName)).thenReturn(barEntityType);
+
+    edmEntityTypeWithBaseType = new EdmEntityTypeImplProv(edmImplProv, barEntityType, "namespace");
+
+  }
+
+  @Test
+  public void getKeyProperties() throws Exception {
+    List<EdmProperty> keyProperties = edmEntityType.getKeyProperties();
+    assertNotNull(keyProperties);
+    assertEquals("Id", keyProperties.get(0).getName());
+  }
+
+  @Test
+  public void getKeyPropertiesNames() throws Exception {
+    List<String> keyProperties = edmEntityType.getKeyPropertyNames();
+    assertNotNull(keyProperties);
+    assertTrue(keyProperties.contains("Id"));
+
+    List<String> properties = edmEntityType.getPropertyNames();
+    assertNotNull(properties);
+    assertTrue(properties.contains("Id"));
+  }
+
+  @Test
+  public void getPropertiesNames() throws Exception {
+    List<String> properties = edmEntityType.getPropertyNames();
+    assertNotNull(properties);
+    assertTrue(properties.contains("Id"));
+  }
+
+  @Test
+  public void getNavProperties() throws Exception {
+    List<String> navProperties = edmEntityType.getNavigationPropertyNames();
+    assertNotNull(navProperties);
+    assertTrue(navProperties.contains("fooBarNav"));
+  }
+
+  @Test
+  public void getKeyPropertiesWithBaseType() throws Exception {
+    List<EdmProperty> keyProperties = edmEntityTypeWithBaseType.getKeyProperties();
+    assertNotNull(keyProperties);
+    assertEquals("Id", keyProperties.get(0).getName());
+  }
+
+  @Test
+  public void getKeyPropertiesNamesWithBaseType() throws Exception {
+    List<String> keyProperties = edmEntityTypeWithBaseType.getKeyPropertyNames();
+    assertNotNull(keyProperties);
+    assertTrue(keyProperties.contains("Id"));
+  }
+
+  @Test
+  public void getPropertiesWithBaseType() throws Exception {
+    List<String> properties = edmEntityTypeWithBaseType.getPropertyNames();
+    assertNotNull(properties);
+    assertTrue(properties.contains("Id"));
+  }
+
+  @Test
+  public void getNavPropertiesWithBaseType() throws Exception {
+    List<String> navProperties = edmEntityTypeWithBaseType.getNavigationPropertyNames();
+    assertNotNull(navProperties);
+    assertTrue(navProperties.contains("barBaseNav"));
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = edmEntityType;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProvTest.java
new file mode 100644
index 0000000..fb9ebe5
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmFunctionImportImplProvTest.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.http.HttpMethods;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntitySet;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImport;
+import org.apache.olingo.odata2.api.edm.provider.FunctionImportParameter;
+import org.apache.olingo.odata2.api.edm.provider.ReturnType;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmFunctionImportImplProvTest extends BaseTest {
+
+  private static EdmFunctionImportImplProv edmFunctionImport;
+  private static EdmFunctionImportImplProv edmFunctionImportWithoutParameters;
+  private static EdmEntityContainerImplProv edmEntityContainer;
+
+  @BeforeClass
+  public static void getEdmEntityContainerImpl() throws Exception {
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    EntityContainerInfo containerInfo = new EntityContainerInfo().setName("Container");
+    when(edmProvider.getEntityContainerInfo("Container")).thenReturn(containerInfo);
+    edmEntityContainer = new EdmEntityContainerImplProv(edmImplProv, containerInfo);
+
+    EntitySet fooEntitySet = new EntitySet().setName("fooEntitySet");
+    when(edmProvider.getEntitySet("Container", "fooEntitySet")).thenReturn(fooEntitySet);
+
+    ReturnType fooReturnType = new ReturnType().setTypeName(EdmSimpleTypeKind.String.getFullQualifiedName()).setMultiplicity(EdmMultiplicity.ONE);
+
+    List<FunctionImportParameter> parameters = new ArrayList<FunctionImportParameter>();
+    FunctionImportParameter parameter = new FunctionImportParameter().setName("fooParameter1").setType(EdmSimpleTypeKind.String);
+    parameters.add(parameter);
+
+    parameter = new FunctionImportParameter().setName("fooParameter2").setType(EdmSimpleTypeKind.String);
+    parameters.add(parameter);
+
+    parameter = new FunctionImportParameter().setName("fooParameter3").setType(EdmSimpleTypeKind.String);
+    parameters.add(parameter);
+
+    FunctionImport functionImportFoo = new FunctionImport().setName("foo").setHttpMethod(HttpMethods.GET).setReturnType(fooReturnType).setEntitySet("fooEntitySet").setParameters(parameters);
+    when(edmProvider.getFunctionImport("Container", "foo")).thenReturn(functionImportFoo);
+    edmFunctionImport = new EdmFunctionImportImplProv(edmImplProv, functionImportFoo, edmEntityContainer);
+
+    FunctionImport functionImportBar = new FunctionImport().setName("bar").setHttpMethod(HttpMethods.GET);
+    when(edmProvider.getFunctionImport("Container", "bar")).thenReturn(functionImportBar);
+    edmFunctionImportWithoutParameters = new EdmFunctionImportImplProv(edmImplProv, functionImportBar, edmEntityContainer);
+
+  }
+
+  @Test
+  public void functionImport() throws Exception {
+    assertEquals("foo", edmFunctionImport.getName());
+    assertEquals(HttpMethods.GET, edmFunctionImport.getHttpMethod());
+
+  }
+
+  @Test
+  public void containerName() throws Exception {
+    assertEquals(edmEntityContainer, edmFunctionImport.getEntityContainer());
+  }
+
+  @Test
+  public void returnType() throws Exception {
+    EdmTyped returnType = edmFunctionImport.getReturnType();
+    assertNotNull(returnType);
+    assertEquals(EdmSimpleTypeKind.String.getFullQualifiedName().getName(), returnType.getType().getName());
+    assertEquals(EdmMultiplicity.ONE, returnType.getMultiplicity());
+  }
+
+  @Test
+  public void entitySet() throws Exception {
+    EdmEntitySet entitySet = edmFunctionImport.getEntitySet();
+    assertNotNull(entitySet);
+    assertEquals("fooEntitySet", entitySet.getName());
+    assertEquals(edmEntityContainer.getEntitySet("fooEntitySet"), entitySet);
+  }
+
+  @Test
+  public void parameterExisting() throws Exception {
+    List<String> parameterNames = edmFunctionImport.getParameterNames();
+    assertTrue(parameterNames.contains("fooParameter1"));
+    assertTrue(parameterNames.contains("fooParameter2"));
+    assertTrue(parameterNames.contains("fooParameter3"));
+
+    EdmParameter parameter = edmFunctionImport.getParameter("fooParameter1");
+    assertNotNull(parameter);
+    assertEquals("fooParameter1", parameter.getName());
+
+    parameter = edmFunctionImport.getParameter("fooParameter1");
+    assertNotNull(parameter);
+    assertEquals("fooParameter1", parameter.getName());
+
+    parameter = edmFunctionImport.getParameter("fooParameter2");
+    assertNotNull(parameter);
+    assertEquals("fooParameter2", parameter.getName());
+
+    parameter = edmFunctionImport.getParameter("fooParameter3");
+    assertNotNull(parameter);
+    assertEquals("fooParameter3", parameter.getName());
+  }
+
+  @Test
+  public void parameterNotExisting() throws Exception {
+    assertNotNull(edmFunctionImportWithoutParameters.getParameterNames());
+
+    EdmParameter parameter = edmFunctionImportWithoutParameters.getParameter("fooParameter1");
+    assertNull(parameter);
+
+    parameter = edmFunctionImportWithoutParameters.getParameter("fooParameter2");
+    assertNull(parameter);
+
+    parameter = edmFunctionImportWithoutParameters.getParameter("fooParameter3");
+    assertNull(parameter);
+  }
+
+  @Test
+  public void parameterAnnotations() throws Exception {
+    EdmParameter parameter = edmFunctionImport.getParameter("fooParameter1");
+    assertNotNull(parameter);
+    EdmAnnotatable annotatable = (EdmAnnotatable) parameter;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = edmFunctionImport;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProvTest.java
new file mode 100644
index 0000000..97cea60
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmImplProvTest.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmImplProvTest extends BaseTest {
+
+  private static EdmImplProv edm;
+
+  @BeforeClass
+  public static void getEdmImpl() throws Exception {
+    EdmProvider edmProvider = mock(EdmProvider.class);
+
+    EntityType entityType = new EntityType().setName("EntityType1");
+    when(edmProvider.getEntityType(new FullQualifiedName("EntityType1Ns", "EntityType1"))).thenReturn(entityType);
+
+    ComplexType complexType = new ComplexType().setName("ComplexType1");
+    when(edmProvider.getComplexType(new FullQualifiedName("ComplexType1Ns", "ComplexType1"))).thenReturn(complexType);
+
+    Association association = new Association().setName("Association1");
+    when(edmProvider.getAssociation(new FullQualifiedName("Association1Ns", "Association1"))).thenReturn(association);
+
+    EntityContainerInfo defaultEntityContainer = new EntityContainerInfo().setName("Container1");
+    when(edmProvider.getEntityContainerInfo(null)).thenReturn(defaultEntityContainer);
+    when(edmProvider.getEntityContainerInfo("Container1")).thenReturn(defaultEntityContainer);
+
+    edm = new EdmImplProv(edmProvider);
+  }
+
+  @Test
+  public void testEntityType() throws EdmException {
+    assertEquals("EntityType1", edm.getEntityType("EntityType1Ns", "EntityType1").getName());
+  }
+
+  @Test
+  public void testComplexType() throws EdmException {
+    assertEquals("ComplexType1", edm.getComplexType("ComplexType1Ns", "ComplexType1").getName());
+  }
+
+  @Test
+  public void testAssociation() throws EdmException {
+    assertEquals("Association1", edm.getAssociation("Association1Ns", "Association1").getName());
+  }
+
+  @Test
+  public void testDefaultEntityContainer() throws EdmException {
+    assertEquals(edm.getEntityContainer("Container1"), edm.getDefaultEntityContainer());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmMappingTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmMappingTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmMappingTest.java
new file mode 100644
index 0000000..d3fede1
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmMappingTest.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.CustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmMappingTest extends BaseTest {
+
+  private static EdmPropertyImplProv propertySimpleProvider;
+  private static EdmNavigationPropertyImplProv navPropertyProvider;
+  private static EdmMappingTest mappedObject;
+
+  @BeforeClass
+  public static void setup() throws Exception {
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    mappedObject = new EdmMappingTest();
+
+    Mapping propertySimpleMapping = new Mapping().setMimeType("mimeType").setInternalName("value").setObject(mappedObject);
+    CustomizableFeedMappings propertySimpleFeedMappings = new CustomizableFeedMappings().setFcKeepInContent(true);
+    SimpleProperty propertySimple = new SimpleProperty().setName("PropertyName").setType(EdmSimpleTypeKind.String)
+        .setMimeType("mimeType").setMapping(propertySimpleMapping).setCustomizableFeedMappings(propertySimpleFeedMappings);
+    propertySimpleProvider = new EdmSimplePropertyImplProv(edmImplProv, propertySimple);
+
+    NavigationProperty navProperty = new NavigationProperty().setName("navProperty").setFromRole("fromRole").setToRole("toRole").setMapping(propertySimpleMapping);
+    navPropertyProvider = new EdmNavigationPropertyImplProv(edmImplProv, navProperty);
+  }
+
+  @Test
+  public void testMappingProperty() throws Exception {
+    EdmMapping mapping = propertySimpleProvider.getMapping();
+    assertNotNull(mapping);
+    assertEquals("value", mapping.getInternalName());
+    assertEquals("mimeType", mapping.getMimeType());
+    assertEquals(mappedObject, mapping.getObject());
+  }
+
+  @Test
+  public void testMappingNavigationProperty() throws Exception {
+    EdmMapping mapping = navPropertyProvider.getMapping();
+    assertNotNull(mapping);
+    assertEquals("value", mapping.getInternalName());
+    assertEquals("mimeType", mapping.getMimeType());
+    assertEquals(mappedObject, mapping.getObject());
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProvTest.java
new file mode 100644
index 0000000..0a60a4e
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNamedImplProvTest.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.mockito.Mockito.mock;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+public class EdmNamedImplProvTest extends BaseTest {
+
+  @Test(expected = EdmException.class)
+  public void testPropertySimple() throws Exception {
+
+    EdmProvider edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    SimpleProperty propertySimple = new SimpleProperty().setName("Prop;ertyName").setType(EdmSimpleTypeKind.String);
+    new EdmSimplePropertyImplProv(edmImplProv, propertySimple);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProvTest.java
new file mode 100644
index 0000000..d92c9d4
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmNavigationPropertyImplProvTest.java
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmAssociation;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.Association;
+import org.apache.olingo.odata2.api.edm.provider.AssociationEnd;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.NavigationProperty;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmNavigationPropertyImplProvTest extends BaseTest {
+
+  private static EdmProvider edmProvider;
+  private static EdmNavigationPropertyImplProv navPropertyProvider;
+
+  @BeforeClass
+  public static void setup() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    FullQualifiedName relationship = new FullQualifiedName("namespace", "associationName");
+    Association association = new Association().setName("associationName");
+    when(edmProvider.getAssociation(relationship)).thenReturn(association);
+
+    AssociationEnd end1 = new AssociationEnd().setRole("fromRole");
+    FullQualifiedName entityName = new FullQualifiedName("namespace", "entityName");
+    AssociationEnd end2 = new AssociationEnd().setRole("toRole").setMultiplicity(EdmMultiplicity.ONE).setType(entityName);
+    association.setEnd1(end1).setEnd2(end2);
+
+    EntityType entityType = new EntityType().setName("entityName");
+    when(edmProvider.getEntityType(entityName)).thenReturn(entityType);
+
+    NavigationProperty navProperty = new NavigationProperty().setName("navProperty").setFromRole("fromRole").setToRole("toRole").setRelationship(relationship);
+    navPropertyProvider = new EdmNavigationPropertyImplProv(edmImplProv, navProperty);
+  }
+
+  @Test
+  public void testNavigationProperty() throws Exception {
+    assertNotNull(navPropertyProvider);
+    assertEquals("navProperty", navPropertyProvider.getName());
+    assertEquals("fromRole", navPropertyProvider.getFromRole());
+    assertEquals("toRole", navPropertyProvider.getToRole());
+    assertEquals(EdmMultiplicity.ONE, navPropertyProvider.getMultiplicity());
+    assertEquals("entityName", navPropertyProvider.getType().getName());
+
+    EdmAssociation association = navPropertyProvider.getRelationship();
+    assertNotNull(association);
+    assertEquals("associationName", association.getName());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = navPropertyProvider;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProvTest.java
----------------------------------------------------------------------
diff --git a/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProvTest.java b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProvTest.java
new file mode 100644
index 0000000..7356c5d
--- /dev/null
+++ b/odata-core/src/test/java/org/apache/olingo/odata2/core/edm/provider/EdmPropertyImplProvTest.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * 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.edm.provider;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmAnnotatable;
+import org.apache.olingo.odata2.api.edm.EdmAnnotations;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.FullQualifiedName;
+import org.apache.olingo.odata2.api.edm.provider.ComplexProperty;
+import org.apache.olingo.odata2.api.edm.provider.ComplexType;
+import org.apache.olingo.odata2.api.edm.provider.CustomizableFeedMappings;
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.edm.provider.SimpleProperty;
+import org.apache.olingo.odata2.core.edm.EdmSimpleTypeFacadeImpl;
+import org.apache.olingo.odata2.testutil.fit.BaseTest;
+
+/**
+ * @author SAP AG
+ */
+public class EdmPropertyImplProvTest extends BaseTest {
+
+  private static EdmProvider edmProvider;
+  private static EdmPropertyImplProv propertySimpleProvider;
+  private static EdmPropertyImplProv propertySimpleWithFacetsProvider;
+  private static EdmPropertyImplProv propertySimpleWithFacetsProvider2;
+  private static EdmPropertyImplProv propertyComplexProvider;
+
+  @BeforeClass
+  public static void setup() throws Exception {
+
+    edmProvider = mock(EdmProvider.class);
+    EdmImplProv edmImplProv = new EdmImplProv(edmProvider);
+
+    Mapping propertySimpleMapping = new Mapping().setMimeType("mimeType2").setInternalName("value");
+    CustomizableFeedMappings propertySimpleFeedMappings = new CustomizableFeedMappings().setFcKeepInContent(true);
+    SimpleProperty propertySimple = new SimpleProperty().setName("PropertyName").setType(EdmSimpleTypeKind.String)
+        .setMimeType("mimeType").setMapping(propertySimpleMapping).setCustomizableFeedMappings(propertySimpleFeedMappings);
+    propertySimpleProvider = new EdmSimplePropertyImplProv(edmImplProv, propertySimple);
+
+    Facets facets = new Facets().setNullable(false);
+    SimpleProperty propertySimpleWithFacets = new SimpleProperty().setName("PropertyName").setType(EdmSimpleTypeKind.String).setFacets(facets);
+    propertySimpleWithFacetsProvider = new EdmSimplePropertyImplProv(edmImplProv, propertySimpleWithFacets);
+
+    Facets facets2 = new Facets().setNullable(true);
+    SimpleProperty propertySimpleWithFacets2 = new SimpleProperty().setName("PropertyName").setType(EdmSimpleTypeKind.String).setFacets(facets2);
+    propertySimpleWithFacetsProvider2 = new EdmSimplePropertyImplProv(edmImplProv, propertySimpleWithFacets2);
+
+    ComplexType complexType = new ComplexType().setName("complexType");
+    FullQualifiedName complexName = new FullQualifiedName("namespace", "complexType");
+    when(edmProvider.getComplexType(complexName)).thenReturn(complexType);
+
+    ComplexProperty propertyComplex = new ComplexProperty().setName("complexProperty").setType(complexName);
+    propertyComplexProvider = new EdmComplexPropertyImplProv(edmImplProv, propertyComplex);
+
+  }
+
+  @Test
+  public void testPropertySimple() throws Exception {
+    assertNotNull(propertySimpleProvider);
+    assertEquals("PropertyName", propertySimpleProvider.getName());
+    assertNotNull(propertySimpleProvider.getType());
+    assertEquals(EdmSimpleTypeFacadeImpl.getEdmSimpleType(EdmSimpleTypeKind.String), propertySimpleProvider.getType());
+    assertEquals("mimeType", propertySimpleProvider.getMimeType());
+    assertNotNull(propertySimpleProvider.getMapping());
+    assertEquals("mimeType2", propertySimpleProvider.getMapping().getMimeType());
+    assertNotNull(propertySimpleProvider.getCustomizableFeedMappings());
+    assertEquals("value", propertySimpleProvider.getMapping().getInternalName());
+    assertNull(propertySimpleProvider.getFacets());
+    assertNotNull(propertySimpleProvider.getMultiplicity());
+    assertEquals(EdmMultiplicity.ZERO_TO_ONE, propertySimpleProvider.getMultiplicity());
+  }
+
+  @Test
+  public void testPropertySimpleWithFacets() throws Exception {
+    assertNotNull(propertySimpleWithFacetsProvider.getFacets());
+    assertNotNull(propertySimpleWithFacetsProvider.getMultiplicity());
+    assertEquals(EdmMultiplicity.ONE, propertySimpleWithFacetsProvider.getMultiplicity());
+
+    assertNotNull(propertySimpleWithFacetsProvider2.getFacets());
+    assertNotNull(propertySimpleWithFacetsProvider2.getMultiplicity());
+    assertEquals(EdmMultiplicity.ZERO_TO_ONE, propertySimpleWithFacetsProvider2.getMultiplicity());
+  }
+
+  @Test
+  public void testPropertyComplex() throws Exception {
+    assertNotNull(propertyComplexProvider);
+    assertEquals("complexProperty", propertyComplexProvider.getName());
+    assertEquals(EdmTypeKind.COMPLEX, propertyComplexProvider.getType().getKind());
+    assertEquals("complexType", propertyComplexProvider.getType().getName());
+  }
+
+  @Test
+  public void getAnnotations() throws Exception {
+    EdmAnnotatable annotatable = propertySimpleProvider;
+    EdmAnnotations annotations = annotatable.getAnnotations();
+    assertNull(annotations.getAnnotationAttributes());
+    assertNull(annotations.getAnnotationElements());
+  }
+}


[41/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilderTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilderTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilderTest.java
new file mode 100644
index 0000000..3684790
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilderTest.java
@@ -0,0 +1,675 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.provider.EntityType;
+import org.apache.olingo.odata2.api.edm.provider.Facets;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmTestModelView;
+
+public class ODataJPAResponseBuilderTest extends JPAEdmTestModelView {
+
+  /*
+   * This Unit is supposed to test the building of Entity Provider Properties for query with $expand
+   */
+  @Test
+  public void testGetEntityProviderPropertiesQuery() {
+    GetEntitySetUriInfo getEntitySetUriInfo = mockEntitySetUriInfoForExpand();
+    ODataJPAContext oDataJPAContext = getODataJPAContext();
+    // Building the edm entity
+    List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
+    Map<String, Object> edmEntity = new HashMap<String, Object>();
+    edmEntity.put("ID", 1);
+    edmEntityList.add(edmEntity);
+    // Invoking the private static method using reflection
+    Class<?> clazz = ODataJPAResponseBuilder.class;
+    Object[] actualParameters = { oDataJPAContext, getEntitySetUriInfo, edmEntityList };
+    Class<?>[] formalParameters = { ODataJPAContext.class,
+        GetEntitySetUriInfo.class, List.class };
+    EntityProviderWriteProperties providerProperties = null;
+    try {
+      ODataJPAResponseBuilder responseBuilder = (ODataJPAResponseBuilder) clazz
+          .newInstance();
+      Method method = clazz.getDeclaredMethod(
+          "getEntityProviderProperties", formalParameters);
+      method.setAccessible(true);
+      providerProperties = (EntityProviderWriteProperties) method.invoke(
+          responseBuilder, actualParameters);
+      assertEquals(1, providerProperties.getExpandSelectTree().getLinks()
+          .size());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InstantiationException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  /*
+   * This Unit is supposed to test the building of Entity Provider Properties for read with $expand
+   */
+  @Test
+  public void testGetEntityProviderPropertiesRead() {
+
+    // Getting the EntityUriInfo
+    GetEntityUriInfo getEntityUriInfo = mockEntityUriInfoForExpand();
+    ODataJPAContext oDataJPAContext = getODataJPAContext();
+    Class<?> clazz = ODataJPAResponseBuilder.class;
+    Object[] actualParameters = { oDataJPAContext, getEntityUriInfo };
+    Class<?>[] formalParameters = { ODataJPAContext.class,
+        GetEntityUriInfo.class };
+    EntityProviderWriteProperties providerProperties = null;
+    try {
+      ODataJPAResponseBuilder responseBuilder = (ODataJPAResponseBuilder) clazz
+          .newInstance();
+      Method method = clazz.getDeclaredMethod(
+          "getEntityProviderProperties", formalParameters);
+      method.setAccessible(true);
+      providerProperties = (EntityProviderWriteProperties) method.invoke(
+          responseBuilder, actualParameters);
+      assertEquals(1, providerProperties.getExpandSelectTree().getLinks()
+          .size());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InstantiationException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @SuppressWarnings("unchecked")
+  @Test
+  public void testConstructListofNavProperty()
+  {
+    List<ArrayList<NavigationPropertySegment>> expand = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    ArrayList<NavigationPropertySegment> navPropList1 = new ArrayList<NavigationPropertySegment>();
+    navPropList1.add(getNavigationPropertySegment("DemoNavigationProperties11"));
+    navPropList1.add(getNavigationPropertySegment("DemoNavigationProperties12"));
+    expand.add(navPropList1);
+    ArrayList<NavigationPropertySegment> navPropList2 = new ArrayList<NavigationPropertySegment>();
+    navPropList2.add(getNavigationPropertySegment("DemoNavigationProperties21"));
+    navPropList2.add(getNavigationPropertySegment("DemoNavigationProperties22"));
+    expand.add(navPropList2);
+    Class<?> clazz = ODataJPAResponseBuilder.class;
+    Object[] actualParameters = { expand };
+    Class<?>[] formalParameters = { List.class };
+    List<EdmNavigationProperty> navigationProperties = null;
+    try {
+      ODataJPAResponseBuilder responseBuilder = (ODataJPAResponseBuilder) clazz
+          .newInstance();
+      Method method = clazz.getDeclaredMethod(
+          "constructListofNavProperty", formalParameters);
+      method.setAccessible(true);
+      navigationProperties = (List<EdmNavigationProperty>) method.invoke(
+          responseBuilder, actualParameters);
+      assertEquals("DemoNavigationProperties21", navigationProperties.get(1).getName());
+      assertEquals("DemoNavigationProperties11", navigationProperties.get(0).getName());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InstantiationException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testBuildListOfTGetEntitySetUriInfoStringODataJPAContext() {
+    try {
+      assertNotNull(ODataJPAResponseBuilder.build(getJPAEntities(),
+          getResultsView(), "application/xml", getODataJPAContext()));
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+  }
+
+  @Test
+  public void testBuildNegatives() {// Bad content type
+    try {
+      EntityType entity = new EntityType();
+      entity.setName("SalesOrderHeader");
+      try {
+        assertNotNull(ODataJPAResponseBuilder.build(getEntity(),
+            getLocalGetURIInfo(), "xml", getODataJPAContext()));
+      } catch (ODataNotFoundException e) {
+        assertTrue(true);
+      }
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);// Nothing to do, Expected.
+    }
+    try {// Bad content type
+      assertNotNull(ODataJPAResponseBuilder.build(getJPAEntities(),
+          getResultsView(), "xml", getODataJPAContext()));
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);// Nothing to do, Expected.
+    }
+
+  }
+
+  @Test
+  public void testBuildObjectGetEntityUriInfoStringODataJPAContext()
+      throws ODataNotFoundException {
+    try {
+      assertNotNull(ODataJPAResponseBuilder.build(new SalesOrderHeader(2,
+          10), getLocalGetURIInfo(), "application/xml",
+          getODataJPAContext()));
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testBuildNullSelects() {// Bad content type
+    try {
+      ODataJPAResponseBuilder.build(getJPAEntities(),
+          getResultsViewWithNullSelects(), "xml",
+          getODataJPAContext());
+    } catch (ODataJPARuntimeException e) {
+      assertTrue(true);// Nothing to do, Expected.
+    } catch (Exception e) {
+      assertTrue(true);
+    }
+  }
+
+  @Test
+  public void testBuildGetCount() {
+    ODataResponse objODataResponse = null;
+    try {
+      objODataResponse = ODataJPAResponseBuilder.build(1,
+          getODataJPAContext());
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertNotNull(objODataResponse);
+  }
+
+  private ODataJPAContext getODataJPAContext() {
+    ODataJPAContext objODataJPAContext = EasyMock
+        .createMock(ODataJPAContext.class);
+    EasyMock.expect(objODataJPAContext.getODataContext()).andStubReturn(
+        getLocalODataContext());
+    EasyMock.replay(objODataJPAContext);
+    return objODataJPAContext;
+  }
+
+  private ODataContext getLocalODataContext() {
+    ODataContext objODataContext = EasyMock.createMock(ODataContext.class);
+    try {
+      EasyMock.expect(objODataContext.getPathInfo()).andStubReturn(
+          getLocalPathInfo());
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(objODataContext);
+    return objODataContext;
+  }
+
+  private PathInfo getLocalPathInfo() {
+    PathInfo pathInfo = EasyMock.createMock(PathInfo.class);
+    EasyMock.expect(pathInfo.getServiceRoot()).andStubReturn(getLocalURI());
+    EasyMock.replay(pathInfo);
+    return pathInfo;
+  }
+
+  private URI getLocalURI() {
+    URI uri = null;
+    try {
+      uri = new URI(
+          "http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/");
+    } catch (URISyntaxException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return uri;
+  }
+
+  private GetEntitySetUriInfo getResultsView() {
+    GetEntitySetUriInfo objGetEntitySetUriInfo = EasyMock
+        .createMock(GetEntitySetUriInfo.class);
+    EasyMock.expect(objGetEntitySetUriInfo.getInlineCount()).andStubReturn(
+        getLocalInlineCount());
+    EasyMock.expect(objGetEntitySetUriInfo.getTargetEntitySet())
+        .andStubReturn(getLocalTargetEntitySet());
+    EasyMock.expect(objGetEntitySetUriInfo.getSelect()).andStubReturn(
+        getSelectItemList());
+    EasyMock.expect(objGetEntitySetUriInfo.getExpand()).andStubReturn(
+        getExpandList());
+    EasyMock.expect(objGetEntitySetUriInfo.getSkip()).andStubReturn(new Integer(1));
+    EasyMock.replay(objGetEntitySetUriInfo);
+    return objGetEntitySetUriInfo;
+  }
+
+  private List<ArrayList<NavigationPropertySegment>> getExpandList() {
+    List<ArrayList<NavigationPropertySegment>> expandList = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    return expandList;
+  }
+
+  private GetEntitySetUriInfo getResultsViewWithNullSelects() {
+    GetEntitySetUriInfo objGetEntitySetUriInfo = EasyMock
+        .createMock(GetEntitySetUriInfo.class);
+    EasyMock.expect(objGetEntitySetUriInfo.getInlineCount()).andStubReturn(
+        getLocalInlineCount());
+    EasyMock.expect(objGetEntitySetUriInfo.getTargetEntitySet())
+        .andStubReturn(getLocalTargetEntitySet());
+    EasyMock.expect(objGetEntitySetUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(objGetEntitySetUriInfo.getExpand()).andStubReturn(null);
+    EasyMock.expect(objGetEntitySetUriInfo.getSkip()).andStubReturn(new Integer(1));
+
+    EasyMock.replay(objGetEntitySetUriInfo);
+    return objGetEntitySetUriInfo;
+  }
+
+  private GetEntityUriInfo getLocalGetURIInfo() {
+    GetEntityUriInfo objGetEntityUriInfo = EasyMock
+        .createMock(GetEntityUriInfo.class);
+    EasyMock.expect(objGetEntityUriInfo.getSelect()).andStubReturn(
+        getSelectItemList());
+    EasyMock.expect(objGetEntityUriInfo.getTargetEntitySet())
+        .andStubReturn(getLocalTargetEntitySet());
+    EasyMock.expect(objGetEntityUriInfo.getExpand()).andStubReturn(
+        getExpandList());
+    EasyMock.replay(objGetEntityUriInfo);
+    return objGetEntityUriInfo;
+  }
+
+  private List<SelectItem> getSelectItemList() {
+    List<SelectItem> selectItems = new ArrayList<SelectItem>();
+    selectItems.add(getSelectItem());
+    return selectItems;
+  }
+
+  private SelectItem getSelectItem() {
+    SelectItem selectItem = EasyMock.createMock(SelectItem.class);
+    EasyMock.expect(selectItem.getProperty()).andStubReturn(
+        getEdmPropertyForSelect());
+    List<NavigationPropertySegment> navigationSegmentList = new ArrayList<NavigationPropertySegment>();
+    EasyMock.expect(selectItem.getNavigationPropertySegments())
+        .andStubReturn(navigationSegmentList);
+    EasyMock.replay(selectItem);
+    return selectItem;
+  }
+
+  private EdmProperty getEdmPropertyForSelect() {
+    EdmSimpleType edmType = EasyMock.createMock(EdmSimpleType.class);
+    EasyMock.expect(edmType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+    Facets facets = new Facets().setNullable(false);
+    try {
+      EasyMock.expect(
+          edmType.valueToString(new Integer(2), EdmLiteralKind.URI,
+              facets)).andStubReturn("2");
+      EasyMock.expect(
+          edmType.valueToString(new Integer(2),
+              EdmLiteralKind.DEFAULT, facets)).andStubReturn("2");
+    } catch (EdmSimpleTypeException e1) {
+      fail("There is an exception in mocking EdmType object "
+          + e1.getMessage());
+    }
+    EasyMock.replay(edmType);
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("soId");
+    EasyMock.expect(edmMapping.getMimeType()).andReturn(null);
+    EasyMock.replay(edmMapping);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("ID");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+      EasyMock.expect(edmProperty.getFacets()).andStubReturn(facets);
+      EasyMock.expect(edmProperty.getCustomizableFeedMappings())
+          .andStubReturn(null);
+      EasyMock.expect(edmProperty.getMimeType()).andStubReturn(null);
+      EasyMock.replay(edmProperty);
+
+    } catch (EdmException e) {
+      fail("There is an exception in mocking some object "
+          + e.getMessage());
+    }
+
+    return edmProperty;
+
+  }
+
+  private EdmEntitySet getLocalTargetEntitySet() {
+    EdmEntitySet objEdmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(objEdmEntitySet.getEntityType()).andStubReturn(
+          getLocalEdmEntityType());
+      EasyMock.expect(objEdmEntitySet.getName()).andStubReturn(
+          "SalesOderHeaders");
+      EasyMock.expect(objEdmEntitySet.getEntityContainer())
+          .andStubReturn(getLocalEdmEntityContainer());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    EasyMock.replay(objEdmEntitySet);
+    return objEdmEntitySet;
+  }
+
+  private EdmEntityContainer getLocalEdmEntityContainer() {
+    EdmEntityContainer edmEntityContainer = EasyMock
+        .createMock(EdmEntityContainer.class);
+    EasyMock.expect(edmEntityContainer.isDefaultEntityContainer())
+        .andStubReturn(true);
+    try {
+      EasyMock.expect(edmEntityContainer.getName()).andStubReturn(
+          "salesorderprocessingContainer");
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    EasyMock.replay(edmEntityContainer);
+    return edmEntityContainer;
+  }
+
+  private EdmEntityType getLocalEdmEntityType() {
+    EdmEntityType objEdmEntityType = EasyMock
+        .createMock(EdmEntityType.class);
+    try {
+      EasyMock.expect(objEdmEntityType.getName()).andStubReturn(
+          "SalesOderHeaders");
+      EasyMock.expect(objEdmEntityType.getNamespace()).andStubReturn(
+          "SalesOderHeaders");
+      EasyMock.expect(objEdmEntityType.hasStream()).andStubReturn(false);
+      EasyMock.expect(objEdmEntityType.hasStream()).andStubReturn(false);
+      ArrayList<String> propertyNames = new ArrayList<String>();
+      propertyNames.add("ID");
+      EasyMock.expect(objEdmEntityType.getProperty("ID")).andStubReturn(
+          getEdmPropertyForSelect());
+      EasyMock.expect(objEdmEntityType.getPropertyNames()).andStubReturn(
+          propertyNames);
+      EasyMock.expect(objEdmEntityType.getNavigationPropertyNames())
+          .andStubReturn(new ArrayList<String>());
+      EasyMock.expect(objEdmEntityType.getKeyPropertyNames())
+          .andStubReturn(propertyNames);
+      EasyMock.expect(objEdmEntityType.getKeyProperties()).andStubReturn(
+          getKeyProperties());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(objEdmEntityType);
+    return objEdmEntityType;
+  }
+
+  private List<EdmProperty> getKeyProperties() {
+    List<EdmProperty> edmProperties = new ArrayList<EdmProperty>();
+    EdmType edmType = EasyMock.createMock(EdmType.class);
+    EasyMock.expect(edmType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+    EasyMock.replay(edmType);
+    EdmProperty edmProperty = EasyMock.createMock(EdmProperty.class);
+    EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
+    EasyMock.expect(edmMapping.getInternalName()).andStubReturn("soId");
+    EasyMock.replay(edmMapping);
+    try {
+      EasyMock.expect(edmProperty.getName()).andStubReturn("ID");
+      EasyMock.expect(edmProperty.getType()).andStubReturn(edmType);
+      EasyMock.expect(edmProperty.getMapping()).andStubReturn(edmMapping);
+      EasyMock.replay(edmProperty);
+    } catch (EdmException e) {
+      fail("There is an exception is mocking some object "
+          + e.getMessage());
+    }
+
+    edmProperties.add(edmProperty);
+    return edmProperties;
+  }
+
+  private InlineCount getLocalInlineCount() {
+    return InlineCount.NONE;
+  }
+
+  class SalesOrderHeader {
+    private int soId;
+    private int Field1;
+
+    public SalesOrderHeader(final int soId, final int field) {
+      this.soId = soId;
+      Field1 = field;
+    }
+
+    public int getField1() {
+      return Field1;
+    }
+
+    public void setField1(final int field1) {
+      Field1 = field1;
+    }
+
+    public int getSoId() {
+      return soId;
+    }
+
+    public void setSoId(final int soId) {
+      this.soId = soId;
+    }
+
+  }
+
+  private List<Object> getJPAEntities() {
+    List<Object> listJPAEntities = new ArrayList<Object>();
+    SalesOrderHeader entity;
+    entity = new SalesOrderHeader(2, 10);
+    listJPAEntities.add(entity);
+    return listJPAEntities;
+  }
+
+  private Object getEntity() {
+    SalesOrderHeader sHeader = new SalesOrderHeader(10, 34);
+    return sHeader;
+  }
+
+  private GetEntityUriInfo mockEntityUriInfoForExpand() {
+
+    List<SelectItem> selectItemList = new ArrayList<SelectItem>();
+    List<ArrayList<NavigationPropertySegment>> expandList = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    ArrayList<NavigationPropertySegment> navigationPropertyList = new ArrayList<NavigationPropertySegment>();
+    // Mocking the navigation property
+    EdmNavigationProperty navigationProperty = EasyMock
+        .createMock(EdmNavigationProperty.class);
+    try {
+      EasyMock.expect(navigationProperty.getName()).andStubReturn(
+          "SalesOrderItemDetails");
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(navigationProperty);
+    // Mocking the navigation property segments and adding to expand list
+    NavigationPropertySegment navigationPropertySegment = EasyMock
+        .createMock(NavigationPropertySegment.class);
+    EasyMock.expect(navigationPropertySegment.getNavigationProperty())
+        .andStubReturn(navigationProperty);
+    EasyMock.expect(navigationPropertySegment.getTargetEntitySet())
+        .andStubReturn(getTargetEntitySetForExpand());
+    EasyMock.replay(navigationPropertySegment);
+    navigationPropertyList.add(navigationPropertySegment);
+    expandList.add(navigationPropertyList);
+    // Mocking EntityUriInfo
+    GetEntityUriInfo entityUriInfo = EasyMock
+        .createMock(GetEntityUriInfo.class);
+    EasyMock.expect(entityUriInfo.getSelect())
+        .andStubReturn(selectItemList);
+    EasyMock.expect(entityUriInfo.getExpand()).andStubReturn(expandList);
+    EasyMock.replay(entityUriInfo);
+    return entityUriInfo;
+  }
+
+  private GetEntitySetUriInfo mockEntitySetUriInfoForExpand() {
+
+    List<SelectItem> selectItemList = new ArrayList<SelectItem>();
+    List<ArrayList<NavigationPropertySegment>> expandList = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    ArrayList<NavigationPropertySegment> navigationPropertyList = new ArrayList<NavigationPropertySegment>();
+    // Mocking the navigation property
+    EdmNavigationProperty navigationProperty = EasyMock
+        .createMock(EdmNavigationProperty.class);
+    try {
+      EasyMock.expect(navigationProperty.getName()).andStubReturn(
+          "SalesOrderItemDetails");
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(navigationProperty);
+    // Mocking the navigation property segments and adding to expand list
+    NavigationPropertySegment navigationPropertySegment = EasyMock
+        .createMock(NavigationPropertySegment.class);
+    EasyMock.expect(navigationPropertySegment.getNavigationProperty())
+        .andStubReturn(navigationProperty);
+    EasyMock.expect(navigationPropertySegment.getTargetEntitySet())
+        .andStubReturn(getTargetEntitySetForExpand());
+    EasyMock.replay(navigationPropertySegment);
+    navigationPropertyList.add(navigationPropertySegment);
+    expandList.add(navigationPropertyList);
+    // Mocking EntityUriInfo
+    GetEntitySetUriInfo entitySetUriInfo = EasyMock
+        .createMock(GetEntitySetUriInfo.class);
+    EasyMock.expect(entitySetUriInfo.getSelect())
+        .andStubReturn(selectItemList);
+    EasyMock.expect(entitySetUriInfo.getExpand()).andStubReturn(expandList);
+    EasyMock.expect(entitySetUriInfo.getInlineCount()).andStubReturn(InlineCount.ALLPAGES);
+    EasyMock.expect(entitySetUriInfo.getSkip()).andStubReturn(new Integer(1));
+    EasyMock.expect(entitySetUriInfo.getTop()).andStubReturn(new Integer(2));
+    EasyMock.replay(entitySetUriInfo);
+    return entitySetUriInfo;
+  }
+
+  private EdmEntitySet getTargetEntitySetForExpand() {
+    EdmEntitySet entitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(entitySet.getName()).andStubReturn(
+          "SalesOrderHeaders");
+      EasyMock.expect(entitySet.getEntityType()).andStubReturn(null);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(entitySet);
+    return entitySet;
+  }
+
+  private NavigationPropertySegment getNavigationPropertySegment(final String navPropertyName)
+  {
+    EdmNavigationProperty navigationProperty = EasyMock.createMock(EdmNavigationProperty.class);
+    try {
+      EasyMock.expect(navigationProperty.getName()).andStubReturn(navPropertyName);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(navigationProperty);
+    NavigationPropertySegment navPropertySegment = EasyMock.createMock(NavigationPropertySegment.class);
+    EasyMock.expect(navPropertySegment.getNavigationProperty()).andStubReturn(navigationProperty);
+    EasyMock.replay(navPropertySegment);
+    return navPropertySegment;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBackTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBackTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBackTest.java
new file mode 100644
index 0000000..232d75e
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBackTest.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.ODataCallback;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPAExpandCallBackTest {
+
+  @Test
+  public void testRetrieveEntryResult() {
+    JPAExpandCallBack callBack = getJPAExpandCallBackObject();
+    WriteEntryCallbackContext writeFeedContext = TestUtil.getWriteEntryCallBackContext();
+    try {
+      Field field = callBack.getClass().getDeclaredField("nextEntitySet");
+      field.setAccessible(true);
+      field.set(callBack, TestUtil.mockTargetEntitySet());
+      WriteEntryCallbackResult result = callBack.retrieveEntryResult(writeFeedContext);
+      assertEquals(1, result.getEntryData().size());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testRetrieveFeedResult() {
+    JPAExpandCallBack callBack = getJPAExpandCallBackObject();
+    WriteFeedCallbackContext writeFeedContext = TestUtil.getWriteFeedCallBackContext();
+    try {
+      Field field = callBack.getClass().getDeclaredField("nextEntitySet");
+      field.setAccessible(true);
+      field.set(callBack, TestUtil.mockTargetEntitySet());
+      WriteFeedCallbackResult result = callBack.retrieveFeedResult(writeFeedContext);
+      assertEquals(2, result.getFeedData().size());
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testGetCallbacks() {
+    Map<String, ODataCallback> callBacks = null;
+    try {
+      URI baseUri = new URI("http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/SalesOrderProcessing.svc/");
+      ExpandSelectTreeNode expandSelectTreeNode = TestUtil.mockExpandSelectTreeNode();
+      List<ArrayList<NavigationPropertySegment>> expandList = TestUtil.getExpandList();
+      callBacks = JPAExpandCallBack.getCallbacks(baseUri, expandSelectTreeNode, expandList);
+    } catch (URISyntaxException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    assertEquals(1, callBacks.size());
+
+  }
+
+  @Test
+  public void testGetNextNavigationProperty()
+  {
+    JPAExpandCallBack callBack = getJPAExpandCallBackObject();
+    List<ArrayList<NavigationPropertySegment>> expandList = TestUtil.getExpandList();
+    ArrayList<NavigationPropertySegment> expands = expandList.get(0);
+    expands.add(TestUtil.mockThirdNavigationPropertySegment());
+    EdmNavigationProperty result = null;
+    try {
+      Field field = callBack.getClass().getDeclaredField("expandList");
+      field.setAccessible(true);
+      field.set(callBack, expandList);
+      Class<?>[] formalParams = { EdmEntityType.class, EdmNavigationProperty.class };
+      Object[] actualParams = { TestUtil.mockSourceEdmEntityType(), TestUtil.mockNavigationProperty() };
+      Method method = callBack.getClass().getDeclaredMethod("getNextNavigationProperty", formalParams);
+      method.setAccessible(true);
+      result = (EdmNavigationProperty) method.invoke(callBack, actualParams);
+      assertEquals("MaterialDetails", result.getName());
+
+    } catch (SecurityException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchFieldException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalArgumentException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (IllegalAccessException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (NoSuchMethodException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (InvocationTargetException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  private JPAExpandCallBack getJPAExpandCallBackObject()
+  {
+    Map<String, ODataCallback> callBacks = null;
+    try {
+      URI baseUri = new URI("http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/SalesOrderProcessing.svc/");
+      ExpandSelectTreeNode expandSelectTreeNode = TestUtil.mockExpandSelectTreeNode();
+      List<ArrayList<NavigationPropertySegment>> expandList = TestUtil.getExpandList();
+      callBacks = JPAExpandCallBack.getCallbacks(baseUri, expandSelectTreeNode, expandList);
+    } catch (URISyntaxException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return (JPAExpandCallBack) callBacks.get("SalesOrderLineItemDetails");
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContextTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContextTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContextTest.java
new file mode 100644
index 0000000..fd70433
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContextTest.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import junit.framework.Assert;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.provider.Mapping;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLContextType;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+import org.apache.olingo.odata2.processor.core.jpa.model.JPAEdmMappingImpl;
+
+public class JPAFunctionContextTest {
+
+  private int VARIANT = 0;
+
+  public JPAFunctionContext build() {
+    JPAFunctionContext functionContext = null;
+    try {
+      if (VARIANT == 0) {
+        functionContext = (JPAFunctionContext) JPAMethodContext
+            .createBuilder(JPQLContextType.FUNCTION, getView())
+            .build();
+      }
+
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    return functionContext;
+  }
+
+  @Test
+  public void testGetEnclosingObject() {
+
+    VARIANT = 0;
+
+    Assert.assertNotNull(build());
+
+  }
+
+  private GetFunctionImportUriInfo getView() {
+    GetFunctionImportUriInfo functiontView = EasyMock
+        .createMock(GetFunctionImportUriInfo.class);
+    EasyMock.expect(functiontView.getFunctionImport()).andStubReturn(
+        getEdmFunctionImport());
+    EasyMock.expect(functiontView.getFunctionImportParameters())
+        .andStubReturn(getFunctionImportParameters());
+
+    EasyMock.replay(functiontView);
+    return functiontView;
+  }
+
+  private Map<String, EdmLiteral> getFunctionImportParameters() {
+    return null;
+  }
+
+  private EdmFunctionImport getEdmFunctionImport() {
+    EdmFunctionImport edmFunctionImport = EasyMock
+        .createMock(EdmFunctionImport.class);
+    try {
+      EasyMock.expect(edmFunctionImport.getMapping()).andStubReturn(
+          getMapping());
+      EasyMock.expect(edmFunctionImport.getParameterNames())
+          .andStubReturn(getParameterNames());
+      EasyMock.expect(edmFunctionImport.getParameter("Gentleman"))
+          .andStubReturn(getParameter("Gentleman"));
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    EasyMock.replay(edmFunctionImport);
+    return edmFunctionImport;
+  }
+
+  private EdmParameter getParameter(final String string) {
+    EdmParameter edmParameter = EasyMock.createMock(EdmParameter.class);
+    try {
+      EasyMock.expect(edmParameter.getMapping()).andStubReturn(
+          getEdmMapping());
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(edmParameter);
+    return edmParameter;
+  }
+
+  private EdmMapping getEdmMapping() {
+    JPAEdmMappingImpl mapping = new JPAEdmMappingImpl();
+    mapping.setJPAType(String.class);
+    ((Mapping) mapping).setInternalName("Gentleman");
+    return mapping;
+  }
+
+  private JPAEdmMappingImpl getMapping() {
+    JPAEdmMappingImpl mapping = new JPAEdmMappingImpl();
+    mapping.setJPAType(FunctionImportTestClass.class);
+    ((Mapping) mapping).setInternalName("testMethod");
+    return mapping;
+  }
+
+  private Collection<String> getParameterNames() {
+    Collection<String> parametersList = new ArrayList<String>();
+    parametersList.add("Gentleman");
+    return parametersList;
+  }
+
+  public static class FunctionImportTestClass {
+
+    public FunctionImportTestClass() {
+
+    }
+
+    public String testMethod(final String message) {
+      return "Hello " + message + "!!";
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImplTest.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImplTest.java b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImplTest.java
new file mode 100644
index 0000000..169a13f
--- /dev/null
+++ b/jpa-core/src/test/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAProcessorImplTest.java
@@ -0,0 +1,464 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.Query;
+import javax.persistence.metamodel.Metamodel;
+
+import junit.framework.Assert;
+
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.PathInfo;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.common.ODataJPATestConstants;
+
+public class JPAProcessorImplTest {
+
+  // -------------------------------- Common Start ------------------------------------common in ODataJPAProcessorDefaultTest as well
+  private static final String STR_LOCAL_URI = "http://localhost:8080/org.apache.olingo.odata2.processor.ref.web/";
+  private static final String SALESORDERPROCESSING_CONTAINER = "salesorderprocessingContainer";
+  private static final String SO_ID = "SoId";
+  private static final String SALES_ORDER = "SalesOrder";
+  private static final String SALES_ORDER_HEADERS = "SalesOrderHeaders";
+  //-------------------------------- Common End ------------------------------------
+
+  JPAProcessorImpl objJPAProcessorImpl;
+
+  @Before
+  public void setUp() throws Exception {
+    objJPAProcessorImpl = new JPAProcessorImpl(getLocalmockODataJPAContext());
+  }
+
+  @Test
+  public void testProcessGetEntitySetCountUriInfo() {
+    try {
+      Assert.assertEquals(11, objJPAProcessorImpl.process(getEntitySetCountUriInfo()));
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testProcessGetEntityCountUriInfo() {
+    try {
+      Assert.assertEquals(11, objJPAProcessorImpl.process(getEntityCountUriInfo()));
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testProcessGetEntitySetUriInfo() {
+    try {
+      Assert.assertNotNull(objJPAProcessorImpl.process(getEntitySetUriInfo()));
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testProcessDeleteUriInfo() {
+    try {
+      Assert.assertNotNull(objJPAProcessorImpl.process(getDeletetUriInfo(), "application/xml"));
+      Assert.assertEquals(new Address(), objJPAProcessorImpl.process(getDeletetUriInfo(), "application/xml"));
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  @Test
+  public void testProcessDeleteUriInfoNegative() {
+    try {
+      Assert.assertNotNull(objJPAProcessorImpl.process(getDeletetUriInfo(), "application/xml"));
+      Assert.assertNotSame(new Object(), objJPAProcessorImpl.process(getDeletetUriInfo(), "application/xml"));
+    } catch (ODataJPAModelException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    } catch (ODataJPARuntimeException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+  }
+
+  // ---------------------------- Common Code Start ---------------- TODO - common in ODataJPAProcessorDefaultTest as well 
+
+  private DeleteUriInfo getDeletetUriInfo() {
+    UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
+    EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
+    EasyMock.expect(objUriInfo.getTop()).andStubReturn(getTop());
+    EasyMock.expect(objUriInfo.getSkip()).andStubReturn(getSkip());
+    EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
+    EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
+    EasyMock.expect(objUriInfo.getKeyPredicates()).andStubReturn(getKeyPredicates());
+    EasyMock.replay(objUriInfo);
+    return objUriInfo;
+  }
+
+  private List<KeyPredicate> getKeyPredicates() {
+    List<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
+    return keyPredicates;
+  }
+
+  private GetEntitySetCountUriInfo getEntitySetCountUriInfo() {
+    return getLocalUriInfo();
+  }
+
+  private GetEntityCountUriInfo getEntityCountUriInfo() {
+    return getLocalUriInfo();
+  }
+
+  private GetEntitySetUriInfo getEntitySetUriInfo() {
+
+    UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
+    EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
+    EasyMock.expect(objUriInfo.getTop()).andStubReturn(getTop());
+    EasyMock.expect(objUriInfo.getSkip()).andStubReturn(getSkip());
+    EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
+    EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
+    //EasyMock.expect(objUriInfo.getFunctionImport()).andStubReturn(getFunctionImport());
+    EasyMock.expect(objUriInfo.getFunctionImport()).andStubReturn(null);
+    EasyMock.replay(objUriInfo);
+    return objUriInfo;
+  }
+
+  /**
+   * @return
+   */
+  private UriInfo getLocalUriInfo() {
+    UriInfo objUriInfo = EasyMock.createMock(UriInfo.class);
+    EasyMock.expect(objUriInfo.getStartEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getTargetEntitySet()).andStubReturn(getLocalEdmEntitySet());
+    EasyMock.expect(objUriInfo.getSelect()).andStubReturn(null);
+    EasyMock.expect(objUriInfo.getOrderBy()).andStubReturn(getOrderByExpression());
+    EasyMock.expect(objUriInfo.getTop()).andStubReturn(getTop());
+    EasyMock.expect(objUriInfo.getSkip()).andStubReturn(getSkip());
+    EasyMock.expect(objUriInfo.getInlineCount()).andStubReturn(getInlineCount());
+    EasyMock.expect(objUriInfo.getFilter()).andStubReturn(getFilter());
+    EasyMock.replay(objUriInfo);
+    return objUriInfo;
+  }
+
+  /**
+   * @return
+   * @throws EdmException
+   */
+  private EdmEntitySet getLocalEdmEntitySet() {
+    EdmEntitySet edmEntitySet = EasyMock.createMock(EdmEntitySet.class);
+    try {
+      EasyMock.expect(edmEntitySet.getName()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntitySet.getEntityContainer()).andStubReturn(getLocalEdmEntityContainer());
+      EasyMock.expect(edmEntitySet.getEntityType()).andStubReturn(getLocalEdmEntityType());
+      EasyMock.replay(edmEntitySet);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return edmEntitySet;
+  }
+
+  /**
+   * @return
+   * @throws EdmException
+   */
+  private EdmEntityType getLocalEdmEntityType() {
+    EdmEntityType edmEntityType = EasyMock.createMock(EdmEntityType.class);
+    try {
+      EasyMock.expect(edmEntityType.getKeyProperties()).andStubReturn(new ArrayList<EdmProperty>());
+      EasyMock.expect(edmEntityType.getPropertyNames()).andStubReturn(getLocalPropertyNames());
+      EasyMock.expect(edmEntityType.getProperty(SO_ID)).andStubReturn(getEdmTypedMockedObj(SALES_ORDER));
+      EasyMock.expect(edmEntityType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.expect(edmEntityType.getNamespace()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntityType.getName()).andStubReturn(SALES_ORDER_HEADERS);
+      EasyMock.expect(edmEntityType.hasStream()).andStubReturn(false);
+      EasyMock.expect(edmEntityType.getNavigationPropertyNames()).andStubReturn(new ArrayList<String>());
+      EasyMock.expect(edmEntityType.getKeyPropertyNames()).andStubReturn(new ArrayList<String>());
+      EasyMock.expect(edmEntityType.getMapping()).andStubReturn(getEdmMappingMockedObj(SALES_ORDER));// ID vs Salesorder ID
+      EasyMock.replay(edmEntityType);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return edmEntityType;
+  }
+
+  private InlineCount getInlineCount() {
+    return InlineCount.NONE;
+  }
+
+  private FilterExpression getFilter() {
+    return null;
+  }
+
+  private Integer getSkip() {
+    return null;
+  }
+
+  private Integer getTop() {
+    return null;
+  }
+
+  private OrderByExpression getOrderByExpression() {
+    return null;
+  }
+
+  private ODataJPAContext getLocalmockODataJPAContext() {
+    ODataJPAContext odataJPAContext = EasyMock.createMock(ODataJPAContext.class);
+    EasyMock.expect(odataJPAContext.getPersistenceUnitName()).andStubReturn("salesorderprocessing");
+    EasyMock.expect(odataJPAContext.getEntityManagerFactory()).andStubReturn(mockEntityManagerFactory());
+    EasyMock.expect(odataJPAContext.getODataContext()).andStubReturn(getLocalODataContext());
+    EasyMock.expect(odataJPAContext.getEntityManager()).andStubReturn(getLocalEntityManager());
+    EasyMock.replay(odataJPAContext);
+    return odataJPAContext;
+  }
+
+  private EntityManagerFactory mockEntityManagerFactory() {
+    EntityManagerFactory emf = EasyMock.createMock(EntityManagerFactory.class);
+    EasyMock.expect(emf.getMetamodel()).andStubReturn(mockMetaModel());
+    EasyMock.expect(emf.createEntityManager()).andStubReturn(getLocalEntityManager());
+    EasyMock.replay(emf);
+    return emf;
+  }
+
+  public EntityManager getLocalEntityManager() {
+    EntityManager em = EasyMock.createMock(EntityManager.class);
+    EasyMock.expect(em.createQuery("SELECT E1 FROM SalesOrderHeaders E1")).andStubReturn(getQuery());
+    EasyMock.expect(em.createQuery("SELECT COUNT ( E1 ) FROM SalesOrderHeaders E1")).andStubReturn(getQueryForSelectCount());
+    EasyMock.expect(em.getTransaction()).andStubReturn(getLocalTransaction()); //For Delete
+    em.flush();
+    em.flush();
+    Address obj = new Address();
+    em.remove(obj);// testing void method
+    em.remove(obj);// testing void method
+    EasyMock.replay(em);
+    return em;
+  }
+
+  private EntityTransaction getLocalTransaction() {
+    EntityTransaction entityTransaction = EasyMock.createMock(EntityTransaction.class);
+    entityTransaction.begin(); // testing void method
+    entityTransaction.begin(); // testing void method
+    entityTransaction.commit();// testing void method
+    entityTransaction.commit();// testing void method
+    EasyMock.replay(entityTransaction);
+    return entityTransaction;
+  }
+
+  private Query getQuery() {
+    Query query = EasyMock.createMock(Query.class);
+    EasyMock.expect(query.getResultList()).andStubReturn(getResultList());
+    EasyMock.replay(query);
+    return query;
+  }
+
+  private Query getQueryForSelectCount() {
+    Query query = EasyMock.createMock(Query.class);
+    EasyMock.expect(query.getResultList()).andStubReturn(getResultListForSelectCount());
+    EasyMock.replay(query);
+    return query;
+  }
+
+  private List<?> getResultList() {
+    List<Object> list = new ArrayList<Object>();
+    list.add(new Address());
+    return list;
+  }
+
+  private List<?> getResultListForSelectCount() {
+    List<Object> list = new ArrayList<Object>();
+    list.add(new Long(11));
+    return list;
+  }
+
+  private class Address {
+    private String soId = "12";
+
+    public String getSoId() {
+      return soId;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+      boolean isEqual = false;
+      if (obj instanceof Address)
+      {
+        isEqual = getSoId().equalsIgnoreCase(((Address) obj).getSoId());//
+      }
+      return isEqual;
+    }
+  }
+
+  private Metamodel mockMetaModel() {
+    Metamodel metaModel = EasyMock.createMock(Metamodel.class);
+    EasyMock.replay(metaModel);
+    return metaModel;
+  }
+
+  private EdmEntityContainer getLocalEdmEntityContainer() {
+    EdmEntityContainer edmEntityContainer = EasyMock.createMock(EdmEntityContainer.class);
+    EasyMock.expect(edmEntityContainer.isDefaultEntityContainer()).andStubReturn(true);
+    try {
+      EasyMock.expect(edmEntityContainer.getName()).andStubReturn(SALESORDERPROCESSING_CONTAINER);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+
+    EasyMock.replay(edmEntityContainer);
+    return edmEntityContainer;
+  }
+
+  private EdmTyped getEdmTypedMockedObj(final String propertyName) {
+    EdmProperty mockedEdmProperty = EasyMock.createMock(EdmProperty.class);
+    try {
+      EasyMock.expect(mockedEdmProperty.getMapping())
+          .andStubReturn(getEdmMappingMockedObj(propertyName));
+      EdmType edmType = EasyMock.createMock(EdmType.class);
+      EasyMock.expect(edmType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
+      EasyMock.replay(edmType);
+      EasyMock.expect(mockedEdmProperty.getName()).andStubReturn("identifier");
+      EasyMock.expect(mockedEdmProperty.getType()).andStubReturn(edmType);
+      EasyMock.expect(mockedEdmProperty.getFacets()).andStubReturn(getEdmFacetsMockedObj());
+
+      EasyMock.replay(mockedEdmProperty);
+    } catch (EdmException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return mockedEdmProperty;
+  }
+
+  private EdmFacets getEdmFacetsMockedObj() {
+    EdmFacets facets = EasyMock.createMock(EdmFacets.class);
+    EasyMock.expect(facets.getConcurrencyMode()).andStubReturn(EdmConcurrencyMode.Fixed);
+
+    EasyMock.replay(facets);
+    return facets;
+  }
+
+  private EdmMapping getEdmMappingMockedObj(final String propertyName) {
+    EdmMapping mockedEdmMapping = EasyMock.createMock(EdmMapping.class);
+    if (propertyName.equalsIgnoreCase(SALES_ORDER)) {
+      EasyMock.expect(mockedEdmMapping.getInternalName())
+          .andStubReturn(SALES_ORDER_HEADERS);
+    } else {
+      EasyMock.expect(mockedEdmMapping.getInternalName())
+          .andStubReturn(propertyName);
+    }
+    EasyMock.replay(mockedEdmMapping);
+    return mockedEdmMapping;
+  }
+
+  private List<String> getLocalPropertyNames() {
+    List<String> list = new ArrayList<String>();
+    list.add(SO_ID);
+    return list;
+  }
+
+  private ODataContext getLocalODataContext() {
+    ODataContext objODataContext = EasyMock.createMock(ODataContext.class);
+    try {
+      EasyMock.expect(objODataContext.getPathInfo()).andStubReturn(getLocalPathInfo());
+    } catch (ODataException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    EasyMock.replay(objODataContext);
+    return objODataContext;
+  }
+
+  private PathInfo getLocalPathInfo() {
+    PathInfo pathInfo = EasyMock.createMock(PathInfo.class);
+    EasyMock.expect(pathInfo.getServiceRoot()).andStubReturn(getLocalURI());
+    EasyMock.replay(pathInfo);
+    return pathInfo;
+  }
+
+  private URI getLocalURI() {
+    URI uri = null;
+    try {
+      uri = new URI(STR_LOCAL_URI);
+    } catch (URISyntaxException e) {
+      fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage()
+          + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
+    }
+    return uri;
+  }
+
+  //-------------------------------- Common End ------------------------------------
+
+}


[25/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksCountUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksCountUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksCountUriInfo.java
new file mode 100644
index 0000000..7fdd5ea
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksCountUriInfo.java
@@ -0,0 +1,131 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the number of links to entities.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntitySetLinksCountUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Determines whether $count has been used in the request URI.
+   * @return whether $count has been used
+   */
+  public boolean isCount();
+
+  /**
+   * Determines whether $links has been used in the request URI.
+   * @return whether $links has been used
+   */
+  public boolean isLinks();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the value of the $skip system query option.
+   * @return skip or null
+   */
+  public Integer getSkip();
+
+  /**
+   * Gets the value of the $top system query option.
+   * @return top or null
+   */
+  public Integer getTop();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksUriInfo.java
new file mode 100644
index 0000000..1302e96
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetLinksUriInfo.java
@@ -0,0 +1,144 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the URIs of entities.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntitySetLinksUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Determines whether $links has been used in the request URI.
+   * @return whether $links has been used
+   */
+  public boolean isLinks();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the value of the $inlinecount system query option.
+   * @return {@link InlineCount} the inline count or null
+   */
+  public InlineCount getInlineCount();
+
+  /**
+   * Gets the value of the $skiptoken system query option.
+   * @return skip token or null
+   */
+  public String getSkipToken();
+
+  /**
+   * Gets the value of the $skip system query option.
+   * @return skip or null
+   */
+  public Integer getSkip();
+
+  /**
+   * Gets the value of the $top system query option.
+   * @return top or null
+   */
+  public Integer getTop();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetUriInfo.java
new file mode 100644
index 0000000..00d0b55
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntitySetUriInfo.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of entities.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntitySetUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the value of the $inlinecount system query option.
+   * @return {@link InlineCount} the inline count or null
+   */
+  public InlineCount getInlineCount();
+
+  /**
+   * Gets the value of the $orderby system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the order-by expression or null
+   */
+  public OrderByExpression getOrderBy();
+
+  /**
+   * Gets the value of the $skiptoken system query option.
+   * @return the skip token or null
+   */
+  public String getSkipToken();
+
+  /**
+   * Gets the value of the $skip system query option.
+   * @return skip or null
+   */
+  public Integer getSkip();
+
+  /**
+   * Gets the value of the $top system query option.
+   * @return top or null
+   */
+  public Integer getTop();
+
+  /**
+   * Gets the value of the $expand system query option as a list of
+   * lists of navigation-property segments, or an empty list if not used.
+   * @return List of a list of {@link NavigationPropertySegment} to be expanded
+   */
+  public List<ArrayList<NavigationPropertySegment>> getExpand();
+
+  /**
+   * Gets the value of the $select system query option as a list of select items,
+   * or an empty list if not used.
+   * @return List of {@link SelectItem} to be selected
+   */
+  public List<SelectItem> getSelect();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityUriInfo.java
new file mode 100644
index 0000000..1e88e94
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetEntityUriInfo.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of a single entity.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetEntityUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the value of the $expand system query option as a list of
+   * lists of navigation-property segments, or an empty list if not used.
+   * @return List of a list of {@link NavigationPropertySegment} to be expanded
+   */
+  public List<ArrayList<NavigationPropertySegment>> getExpand();
+
+  /**
+   * Gets the value of the $select system query option as a list of select items,
+   * or an empty list if not used.
+   * @return List of {@link SelectItem} to be selected
+   */
+  public List<SelectItem> getSelect();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetFunctionImportUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetFunctionImportUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetFunctionImportUriInfo.java
new file mode 100644
index 0000000..2bbf9c9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetFunctionImportUriInfo.java
@@ -0,0 +1,60 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+
+/**
+ * Access to the parts of the request URI that are relevant for requests
+ * of function imports.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetFunctionImportUriInfo {
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMediaResourceUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMediaResourceUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMediaResourceUriInfo.java
new file mode 100644
index 0000000..9acec2b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMediaResourceUriInfo.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the media resource of a single entity.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetMediaResourceUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMetadataUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMetadataUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMetadataUriInfo.java
new file mode 100644
index 0000000..27eb315
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetMetadataUriInfo.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.Map;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the metadata document.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetMetadataUriInfo {
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetServiceDocumentUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetServiceDocumentUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetServiceDocumentUriInfo.java
new file mode 100644
index 0000000..f1791b0
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetServiceDocumentUriInfo.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.Map;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of the service document.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetServiceDocumentUriInfo {
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetSimplePropertyUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetSimplePropertyUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetSimplePropertyUriInfo.java
new file mode 100644
index 0000000..1b856fe
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/GetSimplePropertyUriInfo.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * Access to the parts of the request URI that are relevant for GET requests
+ * of simple properties.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface GetSimplePropertyUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target simple type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the path used to select a (simple or complex) property of an entity,
+   * or an empty list if no property is accessed.
+   * @return List of {@link EdmProperty}
+   */
+  public List<EdmProperty> getPropertyPath();
+
+  /**
+   * Determines whether $value has been used in the request URI.
+   * @return whether $value has been used
+   */
+  public boolean isValue();
+
+  /**
+   * Gets the value of the $format system query option.
+   * @return the format (as set as <code>$format</code> query parameter) or null
+   */
+  public String getFormat();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PostUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PostUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PostUriInfo.java
new file mode 100644
index 0000000..63d09c9
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PostUriInfo.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * 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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+
+/**
+ * Access to the parts of the request URI that are relevant for POST requests.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface PostUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target entity type of the request.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PutMergePatchUriInfo.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PutMergePatchUriInfo.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PutMergePatchUriInfo.java
new file mode 100644
index 0000000..abe2ad7
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/PutMergePatchUriInfo.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.api.uri.info;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmEntityContainer;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.NavigationSegment;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+
+/**
+ * Access to the parts of the request URI that are relevant for PUT, PATCH, or MERGE requests.
+ * @org.apache.olingo.odata2.DoNotImplement
+ * @author SAP AG
+ */
+public interface PutMergePatchUriInfo {
+  /**
+   * Gets the target entity container.
+   * @return {@link EdmEntityContainer} the target entity container
+   */
+  public EdmEntityContainer getEntityContainer();
+
+  /**
+   * Gets the start entity set - identical to the target entity set if no navigation
+   * has been used.
+   * @return {@link EdmEntitySet}
+   */
+  public EdmEntitySet getStartEntitySet();
+
+  /**
+   * Gets the target entity set after navigation.
+   * @return {@link EdmEntitySet} target entity set
+   */
+  public EdmEntitySet getTargetEntitySet();
+
+  /**
+   * Gets the function import.
+   * @return {@link EdmFunctionImport} the function import
+   */
+  public EdmFunctionImport getFunctionImport();
+
+  /**
+   * Gets the target type of the request: an entity type, a simple type, or a complex type.
+   * @return {@link EdmType} the target type
+   */
+  public EdmType getTargetType();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the start entity set,
+   * or an empty list if not used.
+   * @return List of {@link KeyPredicate}
+   * @see #getStartEntitySet()
+   */
+  public List<KeyPredicate> getKeyPredicates();
+
+  /**
+   * Gets the key predicates used to select a single entity out of the target entity set,
+   * or an empty list if not used - identical to the key predicates from the last entry
+   * retrieved from {@link #getNavigationSegments()} or, if no navigation has been used,
+   * to the result of {@link #getKeyPredicates()}.
+   * @return List of {@link KeyPredicate}
+   * @see #getTargetEntitySet()
+   */
+  public List<KeyPredicate> getTargetKeyPredicates();
+
+  /**
+   * Gets the navigation segments, or an empty list if no navigation has been used.
+   * @return List of {@link NavigationSegment}
+   */
+  public List<NavigationSegment> getNavigationSegments();
+
+  /**
+   * Gets the path used to select a (simple or complex) property of an entity,
+   * or an empty list if no property is accessed.
+   * @return List of {@link EdmProperty}
+   */
+  public List<EdmProperty> getPropertyPath();
+
+  /**
+   * Gets the value of the $filter system query option as root object of the
+   * expression tree built during URI parsing.
+   * @return the filter expression or null
+   */
+  public FilterExpression getFilter();
+
+  /**
+   * Gets the parameters of a function import as Map from parameter names to
+   * their corresponding typed values, or an empty list if no function import
+   * is used or no parameters are given in the URI.
+   * @return Map of {@literal <String,} {@link EdmLiteral}{@literal >} function import parameters
+   */
+  public Map<String, EdmLiteral> getFunctionImportParameters();
+
+  /**
+   * Gets the custom query options as Map from option names to their
+   * corresponding String values, or an empty list if no custom query options
+   * are given in the URI.
+   * @return Map of {@literal <String, String>} custom query options
+   */
+  public Map<String, String> getCustomQueryOptions();
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/package-info.java
new file mode 100644
index 0000000..ddb137b
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/info/package-info.java
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <p>URI Parser Result Views</p>
+ * <p>The interfaces of this package provide access to the relevant parts of the parsed
+ * request URI for the methods that process a request inside the dispatcher.</p>
+ */
+package org.apache.olingo.odata2.api.uri.info;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/package-info.java
----------------------------------------------------------------------
diff --git a/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/package-info.java b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/package-info.java
new file mode 100644
index 0000000..f5776f4
--- /dev/null
+++ b/odata-api/src/main/java/org/apache/olingo/odata2/api/uri/package-info.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+/**
+ * <p>URI Parser Facade</p>
+ * <p>The URI package has one central class {@link org.apache.olingo.odata2.api.uri.UriParser}  to parse a request URI
+ * as well as several interfaces that provide access to parsed parts of the URI.
+ * <br>The {@link org.apache.olingo.odata2.api.uri.UriParser} class also provides the possibility to parse a filter or an orderBy Statement. Both are specified in the OData Protocol Specification. 
+ * <br>The URI syntax is specified in the OData Protocol Specification in the form of an ABNF. </p>
+ */
+package org.apache.olingo.odata2.api.uri;

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/pom.xml
----------------------------------------------------------------------
diff --git a/odata-core/pom.xml b/odata-core/pom.xml
new file mode 100644
index 0000000..a0a9d57
--- /dev/null
+++ b/odata-core/pom.xml
@@ -0,0 +1,194 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<artifactId>org.apache.olingo.odata2.core</artifactId>
+	<packaging>jar</packaging>
+
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>org.apache.olingo.odata2.parent</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+		<relativePath>..</relativePath>
+	</parent>
+
+	<!-- not supported because of static behaviour of serialization tests -->
+	<!-- <build> -->
+	<!-- <plugins> -->
+	<!-- <plugin> -->
+	<!-- <groupId>org.apache.maven.plugins</groupId> -->
+	<!-- <artifactId>maven-surefire-plugin</artifactId> -->
+	<!-- <configuration> -->
+	<!-- <parallel>classes</parallel> -->
+	<!-- <threadCount>10</threadCount> -->
+	<!-- </configuration> -->
+	<!-- </plugin> -->
+	<!-- </plugins> -->
+	<!-- </build> -->
+
+	<build>
+		<plugins>
+			<plugin>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+					</archive>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<extensions>true</extensions>
+				<executions>
+					<execution>
+						<id>bundle-manifest</id>
+						<phase>process-classes</phase>
+						<goals>
+							<goal>manifest</goal>
+						</goals>
+					</execution>
+				</executions>
+				<configuration>
+					<instructions>
+						<Import-Package>
+							javax.ws.rs,
+							javax.ws.rs.*,
+							*
+						</Import-Package>
+						<Export-Package>
+							org.apache.olingo.odata2.core.rest.app;version=${project.version},
+							org.apache.olingo.odata2.core.rt;version=${project.version},
+						</Export-Package>
+						<Bundle-DocURL>${project.url}</Bundle-DocURL>
+						<Bundle-ActivationPolicy>lazy</Bundle-ActivationPolicy>
+						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<profiles>
+		<profile>
+			<id>coverage</id>
+			<activation>
+				<property>
+					<name>ldi.parent.emma-coverage</name>
+				</property>
+			</activation>
+			<build>
+				<plugins>
+					<plugin>
+						<!-- copy api during test to target/api_dependency -->
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-dependency-plugin</artifactId>
+						<executions>
+							<execution>
+								<id>copy api classes</id>
+								<phase>generate-test-resources</phase>
+								<goals>
+									<goal>unpack</goal>
+								</goals>
+								<configuration>
+									<artifactItems>
+										<artifactItem>
+											<groupId>org.apache.olingo</groupId>
+											<artifactId>org.apache.olingo.odata2.api</artifactId>
+											<version>${project.version}</version>
+											<outputDirectory>${project.build.directory}/api_dependency</outputDirectory>
+											<overWrite>true</overWrite>
+										</artifactItem>
+									</artifactItems>
+								</configuration>
+							</execution>
+						</executions>
+					</plugin>
+					<plugin>
+						<!-- instrument the copied api classes -->
+						<groupId>org.sonatype.maven.plugin</groupId>
+						<artifactId>emma-maven-plugin</artifactId>
+						<executions>
+							<execution>
+								<id>instrument api classes</id>
+								<phase>process-test-resources</phase>
+								<goals>
+									<goal>instrument</goal>
+								</goals>
+								<configuration>
+									<instrumentationPaths>
+										<param>${project.build.directory}/api_dependency</param>
+									</instrumentationPaths>
+								</configuration>
+							</execution>
+						</executions>
+					</plugin>
+					<plugin>
+						<groupId>org.apache.maven.plugins</groupId>
+						<artifactId>maven-surefire-plugin</artifactId>
+						<configuration>
+							<!-- use the instrumented classes for test execution -->
+							<classesDirectory>${project.build.directory}/generated-classes/emma/classes</classesDirectory>
+						</configuration>
+					</plugin>
+				</plugins>
+			</build>
+		</profile>
+	</profiles>
+
+	<dependencies>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<version>2.5</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.cxf</groupId>
+			<artifactId>cxf-rt-frontend-jaxrs</artifactId>
+			<version>${cxf.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.api</artifactId>
+			<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>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.testutil</artifactId>
+			<version>${project.version}</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
new file mode 100644
index 0000000..131f18c
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/ContentNegotiator.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotAcceptableException;
+import org.apache.olingo.odata2.core.commons.ContentType;
+import org.apache.olingo.odata2.core.commons.ContentType.ODataFormat;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+import org.apache.olingo.odata2.core.uri.UriType;
+
+/**
+ * @author SAP AG
+ */
+public class ContentNegotiator {
+  private static final String URI_INFO_FORMAT_JSON = "json";
+  private static final String URI_INFO_FORMAT_ATOM = "atom";
+  private static final String URI_INFO_FORMAT_XML = "xml";
+  static final String DEFAULT_CHARSET = "utf-8";
+
+  public String doContentNegotiation(final UriInfoImpl uriInfo, final List<String> acceptHeaderContentTypes, final List<String> supportedContentTypes) throws ODataException {
+    ContentType contentType;
+    if (uriInfo.getFormat() == null) {
+      contentType = doContentNegotiationForAcceptHeader(acceptHeaderContentTypes, ContentType.create(supportedContentTypes));
+    } else {
+      contentType = doContentNegotiationForFormat(uriInfo, ContentType.create(supportedContentTypes));
+    }
+
+    if (contentType.getODataFormat() == ODataFormat.CUSTOM) {
+      return contentType.getType();
+    }
+    return contentType.toContentTypeString();
+  }
+
+  private ContentType doContentNegotiationForFormat(final UriInfoImpl uriInfo, final List<ContentType> supportedContentTypes) throws ODataException {
+    validateFormatQuery(uriInfo);
+    ContentType formatContentType = mapFormat(uriInfo);
+    formatContentType = formatContentType.receiveWithCharsetParameter(DEFAULT_CHARSET);
+
+    for (final ContentType contentType : supportedContentTypes) {
+      if (contentType.equals(formatContentType)) {
+        return formatContentType;
+      }
+    }
+
+    throw new ODataNotAcceptableException(ODataNotAcceptableException.NOT_SUPPORTED_CONTENT_TYPE.addContent(uriInfo.getFormat()));
+  }
+
+  /**
+   * Validates that <code>dollar format query/syntax</code> is correct for further processing.
+   * If some validation error occurs an exception is thrown.
+   * 
+   * @param uriInfo
+   * @throws ODataBadRequestException
+   */
+  private void validateFormatQuery(final UriInfoImpl uriInfo) throws ODataBadRequestException {
+    if (uriInfo.isValue()) {
+      throw new ODataBadRequestException(ODataBadRequestException.INVALID_SYNTAX);
+    }
+  }
+
+  private ContentType mapFormat(final UriInfoImpl uriInfo) {
+    final String format = uriInfo.getFormat();
+    if (URI_INFO_FORMAT_XML.equals(format)) {
+      return ContentType.APPLICATION_XML;
+    } else if (URI_INFO_FORMAT_ATOM.equals(format)) {
+      if (uriInfo.getUriType() == UriType.URI0) {
+        // special handling for serviceDocument uris (UriType.URI0)
+        return ContentType.APPLICATION_ATOM_SVC;
+      }
+      return ContentType.APPLICATION_ATOM_XML;
+    } else if (URI_INFO_FORMAT_JSON.equals(format)) {
+      return ContentType.APPLICATION_JSON;
+    }
+
+    return ContentType.create(format);
+  }
+
+  private ContentType doContentNegotiationForAcceptHeader(final List<String> acceptHeaderContentTypes, final List<ContentType> supportedContentTypes) throws ODataException {
+    return contentNegotiation(extractAcceptHeaders(acceptHeaderContentTypes), supportedContentTypes);
+  }
+
+  private List<ContentType> extractAcceptHeaders(final List<String> acceptHeaderValues) throws ODataBadRequestException {
+    final List<ContentType> mediaTypes = new ArrayList<ContentType>();
+    if (acceptHeaderValues != null) {
+      for (final String mediaType : acceptHeaderValues) {
+        try {
+          mediaTypes.add(ContentType.create(mediaType.toString()));
+        } catch (IllegalArgumentException e) {
+          throw new ODataBadRequestException(ODataBadRequestException.INVALID_HEADER.addContent("Accept")
+              .addContent(mediaType.toString()), e);
+        }
+      }
+    }
+
+    return mediaTypes;
+  }
+
+  ContentType contentNegotiation(final List<ContentType> acceptedContentTypes, final List<ContentType> supportedContentTypes) throws ODataException {
+    final Set<ContentType> setSupported = new HashSet<ContentType>(supportedContentTypes);
+
+    if (acceptedContentTypes.isEmpty()) {
+      if (!setSupported.isEmpty()) {
+        return supportedContentTypes.get(0);
+      }
+    } else {
+      for (ContentType contentType : acceptedContentTypes) {
+        contentType = contentType.receiveWithCharsetParameter(DEFAULT_CHARSET);
+        final ContentType match = contentType.match(supportedContentTypes);
+        if (match != null) {
+          return match;
+        }
+      }
+    }
+
+    throw new ODataNotAcceptableException(ODataNotAcceptableException.NOT_SUPPORTED_ACCEPT_HEADER.addContent(acceptedContentTypes.toString()));
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/odata-core/src/main/java/org/apache/olingo/odata2/core/Dispatcher.java
----------------------------------------------------------------------
diff --git a/odata-core/src/main/java/org/apache/olingo/odata2/core/Dispatcher.java b/odata-core/src/main/java/org/apache/olingo/odata2/core/Dispatcher.java
new file mode 100644
index 0000000..e167506
--- /dev/null
+++ b/odata-core/src/main/java/org/apache/olingo/odata2/core/Dispatcher.java
@@ -0,0 +1,304 @@
+/*******************************************************************************
+ * 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;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.ODataService;
+import org.apache.olingo.odata2.api.ODataServiceFactory;
+import org.apache.olingo.odata2.api.batch.BatchHandler;
+import org.apache.olingo.odata2.api.commons.ODataHttpMethod;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMethodNotAllowedException;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.processor.part.BatchProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityComplexPropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinkProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityLinksProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityMediaProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntityProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySetProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyProcessor;
+import org.apache.olingo.odata2.api.processor.part.EntitySimplePropertyValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportProcessor;
+import org.apache.olingo.odata2.api.processor.part.FunctionImportValueProcessor;
+import org.apache.olingo.odata2.api.processor.part.MetadataProcessor;
+import org.apache.olingo.odata2.api.processor.part.ServiceDocumentProcessor;
+import org.apache.olingo.odata2.core.batch.BatchHandlerImpl;
+import org.apache.olingo.odata2.core.exception.ODataRuntimeException;
+import org.apache.olingo.odata2.core.uri.UriInfoImpl;
+
+/**
+ * Request dispatching according to URI type and HTTP method.
+ * @author SAP AG
+ */
+public class Dispatcher {
+
+  private final ODataService service;
+  private final ODataServiceFactory serviceFactory;
+
+  public Dispatcher(final ODataServiceFactory serviceFactory, final ODataService service) {
+    this.service = service;
+    this.serviceFactory = serviceFactory;
+  }
+
+  public ODataResponse dispatch(final ODataHttpMethod method, final UriInfoImpl uriInfo, final InputStream content, final String requestContentType, final String contentType) throws ODataException {
+    switch (uriInfo.getUriType()) {
+    case URI0:
+      if (method == ODataHttpMethod.GET) {
+        return service.getServiceDocumentProcessor().readServiceDocument(uriInfo, contentType);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI1:
+    case URI6B:
+      switch (method) {
+      case GET:
+        return service.getEntitySetProcessor().readEntitySet(uriInfo, contentType);
+      case POST:
+        return service.getEntitySetProcessor().createEntity(uriInfo, content, requestContentType, contentType);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI2:
+      switch (method) {
+      case GET:
+        return service.getEntityProcessor().readEntity(uriInfo, contentType);
+      case PUT:
+        return service.getEntityProcessor().updateEntity(uriInfo, content, requestContentType, false, contentType);
+      case PATCH:
+      case MERGE:
+        return service.getEntityProcessor().updateEntity(uriInfo, content, requestContentType, true, contentType);
+      case DELETE:
+        return service.getEntityProcessor().deleteEntity(uriInfo, contentType);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI3:
+      switch (method) {
+      case GET:
+        return service.getEntityComplexPropertyProcessor().readEntityComplexProperty(uriInfo, contentType);
+      case PUT:
+        return service.getEntityComplexPropertyProcessor().updateEntityComplexProperty(uriInfo, content, requestContentType, false, contentType);
+      case PATCH:
+      case MERGE:
+        return service.getEntityComplexPropertyProcessor().updateEntityComplexProperty(uriInfo, content, requestContentType, true, contentType);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI4:
+    case URI5:
+      switch (method) {
+      case GET:
+        if (uriInfo.isValue()) {
+          return service.getEntitySimplePropertyValueProcessor().readEntitySimplePropertyValue(uriInfo, contentType);
+        } else {
+          return service.getEntitySimplePropertyProcessor().readEntitySimpleProperty(uriInfo, contentType);
+        }
+      case PUT:
+      case PATCH:
+      case MERGE:
+        if (uriInfo.isValue()) {
+          return service.getEntitySimplePropertyValueProcessor().updateEntitySimplePropertyValue(uriInfo, content, requestContentType, contentType);
+        } else {
+          return service.getEntitySimplePropertyProcessor().updateEntitySimpleProperty(uriInfo, content, requestContentType, contentType);
+        }
+      case DELETE:
+        if (uriInfo.isValue()) {
+          return service.getEntitySimplePropertyValueProcessor().deleteEntitySimplePropertyValue(uriInfo, contentType);
+        } else {
+          throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+        }
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI6A:
+      switch (method) {
+      case GET:
+        return service.getEntityProcessor().readEntity(uriInfo, contentType);
+      case PUT:
+      case PATCH:
+      case MERGE:
+      case DELETE:
+        throw new ODataBadRequestException(ODataBadRequestException.NOTSUPPORTED);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI7A:
+      switch (method) {
+      case GET:
+        return service.getEntityLinkProcessor().readEntityLink(uriInfo, contentType);
+      case PUT:
+      case PATCH:
+      case MERGE:
+        return service.getEntityLinkProcessor().updateEntityLink(uriInfo, content, requestContentType, contentType);
+      case DELETE:
+        return service.getEntityLinkProcessor().deleteEntityLink(uriInfo, contentType);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI7B:
+      switch (method) {
+      case GET:
+        return service.getEntityLinksProcessor().readEntityLinks(uriInfo, contentType);
+      case POST:
+        return service.getEntityLinksProcessor().createEntityLink(uriInfo, content, requestContentType, contentType);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI8:
+      if (method == ODataHttpMethod.GET) {
+        return service.getMetadataProcessor().readMetadata(uriInfo, contentType);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI9:
+      if (method == ODataHttpMethod.POST) {
+        BatchHandler handler = new BatchHandlerImpl(serviceFactory, service);
+        return service.getBatchProcessor().executeBatch(handler, requestContentType, content);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI10:
+    case URI11:
+    case URI12:
+    case URI13:
+      return service.getFunctionImportProcessor().executeFunctionImport(uriInfo, contentType);
+
+    case URI14:
+      if (uriInfo.isValue()) {
+        return service.getFunctionImportValueProcessor().executeFunctionImportValue(uriInfo, contentType);
+      } else {
+        return service.getFunctionImportProcessor().executeFunctionImport(uriInfo, contentType);
+      }
+
+    case URI15:
+      if (method == ODataHttpMethod.GET) {
+        return service.getEntitySetProcessor().countEntitySet(uriInfo, contentType);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI16:
+      if (method == ODataHttpMethod.GET) {
+        return service.getEntityProcessor().existsEntity(uriInfo, contentType);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI17:
+      switch (method) {
+      case GET:
+        return service.getEntityMediaProcessor().readEntityMedia(uriInfo, contentType);
+      case PUT:
+        return service.getEntityMediaProcessor().updateEntityMedia(uriInfo, content, requestContentType, contentType);
+      case DELETE:
+        return service.getEntityMediaProcessor().deleteEntityMedia(uriInfo, contentType);
+      default:
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI50A:
+      if (method == ODataHttpMethod.GET) {
+        return service.getEntityLinkProcessor().existsEntityLink(uriInfo, contentType);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    case URI50B:
+      if (method == ODataHttpMethod.GET) {
+        return service.getEntityLinksProcessor().countEntityLinks(uriInfo, contentType);
+      } else {
+        throw new ODataMethodNotAllowedException(ODataMethodNotAllowedException.DISPATCH);
+      }
+
+    default:
+      throw new ODataRuntimeException("Unknown or not implemented URI type: " + uriInfo.getUriType());
+    }
+  }
+
+  protected static Class<? extends ODataProcessor> mapUriTypeToProcessorFeature(final UriInfoImpl uriInfo) {
+    Class<? extends ODataProcessor> feature;
+
+    switch (uriInfo.getUriType()) {
+    case URI0:
+      feature = ServiceDocumentProcessor.class;
+      break;
+    case URI1:
+    case URI6B:
+    case URI15:
+      feature = EntitySetProcessor.class;
+      break;
+    case URI2:
+    case URI6A:
+    case URI16:
+      feature = EntityProcessor.class;
+      break;
+    case URI3:
+      feature = EntityComplexPropertyProcessor.class;
+      break;
+    case URI4:
+    case URI5:
+      feature = uriInfo.isValue() ? EntitySimplePropertyValueProcessor.class : EntitySimplePropertyProcessor.class;
+      break;
+    case URI7A:
+    case URI50A:
+      feature = EntityLinkProcessor.class;
+      break;
+    case URI7B:
+    case URI50B:
+      feature = EntityLinksProcessor.class;
+      break;
+    case URI8:
+      feature = MetadataProcessor.class;
+      break;
+    case URI9:
+      feature = BatchProcessor.class;
+      break;
+    case URI10:
+    case URI11:
+    case URI12:
+    case URI13:
+      feature = FunctionImportProcessor.class;
+      break;
+    case URI14:
+      feature = uriInfo.isValue() ? FunctionImportValueProcessor.class : FunctionImportProcessor.class;
+      break;
+    case URI17:
+      feature = EntityMediaProcessor.class;
+      break;
+    default:
+      throw new ODataRuntimeException("Unknown or not implemented URI type: " + uriInfo.getUriType());
+    }
+
+    return feature;
+  }
+}


[47/51] [partial] initial commit

Posted by fm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-api/src/main/resources/JPAEDMMappingModel.xsd
----------------------------------------------------------------------
diff --git a/jpa-api/src/main/resources/JPAEDMMappingModel.xsd b/jpa-api/src/main/resources/JPAEDMMappingModel.xsd
new file mode 100644
index 0000000..c7f11e4
--- /dev/null
+++ b/jpa-api/src/main/resources/JPAEDMMappingModel.xsd
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema attributeFormDefault="unqualified"
+	elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+	targetNamespace="http://www.sap.com/core/odata/processor/api/jpa/model/mapping"
+	xmlns:tns="http://www.sap.com/core/odata/processor/api/jpa/model/mapping">
+
+	<xs:element name="JPAEDMMappingModel">
+		<xs:annotation>
+			<xs:documentation xml:lang="en">
+				Java Persistence (JPA) -
+				Entity Data Model (EDM) Mapping schema. The schema defines a mapping
+				model to describe EDM names for entity types, entity sets, entity
+				properties, entity navigation properties. By default the names of
+				Java Persistence entity types, entity attributes and entity
+				relationships are transformed into their corresponding EDM names. To
+				override the default names the mapping model is defined. Note:-
+				Define the mapping model for only those default names that needs to
+				be overriden.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element name="PersistenceUnit" type="tns:JPAPersistenceUnitMapType"
+					maxOccurs="1" minOccurs="1" />
+			</xs:sequence>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:complexType name="JPAAttributeMapType">
+		<xs:annotation>
+			<xs:documentation xml:lang="en">
+				The default name for EDM
+				property is derived from JPA attribute name. This can be overriden
+				using
+				JPAAttributeMapType.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:sequence>
+			<xs:element name="JPAAttribute" maxOccurs="unbounded"
+				minOccurs="0">
+				<xs:complexType>
+					<xs:simpleContent>
+						<xs:extension base="xs:string">
+							<xs:attribute type="xs:string" name="name" use="required" />
+							<xs:attribute type="xs:boolean" name="exclude" use="optional"
+								default="false" />
+						</xs:extension>
+					</xs:simpleContent>
+				</xs:complexType>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+
+	<xs:complexType name="JPARelationshipMapType">
+		<xs:annotation>
+			<xs:documentation xml:lang="en">
+				The default name for EDM
+				navigation property is derived from JPA relationship name.
+				This can
+				be overriden using JPARelationshipMapType.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:sequence>
+			<xs:element name="JPARelationship" maxOccurs="unbounded"
+				minOccurs="0">
+				<xs:complexType>
+					<xs:simpleContent>
+						<xs:extension base="xs:string">
+							<xs:attribute type="xs:string" name="name" use="required" />
+						</xs:extension>
+					</xs:simpleContent>
+				</xs:complexType>
+			</xs:element>
+		</xs:sequence>
+	</xs:complexType>
+
+	<xs:complexType name="JPAEntityTypeMapType">
+		<xs:annotation>
+			<xs:documentation xml:lang="en">
+				The default name for EDM
+				entity type is derived from JPA entity type name. This can be
+				overriden using JPAEntityTypeMapType.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:sequence>
+			<xs:element type="xs:string" name="EDMEntityType"
+				maxOccurs="1" minOccurs="0" />
+			<xs:element type="xs:string" name="EDMEntitySet"
+				maxOccurs="1" minOccurs="0" />
+			<xs:element name="JPAAttributes" type="tns:JPAAttributeMapType" />
+			<xs:element name="JPARelationships" type="tns:JPARelationshipMapType" />
+		</xs:sequence>
+		<xs:attribute type="xs:string" name="name" use="required" />
+		<xs:attribute type="xs:boolean" name="exclude" use="optional"
+			default="false" />
+	</xs:complexType>
+
+	<xs:complexType name="JPAEntityTypesMapType">
+		<xs:sequence>
+			<xs:element name="JPAEntityType" type="tns:JPAEntityTypeMapType"
+				maxOccurs="unbounded" minOccurs="0" />
+		</xs:sequence>
+	</xs:complexType>
+	<xs:complexType name="JPAEmbeddableTypeMapType">
+		<xs:annotation>
+			<xs:documentation xml:lang="en">
+				The default name for EDM
+				complex type is derived from JPA Embeddable type name. This can be
+				overriden using JPAEmbeddableTypeMapType.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:sequence>
+			<xs:element type="xs:string" name="EDMComplexType"
+				maxOccurs="1" minOccurs="0" />
+			<xs:element name="JPAAttributes" type="tns:JPAAttributeMapType" />
+		</xs:sequence>
+		<xs:attribute type="xs:string" name="name" use="required" />
+		<xs:attribute type="xs:boolean" name="exclude" use="optional"
+			default="false" />
+	</xs:complexType>
+
+	<xs:complexType name="JPAEmbeddableTypesMapType">
+		<xs:sequence>
+			<xs:element name="JPAEmbeddableType" type="tns:JPAEmbeddableTypeMapType"
+				maxOccurs="unbounded" minOccurs="0" />
+		</xs:sequence>
+	</xs:complexType>
+
+	<xs:complexType name="JPAPersistenceUnitMapType">
+		<xs:annotation>
+			<xs:documentation xml:lang="en">
+				By default Java
+				Persistence Unit name is taken as EDM schema name. This can be
+				overriden using JPAPersistenceUnitMapType.
+			</xs:documentation>
+		</xs:annotation>
+		<xs:sequence>
+			<xs:element type="xs:string" name="EDMSchemaNamespace"
+				maxOccurs="1" minOccurs="0" />
+			<xs:element name="JPAEntityTypes" type="tns:JPAEntityTypesMapType" />
+			<xs:element name="JPAEmbeddableTypes" type="tns:JPAEmbeddableTypesMapType" />
+		</xs:sequence>
+		<xs:attribute type="xs:string" name="name" use="required" />
+	</xs:complexType>
+
+
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/.gitignore
----------------------------------------------------------------------
diff --git a/jpa-core/.gitignore b/jpa-core/.gitignore
new file mode 100644
index 0000000..fe5d89b
--- /dev/null
+++ b/jpa-core/.gitignore
@@ -0,0 +1,8 @@
+.project
+.classpath
+.settings
+target
+bin
+*.bak
+classes
+.DS_Store
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/pom.xml
----------------------------------------------------------------------
diff --git a/jpa-core/pom.xml b/jpa-core/pom.xml
new file mode 100644
index 0000000..41243a0
--- /dev/null
+++ b/jpa-core/pom.xml
@@ -0,0 +1,104 @@
+<?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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<groupId>org.apache.olingo</groupId>
+		<artifactId>org.apache.olingo.odata2.parent</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+		<relativePath>../</relativePath>
+	</parent>
+
+	<artifactId>org.apache.olingo.odata2.processor.core</artifactId>
+	<packaging>jar</packaging>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.api.annotation</artifactId>
+			<version>${project.version}</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- ########################## -->
+		<!-- Java Persistence API -->
+		<!-- ########################## -->
+		<dependency>
+			<groupId>org.eclipse.persistence</groupId>
+			<artifactId>javax.persistence</artifactId>
+			<version>${version.javax.persistence}</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- ########################## -->
+		<!-- OData Java Library Support -->
+		<!-- ########################## -->
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.api</artifactId>
+			<version>${project.version}</version>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.core</artifactId>
+			<version>${project.version}</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- ########################## -->
+		<!-- OData Java JPA API -->
+		<!-- ########################## -->
+		<dependency>
+			<groupId>org.apache.olingo</groupId>
+			<artifactId>org.apache.olingo.odata2.processor.api</artifactId>
+			<version>${project.version}</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<!-- ########################## -->
+		<!-- For Testing -->
+		<!-- ########################## -->
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<version>4.9</version>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.easymock</groupId>
+			<artifactId>easymock</artifactId>
+			<version>3.1</version>
+		</dependency>
+
+		<!-- ########################## -->
+		<!-- Supportability Tools -->
+		<!-- ########################## -->
+		<dependency>
+			<groupId>org.slf4j</groupId>
+			<artifactId>slf4j-api</artifactId>
+			<version>1.7.2</version>
+			<scope>test</scope>
+		</dependency>
+	</dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/META-INF/MANIFEST.MF
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/META-INF/MANIFEST.MF b/jpa-core/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..5e94951
--- /dev/null
+++ b/jpa-core/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path: 
+

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataEntityParser.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataEntityParser.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataEntityParser.java
new file mode 100644
index 0000000..500f29f
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataEntityParser.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+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.entry.ODataEntry;
+import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.uri.PathSegment;
+import org.apache.olingo.odata2.api.uri.UriInfo;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+public final class ODataEntityParser {
+
+  private ODataJPAContext context;
+
+  public ODataEntityParser(final ODataJPAContext context) {
+    this.context = context;
+  }
+
+  public final ODataEntry parseEntry(final EdmEntitySet entitySet,
+      final InputStream content, final String requestContentType, final boolean merge)
+      throws ODataBadRequestException {
+    return null;
+
+  }
+
+  public final UriInfo parseLinkURI() throws ODataJPARuntimeException {
+    UriInfo uriInfo = null;
+
+    Edm edm;
+    try {
+      edm = context.getODataContext().getService().getEntityDataModel();
+
+      List<PathSegment> pathSegments = context.getODataContext().getPathInfo().getODataSegments();
+      List<PathSegment> subPathSegments = pathSegments.subList(0, pathSegments.size() - 2);
+
+      uriInfo = UriParser.parse(edm, subPathSegments, Collections.<String, String> emptyMap());
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return uriInfo;
+  }
+
+  public final UriInfo parseLink(final EdmEntitySet entitySet, final InputStream content, final String contentType)
+      throws ODataJPARuntimeException {
+
+    String uriString = null;
+    UriInfo uri = null;
+
+    try {
+      uriString = EntityProvider.readLink(contentType, entitySet, content);
+      ODataContext odataContext = context.getODataContext();
+      final String serviceRoot = odataContext.getPathInfo().getServiceRoot().toString();
+
+      final String path = uriString.startsWith(serviceRoot.toString()) ?
+          uriString.substring(serviceRoot.length()) : uriString;
+
+      final PathSegment pathSegment = new PathSegment() {
+        @Override
+        public String getPath() {
+          return path;
+        }
+
+        @Override
+        public Map<String, List<String>> getMatrixParameters() {
+          return null;
+        }
+      };
+
+      final Edm edm = odataContext.getService().getEntityDataModel();
+
+      uri = UriParser.parse(edm, Arrays.asList(pathSegment), Collections.<String, String> emptyMap());
+
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return uri;
+
+  }
+
+  public List<UriInfo> parseLinks(final EdmEntitySet entitySet, final InputStream content, final String contentType)
+      throws ODataJPARuntimeException {
+
+    List<String> uriList = new ArrayList<String>();
+    List<UriInfo> uriInfoList = new ArrayList<UriInfo>();
+
+    try {
+
+      uriList = EntityProvider.readLinks(contentType, entitySet, content);
+      ODataContext odataContext = context.getODataContext();
+      final String serviceRoot = odataContext.getPathInfo().getServiceRoot().toString();
+      final int length = serviceRoot.length();
+      final Edm edm = odataContext.getService().getEntityDataModel();
+
+      for (String uriString : uriList) {
+        final String path = uriString.startsWith(serviceRoot) ?
+            uriString.substring(length) : uriString;
+
+        final PathSegment pathSegment = new PathSegment() {
+          @Override
+          public String getPath() {
+            return path;
+          }
+
+          @Override
+          public Map<String, List<String>> getMatrixParameters() {
+            return null;
+          }
+        };
+
+        UriInfo uriInfo = UriParser.parse(edm, Arrays.asList(pathSegment), Collections.<String, String> emptyMap());
+        uriInfoList.add(uriInfo);
+      }
+    } catch (EntityProviderException e) {
+      return null;
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return uriInfoList;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataExpressionParser.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataExpressionParser.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataExpressionParser.java
new file mode 100644
index 0000000..2233b5e
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataExpressionParser.java
@@ -0,0 +1,364 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataNotImplementedException;
+import org.apache.olingo.odata2.api.uri.KeyPredicate;
+import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
+import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
+import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
+import org.apache.olingo.odata2.api.uri.expression.MemberExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
+import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.api.uri.expression.OrderExpression;
+import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
+import org.apache.olingo.odata2.api.uri.expression.SortOrder;
+import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.jpql.JPQLStatement;
+
+/**
+ * This class contains utility methods for parsing the filter expressions built by core library from user OData Query.
+ * 
+ * @author SAP AG
+ *
+ */
+public class ODataExpressionParser {
+
+  public static final String EMPTY = ""; //$NON-NLS-1$
+  public static Integer methodFlag = 0;
+
+  /**
+   * This method returns the parsed where condition corresponding to the filter input in the user query.
+   * 
+   * @param whereExpression
+   * 
+   * @return Parsed where condition String
+   * @throws ODataException
+   */
+
+  public static String parseToJPAWhereExpression(final CommonExpression whereExpression, final String tableAlias) throws ODataException {
+    switch (whereExpression.getKind()) {
+    case UNARY:
+      final UnaryExpression unaryExpression = (UnaryExpression) whereExpression;
+      final String operand = parseToJPAWhereExpression(unaryExpression.getOperand(), tableAlias);
+
+      switch (unaryExpression.getOperator()) {
+      case NOT:
+        return JPQLStatement.Operator.NOT + "(" + operand + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+      case MINUS:
+        if (operand.startsWith("-")) {
+          return operand.substring(1);
+        }
+        else {
+          return "-" + operand; //$NON-NLS-1$
+        }
+      default:
+        throw new ODataNotImplementedException();
+      }
+
+    case FILTER:
+      return parseToJPAWhereExpression(((FilterExpression) whereExpression).getExpression(), tableAlias);
+    case BINARY:
+      final BinaryExpression binaryExpression = (BinaryExpression) whereExpression;
+      if ((binaryExpression.getLeftOperand().getKind() == ExpressionKind.METHOD) && ((binaryExpression.getOperator() == BinaryOperator.EQ) || (binaryExpression.getOperator() == BinaryOperator.NE)) && (((MethodExpression) binaryExpression.getLeftOperand()).getMethod() == MethodOperator.SUBSTRINGOF)) {
+        methodFlag = 1;
+      }
+      final String left = parseToJPAWhereExpression(binaryExpression.getLeftOperand(), tableAlias);
+      final String right = parseToJPAWhereExpression(binaryExpression.getRightOperand(), tableAlias);
+
+      switch (binaryExpression.getOperator()) {
+      case AND:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.AND + JPQLStatement.DELIMITER.SPACE + right;
+      case OR:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.OR + JPQLStatement.DELIMITER.SPACE + right;
+      case EQ:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.EQ + JPQLStatement.DELIMITER.SPACE + right;
+      case NE:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.NE + JPQLStatement.DELIMITER.SPACE + right;
+      case LT:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.LT + JPQLStatement.DELIMITER.SPACE + right;
+      case LE:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.LE + JPQLStatement.DELIMITER.SPACE + right;
+      case GT:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.GT + JPQLStatement.DELIMITER.SPACE + right;
+      case GE:
+        return left + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.GE + JPQLStatement.DELIMITER.SPACE + right;
+      case PROPERTY_ACCESS:
+        throw new ODataNotImplementedException();
+      default:
+        throw new ODataNotImplementedException();
+      }
+
+    case PROPERTY:
+      String returnStr = tableAlias + JPQLStatement.DELIMITER.PERIOD + ((EdmProperty) ((PropertyExpression) whereExpression).getEdmProperty()).getMapping().getInternalName();
+      return returnStr;
+
+    case MEMBER:
+      String memberExpStr = EMPTY;
+      int i = 0;
+      MemberExpression member = null;
+      CommonExpression tempExp = whereExpression;
+      while (tempExp != null && tempExp.getKind() == ExpressionKind.MEMBER) {
+        member = (MemberExpression) tempExp;
+        if (i > 0) {
+          memberExpStr = JPQLStatement.DELIMITER.PERIOD + memberExpStr;
+        }
+        i++;
+        memberExpStr = ((EdmProperty) ((PropertyExpression) member.getProperty()).getEdmProperty()).getMapping().getInternalName() + memberExpStr;
+        tempExp = member.getPath();
+      }
+      memberExpStr = ((EdmProperty) ((PropertyExpression) tempExp).getEdmProperty()).getMapping().getInternalName() + JPQLStatement.DELIMITER.PERIOD + memberExpStr;
+      return tableAlias + JPQLStatement.DELIMITER.PERIOD + memberExpStr;
+
+    case LITERAL:
+      final LiteralExpression literal = (LiteralExpression) whereExpression;
+      final EdmSimpleType literalType = (EdmSimpleType) literal.getEdmType();
+      String value = literalType.valueToString(literalType.valueOfString(literal.getUriLiteral(), EdmLiteralKind.URI, null, literalType.getDefaultType()), EdmLiteralKind.DEFAULT, null);
+      return evaluateComparingExpression(value, literalType);
+
+    case METHOD:
+      final MethodExpression methodExpression = (MethodExpression) whereExpression;
+      String first = parseToJPAWhereExpression(methodExpression.getParameters().get(0), tableAlias);
+      final String second = methodExpression.getParameterCount() > 1 ?
+          parseToJPAWhereExpression(methodExpression.getParameters().get(1), tableAlias) : null;
+      String third = methodExpression.getParameterCount() > 2 ?
+          parseToJPAWhereExpression(methodExpression.getParameters().get(2), tableAlias) : null;
+
+      switch (methodExpression.getMethod()) {
+      case SUBSTRING:
+        third = third != null ? ", " + third : "";
+        return String.format("SUBSTRING(%s, %s + 1 %s)", first, second, third);
+      case SUBSTRINGOF:
+        first = first.substring(1, first.length() - 1);
+        if (methodFlag == 1) {
+          methodFlag = 0;
+          return String.format("(CASE WHEN %s LIKE '%%%s%%' THEN TRUE ELSE FALSE END)", second, first);
+        }
+        else {
+          return String.format("(CASE WHEN %s LIKE '%%%s%%' THEN TRUE ELSE FALSE END) = true", second, first);
+        }
+      case TOLOWER:
+        return String.format("LOWER(%s)", first);
+      default:
+        throw new ODataNotImplementedException();
+      }
+
+    default:
+      throw new ODataNotImplementedException();
+    }
+  }
+
+  /**
+   * This method parses the select clause
+   * 
+   * @param tableAlias
+   * @param selectedFields
+   * @return
+   */
+  public static String parseToJPASelectExpression(final String tableAlias, final ArrayList<String> selectedFields) {
+
+    if ((selectedFields == null) || (selectedFields.size() == 0)) {
+      return tableAlias;
+    }
+
+    String selectClause = EMPTY;
+    Iterator<String> itr = selectedFields.iterator();
+    int count = 0;
+
+    while (itr.hasNext()) {
+      selectClause = selectClause + tableAlias + JPQLStatement.DELIMITER.PERIOD + itr.next();
+      count++;
+
+      if (count < selectedFields.size()) {
+        selectClause = selectClause + JPQLStatement.DELIMITER.COMMA + JPQLStatement.DELIMITER.SPACE;
+      }
+    }
+    return selectClause;
+  }
+
+  /**
+   * This method parses the order by condition in the query.
+   * 
+   * @param orderByExpression
+   * @return
+   * @throws ODataJPARuntimeException
+   */
+  public static HashMap<String, String> parseToJPAOrderByExpression(final OrderByExpression orderByExpression, final String tableAlias) throws ODataJPARuntimeException {
+    HashMap<String, String> orderByMap = new HashMap<String, String>();
+    if (orderByExpression != null && orderByExpression.getOrders() != null) {
+      List<OrderExpression> orderBys = orderByExpression.getOrders();
+      String orderByField = null;
+      String orderByDirection = null;
+      for (OrderExpression orderBy : orderBys) {
+
+        try {
+          orderByField = ((EdmProperty) ((PropertyExpression) orderBy.getExpression()).getEdmProperty()).getMapping().getInternalName();
+          orderByDirection = (orderBy.getSortOrder() == SortOrder.asc) ? EMPTY : "DESC"; //$NON-NLS-1$
+          orderByMap.put(tableAlias + JPQLStatement.DELIMITER.PERIOD + orderByField, orderByDirection);
+        } catch (EdmException e) {
+          throw ODataJPARuntimeException.throwException(
+              ODataJPARuntimeException.GENERAL.addContent(e
+                  .getMessage()), e);
+        }
+      }
+    }
+    return orderByMap;
+  }
+
+  /**
+   * This method evaluated the where expression for read of an entity based on the keys specified in the query.
+   * 
+   * @param keyPredicates
+   * @return the evaluated where expression
+   */
+
+  public static String parseKeyPredicates(final List<KeyPredicate> keyPredicates, final String tableAlias) throws ODataJPARuntimeException {
+    String literal = null;
+    String propertyName = null;
+    EdmSimpleType edmSimpleType = null;
+    StringBuilder keyFilters = new StringBuilder();
+    int i = 0;
+    for (KeyPredicate keyPredicate : keyPredicates) {
+      if (i > 0) {
+        keyFilters.append(JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.AND + JPQLStatement.DELIMITER.SPACE);
+      }
+      i++;
+      literal = keyPredicate.getLiteral();
+      try {
+        propertyName = keyPredicate.getProperty().getMapping().getInternalName();
+        edmSimpleType = (EdmSimpleType) keyPredicate.getProperty().getType();
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      }
+
+      literal = evaluateComparingExpression(literal, edmSimpleType);
+
+      if (edmSimpleType == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
+          || edmSimpleType == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()) {
+        literal = literal.substring(literal.indexOf('\''), literal.indexOf('}'));
+      }
+
+      keyFilters.append(tableAlias + JPQLStatement.DELIMITER.PERIOD + propertyName + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.EQ + JPQLStatement.DELIMITER.SPACE + literal);
+    }
+    if (keyFilters.length() > 0) {
+      return keyFilters.toString();
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * This method evaluates the expression based on the type instance. Used for adding escape characters where necessary.
+   * 
+   * @param value
+   * @param edmSimpleType
+   * @return the evaluated expression
+   * @throws ODataJPARuntimeException 
+   */
+  private static String evaluateComparingExpression(String value, final EdmSimpleType edmSimpleType) throws ODataJPARuntimeException {
+
+    if (edmSimpleType == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()
+        || edmSimpleType == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance())
+    {
+      value = "\'" + value + "\'"; //$NON-NLS-1$	//$NON-NLS-2$
+    } else if (edmSimpleType == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
+        || edmSimpleType == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance())
+    {
+      try {
+        Calendar datetime = (Calendar) edmSimpleType.valueOfString(value, EdmLiteralKind.DEFAULT, null, edmSimpleType.getDefaultType());
+
+        String year = String.format("%04d", datetime.get(Calendar.YEAR));
+        String month = String.format("%02d", datetime.get(Calendar.MONTH) + 1);
+        String day = String.format("%02d", datetime.get(Calendar.DAY_OF_MONTH));
+        String hour = String.format("%02d", datetime.get(Calendar.HOUR_OF_DAY));
+        String min = String.format("%02d", datetime.get(Calendar.MINUTE));
+        String sec = String.format("%02d", datetime.get(Calendar.SECOND));
+
+        value = JPQLStatement.DELIMITER.LEFT_BRACE + JPQLStatement.KEYWORD.TIMESTAMP + JPQLStatement.DELIMITER.SPACE + "\'" + year + JPQLStatement.DELIMITER.HYPHEN + month + JPQLStatement.DELIMITER.HYPHEN + day + JPQLStatement.DELIMITER.SPACE + hour + JPQLStatement.DELIMITER.COLON + min + JPQLStatement.DELIMITER.COLON + sec + JPQLStatement.KEYWORD.OFFSET + "\'" + JPQLStatement.DELIMITER.RIGHT_BRACE;
+
+      } catch (EdmSimpleTypeException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      }
+
+    } else if (edmSimpleType == EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance()) {
+      try {
+        Calendar time = (Calendar) edmSimpleType.valueOfString(value, EdmLiteralKind.DEFAULT, null, edmSimpleType.getDefaultType());
+
+        String hourValue = String.format("%02d", time.get(Calendar.HOUR_OF_DAY));
+        String minValue = String.format("%02d", time.get(Calendar.MINUTE));
+        String secValue = String.format("%02d", time.get(Calendar.SECOND));
+
+        value = "\'" + hourValue + JPQLStatement.DELIMITER.COLON + minValue + JPQLStatement.DELIMITER.COLON + secValue + "\'";
+      } catch (EdmSimpleTypeException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      }
+
+    } else if (edmSimpleType == EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance()) {
+      value = value + JPQLStatement.DELIMITER.LONG; //$NON-NLS-1$
+    }
+    return value;
+  }
+
+  public static HashMap<String, String> parseKeyPropertiesToJPAOrderByExpression(final List<EdmProperty> edmPropertylist, final String tableAlias) throws ODataJPARuntimeException {
+    HashMap<String, String> orderByMap = new HashMap<String, String>();
+    String propertyName = null;
+    for (EdmProperty edmProperty : edmPropertylist) {
+      try {
+        EdmMapping mapping = edmProperty.getMapping();
+        if (mapping != null && mapping.getInternalName() != null) {
+          propertyName = mapping.getInternalName();// For embedded/complex keys
+        } else {
+          propertyName = edmProperty.getName();
+        }
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      }
+      orderByMap.put(tableAlias + JPQLStatement.DELIMITER.PERIOD + propertyName, EMPTY);
+    }
+    return orderByMap;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImpl.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImpl.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImpl.java
new file mode 100644
index 0000000..e7ad2f9
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAContextImpl.java
@@ -0,0 +1,135 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.olingo.odata2.api.edm.provider.EdmProvider;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmExtension;
+
+public class ODataJPAContextImpl implements ODataJPAContext {
+
+  private String pUnitName;
+  private EntityManagerFactory emf;
+  private EntityManager em;
+  private ODataContext odataContext;
+  private ODataProcessor processor;
+  private EdmProvider edmProvider;
+  private String jpaEdmMappingModelName;
+  private JPAEdmExtension jpaEdmExtension;
+  private static final ThreadLocal<ODataContext> oDataContextThreadLocal = new ThreadLocal<ODataContext>();
+
+  @Override
+  public String getPersistenceUnitName() {
+    return pUnitName;
+  }
+
+  @Override
+  public void setPersistenceUnitName(final String pUnitName) {
+    this.pUnitName = pUnitName;
+  }
+
+  @Override
+  public EntityManagerFactory getEntityManagerFactory() {
+    return emf;
+  }
+
+  @Override
+  public void setEntityManagerFactory(final EntityManagerFactory emf) {
+    this.emf = emf;
+  }
+
+  @Override
+  public void setODataContext(final ODataContext ctx) {
+    odataContext = ctx;
+    setContextInThreadLocal(odataContext);
+  }
+
+  @Override
+  public ODataContext getODataContext() {
+    return odataContext;
+  }
+
+  @Override
+  public void setODataProcessor(final ODataProcessor processor) {
+    this.processor = processor;
+  }
+
+  @Override
+  public ODataProcessor getODataProcessor() {
+    return processor;
+  }
+
+  @Override
+  public void setEdmProvider(final EdmProvider edmProvider) {
+    this.edmProvider = edmProvider;
+  }
+
+  @Override
+  public EdmProvider getEdmProvider() {
+    return edmProvider;
+  }
+
+  @Override
+  public void setJPAEdmMappingModel(final String name) {
+    jpaEdmMappingModelName = name;
+
+  }
+
+  @Override
+  public String getJPAEdmMappingModel() {
+    return jpaEdmMappingModelName;
+  }
+
+  public static void setContextInThreadLocal(final ODataContext ctx) {
+    oDataContextThreadLocal.set(ctx);
+  }
+
+  public static void unsetContextInThreadLocal() {
+    oDataContextThreadLocal.remove();
+  }
+
+  public static ODataContext getContextInThreadLocal() {
+    return (ODataContext) oDataContextThreadLocal.get();
+  }
+
+  @Override
+  public EntityManager getEntityManager() {
+    if (em == null) {
+      em = emf.createEntityManager();
+    }
+
+    return em;
+  }
+
+  @Override
+  public void setJPAEdmExtension(final JPAEdmExtension jpaEdmExtension) {
+    this.jpaEdmExtension = jpaEdmExtension;
+
+  }
+
+  @Override
+  public JPAEdmExtension getJPAEdmExtension() {
+    return jpaEdmExtension;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefault.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefault.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefault.java
new file mode 100644
index 0000000..f190411
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAProcessorDefault.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import java.io.InputStream;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAProcessor;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAException;
+
+public class ODataJPAProcessorDefault extends ODataJPAProcessor {
+
+  public ODataJPAProcessorDefault(final ODataJPAContext oDataJPAContext) {
+    super(oDataJPAContext);
+    if (oDataJPAContext == null) {
+      throw new IllegalArgumentException(
+          ODataJPAException.ODATA_JPACTX_NULL);
+    }
+  }
+
+  @Override
+  public ODataResponse readEntitySet(final GetEntitySetUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    List<?> jpaEntities = jpaProcessor.process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(
+        jpaEntities, uriParserResultView, contentType, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse readEntity(final GetEntityUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    Object jpaEntity = jpaProcessor.process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(jpaEntity,
+        uriParserResultView, contentType, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse countEntitySet(final GetEntitySetCountUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    long jpaEntityCount = jpaProcessor.process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(
+        jpaEntityCount, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse existsEntity(final GetEntityCountUriInfo uriInfo,
+      final String contentType) throws ODataException {
+
+    long jpaEntityCount = jpaProcessor.process(uriInfo);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(
+        jpaEntityCount, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse createEntity(final PostUriInfo uriParserResultView, final InputStream content,
+      final String requestContentType, final String contentType)
+      throws ODataException {
+
+    List<Object> createdJpaEntityList = jpaProcessor.process(uriParserResultView, content,
+        requestContentType);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(createdJpaEntityList,
+        uriParserResultView, contentType, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse updateEntity(final PutMergePatchUriInfo uriParserResultView,
+      final InputStream content, final String requestContentType, final boolean merge,
+      final String contentType) throws ODataException {
+
+    Object jpaEntity = jpaProcessor.process(uriParserResultView, content,
+        requestContentType);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(jpaEntity,
+        uriParserResultView);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse deleteEntity(final DeleteUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    Object deletedObj = jpaProcessor.process(uriParserResultView,
+        contentType);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(deletedObj,
+        uriParserResultView);
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse executeFunctionImport(
+      final GetFunctionImportUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    List<Object> resultEntity = jpaProcessor
+        .process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(
+        resultEntity, uriParserResultView, contentType,
+        oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse executeFunctionImportValue(
+      final GetFunctionImportUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    List<Object> result = jpaProcessor.process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(result,
+        uriParserResultView, contentType, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse readEntityLink(
+      final GetEntityLinkUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    Object jpaEntity = jpaProcessor.process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(jpaEntity,
+        uriParserResultView, contentType, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse readEntityLinks(
+      final GetEntitySetLinksUriInfo uriParserResultView,
+      final String contentType) throws ODataException {
+
+    List<Object> jpaEntity = jpaProcessor.process(uriParserResultView);
+
+    ODataResponse oDataResponse = ODataJPAResponseBuilder.build(jpaEntity,
+        uriParserResultView, contentType, oDataJPAContext);
+
+    return oDataResponse;
+  }
+
+  @Override
+  public ODataResponse createEntityLink(
+      final PostUriInfo uriParserResultView, final InputStream content,
+      final String requestContentType, final String contentType) throws ODataException {
+
+    jpaProcessor.process(uriParserResultView, content, requestContentType, contentType);
+
+    return ODataResponse.newBuilder().build();
+  }
+
+  @Override
+  public ODataResponse updateEntityLink(final PutMergePatchUriInfo uriParserResultView,
+      final InputStream content, final String requestContentType, final String contentType)
+      throws ODataException {
+
+    jpaProcessor.process(uriParserResultView, content, requestContentType, contentType);
+
+    return ODataResponse.newBuilder().build();
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/ff2b0a0e/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java
----------------------------------------------------------------------
diff --git a/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java
new file mode 100644
index 0000000..78e2e7d
--- /dev/null
+++ b/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java
@@ -0,0 +1,721 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
+import org.apache.olingo.odata2.api.commons.InlineCount;
+import org.apache.olingo.odata2.api.edm.EdmEntitySet;
+import org.apache.olingo.odata2.api.edm.EdmEntityType;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
+import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties.ODataEntityProviderPropertiesBuilder;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataHttpException;
+import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
+import org.apache.olingo.odata2.api.processor.ODataContext;
+import org.apache.olingo.odata2.api.processor.ODataResponse;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.api.uri.SelectItem;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
+import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntityParser;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAExpandCallBack;
+
+public final class ODataJPAResponseBuilder {
+
+  /* Response for Read Entity Set */
+  public static <T> ODataResponse build(final List<T> jpaEntities,
+      final GetEntitySetUriInfo resultsView, final String contentType,
+      final ODataJPAContext odataJPAContext) throws ODataJPARuntimeException {
+
+    EdmEntityType edmEntityType = null;
+    ODataResponse odataResponse = null;
+    List<ArrayList<NavigationPropertySegment>> expandList = null;
+
+    try {
+      edmEntityType = resultsView.getTargetEntitySet().getEntityType();
+      List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
+      Map<String, Object> edmPropertyValueMap = null;
+      JPAEntityParser jpaResultParser = JPAEntityParser.create();
+      final List<SelectItem> selectedItems = resultsView.getSelect();
+      if (selectedItems != null && selectedItems.size() > 0) {
+        for (Object jpaEntity : jpaEntities) {
+          edmPropertyValueMap = jpaResultParser
+              .parse2EdmPropertyValueMap(
+                  jpaEntity,
+                  buildSelectItemList(selectedItems,
+                      edmEntityType));
+          edmEntityList.add(edmPropertyValueMap);
+        }
+      } else {
+        for (Object jpaEntity : jpaEntities) {
+          edmPropertyValueMap = jpaResultParser
+              .parse2EdmPropertyValueMap(jpaEntity, edmEntityType);
+          edmEntityList.add(edmPropertyValueMap);
+        }
+      }
+      expandList = resultsView.getExpand();
+      if (expandList != null && expandList.size() != 0) {
+        int count = 0;
+        for (Object jpaEntity : jpaEntities) {
+          Map<String, Object> relationShipMap = edmEntityList.get(count);
+          HashMap<String, Object> navigationMap = jpaResultParser.parse2EdmNavigationValueMap(
+              jpaEntity, constructListofNavProperty(expandList));
+          relationShipMap.putAll(navigationMap);
+          count++;
+        }
+      }
+
+      EntityProviderWriteProperties feedProperties = null;
+
+      feedProperties = getEntityProviderProperties(odataJPAContext,
+          resultsView, edmEntityList);
+      odataResponse = EntityProvider.writeFeed(contentType,
+          resultsView.getTargetEntitySet(), edmEntityList,
+          feedProperties);
+      odataResponse = ODataResponse.fromResponse(odataResponse)
+          .status(HttpStatusCodes.OK).build();
+
+    } catch (EntityProviderException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return odataResponse;
+  }
+
+  /* Response for Read Entity */
+  public static ODataResponse build(final Object jpaEntity,
+      final GetEntityUriInfo resultsView, final String contentType,
+      final ODataJPAContext oDataJPAContext) throws ODataJPARuntimeException,
+      ODataNotFoundException {
+
+    List<ArrayList<NavigationPropertySegment>> expandList = null;
+    if (jpaEntity == null) {
+      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+    }
+    EdmEntityType edmEntityType = null;
+    ODataResponse odataResponse = null;
+
+    try {
+
+      edmEntityType = resultsView.getTargetEntitySet().getEntityType();
+      Map<String, Object> edmPropertyValueMap = null;
+
+      JPAEntityParser jpaResultParser = JPAEntityParser.create();
+      final List<SelectItem> selectedItems = resultsView.getSelect();
+      if (selectedItems != null && selectedItems.size() > 0) {
+        edmPropertyValueMap = jpaResultParser
+            .parse2EdmPropertyValueMap(
+                jpaEntity,
+                buildSelectItemList(selectedItems, resultsView
+                    .getTargetEntitySet().getEntityType()));
+      } else {
+        edmPropertyValueMap = jpaResultParser
+            .parse2EdmPropertyValueMap(jpaEntity, edmEntityType);
+      }
+
+      expandList = resultsView.getExpand();
+      if (expandList != null && expandList.size() != 0)
+      {
+        HashMap<String, Object> navigationMap = jpaResultParser.parse2EdmNavigationValueMap(
+            jpaEntity, constructListofNavProperty(expandList));
+        edmPropertyValueMap.putAll(navigationMap);
+      }
+      EntityProviderWriteProperties feedProperties = null;
+      feedProperties = getEntityProviderProperties(oDataJPAContext,
+          resultsView);
+      odataResponse = EntityProvider.writeEntry(contentType,
+          resultsView.getTargetEntitySet(), edmPropertyValueMap,
+          feedProperties);
+
+      odataResponse = ODataResponse.fromResponse(odataResponse)
+          .status(HttpStatusCodes.OK).build();
+
+    } catch (EntityProviderException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return odataResponse;
+  }
+
+  /* Response for $count */
+  public static ODataResponse build(final long jpaEntityCount,
+      final ODataJPAContext oDataJPAContext) throws ODataJPARuntimeException {
+
+    ODataResponse odataResponse = null;
+    try {
+      odataResponse = EntityProvider.writeText(String
+          .valueOf(jpaEntityCount));
+      odataResponse = ODataResponse.fromResponse(odataResponse).build();
+    } catch (EntityProviderException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    return odataResponse;
+  }
+
+  /* Response for Create Entity */
+  @SuppressWarnings("unchecked")
+  public static ODataResponse build(final List<Object> createdObjectList,
+      final PostUriInfo uriInfo, final String contentType,
+      final ODataJPAContext oDataJPAContext) throws ODataJPARuntimeException,
+      ODataNotFoundException {
+
+    if (createdObjectList == null || createdObjectList.size() == 0 || createdObjectList.get(0) == null) {
+      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+    }
+
+    EdmEntityType edmEntityType = null;
+    ODataResponse odataResponse = null;
+
+    try {
+
+      edmEntityType = uriInfo.getTargetEntitySet().getEntityType();
+      Map<String, Object> edmPropertyValueMap = null;
+
+      JPAEntityParser jpaResultParser = JPAEntityParser.create();
+      edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(
+          createdObjectList.get(0), edmEntityType);
+
+      List<ArrayList<NavigationPropertySegment>> expandList = null;
+      if (createdObjectList.get(1) != null && ((Map<EdmNavigationProperty, EdmEntitySet>) createdObjectList.get(1)).size() > 0) {
+        expandList = getExpandList((Map<EdmNavigationProperty, EdmEntitySet>) createdObjectList.get(1));
+        HashMap<String, Object> navigationMap = jpaResultParser.parse2EdmNavigationValueMap(
+            createdObjectList.get(0), constructListofNavProperty(expandList));
+        edmPropertyValueMap.putAll(navigationMap);
+      }
+      EntityProviderWriteProperties feedProperties = null;
+      try {
+        feedProperties = getEntityProviderPropertiesforPost(oDataJPAContext, uriInfo, expandList);
+      } catch (ODataException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.INNER_EXCEPTION, e);
+      }
+
+      odataResponse = EntityProvider.writeEntry(contentType,
+          uriInfo.getTargetEntitySet(), edmPropertyValueMap,
+          feedProperties);
+
+      odataResponse = ODataResponse.fromResponse(odataResponse)
+          .status(HttpStatusCodes.CREATED).build();
+
+    } catch (EntityProviderException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return odataResponse;
+  }
+
+  /* Response for Update Entity */
+  public static ODataResponse build(final Object updatedObject,
+      final PutMergePatchUriInfo putUriInfo) throws ODataJPARuntimeException,
+      ODataNotFoundException {
+    if (updatedObject == null) {
+      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+    }
+    return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
+  }
+
+  /* Response for Delete Entity */
+  public static ODataResponse build(final Object deletedObject,
+      final DeleteUriInfo deleteUriInfo) throws ODataJPARuntimeException,
+      ODataNotFoundException {
+
+    if (deletedObject == null) {
+      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+    }
+    return ODataResponse.status(HttpStatusCodes.OK).build();
+  }
+
+  /* Response for Function Import Single Result */
+  public static ODataResponse build(final Object result,
+      final GetFunctionImportUriInfo resultsView)
+      throws ODataJPARuntimeException {
+
+    try {
+      final EdmFunctionImport functionImport = resultsView
+          .getFunctionImport();
+      final EdmSimpleType type = (EdmSimpleType) functionImport
+          .getReturnType().getType();
+
+      if (result != null) {
+        ODataResponse response = null;
+
+        final String value = type.valueToString(result,
+            EdmLiteralKind.DEFAULT, null);
+        response = EntityProvider.writeText(value);
+
+        return ODataResponse.fromResponse(response).build();
+      } else {
+        throw new ODataNotFoundException(ODataHttpException.COMMON);
+      }
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (EntityProviderException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.INNER_EXCEPTION, e);
+    }
+  }
+
+  /* Response for Function Import Multiple Result */
+  public static ODataResponse build(final List<Object> resultList,
+      final GetFunctionImportUriInfo resultsView, final String contentType,
+      final ODataJPAContext oDataJPAContext) throws ODataJPARuntimeException,
+      ODataNotFoundException {
+
+    ODataResponse odataResponse = null;
+
+    if (resultList != null && !resultList.isEmpty()) {
+      JPAEntityParser jpaResultParser = JPAEntityParser.create();
+      EdmType edmType = null;
+      EdmFunctionImport functionImport = null;
+      Map<String, Object> edmPropertyValueMap = null;
+      List<Map<String, Object>> edmEntityList = null;
+      Object result = null;
+      try {
+        EntityProviderWriteProperties feedProperties = null;
+
+        feedProperties = EntityProviderWriteProperties.serviceRoot(
+            oDataJPAContext.getODataContext().getPathInfo()
+                .getServiceRoot()).build();
+
+        functionImport = resultsView.getFunctionImport();
+        edmType = functionImport.getReturnType().getType();
+
+        if (edmType.getKind().equals(EdmTypeKind.ENTITY)
+            || edmType.getKind().equals(EdmTypeKind.COMPLEX)) {
+          if (functionImport.getReturnType().getMultiplicity()
+              .equals(EdmMultiplicity.MANY)) {
+            edmEntityList = new ArrayList<Map<String, Object>>();
+            for (Object jpaEntity : resultList) {
+              edmPropertyValueMap = jpaResultParser
+                  .parse2EdmPropertyValueMap(jpaEntity,
+                      (EdmStructuralType) edmType);
+              edmEntityList.add(edmPropertyValueMap);
+            }
+            result = edmEntityList;
+          } else {
+
+            Object resultObject = resultList.get(0);
+            edmPropertyValueMap = jpaResultParser
+                .parse2EdmPropertyValueMap(resultObject,
+                    (EdmStructuralType) edmType);
+
+            result = edmPropertyValueMap;
+          }
+
+        } else if (edmType.getKind().equals(EdmTypeKind.SIMPLE)) {
+          result = resultList.get(0);
+        }
+
+        odataResponse = EntityProvider
+            .writeFunctionImport(contentType,
+                resultsView.getFunctionImport(), result,
+                feedProperties);
+        odataResponse = ODataResponse.fromResponse(odataResponse)
+            .status(HttpStatusCodes.OK).build();
+
+      } catch (EdmException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (EntityProviderException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.GENERAL.addContent(e
+                .getMessage()), e);
+      } catch (ODataException e) {
+        throw ODataJPARuntimeException.throwException(
+            ODataJPARuntimeException.INNER_EXCEPTION, e);
+      }
+
+    } else {
+      throw new ODataNotFoundException(ODataHttpException.COMMON);
+    }
+
+    return odataResponse;
+  }
+
+  /* Response for Read Entity Link */
+  public static ODataResponse build(final Object jpaEntity,
+      final GetEntityLinkUriInfo resultsView, final String contentType, final ODataJPAContext oDataJPAContext)
+      throws ODataNotFoundException, ODataJPARuntimeException {
+
+    if (jpaEntity == null) {
+      throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+    }
+    EdmEntityType edmEntityType = null;
+    ODataResponse odataResponse = null;
+
+    try {
+
+      EdmEntitySet entitySet = resultsView.getTargetEntitySet();
+      edmEntityType = entitySet.getEntityType();
+      Map<String, Object> edmPropertyValueMap = null;
+
+      JPAEntityParser jpaResultParser = JPAEntityParser.create();
+      edmPropertyValueMap = jpaResultParser
+          .parse2EdmPropertyValueMap(
+              jpaEntity,
+              edmEntityType.getKeyProperties());
+
+      EntityProviderWriteProperties entryProperties = EntityProviderWriteProperties
+          .serviceRoot(oDataJPAContext.getODataContext().getPathInfo().getServiceRoot())
+          .build();
+
+      ODataResponse response = EntityProvider.writeLink(contentType, entitySet, edmPropertyValueMap, entryProperties);
+
+      odataResponse = ODataResponse.fromResponse(response).build();
+
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.INNER_EXCEPTION, e);
+
+    }
+
+    return odataResponse;
+  }
+
+  /* Response for Read Entity Links */
+  public static <T> ODataResponse build(final List<T> jpaEntities,
+      final GetEntitySetLinksUriInfo resultsView, final String contentType,
+      final ODataJPAContext oDataJPAContext)
+      throws ODataJPARuntimeException {
+    EdmEntityType edmEntityType = null;
+    ODataResponse odataResponse = null;
+
+    try {
+
+      EdmEntitySet entitySet = resultsView.getTargetEntitySet();
+      edmEntityType = entitySet.getEntityType();
+      List<EdmProperty> keyProperties = edmEntityType.getKeyProperties();
+
+      List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
+      Map<String, Object> edmPropertyValueMap = null;
+      JPAEntityParser jpaResultParser = JPAEntityParser.create();
+
+      for (Object jpaEntity : jpaEntities) {
+        edmPropertyValueMap = jpaResultParser
+            .parse2EdmPropertyValueMap(
+                jpaEntity,
+                keyProperties);
+        edmEntityList.add(edmPropertyValueMap);
+      }
+
+      Integer count = null;
+      if (resultsView.getInlineCount() != null) {
+        if ((resultsView.getSkip() != null || resultsView.getTop() != null)) {
+          // when $skip and/or $top is present with $inlinecount
+          count = getInlineCountForNonFilterQueryLinks(edmEntityList, resultsView);
+        } else {
+          // In all other cases
+          count = resultsView.getInlineCount() == InlineCount.ALLPAGES ? edmEntityList
+              .size() : null;
+        }
+      }
+
+      ODataContext context = oDataJPAContext.getODataContext();
+      EntityProviderWriteProperties entryProperties = EntityProviderWriteProperties
+          .serviceRoot(context.getPathInfo().getServiceRoot())
+          .inlineCountType(resultsView.getInlineCount())
+          .inlineCount(count)
+          .build();
+
+      odataResponse = EntityProvider.writeLinks(contentType, entitySet, edmEntityList, entryProperties);
+
+      odataResponse = ODataResponse.fromResponse(odataResponse).build();
+
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+
+    return odataResponse;
+
+  }
+
+  /*
+   * This method handles $inlinecount request. It also modifies the list of results in case of 
+   * $inlinecount and $top/$skip combinations. Specific to LinksUriInfo. //TODO
+   * 
+   * @param edmEntityList
+   * @param resultsView 
+   * 
+   * @return
+   */
+  private static Integer getInlineCountForNonFilterQueryLinks(final List<Map<String, Object>> edmEntityList, final GetEntitySetLinksUriInfo resultsView) {
+    // when $skip and/or $top is present with $inlinecount, first get the total count
+    Integer count = null;
+    if (resultsView.getInlineCount() == InlineCount.ALLPAGES) {
+      if (resultsView.getSkip() != null || resultsView.getTop() != null) {
+        count = edmEntityList.size();
+        // Now update the list
+        if (resultsView.getSkip() != null) {
+          // Index checks to avoid IndexOutOfBoundsException
+          if (resultsView.getSkip() > edmEntityList.size()) {
+            edmEntityList.clear();
+            return count;
+          }
+          edmEntityList.subList(0, resultsView.getSkip()).clear();
+        }
+        if (resultsView.getTop() != null && resultsView.getTop() >= 0 && resultsView.getTop() < edmEntityList.size()) {
+          edmEntityList.subList(0, resultsView.getTop());
+        }
+      }
+    }// Inlinecount of None is handled by default - null
+    return count;
+  }
+
+  /*
+   * Method to build the entity provider Property.Callbacks for $expand would
+   * be registered here
+   */
+  private static EntityProviderWriteProperties getEntityProviderProperties(
+      final ODataJPAContext odataJPAContext, final GetEntitySetUriInfo resultsView,
+      final List<Map<String, Object>> edmEntityList)
+      throws ODataJPARuntimeException {
+    ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
+
+    Integer count = null;
+    if (resultsView.getInlineCount() != null) {
+      if ((resultsView.getSkip() != null || resultsView.getTop() != null)) {
+        // when $skip and/or $top is present with $inlinecount
+        count = getInlineCountForNonFilterQueryEntitySet(edmEntityList, resultsView);
+      } else {
+        // In all other cases
+        count = resultsView.getInlineCount() == InlineCount.ALLPAGES ? edmEntityList
+            .size() : null;
+      }
+    }
+
+    try {
+      entityFeedPropertiesBuilder = EntityProviderWriteProperties
+          .serviceRoot(odataJPAContext.getODataContext()
+              .getPathInfo().getServiceRoot());
+      entityFeedPropertiesBuilder.inlineCount(count);
+      entityFeedPropertiesBuilder.inlineCountType(resultsView
+          .getInlineCount());
+      ExpandSelectTreeNode expandSelectTree = UriParser
+          .createExpandSelectTree(resultsView.getSelect(),
+              resultsView.getExpand());
+      entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack
+          .getCallbacks(odataJPAContext.getODataContext()
+              .getPathInfo().getServiceRoot(), expandSelectTree,
+              resultsView.getExpand()));
+      entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
+
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.INNER_EXCEPTION, e);
+    }
+
+    return entityFeedPropertiesBuilder.build();
+  }
+
+  /*
+   * This method handles $inlinecount request. It also modifies the list of results in case of 
+   * $inlinecount and $top/$skip combinations. Specific to Entity Set. //TODO
+   * 
+   */
+  private static Integer getInlineCountForNonFilterQueryEntitySet(final List<Map<String, Object>> edmEntityList, final GetEntitySetUriInfo resultsView) {
+    // when $skip and/or $top is present with $inlinecount, first get the total count
+    Integer count = null;
+    if (resultsView.getInlineCount() == InlineCount.ALLPAGES) {
+      if (resultsView.getSkip() != null || resultsView.getTop() != null) {
+        count = edmEntityList.size();
+        // Now update the list
+        if (resultsView.getSkip() != null) {
+          // Index checks to avoid IndexOutOfBoundsException
+          if (resultsView.getSkip() > edmEntityList.size()) {
+            edmEntityList.clear();
+            return count;
+          }
+          edmEntityList.subList(0, resultsView.getSkip()).clear();
+        }
+        if (resultsView.getTop() != null && resultsView.getTop() >= 0 && resultsView.getTop() < edmEntityList.size()) {
+          edmEntityList.retainAll(edmEntityList.subList(0, resultsView.getTop()));
+        }
+      }
+    }// Inlinecount of None is handled by default - null
+    return count;
+  }
+
+  private static EntityProviderWriteProperties getEntityProviderProperties(
+      final ODataJPAContext odataJPAContext, final GetEntityUriInfo resultsView)
+      throws ODataJPARuntimeException {
+    ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
+    ExpandSelectTreeNode expandSelectTree = null;
+    try {
+      entityFeedPropertiesBuilder = EntityProviderWriteProperties
+          .serviceRoot(odataJPAContext.getODataContext()
+              .getPathInfo().getServiceRoot());
+      expandSelectTree = UriParser.createExpandSelectTree(
+          resultsView.getSelect(), resultsView.getExpand());
+      entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
+      entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack
+          .getCallbacks(odataJPAContext.getODataContext()
+              .getPathInfo().getServiceRoot(), expandSelectTree,
+              resultsView.getExpand()));
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.INNER_EXCEPTION, e);
+    }
+
+    return entityFeedPropertiesBuilder.build();
+  }
+
+  private static EntityProviderWriteProperties getEntityProviderPropertiesforPost(
+      final ODataJPAContext odataJPAContext, final PostUriInfo resultsView, final List<ArrayList<NavigationPropertySegment>> expandList)
+      throws ODataJPARuntimeException {
+    ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
+    ExpandSelectTreeNode expandSelectTree = null;
+    try {
+      entityFeedPropertiesBuilder = EntityProviderWriteProperties
+          .serviceRoot(odataJPAContext.getODataContext()
+              .getPathInfo().getServiceRoot());
+      expandSelectTree = UriParser.createExpandSelectTree(
+          null, expandList);
+      entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
+      entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack
+          .getCallbacks(odataJPAContext.getODataContext()
+              .getPathInfo().getServiceRoot(), expandSelectTree,
+              expandList));
+    } catch (ODataException e) {
+      throw ODataJPARuntimeException.throwException(
+          ODataJPARuntimeException.INNER_EXCEPTION, e);
+    }
+
+    return entityFeedPropertiesBuilder.build();
+  }
+
+  private static List<ArrayList<NavigationPropertySegment>> getExpandList(final Map<EdmNavigationProperty, EdmEntitySet> navPropEntitySetMap) {
+    List<ArrayList<NavigationPropertySegment>> expandList = new ArrayList<ArrayList<NavigationPropertySegment>>();
+    ArrayList<NavigationPropertySegment> navigationPropertySegmentList = new ArrayList<NavigationPropertySegment>();
+    for (Map.Entry<EdmNavigationProperty, EdmEntitySet> entry : navPropEntitySetMap.entrySet()) {
+      final EdmNavigationProperty edmNavigationProperty = entry.getKey();
+      final EdmEntitySet edmEntitySet = entry.getValue();
+      NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment() {
+
+        @Override
+        public EdmEntitySet getTargetEntitySet() {
+          return edmEntitySet;
+        }
+
+        @Override
+        public EdmNavigationProperty getNavigationProperty() {
+          return edmNavigationProperty;
+        }
+      };
+      navigationPropertySegmentList.add(navigationPropertySegment);
+    }
+    expandList.add(navigationPropertySegmentList);
+    return expandList;
+  }
+
+  private static List<EdmProperty> buildSelectItemList(
+      final List<SelectItem> selectItems, final EdmEntityType entity) throws ODataJPARuntimeException {
+    boolean flag = false;
+    List<EdmProperty> selectPropertyList = new ArrayList<EdmProperty>();
+    try {
+      for (SelectItem selectItem : selectItems) {
+        selectPropertyList.add(selectItem.getProperty());
+      }
+      for (EdmProperty keyProperty : entity.getKeyProperties()) {
+        flag = true;
+        for (SelectItem selectedItem : selectItems) {
+          if (selectedItem.getProperty().equals(keyProperty)) {
+            flag = false;
+            break;
+          }
+        }
+        if (flag == true) {
+          selectPropertyList.add(keyProperty);
+        }
+      }
+
+    } catch (EdmException e) {
+      throw ODataJPARuntimeException
+          .throwException(ODataJPARuntimeException.GENERAL
+              .addContent(e.getMessage()), e);
+    }
+    return selectPropertyList;
+  }
+
+  private static List<EdmNavigationProperty> constructListofNavProperty(
+      final List<ArrayList<NavigationPropertySegment>> expandList) {
+    List<EdmNavigationProperty> navigationPropertyList = new ArrayList<EdmNavigationProperty>();
+    for (ArrayList<NavigationPropertySegment> navpropSegment : expandList) {
+      navigationPropertyList.add(navpropSegment.get(0)
+          .getNavigationProperty());
+    }
+    return navigationPropertyList;
+  }
+
+}