[OLINGO-644 and OLINGO-647] Support for nested method expressions in
$filter and preserve order by clause order
Signed-off-by: Chandan V A <chandan.v.a@sap.com>
diff --git a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java
index 072dc3d..fc41411 100644
--- a/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java
+++ b/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java
@@ -18,7 +18,6 @@
******************************************************************************/
package org.apache.olingo.odata2.jpa.processor.api.jpql;
-import java.util.Map;
/**
* The interface provide a view on JPQL select context.The interface provides
@@ -40,18 +39,11 @@
public String getSelectExpression();
/**
- * The method returns an ordered map of JPQL ORDERBY clause. The ORDERBY clause
+ * The method returns an JPQL ORDERBY clause. The ORDERBY clause
* is built from $orderby OData system query option. The hash map contains
- * <ol>
- * <li>Key - JPA Entity Property name to be ordered</li>
- * <li>Value - Sort Order in JPQL (desc,asc)</li>
- * </ol>
- * in the order based on the expression specified
- * (accessible with <code>Map.entrySet(..)</code>).
- *
- * @return an ordered map of (JPA Property Name,Sort Order)
+ * @return an order by expression (JPA Property Name,Sort Order)
*/
- public Map<String, String> getOrderByCollection();
+ public String getOrderByCollection();
/**
* The method returns a JPQL WHERE condition as string. The WHERE condition
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java
index d86461c..830aaa8 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -20,14 +20,12 @@
import java.util.ArrayList;
import java.util.Calendar;
-import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedHashMap;
import java.util.List;
import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
-import org.apache.olingo.odata2.api.edm.EdmMappable;
import org.apache.olingo.odata2.api.edm.EdmMapping;
import org.apache.olingo.odata2.api.edm.EdmProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
@@ -55,9 +53,9 @@
/**
* This class contains utility methods for parsing the filter expressions built by core library from user OData Query.
- *
- *
- *
+ *
+ *
+ *
*/
public class ODataExpressionParser {
@@ -66,9 +64,9 @@
/**
* 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
*/
@@ -167,9 +165,8 @@
}
case PROPERTY:
- String returnStr =
- tableAlias + JPQLStatement.DELIMITER.PERIOD
- + ((EdmProperty) ((PropertyExpression) whereExpression).getEdmProperty()).getMapping().getInternalName();
+ String returnStr = tableAlias + JPQLStatement.DELIMITER.PERIOD
+ + getPropertyName(whereExpression);
return returnStr;
case MEMBER:
@@ -183,23 +180,18 @@
memberExpStr = JPQLStatement.DELIMITER.PERIOD + memberExpStr;
}
i++;
- memberExpStr =
- ((EdmProperty) ((PropertyExpression) member.getProperty()).getEdmProperty()).getMapping().getInternalName()
- + memberExpStr;
+ memberExpStr = getPropertyName(member.getProperty()) + memberExpStr;
tempExp = member.getPath();
}
memberExpStr =
- ((EdmMappable) ((PropertyExpression) tempExp).getEdmProperty()).getMapping().getInternalName()
- + JPQLStatement.DELIMITER.PERIOD + memberExpStr;
+ getPropertyName(tempExp) + 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);
+ EdmLiteral uriLiteral = EdmSimpleTypeKind.parseUriLiteral(literal.getUriLiteral());
+ return evaluateComparingExpression(uriLiteral.getLiteral(), literalType);
case METHOD:
final MethodExpression methodExpression = (MethodExpression) whereExpression;
@@ -216,21 +208,21 @@
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.get() != null && methodFlag.get() == 1) {
methodFlag.set(null);
- return String.format("(CASE WHEN (%s LIKE '%%%s%%') THEN TRUE ELSE FALSE END)", second, first);
+ return String.format("(CASE WHEN (%s LIKE CONCAT('%%',%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);
+ return String.format("(CASE WHEN (%s LIKE CONCAT('%%',%s,'%%')) THEN TRUE ELSE FALSE END) = true", second,
+ first);
}
case TOLOWER:
return String.format("LOWER(%s)", first);
case STARTSWITH:
- second = second.substring(1, second.length() - 1);
- return String.format("%s LIKE '%s%%'", first, second);
+ // second = second.substring(1, second.length() - 1);
+ return String.format("%s LIKE CONCAT(%s,'%%')", first, second);
case ENDSWITH:
- second = second.substring(1, second.length() - 1);
- return String.format("%s LIKE '%%%s'", first, second);
+ // second = second.substring(1, second.length() - 1);
+ return String.format("%s LIKE CONCAT('%%',%s)", first, second);
default:
throw new ODataNotImplementedException();
}
@@ -242,7 +234,7 @@
/**
* This method parses the select clause
- *
+ *
* @param tableAlias
* @param selectedFields
* @return a select expression
@@ -270,14 +262,14 @@
/**
* This method parses the order by condition in the query.
- *
+ *
* @param orderByExpression
* @return a map of JPA attributes and their sort order
* @throws ODataJPARuntimeException
*/
- public static HashMap<String, String> parseToJPAOrderByExpression(final OrderByExpression orderByExpression,
+ public static String parseToJPAOrderByExpression(final OrderByExpression orderByExpression,
final String tableAlias) throws ODataJPARuntimeException {
- HashMap<String, String> orderByMap = new HashMap<String, String>();
+ String jpqlOrderByExpression = "";
if (orderByExpression != null && orderByExpression.getOrders() != null) {
List<OrderExpression> orderBys = orderByExpression.getOrders();
String orderByField = null;
@@ -285,22 +277,30 @@
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);
+ orderByField = getPropertyName(orderBy.getExpression());
+ orderByDirection = (orderBy.getSortOrder() == SortOrder.asc) ? EMPTY :
+ JPQLStatement.DELIMITER.SPACE + "DESC"; //$NON-NLS-1$
+ jpqlOrderByExpression +=
+ tableAlias + JPQLStatement.DELIMITER.PERIOD + orderByField + orderByDirection + " , ";
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
}
}
- return orderByMap;
+ return normalizeOrderByExpression(jpqlOrderByExpression);
+ }
+
+ private static String normalizeOrderByExpression(final String jpqlOrderByExpression) {
+ if (jpqlOrderByExpression != "") {
+ return jpqlOrderByExpression.substring(0, jpqlOrderByExpression.length() - 3);
+ } else {
+ return jpqlOrderByExpression;
+ }
}
/**
* 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
*/
@@ -342,10 +342,13 @@
}
}
- public static HashMap<String, String> parseKeyPropertiesToJPAOrderByExpression(
+ public static String parseKeyPropertiesToJPAOrderByExpression(
final List<EdmProperty> edmPropertylist, final String tableAlias) throws ODataJPARuntimeException {
- LinkedHashMap<String, String> orderByMap = new LinkedHashMap<String, String>();
String propertyName = null;
+ String orderExpression = "";
+ if (edmPropertylist == null) {
+ return orderExpression;
+ }
for (EdmProperty edmProperty : edmPropertylist) {
try {
EdmMapping mapping = edmProperty.getMapping();
@@ -357,31 +360,32 @@
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
- orderByMap.put(tableAlias + JPQLStatement.DELIMITER.PERIOD + propertyName, EMPTY);
+ orderExpression += tableAlias + JPQLStatement.DELIMITER.PERIOD + propertyName + " , ";
}
- return orderByMap;
+ return normalizeOrderByExpression(orderExpression);
}
/**
* This method evaluates the expression based on the type instance. Used for adding escape characters where necessary.
- *
- * @param value
+ *
+ * @param uriLiteral
* @param edmSimpleType
* @return the evaluated expression
* @throws ODataJPARuntimeException
*/
- private static String evaluateComparingExpression(String value, final EdmSimpleType edmSimpleType)
+ private static String evaluateComparingExpression(String uriLiteral, final EdmSimpleType edmSimpleType)
throws ODataJPARuntimeException {
- if (edmSimpleType == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()
- || edmSimpleType == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()) {
- value = value.replaceAll("'", "''");
- value = "\'" + value + "\'"; //$NON-NLS-1$ //$NON-NLS-2$
- } else if (edmSimpleType == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
- || edmSimpleType == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()) {
+ if (EdmSimpleTypeKind.String.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)
+ || EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)) {
+ uriLiteral = uriLiteral.replaceAll("'", "''");
+ uriLiteral = "'" + uriLiteral + "'"; //$NON-NLS-1$ //$NON-NLS-2$
+ } else if (EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)
+ || EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)) {
try {
Calendar datetime =
- (Calendar) edmSimpleType.valueOfString(value, EdmLiteralKind.DEFAULT, null, edmSimpleType.getDefaultType());
+ (Calendar) edmSimpleType.valueOfString(uriLiteral, EdmLiteralKind.DEFAULT, null, edmSimpleType
+ .getDefaultType());
String year = String.format("%04d", datetime.get(Calendar.YEAR));
String month = String.format("%02d", datetime.get(Calendar.MONTH) + 1);
@@ -390,7 +394,7 @@
String min = String.format("%02d", datetime.get(Calendar.MINUTE));
String sec = String.format("%02d", datetime.get(Calendar.SECOND));
- value =
+ uriLiteral =
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
@@ -401,26 +405,33 @@
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
- } else if (edmSimpleType == EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance()) {
+ } else if (EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)) {
try {
Calendar time =
- (Calendar) edmSimpleType.valueOfString(value, EdmLiteralKind.DEFAULT, null, edmSimpleType.getDefaultType());
+ (Calendar) edmSimpleType.valueOfString(uriLiteral, 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 =
+ uriLiteral =
"\'" + 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$
+ } else if (EdmSimpleTypeKind.Int64.getEdmSimpleTypeInstance().isCompatible(edmSimpleType)) {
+ uriLiteral = uriLiteral + JPQLStatement.DELIMITER.LONG; //$NON-NLS-1$
}
- return value;
+ return uriLiteral;
}
+ private static String getPropertyName(final CommonExpression whereExpression) throws EdmException {
+ EdmProperty property = ((EdmProperty) ((PropertyExpression) whereExpression).getEdmProperty());
+ EdmMapping mapping = property.getMapping();
+ String name = mapping != null ? mapping.getInternalName() : property.getName();
+ return name;
+ }
}
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
index e5d9df8..9812327 100644
--- 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
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
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
index 199f05a..56b1686 100644
--- 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
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
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
index 0a9a5b9..3682205 100644
--- 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
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java
index 40ceeba..246cffb 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,9 +18,7 @@
******************************************************************************/
package org.apache.olingo.odata2.jpa.processor.core.jpql;
-import java.util.Iterator;
import java.util.List;
-import java.util.Map.Entry;
import org.apache.olingo.odata2.jpa.processor.api.access.JPAJoinClause;
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
@@ -118,23 +116,10 @@
}
- if (context.getOrderByCollection() != null && context.getOrderByCollection().size() > 0) {
+ if (context.getOrderByCollection() != null && context.getOrderByCollection().length() > 0) {
StringBuilder orderByBuilder = new StringBuilder();
- Iterator<Entry<String, String>> orderItr = context.getOrderByCollection().entrySet().iterator();
-
- int i = 0;
-
- while (orderItr.hasNext()) {
- if (i != 0) {
- orderByBuilder.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.DELIMITER.COMMA).append(
- JPQLStatement.DELIMITER.SPACE);
- }
- Entry<String, String> entry = orderItr.next();
- orderByBuilder.append(entry.getKey()).append(JPQLStatement.DELIMITER.SPACE);
- orderByBuilder.append(entry.getValue());
- i++;
- }
+ orderByBuilder.append(context.getOrderByCollection());
jpqlQuery.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.KEYWORD.ORDERBY).append(
JPQLStatement.DELIMITER.SPACE);
jpqlQuery.append(orderByBuilder);
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
index 4668b7d..34f8655 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,8 +18,6 @@
******************************************************************************/
package org.apache.olingo.odata2.jpa.processor.core.jpql;
-import java.util.HashMap;
-
import org.apache.olingo.odata2.api.edm.EdmEntityType;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmMapping;
@@ -35,7 +33,7 @@
public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextView {
protected String selectExpression;
- protected HashMap<String, String> orderByCollection;
+ protected String orderByCollection;
protected String whereCondition;
protected boolean isCountOnly = false;// Support for $count
@@ -44,7 +42,7 @@
this.isCountOnly = isCountOnly;
}
- protected final void setOrderByCollection(final HashMap<String, String> orderByCollection) {
+ protected final void setOrderByCollection(final String orderByCollection) {
this.orderByCollection = orderByCollection;
}
@@ -62,7 +60,7 @@
}
@Override
- public HashMap<String, String> getOrderByCollection() {
+ public String getOrderByCollection() {
return orderByCollection;
}
@@ -72,7 +70,7 @@
}
public class JPQLSelectContextBuilder extends
- org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder {
+ org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder {
protected GetEntitySetUriInfo entitySetView;
@@ -134,7 +132,7 @@
/*
* Generate Order By Clause Fields
*/
- protected HashMap<String, String> generateOrderByFileds() throws ODataJPARuntimeException, EdmException {
+ protected String generateOrderByFileds() throws ODataJPARuntimeException, EdmException {
if (entitySetView.getOrderBy() != null) {
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java
index ac54d2c..99715223 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -55,7 +55,7 @@
}
public class JPQLSelectSingleContextBuilder extends
- org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder {
+ org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContext.JPQLContextBuilder {
protected GetEntityUriInfo entityView;
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java
index 4e06b9e..0db1084 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java
index 22dcc9a..49ed28b 100644
--- a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,9 +18,6 @@
******************************************************************************/
package org.apache.olingo.odata2.jpa.processor.core.jpql;
-import java.util.Iterator;
-import java.util.Map.Entry;
-
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextType;
import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLContextView;
@@ -69,23 +66,10 @@
jpqlQuery.append(context.getWhereExpression());
}
- if (context.getOrderByCollection() != null && context.getOrderByCollection().size() > 0) {
+ if (context.getOrderByCollection() != null && context.getOrderByCollection().length() > 0) {
StringBuilder orderByBuilder = new StringBuilder();
- Iterator<Entry<String, String>> orderItr = context.getOrderByCollection().entrySet().iterator();
-
- int i = 0;
-
- while (orderItr.hasNext()) {
- if (i != 0) {
- orderByBuilder.append(JPQLStatement.DELIMITER.SPACE).append(JPQLStatement.DELIMITER.COMMA).append(
- JPQLStatement.DELIMITER.SPACE);
- }
- Entry<String, String> entry = orderItr.next();
- orderByBuilder.append(entry.getKey()).append(JPQLStatement.DELIMITER.SPACE);
- orderByBuilder.append(entry.getValue());
- i++;
- }
+ orderByBuilder.append(context.getOrderByCollection());
jpqlQuery.append(JPQLStatement.DELIMITER.SPACE);
jpqlQuery.append(JPQLStatement.KEYWORD.ORDERBY).append(JPQLStatement.DELIMITER.SPACE);
jpqlQuery.append(orderByBuilder);
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParserTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParserTest.java
deleted file mode 100644
index 3ca93c5..0000000
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParserTest.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*******************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ******************************************************************************/
-package org.apache.olingo.odata2.jpa.processor.core;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.olingo.odata2.api.edm.EdmException;
-import org.apache.olingo.odata2.api.edm.EdmFacets;
-import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
-import org.apache.olingo.odata2.api.edm.EdmMapping;
-import org.apache.olingo.odata2.api.edm.EdmProperty;
-import org.apache.olingo.odata2.api.edm.EdmSimpleType;
-import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
-import org.apache.olingo.odata2.api.edm.EdmTypeKind;
-import org.apache.olingo.odata2.api.edm.EdmTyped;
-import org.apache.olingo.odata2.api.exception.ODataException;
-import org.apache.olingo.odata2.api.uri.KeyPredicate;
-import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
-import org.apache.olingo.odata2.api.uri.expression.BinaryOperator;
-import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
-import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
-import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
-import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
-import org.apache.olingo.odata2.api.uri.expression.MemberExpression;
-import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
-import org.apache.olingo.odata2.api.uri.expression.MethodOperator;
-import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
-import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
-import org.apache.olingo.odata2.api.uri.expression.UnaryOperator;
-import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
-import org.apache.olingo.odata2.jpa.processor.core.common.ODataJPATestConstants;
-import org.easymock.EasyMock;
-import org.junit.Test;
-
-public class ODataExpressionParserTest {
-
- private static final String EXPECTED_STR_1 = "(gwt1.SalesOrder = 1234)";
- private static final String EXPECTED_STR_2 = "((gwt1.SalesOrder >= 1234) AND (gwt1.SalesABC <> XYZ))";
- private static final String EXPECTED_STR_3 = "((gwt1.SalesOrder >= 1234) OR (gwt1.SalesABC <> XYZ))";
- private static final String EXPECTED_STR_4 = "((gwt1.SalesOrder < 1234) AND (gwt1.SalesABC <= XYZ))";
- private static final String EXPECTED_STR_5 = "((gwt1.LineItems > 2345) AND (gwt1.SalesOrder >= Amazon))";
- private static final String EXPECTED_STR_6 = "(gwt1.Address.city = \'City_3\')";
- private static final String EXPECTED_STR_7 = "(gwt1.Address.city.area = \'BTM\')";
- private static final String EXPECTED_STR_8 = "gwt1.field1 = 1 AND gwt1.field2 = 'abc'";
- private static final String EXPECTED_STR_9 = "gwt1.BuyerAddress, gwt1.BuyerName, gwt1.BuyerId";
- private static final String EXPECTED_STR_10 = "gwt1.SalesOrder";
- private static final String EXPECTED_STR_11 = "NOT(gwt1.deliveryStatus)";
- private static final String EXPECTED_STR_12 =
- "((CASE WHEN (gwt1.currencyCode LIKE '%Ru%') THEN TRUE ELSE FALSE END) = true)";
- private static final String EXPECTED_STR_13 = "(SUBSTRING(gwt1.currencyCode, 1 + 1 , 2) = 'NR')";
- private static final String EXPECTED_STR_14 = "(LOWER(gwt1.currencyCode) = 'inr rupees')";
- private static final String EXPECTED_STR_15 =
- "((CASE WHEN (LOWER(gwt1.currencyCode) LIKE '%nr rupees%') THEN TRUE ELSE FALSE END) = true)";
- private static final String EXPECTED_STR_16 =
- "(CASE WHEN (gwt1.currencyCode LIKE '%INR%') THEN TRUE ELSE FALSE END) = true";
- private static final String EXPECTED_STR_17 =
- "(CASE WHEN (LOWER(gwt1.currencyCode) LIKE '%nr rupees%') THEN TRUE ELSE FALSE END) = true";
-
- private static final String ADDRESS = "Address";
- private static final String CITY = "city";
- private static final String AREA = "area";
- private static final String SALES_ORDER = "SalesOrder";
- private static final String SALES_ABC = "SalesABC";
- private static final String SAMPLE_DATA_1 = "1234";
- private static final String SAMPLE_DATA_2 = "2345";
- private static final String SAMPLE_DATA_XYZ = "XYZ";
- private static final String SAMPLE_DATA_BTM = "\'BTM\'";
- private static final String SAMPLE_DATA_CITY_3 = "\'City_3\'";
- private static final String SAMPLE_DATA_LINE_ITEMS = "LineItems";
- private static final String SAMPLE_DATA_AMAZON = "Amazon";
- private static final String SAMPLE_DATA_FIELD1 = "field1";
- private static final String SAMPLE_DATA_FIELD2 = "field2";
-
- private static final String TABLE_ALIAS = "gwt1"; //$NON-NLS-1$
-
- @Test
- public void testParseWhereExpression() {
- try {
- String parsedStr = ODataJPATestConstants.EMPTY_STRING;
- // Simple Binary query -
- parsedStr =
- ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpressionMockedObj(BinaryOperator.EQ,
- ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1), TABLE_ALIAS);
-
- assertEquals(EXPECTED_STR_1, parsedStr);
- // complex query -
- parsedStr = ODataJPATestConstants.EMPTY_STRING;
-
- CommonExpression exp1 =
- getBinaryExpressionMockedObj(BinaryOperator.GE, ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1);
- CommonExpression exp2 =
- getBinaryExpressionMockedObj(BinaryOperator.NE, ExpressionKind.PROPERTY, SALES_ABC, SAMPLE_DATA_XYZ);
- parsedStr =
- ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(exp1, BinaryOperator.AND, exp2),
- TABLE_ALIAS);
- assertEquals(EXPECTED_STR_2, parsedStr);
- } catch (EdmException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- }
-
- @Test
- public void testMoreThanOneBinaryExpression() {
- // complex query -
- String parsedStr = ODataJPATestConstants.EMPTY_STRING;
- CommonExpression exp1 =
- getBinaryExpressionMockedObj(BinaryOperator.GE, ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1);
- CommonExpression exp2 =
- getBinaryExpressionMockedObj(BinaryOperator.NE, ExpressionKind.PROPERTY, SALES_ABC, SAMPLE_DATA_XYZ);
- try {
- parsedStr =
- ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(exp1, BinaryOperator.AND, exp2),
- TABLE_ALIAS);
- assertEquals(EXPECTED_STR_2, parsedStr);
- parsedStr =
- ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(exp1, BinaryOperator.OR, exp2),
- TABLE_ALIAS);
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- assertEquals(EXPECTED_STR_3, parsedStr);
- }
-
- @Test
- public void testParseFilterExpression() {
- try {
- assertEquals(EXPECTED_STR_10, ODataExpressionParser.parseToJPAWhereExpression(getFilterExpressionMockedObj(
- ExpressionKind.PROPERTY, SALES_ORDER), TABLE_ALIAS));
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- }
-
- @Test
- public void testAllBinaryOperators() { // Test for all Binary Operators
- // complex query -
- String parsedStr1 = ODataJPATestConstants.EMPTY_STRING;
- String parsedStr2 = ODataJPATestConstants.EMPTY_STRING;
-
- CommonExpression exp1 =
- getBinaryExpressionMockedObj(BinaryOperator.LT, ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_1);
- CommonExpression exp2 =
- getBinaryExpressionMockedObj(BinaryOperator.LE, ExpressionKind.PROPERTY, SALES_ABC, SAMPLE_DATA_XYZ);
-
- try {
- parsedStr1 =
- ODataExpressionParser.parseToJPAWhereExpression((BinaryExpression) getBinaryExpression(exp1,
- BinaryOperator.AND, exp2), TABLE_ALIAS);
- assertEquals(EXPECTED_STR_4, parsedStr1);
-
- CommonExpression exp3 =
- getBinaryExpressionMockedObj(BinaryOperator.GT, ExpressionKind.PROPERTY, SAMPLE_DATA_LINE_ITEMS,
- SAMPLE_DATA_2);
- CommonExpression exp4 =
- getBinaryExpressionMockedObj(BinaryOperator.GE, ExpressionKind.PROPERTY, SALES_ORDER, SAMPLE_DATA_AMAZON);
-
- parsedStr2 =
- ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(exp3, BinaryOperator.AND, exp4),
- TABLE_ALIAS);
-
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- assertEquals(EXPECTED_STR_5, parsedStr2);
- }
-
- @Test
- public void testParseMemberExpression() {
- try {
- assertEquals(EXPECTED_STR_6, ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(
- getMemberExpressionMockedObj(ADDRESS, CITY), BinaryOperator.EQ,
- getLiteralExpressionMockedObj(SAMPLE_DATA_CITY_3)), TABLE_ALIAS));
- assertEquals(EXPECTED_STR_7, ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(
- getMultipleMemberExpressionMockedObj(ADDRESS, CITY, AREA), BinaryOperator.EQ,
- getLiteralExpressionMockedObj(SAMPLE_DATA_BTM)), TABLE_ALIAS));
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- }
-
- @Test
- public void testParseMethodExpression() {
- try {
- assertEquals(EXPECTED_STR_12, ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(
- getMethodExpressionMockedObj(MethodOperator.SUBSTRINGOF, "'Ru'", "currencyCode", null, 2), BinaryOperator.EQ,
- getLiteralExpressionMockedObj("true")), TABLE_ALIAS));
- assertEquals(EXPECTED_STR_13, ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(
- getMethodExpressionMockedObj(MethodOperator.SUBSTRING, "currencyCode", "1", "2", 3), BinaryOperator.EQ,
- getLiteralExpressionMockedObj("'NR'")), TABLE_ALIAS));
- assertEquals(EXPECTED_STR_14, ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(
- getMethodExpressionMockedObj(MethodOperator.TOLOWER, "currencyCode", null, null, 1), BinaryOperator.EQ,
- getLiteralExpressionMockedObj("'inr rupees'")), TABLE_ALIAS));
- assertEquals(EXPECTED_STR_15, ODataExpressionParser.parseToJPAWhereExpression(getBinaryExpression(
- getMultipleMethodExpressionMockedObj(MethodOperator.SUBSTRINGOF, "'nr rupees'", MethodOperator.TOLOWER,
- "currencyCode", 2, 1), BinaryOperator.EQ, getLiteralExpressionMockedObj("true")), TABLE_ALIAS));
- assertEquals(EXPECTED_STR_16, ODataExpressionParser.parseToJPAWhereExpression(
- getFilterExpressionForFunctionsMockedObj(MethodOperator.SUBSTRINGOF, "'INR'", null, "currencyCode", 2, null)
- /*
- * getBinaryExpression(
- * getMemberExpressionMockedObj(ADDRESS,
- * CITY),
- * BinaryOperator.EQ,
- * getLiteralExpressionMockedObj(SAMPLE_DATA_CITY_3))
- */, TABLE_ALIAS));
- assertEquals(EXPECTED_STR_17, ODataExpressionParser.parseToJPAWhereExpression(
- getFilterExpressionForFunctionsMockedObj(MethodOperator.SUBSTRINGOF, "'nr rupees'", MethodOperator.TOLOWER,
- "currencyCode", 2, 1)
- /*
- * getBinaryExpression(
- * getMemberExpressionMockedObj(ADDRESS,
- * CITY),
- * BinaryOperator.EQ,
- * getLiteralExpressionMockedObj(SAMPLE_DATA_CITY_3))
- */, TABLE_ALIAS));
-
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- }
-
- private CommonExpression getMethodExpressionMockedObj(final MethodOperator methodOperator, final String firstName,
- final String secondName, final String thirdName, final Integer parameterCount) {
-
- List<CommonExpression> parameters = new ArrayList<CommonExpression>();
-
- if (methodOperator == MethodOperator.SUBSTRINGOF) {
- parameters.add(getLiteralExpressionMockedObj(firstName));
- parameters.add(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, secondName));
- } else if (methodOperator == MethodOperator.SUBSTRING) {
- parameters.add(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, firstName));
- parameters.add(getLiteralExpressionMockedObj(secondName));
- parameters.add(getLiteralExpressionMockedObj(thirdName));
- } else if (methodOperator == MethodOperator.TOLOWER) {
- parameters.add(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, firstName));
- }
-
- MethodExpression methodExpression = EasyMock.createMock(MethodExpression.class);
-
- EasyMock.expect(methodExpression.getKind()).andStubReturn(ExpressionKind.METHOD);
- EasyMock.expect(methodExpression.getMethod()).andStubReturn(methodOperator);
- EasyMock.expect(methodExpression.getParameterCount()).andStubReturn(parameterCount);
- EasyMock.expect(methodExpression.getParameters()).andStubReturn(parameters);
- EasyMock.replay(methodExpression);
-
- return methodExpression;
- }
-
- private CommonExpression getMultipleMethodExpressionMockedObj(final MethodOperator methodOperator1,
- final String firstName, final MethodOperator methodOperator2, final String secondName,
- final Integer parameterCount1, final Integer parameterCount2) {
-
- // complex query
- List<CommonExpression> parameters = new ArrayList<CommonExpression>();
-
- parameters.add(getLiteralExpressionMockedObj(firstName));
- parameters.add(getMethodExpressionMockedObj(methodOperator2, secondName, null, null, 1));
-
- MethodExpression methodExpression = EasyMock.createMock(MethodExpression.class);
-
- EasyMock.expect(methodExpression.getKind()).andStubReturn(ExpressionKind.METHOD);
- EasyMock.expect(methodExpression.getMethod()).andStubReturn(methodOperator1);
- EasyMock.expect(methodExpression.getParameterCount()).andStubReturn(parameterCount1);
- EasyMock.expect(methodExpression.getParameters()).andStubReturn(parameters);
- EasyMock.replay(methodExpression);
-
- return methodExpression;
- }
-
- private CommonExpression getMultipleMemberExpressionMockedObj(final String string1, final String string2,
- final String string3) {
-
- MemberExpression memberExpression = EasyMock.createMock(MemberExpression.class);
-
- EasyMock.expect(memberExpression.getPath()).andStubReturn(getMemberExpressionMockedObj(string1, string2));
- EasyMock.expect(memberExpression.getProperty()).andStubReturn(
- getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, string3));
- EasyMock.expect(memberExpression.getKind()).andStubReturn(ExpressionKind.MEMBER);
- EasyMock.replay(memberExpression);
-
- return memberExpression;
- }
-
- @Test
- public void testParseUnaryExpression() {
-
- UnaryExpression unaryExpression =
- getUnaryExpressionMockedObj(getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, "deliveryStatus"),
- org.apache.olingo.odata2.api.uri.expression.UnaryOperator.NOT);
- try {
- assertEquals(EXPECTED_STR_11, ODataExpressionParser.parseToJPAWhereExpression(unaryExpression, TABLE_ALIAS));
- } catch (ODataException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
-
- }
-
- private UnaryExpression
- getUnaryExpressionMockedObj(final CommonExpression operand, final UnaryOperator unaryOperator) {
- UnaryExpression unaryExpression = EasyMock.createMock(UnaryExpression.class);
- EasyMock.expect(unaryExpression.getKind()).andStubReturn(ExpressionKind.UNARY);
- EasyMock.expect(unaryExpression.getOperand()).andStubReturn(operand);
- EasyMock.expect(unaryExpression.getOperator()).andStubReturn(unaryOperator);
-
- EasyMock.replay(unaryExpression);
- return unaryExpression;
- }
-
- private CommonExpression getMemberExpressionMockedObj(final String pathUriLiteral, final String propertyUriLiteral) {
- MemberExpression memberExpression = EasyMock.createMock(MemberExpression.class);
- EasyMock.expect(memberExpression.getPath()).andStubReturn(
- getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, pathUriLiteral));
- EasyMock.expect(memberExpression.getProperty()).andStubReturn(
- getPropertyExpressionMockedObj(ExpressionKind.PROPERTY, propertyUriLiteral));
- EasyMock.expect(memberExpression.getKind()).andStubReturn(ExpressionKind.MEMBER);
-
- EasyMock.replay(memberExpression);
- return memberExpression;
- }
-
- private LiteralExpression getLiteralExpressionMockedObj(final String uriLiteral) {
- LiteralExpression rightOperandLiteralExpresion = EasyMock.createMock(LiteralExpression.class);
- EasyMock.expect(rightOperandLiteralExpresion.getKind()).andStubReturn(ExpressionKind.LITERAL);
- EasyMock.expect(rightOperandLiteralExpresion.getUriLiteral()).andStubReturn(uriLiteral);// SAMPLE_DATA
- EasyMock.expect(rightOperandLiteralExpresion.getEdmType()).andStubReturn(getEdmSimpleTypeMockedObj(uriLiteral));
- EasyMock.replay(rightOperandLiteralExpresion);
- return rightOperandLiteralExpresion;
-
- }
-
- private EdmSimpleType getEdmSimpleTypeMockedObj(final String value) {
- EdmSimpleType edmSimpleType = EasyMock.createMock(EdmSimpleType.class);
- try {
- EasyMock.expect(edmSimpleType.getName()).andReturn(value);
- EasyMock.expect(edmSimpleType.getKind()).andStubReturn(EdmTypeKind.SIMPLE);
- EasyMock.expect(edmSimpleType.valueOfString(value, EdmLiteralKind.URI, getEdmFacetsMockedObj(), null))
- .andStubReturn(value);
- EasyMock.expect(edmSimpleType.valueOfString(value, EdmLiteralKind.URI, null, null)).andStubReturn(value);
- EasyMock.expect(edmSimpleType.valueToString(value, EdmLiteralKind.DEFAULT, getEdmFacetsMockedObj()))
- .andStubReturn(value);
- EasyMock.expect(edmSimpleType.valueToString(value, EdmLiteralKind.DEFAULT, null)).andStubReturn(value);
- } catch (EdmException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- EasyMock.expect(edmSimpleType.getDefaultType()).andStubReturn(null);
- EasyMock.replay(edmSimpleType);
- return edmSimpleType;
- }
-
- private EdmFacets getEdmFacetsMockedObj() {
- EdmFacets facets = EasyMock.createMock(EdmFacets.class);
-
- EasyMock.replay(facets);
- return facets;
- }
-
- private PropertyExpression getPropertyExpressionMockedObj(final ExpressionKind expKind, final String propertyName) {
- PropertyExpression leftOperandPropertyExpresion = EasyMock.createMock(PropertyExpression.class);
- EasyMock.expect(leftOperandPropertyExpresion.getKind()).andStubReturn(ExpressionKind.PROPERTY);
- EasyMock.expect(leftOperandPropertyExpresion.getPropertyName()).andStubReturn(propertyName);
- EasyMock.expect(leftOperandPropertyExpresion.getEdmProperty()).andStubReturn(getEdmTypedMockedObj(propertyName));
- EasyMock.replay(leftOperandPropertyExpresion);
- return leftOperandPropertyExpresion;
- }
-
- private EdmTyped getEdmTypedMockedObj(final String propertyName) {
- EdmProperty mockedEdmProperty = EasyMock.createMock(EdmProperty.class);
- try {
- EasyMock.expect(mockedEdmProperty.getMapping()).andStubReturn(getEdmMappingMockedObj(propertyName));
- EasyMock.replay(mockedEdmProperty);
- } catch (EdmException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- return mockedEdmProperty;
- }
-
- private EdmMapping getEdmMappingMockedObj(final String propertyName) {
- EdmMapping mockedEdmMapping = EasyMock.createMock(EdmMapping.class);
- EasyMock.expect(mockedEdmMapping.getInternalName()).andStubReturn(propertyName);
- EasyMock.replay(mockedEdmMapping);
- return mockedEdmMapping;
- }
-
- private BinaryExpression getBinaryExpressionMockedObj(final BinaryOperator operator,
- final ExpressionKind leftOperandExpKind, final String propertyName, final String literalStr) {
- BinaryExpression binaryExpression = EasyMock.createMock(BinaryExpression.class);
- EasyMock.expect(binaryExpression.getKind()).andStubReturn(ExpressionKind.BINARY);
- EasyMock.expect(binaryExpression.getLeftOperand()).andStubReturn(
- getPropertyExpressionMockedObj(leftOperandExpKind, propertyName));
- EasyMock.expect(binaryExpression.getOperator()).andStubReturn(operator);
- EasyMock.expect(binaryExpression.getRightOperand()).andStubReturn(getLiteralExpressionMockedObj(literalStr));
-
- EasyMock.replay(binaryExpression);
- return binaryExpression;
- }
-
- private FilterExpression getFilterExpressionMockedObj(final ExpressionKind leftOperandExpKind,
- final String propertyName) {
- FilterExpression filterExpression = EasyMock.createMock(FilterExpression.class);
- EasyMock.expect(filterExpression.getKind()).andStubReturn(ExpressionKind.FILTER);
- EasyMock.expect(filterExpression.getExpression()).andStubReturn(
- getPropertyExpressionMockedObj(leftOperandExpKind, propertyName));
-
- EasyMock.replay(filterExpression);
- return filterExpression;
- }
-
- private FilterExpression getFilterExpressionForFunctionsMockedObj(final MethodOperator methodOperator1,
- final String firstName, final MethodOperator methodOperator2, final String secondName,
- final Integer parameterCount1, final Integer parameterCount2) {
- // default value handling of SUBSTRINGOF
- FilterExpression filterExpression = EasyMock.createMock(FilterExpression.class);
- EasyMock.expect(filterExpression.getKind()).andStubReturn(ExpressionKind.FILTER);
- if ((methodOperator2 != null) && (parameterCount2 != null)) {
- EasyMock.expect(filterExpression.getExpression()).andStubReturn(
- getMultipleMethodExpressionMockedObj(methodOperator1, firstName, methodOperator2, secondName,
- parameterCount1, parameterCount2));
- } else {
- EasyMock.expect(filterExpression.getExpression()).andStubReturn(
- getMethodExpressionMockedObj(methodOperator1, firstName, secondName, null, parameterCount1));
- }
-
- EasyMock.replay(filterExpression);
- return filterExpression;
- }
-
- private CommonExpression getBinaryExpression(final CommonExpression leftOperand, final BinaryOperator operator,
- final CommonExpression rightOperand) {
- BinaryExpression binaryExpression = EasyMock.createMock(BinaryExpression.class);
- EasyMock.expect(binaryExpression.getKind()).andStubReturn(ExpressionKind.BINARY);
- EasyMock.expect(binaryExpression.getLeftOperand()).andStubReturn(leftOperand);
- EasyMock.expect(binaryExpression.getRightOperand()).andStubReturn(rightOperand);
- EasyMock.expect(binaryExpression.getOperator()).andStubReturn(operator);
-
- EasyMock.replay(binaryExpression);
- return binaryExpression;
- }
-
- @Test
- public void testParseKeyPredicates() {
- // Setting up the expected value
- KeyPredicate keyPredicate1 = EasyMock.createMock(KeyPredicate.class);
- EdmProperty kpProperty1 = EasyMock.createMock(EdmProperty.class);
- EasyMock.expect(keyPredicate1.getLiteral()).andStubReturn("1");
- KeyPredicate keyPredicate2 = EasyMock.createMock(KeyPredicate.class);
- EdmProperty kpProperty2 = EasyMock.createMock(EdmProperty.class);
- EasyMock.expect(keyPredicate2.getLiteral()).andStubReturn("abc");
- EdmMapping edmMapping = EasyMock.createMock(EdmMapping.class);
- try {
- EasyMock.expect(kpProperty1.getName()).andStubReturn(SAMPLE_DATA_FIELD1);
- EasyMock.expect(kpProperty1.getType()).andStubReturn(EdmSimpleTypeKind.Int32.getEdmSimpleTypeInstance());
- EasyMock.expect(kpProperty2.getName()).andStubReturn(SAMPLE_DATA_FIELD2);
- EasyMock.expect(kpProperty2.getType()).andStubReturn(EdmSimpleTypeKind.String.getEdmSimpleTypeInstance());
- EasyMock.expect(keyPredicate1.getProperty()).andStubReturn(kpProperty1);
- EasyMock.expect(kpProperty1.getMapping()).andReturn(edmMapping);
- EasyMock.expect(edmMapping.getInternalName()).andReturn(SAMPLE_DATA_FIELD1);
- EasyMock.expect(keyPredicate2.getProperty()).andStubReturn(kpProperty2);
- EasyMock.expect(kpProperty2.getMapping()).andReturn(edmMapping);
- } catch (EdmException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
- EasyMock.expect(edmMapping.getInternalName()).andReturn(SAMPLE_DATA_FIELD2);
- EasyMock.replay(edmMapping);
- EasyMock.replay(kpProperty1, keyPredicate1, kpProperty2, keyPredicate2);
-
- ArrayList<KeyPredicate> keyPredicates = new ArrayList<KeyPredicate>();
- keyPredicates.add(keyPredicate1);
- keyPredicates.add(keyPredicate2);
- String str = null;
-
- try {
- str = ODataExpressionParser.parseKeyPredicates(keyPredicates, TABLE_ALIAS);
- } catch (ODataJPARuntimeException e) {
- fail(ODataJPATestConstants.EXCEPTION_MSG_PART_1 + e.getMessage() + ODataJPATestConstants.EXCEPTION_MSG_PART_2);
- }
-
- assertEquals(EXPECTED_STR_8, str);
- }
-
- @Test
- public void testParseToJPASelectExpression() {
-
- ArrayList<String> selectedFields = new ArrayList<String>();
- selectedFields.add("BuyerAddress");
- selectedFields.add("BuyerName");
- selectedFields.add("BuyerId");
-
- assertEquals(EXPECTED_STR_9, ODataExpressionParser.parseToJPASelectExpression(TABLE_ALIAS, selectedFields));
- assertEquals(TABLE_ALIAS, ODataExpressionParser.parseToJPASelectExpression(TABLE_ALIAS, null));
-
- selectedFields.clear();
- assertEquals(TABLE_ALIAS, ODataExpressionParser.parseToJPASelectExpression(TABLE_ALIAS, selectedFields));
- }
-}
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java
new file mode 100644
index 0000000..33419d5
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ODataFilterExpressionParserTest {
+ private static final short INPUT = 0;
+ private static final short OUTPUT = 1;
+ private static final String TABLE_ALIAS = "E1";
+ private static final String NAMESPACE = "SalesOrderProcessing";
+ private static final String ENTITY_NOTE = "Note";
+ // Index 0 - Is test input and Index 1 - Is expected output
+ private static final String[] EXPRESSION_EQ = { "id eq '123'", "(E1.id = '123')" };
+ private static final String[] EXPRESSION_NE = { "id ne '123'", "(E1.id <> '123')" };
+ private static final String[] EXPRESSION_ESCAPE = { "id ne '123''22'", "(E1.id <> '123''22')" };
+ private static final String[] EXPRESSION_BINARY_AND =
+ {
+ "id le '123' and soId eq 123L and not (substringof(id,'123') eq false) eq true",
+ "(((E1.id <= '123') AND (E1.soId = 123L)) AND (NOT(((CASE WHEN ('123' LIKE CONCAT('%',E1.id,'%')) "
+ + "THEN TRUE ELSE FALSE END) = false)) = true))" };
+ private static final String[] EXPRESSION_BINARY_OR = { "id ge '123' or soId gt 123L",
+ "((E1.id >= '123') OR (E1.soId > 123L))" };
+ private static final String[] EXPRESSION_MEMBER_OR = { "id lt '123' or oValue/Currency eq 'INR'",
+ "((E1.id < '123') OR (E1.oValue.Currency = 'INR'))" };
+ private static final String[] EXPRESSION_STARTS_WITH = { "startswith(oValue/Currency,'INR')",
+ "E1.oValue.Currency LIKE CONCAT('INR','%')" };
+ private static final String[] EXPRESSION_STARTS_WITH_EQUAL = { "startswith(oValue/Currency,'INR') eq true",
+ "(E1.oValue.Currency LIKE CONCAT('INR','%') )" };
+ private static final String[] EXPRESSION_NOT_STARTS_WITH = { "startswith(oValue/Currency,'INR') eq false",
+ "(E1.oValue.Currency NOT LIKE CONCAT('INR','%') )" };
+ private static final String[] EXPRESSION_NOT_ENDS_WITH = { "endswith(oValue/Currency,tolower('INR')) eq false",
+ "(E1.oValue.Currency NOT LIKE CONCAT('%',LOWER('INR')) )" };
+ private static final String[] EXPRESSION_NESTED_METHOD = {
+ "endswith(substring(oValue/Currency,2),'INR') eq false",
+ "(SUBSTRING(E1.oValue.Currency, 2L + 1 ) NOT LIKE CONCAT('%','INR') )" };
+ private static final String[] EXPRESSION_SUBSTRING_OF = {
+ "substringof(id,'123') ne true",
+ "((CASE WHEN ('123' LIKE CONCAT('%',E1.id,'%')) THEN TRUE ELSE FALSE END) <> true)" };
+ private static final String[] EXPRESSION_STARTS_WITH_WRONG_OP = { "startswith(oValue/Currency,'INR') lt true", "" };
+ private static final String[] EXPRESSION_SUBSTRING_ALL_OP = { "substring(oValue/Currency,1,3) eq 'INR'",
+ "(SUBSTRING(E1.oValue.Currency, 1L + 1 , 3L) = 'INR')" };
+ private static final String[] EXPRESSION_SUBSTRINGOF_INJECTION1 = {
+ "substringof('a'' OR 1=1 OR E1.id LIKE ''b',id) eq true",
+ "((CASE WHEN (E1.id LIKE CONCAT('%','a'' OR 1=1 OR E1.id LIKE ''b','%')) THEN TRUE ELSE FALSE END) = true)" };
+ private static final String[] EXPRESSION_SUBSTRINGOF_INJECTION2 =
+ {
+ "substringof('substringof(''a'' OR 1=1 OR E1.id LIKE ''b'',id)',id) eq true",
+ "((CASE WHEN (E1.id LIKE CONCAT('%','substringof(''a'' OR 1=1 OR E1.id LIKE ''b'',id)','%')) "
+ + "THEN TRUE ELSE FALSE END) = true)" };
+ private static final String[] EXPRESSION_SUBSTRINGOF_INJECTION3 =
+ {
+ "substringof( substring(' ) OR execute_my_sql OR '' LIKE ',3),'de''') eq true",
+ "((CASE WHEN ('de''' LIKE CONCAT('%',SUBSTRING(' ) OR execute_my_sql OR '' LIKE ', 3L + 1 ),'%')) "
+ + "THEN TRUE ELSE FALSE END) = true)" };
+ private static final String[] EXPRESSION_ENDSWITH_INJECTION1 = { "endswith(id,'Str''eet') eq true",
+ "(E1.id LIKE CONCAT('%','Str''eet') )" };
+ private static final String[] EXPRESSION_PRECEDENCE = {
+ "id eq '123' and id ne '123' or (id eq '123' and id ne '123')",
+ "(((E1.id = '123') AND (E1.id <> '123')) OR ((E1.id = '123') AND (E1.id <> '123')))" };
+ private static final String[] EXPRESSION_DATETIME = { "date eq datetime'2000-01-01T00:00:00'",
+ "(E1.date = {ts '2000-01-01 00:00:00.000'})" };
+ private static Edm edm = null;
+
+ @BeforeClass
+ public static void setup() {
+ InputStream metadataStream =
+ ODataFilterExpressionParserTest.class.getClassLoader().getResourceAsStream("metadata.xml");
+ try {
+ edm = EntityProvider.readMetadata(metadataStream, true);
+ } catch (EntityProviderException e) {
+ fail("Not expected");
+ }
+ }
+
+ @Test
+ public void testDateTime() {
+ assertEquals(EXPRESSION_DATETIME[OUTPUT], parseWhereExpression(
+ EXPRESSION_DATETIME[INPUT], false));
+ }
+
+ @Test
+ public void testPrecedence() {
+ assertEquals(EXPRESSION_PRECEDENCE[OUTPUT], parseWhereExpression(
+ EXPRESSION_PRECEDENCE[INPUT], false));
+ }
+
+ @Test
+ public void testSubStringOfSQLInjection() {
+ assertEquals(EXPRESSION_SUBSTRINGOF_INJECTION1[OUTPUT], parseWhereExpression(
+ EXPRESSION_SUBSTRINGOF_INJECTION1[INPUT], false));
+ assertEquals(EXPRESSION_SUBSTRINGOF_INJECTION2[OUTPUT], parseWhereExpression(
+ EXPRESSION_SUBSTRINGOF_INJECTION2[INPUT], false));
+ assertEquals(EXPRESSION_SUBSTRINGOF_INJECTION3[OUTPUT], parseWhereExpression(
+ EXPRESSION_SUBSTRINGOF_INJECTION3[INPUT], false));
+ }
+
+ @Test
+ public void testEndsWithSQLInjection() {
+ assertEquals(EXPRESSION_ENDSWITH_INJECTION1[OUTPUT], parseWhereExpression(
+ EXPRESSION_ENDSWITH_INJECTION1[INPUT], false));
+ }
+
+ @Test
+ public void testSubStringWithAllOperator() {
+ assertEquals(EXPRESSION_SUBSTRING_ALL_OP[OUTPUT], parseWhereExpression(EXPRESSION_SUBSTRING_ALL_OP[INPUT], false));
+ }
+
+ @Test
+ public void testStartsWithWrongOperator() {
+ parseWhereExpression(EXPRESSION_STARTS_WITH_WRONG_OP[INPUT], true);
+ }
+
+ @Test
+ public void testSubStringOf() {
+ assertEquals(EXPRESSION_SUBSTRING_OF[OUTPUT], parseWhereExpression(EXPRESSION_SUBSTRING_OF[INPUT], false));
+ }
+
+ @Test
+ public void testStartsWithEqual() {
+ assertEquals(EXPRESSION_STARTS_WITH_EQUAL[OUTPUT], parseWhereExpression(EXPRESSION_STARTS_WITH_EQUAL[INPUT],
+ false));
+ }
+
+ @Test
+ public void testEscapeCharacters() {
+ assertEquals(EXPRESSION_ESCAPE[OUTPUT], parseWhereExpression(EXPRESSION_ESCAPE[INPUT], false));
+ }
+
+ @Test
+ public void testNotEndsWithToLowerMethod() {
+ assertEquals(EXPRESSION_NOT_ENDS_WITH[OUTPUT], parseWhereExpression(EXPRESSION_NOT_ENDS_WITH[INPUT], false));
+ }
+
+ @Test
+ public void testNestedMethod() {
+ assertEquals(EXPRESSION_NESTED_METHOD[OUTPUT], parseWhereExpression(EXPRESSION_NESTED_METHOD[INPUT], false));
+ }
+
+ @Test
+ public void testNotStartsWith() {
+ assertEquals(EXPRESSION_NOT_STARTS_WITH[OUTPUT], parseWhereExpression(EXPRESSION_NOT_STARTS_WITH[INPUT], false));
+ }
+
+ @Test
+ public void testStartsWith() {
+ assertEquals(EXPRESSION_STARTS_WITH[OUTPUT], parseWhereExpression(EXPRESSION_STARTS_WITH[INPUT], false));
+ }
+
+ @Test
+ public void testSimpleEqRelation() {
+ assertEquals(EXPRESSION_EQ[OUTPUT], parseWhereExpression(EXPRESSION_EQ[INPUT], false));
+ }
+
+ @Test
+ public void testSimpleNeRelation() {
+ assertEquals(EXPRESSION_NE[OUTPUT], parseWhereExpression(EXPRESSION_NE[INPUT], false));
+ }
+
+ @Test
+ public void testBinaryAnd() {
+ assertEquals(EXPRESSION_BINARY_AND[OUTPUT], parseWhereExpression(EXPRESSION_BINARY_AND[INPUT], false));
+ }
+
+ @Test
+ public void testBinaryOr() {
+ assertEquals(EXPRESSION_BINARY_OR[OUTPUT], parseWhereExpression(EXPRESSION_BINARY_OR[INPUT], false));
+ }
+
+ @Test
+ public void testMemberOr() {
+ assertEquals(EXPRESSION_MEMBER_OR[OUTPUT], parseWhereExpression(EXPRESSION_MEMBER_OR[INPUT], false));
+ }
+
+ private String parseWhereExpression(final String input, final boolean isExceptionExpected) {
+ FilterExpression expression;
+ try {
+ expression = UriParser.parseFilter(edm, edm.getEntityType(NAMESPACE, ENTITY_NOTE), input);
+ String expressionString = ODataExpressionParser.parseToJPAWhereExpression(expression, TABLE_ALIAS);
+ return expressionString;
+ } catch (ExpressionParserException e) {
+ fail("Not expected");
+ } catch (EdmException e) {
+ fail("Not expected");
+ } catch (ODataMessageException e) {
+ fail("Not expected");
+ } catch (ODataException e) {
+ if (isExceptionExpected) {
+ assertTrue(true);
+ } else {
+ fail("Not expected");
+ }
+ }
+ return "";
+ }
+}
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataSelectExpressionParserTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataSelectExpressionParserTest.java
new file mode 100644
index 0000000..cbfab7b
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataSelectExpressionParserTest.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ******************************************************************************/
+package org.apache.olingo.odata2.jpa.processor.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+import org.apache.olingo.odata2.api.edm.Edm;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.ep.EntityProvider;
+import org.apache.olingo.odata2.api.ep.EntityProviderException;
+import org.apache.olingo.odata2.api.exception.ODataException;
+import org.apache.olingo.odata2.api.exception.ODataMessageException;
+import org.apache.olingo.odata2.api.uri.UriParser;
+import org.apache.olingo.odata2.api.uri.expression.ExpressionParserException;
+import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
+import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ODataSelectExpressionParserTest {
+ private static final String TABLE_ALIAS = "E1";
+ private static final short INPUT = 0;
+ private static final short OUTPUT = 1;
+ private static final String NAMESPACE = "SalesOrderProcessing";
+ private static final String ENTITY_NOTE = "Note";
+ private static Edm edm = null;
+ private static final String[] EXPRESSION_ORDERBY = { "id,soId", "E1.id , E1.soId" };
+ private static final String[] EXPRESSION_ORDERBY_ASC = { "id asc,soId", "E1.id , E1.soId" };
+ private static final String[] EXPRESSION_ORDERBY_DESC = { "id desc,soId", "E1.id DESC , E1.soId" };
+ private static final String[] EXPRESSION_ORDERBY_ASC_DESC = { "id desc,soId asc", "E1.id DESC , E1.soId" };
+ private static final String[] EXPRESSION_ORDERBY_SINGLE = { "id desc", "E1.id DESC" };
+
+ @BeforeClass
+ public static void setup() {
+ InputStream metadataStream =
+ ODataFilterExpressionParserTest.class.getClassLoader().getResourceAsStream("metadata.xml");
+ try {
+ edm = EntityProvider.readMetadata(metadataStream, true);
+ } catch (EntityProviderException e) {
+ fail("Not expected");
+ }
+ }
+
+ @Test
+ public void testSelectExpression() {
+ ArrayList<String> selectedFields = new ArrayList<String>();
+ selectedFields.add("id");
+ selectedFields.add("oValue/Currency");
+ assertEquals("E1.id, E1.oValue/Currency",
+ ODataExpressionParser.parseToJPASelectExpression(TABLE_ALIAS, selectedFields));
+ }
+
+ @Test
+ public void testOrderByExpressionSingle() {
+ assertEquals(EXPRESSION_ORDERBY_SINGLE[OUTPUT], parseOrderByExpression(EXPRESSION_ORDERBY_SINGLE[INPUT], false));
+ }
+
+ @Test
+ public void testOrderByExpression() {
+ assertEquals(EXPRESSION_ORDERBY[OUTPUT], parseOrderByExpression(EXPRESSION_ORDERBY[INPUT], false));
+ }
+
+ @Test
+ public void testOrderByExpressionAsc() {
+ assertEquals(EXPRESSION_ORDERBY_ASC[OUTPUT], parseOrderByExpression(EXPRESSION_ORDERBY_ASC[INPUT], false));
+ }
+
+ @Test
+ public void testOrderByExpressionDesc() {
+ assertEquals(EXPRESSION_ORDERBY_DESC[OUTPUT], parseOrderByExpression(EXPRESSION_ORDERBY_DESC[INPUT], false));
+ }
+
+ @Test
+ public void testOrderByExpressionAscDesc() {
+ assertEquals(EXPRESSION_ORDERBY_ASC_DESC[OUTPUT], parseOrderByExpression(EXPRESSION_ORDERBY_ASC_DESC[INPUT],
+ false));
+ }
+
+ @Test
+ public void testOrderByKeyPredicates() {
+ try {
+ assertEquals("E1.id", ODataExpressionParser.parseKeyPropertiesToJPAOrderByExpression(edm.getEntityType(NAMESPACE,
+ ENTITY_NOTE)
+ .getKeyProperties(), TABLE_ALIAS));
+ } catch (ODataJPARuntimeException e) {
+ fail("Not expected");
+ } catch (EdmException e) {
+ fail("Not expected");
+ }
+ }
+
+ @Test
+ public void testOrderByKeyPredicatesNull() {
+ try {
+ assertEquals("", ODataExpressionParser.parseKeyPropertiesToJPAOrderByExpression(null, TABLE_ALIAS));
+ } catch (ODataJPARuntimeException e) {
+ fail("Not expected");
+ }
+ }
+
+ private String parseOrderByExpression(final String input, final boolean isExceptionExpected) {
+ OrderByExpression expression;
+ try {
+ expression = UriParser.parseOrderBy(edm, edm.getEntityType(NAMESPACE, ENTITY_NOTE), input);
+ String expressionString = ODataExpressionParser.parseToJPAOrderByExpression(expression, TABLE_ALIAS);
+ return expressionString;
+ } catch (ExpressionParserException e) {
+ fail("Not expected");
+ } catch (EdmException e) {
+ fail("Not expected");
+ } catch (ODataMessageException e) {
+ fail("Not expected");
+ } catch (ODataException e) {
+ if (isExceptionExpected) {
+ assertTrue(true);
+ } else {
+ fail("Not expected");
+ }
+ }
+ return "";
+ }
+}
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinContextTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinContextTest.java
index c94160c..293b0af 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinContextTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinContextTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContextTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContextTest.java
index 117d21f..73b93c4 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContextTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContextTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilderTest.java
index b5412a8..7b6b8c4 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilderTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -88,7 +88,7 @@
assertEquals(
"SELECT gt1 FROM SOHeader soh JOIN soh.soItem soi JOIN soi.material mat WHERE soh.soId = 1 AND " +
"soi.shId = soh.soId AND mat.id = 'abc'",
- jpqlStatement.toString());
+ jpqlStatement.toString());
} catch (ODataJPARuntimeException e) {
fail("Should not have come here");
}
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilderTest.java
index 2a0d4f7..5701a4c 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilderTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -23,7 +23,6 @@
import static org.junit.Assert.fail;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import org.apache.olingo.odata2.jpa.processor.api.access.JPAJoinClause;
@@ -53,9 +52,7 @@
EasyMock.expect(context.getType()).andStubReturn(JPQLContextType.SELECT);
EasyMock.expect(context.getSelectExpression()).andStubReturn("mat");
EasyMock.expect(context.getWhereExpression()).andStubReturn("soh.buyerId = 2");
- HashMap<String, String> orderByMap = new HashMap<String, String>();
- orderByMap.put("mat.buyerId", "asc");
- orderByMap.put("mat.city", "desc");
+ String orderByMap = new String("mat.buyerId asc , mat.city desc");
EasyMock.expect(context.getOrderByCollection()).andStubReturn(orderByMap);
EasyMock.expect(context.getJPAJoinClauses()).andStubReturn(joinClauseList);
EasyMock.replay(context);
@@ -90,7 +87,7 @@
"soh.createdBy = 'Peter' AND soi.shId = soh.soId AND mat.id = 'abc' "
+
"ORDER BY mat.buyerId asc , mat.city desc",
- jpqlStatement.toString());
+ jpqlStatement.toString());
} catch (ODataJPARuntimeException e) {
fail("Should not have come here");
}
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContextImplTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContextImplTest.java
index e793817..2f81bf4 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContextImplTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContextImplTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -269,11 +269,7 @@
@Test
public void testGetOrderByCollection() {
buildSelectContext(false, false, true, true, true);
- assertEquals(true, selectContext.getOrderByCollection().containsKey("E1." + JPQLSelectContextImplTest.fields[0]));
- assertEquals("", selectContext.getOrderByCollection().get("E1." + JPQLSelectContextImplTest.fields[0]));
-
- assertEquals(true, selectContext.getOrderByCollection().containsKey("E1." + JPQLSelectContextImplTest.fields[1]));
- assertEquals("DESC", selectContext.getOrderByCollection().get("E1." + JPQLSelectContextImplTest.fields[1]));
+ assertEquals("E1.Field1 , E1.Field2 DESC", selectContext.getOrderByCollection());
}
@Test
@@ -324,21 +320,14 @@
@Test
public void testOrderingWithSkip() {
buildSelectContext(true, false, true, true, false);
- assertEquals(true, selectContext.getOrderByCollection().containsKey("E1." + JPQLSelectContextImplTest.fields[0]));
- assertEquals("", selectContext.getOrderByCollection().get("E1." + JPQLSelectContextImplTest.fields[0]));
-
- assertEquals(false, selectContext.getOrderByCollection().containsKey("E1." + JPQLSelectContextImplTest.fields[1]));
+ assertEquals("E1.Field1", selectContext.getOrderByCollection());
}
@Test
public void testOrderingWithTop() {
buildSelectContext(true, false, true, false, true);
- assertEquals(true, selectContext.getOrderByCollection().containsKey("E1." + JPQLSelectContextImplTest.fields[0]));
- assertEquals("", selectContext.getOrderByCollection().get("E1." + JPQLSelectContextImplTest.fields[0]));
-
- assertEquals(false, selectContext.getOrderByCollection().containsKey("E1." + JPQLSelectContextImplTest.fields[1]));
-
+ assertEquals("E1.Field1", selectContext.getOrderByCollection());
}
@Test
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContextImplTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContextImplTest.java
index 0394e54..7c4ecbb 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContextImplTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContextImplTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilderTest.java
index 25fd5ae..58cddc7 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilderTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
diff --git a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilderTest.java b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilderTest.java
index 617365b..843ace4 100644
--- a/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilderTest.java
+++ b/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilderTest.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -17,14 +17,13 @@
* under the License.
******************************************************************************/
/**
- *
+ *
*/
package org.apache.olingo.odata2.jpa.processor.core.jpql;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
-import java.util.HashMap;
import java.util.List;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
@@ -109,10 +108,7 @@
OrderByExpression orderByExpression = EasyMock.createMock(OrderByExpression.class);
JPQLSelectContext jpqlSelectContextImpl = createSelectContext(orderByExpression, null);
- HashMap<String, String> orderByCollection = new HashMap<String, String>();
- orderByCollection.put("E1.soID", "ASC");
- orderByCollection.put("E1.buyerId", "DESC");
- jpqlSelectContextImpl.setOrderByCollection(orderByCollection);
+ jpqlSelectContextImpl.setOrderByCollection("E1.soID ASC , E1.buyerId DESC");
jpqlSelectStatementBuilder = new JPQLSelectStatementBuilder(jpqlSelectContextImpl);
assertEquals("SELECT E1 FROM SalesOrderHeader E1 ORDER BY E1.soID ASC , E1.buyerId DESC",
diff --git a/odata2-jpa-processor/jpa-core/src/test/resources/metadata.xml b/odata2-jpa-processor/jpa-core/src/test/resources/metadata.xml
index 1fd46a4..96f7c99 100644
--- a/odata2-jpa-processor/jpa-core/src/test/resources/metadata.xml
+++ b/odata2-jpa-processor/jpa-core/src/test/resources/metadata.xml
@@ -1,62 +1,71 @@
<?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.
--->
-<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
- <edmx:DataServices m:DataServiceVersion="1.0" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
- <Schema Namespace="SalesOrderProcessing" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ you under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License. -->
+<edmx:Edmx Version="1.0"
+ xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx">
+ <edmx:DataServices m:DataServiceVersion="1.0"
+ xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
+ <Schema Namespace="SalesOrderProcessing"
+ xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityType Name="Note">
<Key>
- <PropertyRef Name="id"/>
+ <PropertyRef Name="id" />
</Key>
- <Property Name="id" Type="Edm.String" Nullable="false"/>
- <Property Name="soId" Type="Edm.Int64" Nullable="true"/>
- <Property Name="text" Type="Edm.String" Nullable="true" MaxLength="255"/>
- <NavigationProperty Name="salesOrderHeader" Relationship="SalesOrderProcessing.Note_SalesOrder" FromRole="Note" ToRole="SalesOrder"/>
+ <Property Name="id" Type="Edm.String" Nullable="false" />
+ <Property Name="soId" Type="Edm.Int64" Nullable="true" />
+ <Property Name="oValue" Type="SalesOrderProcessing.OrderValue" />
+ <Property Name="date" Type="Edm.DateTime" Nullable="false" />
+ <Property Name="time" Type="Edm.Time" Nullable="false" />
+ <Property Name="text" Type="Edm.String" Nullable="true"
+ MaxLength="255" />
+ <NavigationProperty Name="salesOrderHeader"
+ Relationship="SalesOrderProcessing.Note_SalesOrder" FromRole="Note"
+ ToRole="SalesOrder" />
</EntityType>
<EntityType Name="SalesOrder">
<Key>
- <PropertyRef Name="ID"/>
+ <PropertyRef Name="ID" />
</Key>
- <Property Name="ID" Type="Edm.Int64" Nullable="false"/>
- <NavigationProperty Name="NotesDetails" Relationship="SalesOrderProcessing.Note_SalesOrder" FromRole="SalesOrder" ToRole="Note"/>
+ <Property Name="ID" Type="Edm.Int64" Nullable="false" />
+ <NavigationProperty Name="NotesDetails"
+ Relationship="SalesOrderProcessing.Note_SalesOrder" FromRole="SalesOrder"
+ ToRole="Note" />
</EntityType>
-
+ <ComplexType Name="OrderValue">
+ <Property Name="Amount" Type="Edm.Double" />
+ <Property Name="Currency" Type="Edm.String" />
+ </ComplexType>
<Association Name="Note_SalesOrder">
- <End Type="SalesOrderProcessing.Note" Multiplicity="*" Role="Note"/>
- <End Type="SalesOrderProcessing.SalesOrder" Multiplicity="1" Role="SalesOrder"/>
+ <End Type="SalesOrderProcessing.Note" Multiplicity="*" Role="Note" />
+ <End Type="SalesOrderProcessing.SalesOrder" Multiplicity="1"
+ Role="SalesOrder" />
<ReferentialConstraint>
<Principal Role="SalesOrder">
- <PropertyRef Name="ID"/>
+ <PropertyRef Name="ID" />
</Principal>
<Dependent Role="Note">
- <PropertyRef Name="soId"/>
+ <PropertyRef Name="soId" />
</Dependent>
</ReferentialConstraint>
</Association>
- <EntityContainer Name="SalesOrderProcessingContainer" m:IsDefaultEntityContainer="true">
- <EntitySet Name="Notes" EntityType="SalesOrderProcessing.Note"/>
- <EntitySet Name="SalesOrders" EntityType="SalesOrderProcessing.SalesOrder"/>
+ <EntityContainer Name="SalesOrderProcessingContainer"
+ m:IsDefaultEntityContainer="true">
+ <EntitySet Name="Notes" EntityType="SalesOrderProcessing.Note" />
+ <EntitySet Name="SalesOrders" EntityType="SalesOrderProcessing.SalesOrder" />
- <AssociationSet Name="Note_SalesOrderSet" Association="SalesOrderProcessing.Note_SalesOrder">
- <End EntitySet="Notes" Role="Note"/>
- <End EntitySet="SalesOrders" Role="SalesOrder"/>
+ <AssociationSet Name="Note_SalesOrderSet"
+ Association="SalesOrderProcessing.Note_SalesOrder">
+ <End EntitySet="Notes" Role="Note" />
+ <End EntitySet="SalesOrders" Role="SalesOrder" />
</AssociationSet>
</EntityContainer>