[OLINGO-644 and OLINGO-647] Support for nested method expressions in $filter and preserve order by clause order
Signed-off-by: Chandan V A <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/olingo-odata2/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata2/commit/bd4e7efd Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata2/tree/bd4e7efd Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata2/diff/bd4e7efd Branch: refs/heads/master Commit: bd4e7efd9977ea0b3b9dbb609cb7b6be62ecd36a Parents: 763755f Author: Chandan V A <[email protected]> Authored: Sun May 3 13:35:49 2015 +0530 Committer: Chandan V A <[email protected]> Committed: Sun May 3 13:35:49 2015 +0530 ---------------------------------------------------------------------- .../api/jpql/JPQLSelectContextView.java | 14 +- .../processor/core/ODataExpressionParser.java | 133 ++--- .../core/jpql/JPQLJoinSelectContext.java | 4 +- .../core/jpql/JPQLJoinSelectSingleContext.java | 4 +- .../JPQLJoinSelectSingleStatementBuilder.java | 4 +- .../core/jpql/JPQLJoinStatementBuilder.java | 23 +- .../processor/core/jpql/JPQLSelectContext.java | 16 +- .../core/jpql/JPQLSelectSingleContext.java | 6 +- .../jpql/JPQLSelectSingleStatementBuilder.java | 4 +- .../core/jpql/JPQLSelectStatementBuilder.java | 24 +- .../core/ODataExpressionParserTest.java | 515 ------------------- .../core/ODataFilterExpressionParserTest.java | 228 ++++++++ .../core/ODataSelectExpressionParserTest.java | 143 +++++ .../core/jpql/JPQLJoinContextTest.java | 4 +- .../jpql/JPQLJoinSelectSingleContextTest.java | 4 +- ...PQLJoinSelectSingleStatementBuilderTest.java | 6 +- .../core/jpql/JPQLJoinStatementBuilderTest.java | 11 +- .../core/jpql/JPQLSelectContextImplTest.java | 21 +- .../jpql/JPQLSelectSingleContextImplTest.java | 4 +- .../JPQLSelectSingleStatementBuilderTest.java | 4 +- .../jpql/JPQLSelectStatementBuilderTest.java | 12 +- .../jpa-core/src/test/resources/metadata.xml | 89 ++-- 22 files changed, 545 insertions(+), 728 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-api/src/main/java/org/apache/olingo/odata2/jpa/processor/api/jpql/JPQLSelectContextView.java ---------------------------------------------------------------------- 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 interface JPQLSelectContextView extends JPQLContextView { 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParser.java ---------------------------------------------------------------------- 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 @@ package org.apache.olingo.odata2.jpa.processor.core; 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 @@ import org.apache.olingo.odata2.jpa.processor.api.jpql.JPQLStatement; /** * 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 @@ public class ODataExpressionParser { /** * 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 @@ public class ODataExpressionParser { } 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 @@ public class ODataExpressionParser { 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 @@ public class ODataExpressionParser { 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 @@ public class ODataExpressionParser { /** * This method parses the select clause - * + * * @param tableAlias * @param selectedFields * @return a select expression @@ -270,14 +262,14 @@ public class ODataExpressionParser { /** * 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 @@ public class ODataExpressionParser { 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 class ODataExpressionParser { } } - 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 @@ public class ODataExpressionParser { } 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 @@ public class ODataExpressionParser { 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 @@ public class ODataExpressionParser { 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; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectContext.java 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContext.java 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java ---------------------------------------------------------------------- diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilder.java 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilder.java ---------------------------------------------------------------------- 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 @@ public class JPQLJoinStatementBuilder extends JPQLStatementBuilder { } - 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); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectContext.java ---------------------------------------------------------------------- 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 @@ import org.apache.olingo.odata2.jpa.processor.core.ODataExpressionParser; 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 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV 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 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV } @Override - public HashMap<String, String> getOrderByCollection() { + public String getOrderByCollection() { return orderByCollection; } @@ -72,7 +70,7 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV } 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 @@ public class JPQLSelectContext extends JPQLContext implements JPQLSelectContextV /* * Generate Order By Clause Fields */ - protected HashMap<String, String> generateOrderByFileds() throws ODataJPARuntimeException, EdmException { + protected String generateOrderByFileds() throws ODataJPARuntimeException, EdmException { if (entitySetView.getOrderBy() != null) { http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleContext.java ---------------------------------------------------------------------- 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 JPQLSelectSingleContext extends JPQLContext implements JPQLSelectSi } 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; http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectSingleStatementBuilder.java ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLSelectStatementBuilder.java ---------------------------------------------------------------------- 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 @@ public class JPQLSelectStatementBuilder extends JPQLStatementBuilder { 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); http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataExpressionParserTest.java ---------------------------------------------------------------------- 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)); - } -} http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataFilterExpressionParserTest.java ---------------------------------------------------------------------- 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 ""; + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/ODataSelectExpressionParserTest.java ---------------------------------------------------------------------- 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 ""; + } +} http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinContextTest.java ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleContextTest.java ---------------------------------------------------------------------- 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 http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinSelectSingleStatementBuilderTest.java ---------------------------------------------------------------------- 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 @@ public class JPQLJoinSelectSingleStatementBuilderTest { 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"); } http://git-wip-us.apache.org/repos/asf/olingo-odata2/blob/bd4e7efd/odata2-jpa-processor/jpa-core/src/test/java/org/apache/olingo/odata2/jpa/processor/core/jpql/JPQLJoinStatementBuilderTest.java ---------------------------------------------------------------------- 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.assertTrue; 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 @@ public class JPQLJoinStatementBuilderTest { 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 @@ public class JPQLJoinStatementBuilderTest { "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"); }
