You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by tb...@apache.org on 2014/01/02 13:47:20 UTC

[33/47] [OLINGO-99] Re-factor Package Names. Following are the changes

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.java
new file mode 100644
index 0000000..97e438e
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmMappingModelService.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.jpa.processor.core.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.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAEdmMappingModel;
+import org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAEmbeddableTypeMapType;
+import org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAEntityTypeMapType;
+import org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAPersistenceUnitMapType;
+import org.apache.olingo.odata2.jpa.processor.api.model.mapping.JPAAttributeMapType.JPAAttribute;
+import org.apache.olingo.odata2.jpa.processor.api.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 && jpaEntityTypeMap.getJPARelationships() != 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;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
new file mode 100644
index 0000000..5c8c999
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPAEdmNameBuilder.java
@@ -0,0 +1,499 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core.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.ComplexType;
+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.jpa.processor.api.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmAssociationEndView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmAssociationSetView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmAssociationView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmBaseView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmComplexPropertyView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmEntityContainerView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmEntitySetView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmEntityTypeView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmMapping;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmNavigationPropertyView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmPropertyView;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmSchemaView;
+import org.apache.olingo.odata2.jpa.processor.core.model.JPAEdmComplexType;
+import org.apache.olingo.odata2.jpa.processor.core.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,
+      final boolean skipDefaultNaming) {
+    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 (skipDefaultNaming == false && propertyName == null) {
+      propertyName = Character.toUpperCase(jpaAttributeName.charAt(0)) + jpaAttributeName.substring(1);
+    } else if (propertyName == null) {
+      propertyName = jpaAttributeName;
+    }
+
+    view.getEdmSimpleProperty().setName(propertyName);
+
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    ((Mapping) mapping).setInternalName(jpaAttributeName);
+    mapping.setJPAType(jpaAttribute.getJavaType());
+
+    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.getField(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);
+    ComplexType complexType = view.getEdmComplexType();
+    complexType.setName(edmComplexTypeName);
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    mapping.setJPAType(view.getJPAEmbeddableType().getJavaType());
+    complexType.setMapping((Mapping) mapping);
+
+  }
+
+  /*
+   * ************************************************************************
+   * 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, final boolean skipDefaultNaming) {
+
+    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 (skipDefaultNaming == false && propertyName == null) {
+      propertyName = Character.toUpperCase(jpaAttributeName.charAt(0)) + jpaAttributeName.substring(1);
+    } else if (propertyName == null) {
+      propertyName = jpaAttributeName;
+    }
+
+    // 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, final boolean skipDefaultNaming) {
+    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 (skipDefaultNaming == false && propertyName == null) {
+      propertyName = Character.toUpperCase(jpaAttributeName.charAt(0)) + jpaAttributeName.substring(1);
+    } else if (propertyName == null) {
+      propertyName = jpaAttributeName;
+    }
+
+    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;
+    Attribute<?, ?> jpaAttribute = propertyView.getJPAAttribute();
+    if (jpaAttribute.isCollection()) {
+      jpaEntityTypeName = ((PluralAttribute<?, ?, ?>) jpaAttribute).getElementType().getJavaType()
+          .getSimpleName();
+    } else {
+      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 boolean skipDefaultNaming, 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();
+    JPAEdmMapping mapping = new JPAEdmMappingImpl();
+    ((Mapping) mapping).setInternalName(jpaAttribute.getName());
+    mapping.setJPAType(jpaAttribute.getJavaType());
+    navProp.setMapping((Mapping) mapping);
+
+    String jpaEntityTypeName = propertyView.getJPAEdmEntityTypeView()
+        .getJPAEntityType().getName();
+    JPAEdmMappingModelAccess mappingModelAccess = navPropertyView
+        .getJPAEdmMappingModelAccess();
+
+    String targetEntityTypeName = null;
+    if (jpaAttribute.isCollection()) {
+      targetEntityTypeName = ((PluralAttribute<?, ?, ?>) jpaAttribute).getElementType().getJavaType().getSimpleName();
+    } else {
+      targetEntityTypeName = jpaAttribute.getJavaType().getSimpleName();
+    }
+
+    if (mappingModelAccess != null
+        && mappingModelAccess.isMappingModelExists()) {
+      navPropName = mappingModelAccess.mapJPARelationship(
+          jpaEntityTypeName, jpaAttribute.getName());
+      toName = mappingModelAccess.mapJPAEntityType(targetEntityTypeName);
+      fromName = mappingModelAccess
+          .mapJPAEntityType(jpaEntityTypeName);
+    }
+    if (toName == null) {
+      toName = targetEntityTypeName;
+    }
+
+    if (fromName == null) {
+      fromName = jpaEntityTypeName;
+    }
+
+    if (skipDefaultNaming == false) {
+      if (navPropName == null) {
+        navPropName = toName.concat(NAVIGATION_NAME);
+      }
+      if (count > 1) {
+        navPropName = navPropName + Integer.toString(count - 1);
+      }
+    } else if (navPropName == null) {
+      navPropName = jpaAttribute.getName();
+    }
+
+    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/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.java
new file mode 100644
index 0000000..e35e4cf
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/access/model/JPATypeConvertor.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.jpa.processor.core.access.model;
+
+import java.lang.reflect.Field;
+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.jpa.processor.api.exception.ODataJPAModelException;
+
+/**
+ * This class holds utility methods for Type conversions between JPA and OData Types.
+ * 
+ * 
+ * 
+ */
+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 org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException
+   * 
+   * @see EdmSimpleTypeKind
+   */
+
+  private static final String OBJECT_TYPE = "java.lang.Object";
+
+  public static EdmSimpleTypeKind
+      convertToEdmSimpleType(final Class<?> jpaType, final Attribute<?, ?> currentAttribute)
+          throws ODataJPAModelException {
+    if (jpaType.equals(String.class) || jpaType.equals(Character.class) || jpaType.equals(char.class)
+        || jpaType.equals(char[].class) ||
+        jpaType.equals(Character[].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)
+            && (determineTemporalType(currentAttribute.getDeclaringType().getJavaType(), currentAttribute.getName())
+              == TemporalType.TIME)) {
+          return EdmSimpleTypeKind.Time;
+        } else {
+          return EdmSimpleTypeKind.DateTime;
+        }
+      } 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);
+  }
+
+  private static TemporalType determineTemporalType(final Class<?> type, final String fieldName)
+      throws ODataJPAModelException {
+    if (type != null && !type.getName().equals(OBJECT_TYPE)) {
+      try {
+        Field field = type.getField(fieldName);
+        return field.getAnnotation(Temporal.class).value();
+      } catch (NoSuchFieldException e) {
+        determineTemporalType(type.getSuperclass(), fieldName);
+      } catch (SecurityException e) {
+        throw ODataJPAModelException.throwException(ODataJPAModelException.GENERAL.addContent(e.getMessage()), e);
+      }
+    }
+    return null;
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/edm/ODataJPAEdmProvider.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/edm/ODataJPAEdmProvider.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/edm/ODataJPAEdmProvider.java
new file mode 100644
index 0000000..101db9b
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/edm/ODataJPAEdmProvider.java
@@ -0,0 +1,295 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core.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.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAException;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.jpa.processor.api.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;
+
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/exception/ODataJPAMessageServiceDefault.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/exception/ODataJPAMessageServiceDefault.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/exception/ODataJPAMessageServiceDefault.java
new file mode 100644
index 0000000..cd96b40
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/exception/ODataJPAMessageServiceDefault.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.jpa.processor.core.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.jpa.processor.api.exception.ODataJPAMessageService;
+import org.apache.olingo.odata2.jpa.processor.core.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/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/factory/ODataJPAFactoryImpl.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/factory/ODataJPAFactoryImpl.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/factory/ODataJPAFactoryImpl.java
new file mode 100644
index 0000000..d27713f
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/factory/ODataJPAFactoryImpl.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core.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.jpa.processor.api.ODataJPAContext;
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAEdmMappingModelAccess;
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAProcessor;
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAMethodContext.JPAMethodContextBuilder;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAMessageService;
+import org.apache.olingo.odata2.jpa.processor.api.factory.JPAAccessFactory;
+import org.apache.olingo.odata2.jpa.processor.api.factory.JPQLBuilderFactory;
+import org.apache.olingo.odata2.jpa.processor.api.factory.ODataJPAAccessFactory;
+import org.apache.olingo.odata2.jpa.processor.api.factory.ODataJPAFactory;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement.JPQLStatementBuilder;
+import org.apache.olingo.odata2.jpa.processor.api.model.JPAEdmModelView;
+import org.apache.olingo.odata2.jpa.processor.core.ODataJPAContextImpl;
+import org.apache.olingo.odata2.jpa.processor.core.ODataJPAProcessorDefault;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAFunctionContext;
+import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAProcessorImpl;
+import org.apache.olingo.odata2.jpa.processor.core.access.model.JPAEdmMappingModelService;
+import org.apache.olingo.odata2.jpa.processor.core.edm.ODataJPAEdmProvider;
+import org.apache.olingo.odata2.jpa.processor.core.exception.ODataJPAMessageServiceDefault;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLJoinSelectContext;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLJoinSelectSingleContext;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLJoinSelectSingleStatementBuilder;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLJoinStatementBuilder;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLSelectContext;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLSelectSingleContext;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLSelectSingleStatementBuilder;
+import org.apache.olingo.odata2.jpa.processor.core.jpql.JPQLSelectStatementBuilder;
+import org.apache.olingo.odata2.jpa.processor.core.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/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java
new file mode 100644
index 0000000..e69a2d6
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.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.jpa.processor.core.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.jpa.processor.api.access.JPAJoinClause;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinContextView;
+import org.apache.olingo.odata2.jpa.processor.core.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/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java
new file mode 100644
index 0000000..199f05a
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.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.jpa.processor.core.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.jpa.processor.api.access.JPAJoinClause;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinSelectSingleContextView;
+import org.apache.olingo.odata2.jpa.processor.core.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/63b621a8/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java
new file mode 100644
index 0000000..0a9a5b9
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.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.jpa.processor.core.jpql;
+
+import java.util.List;
+
+import org.apache.olingo.odata2.jpa.processor.api.access.JPAJoinClause;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLJoinSelectSingleContextView;
+import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement;
+import org.apache.olingo.odata2.jpa.processor.api.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();
+
+  }
+
+}