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:52 UTC
[47/51] [partial] initial commit
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;
+ }
+
+}