You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2016/04/18 15:07:50 UTC
[2/3] olingo-odata4 git commit: [OLINGO-935]URI-parser support of the
data aggregation extension
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
index 0cc1977..eb5d679 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/Parser.java
@@ -38,6 +38,8 @@ import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.UriResourceRef;
import org.apache.olingo.server.api.uri.UriResourceValue;
import org.apache.olingo.server.api.uri.queryoption.AliasQueryOption;
+import org.apache.olingo.server.api.uri.queryoption.ApplyItem;
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
import org.apache.olingo.server.api.uri.queryoption.ExpandItem;
import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
import org.apache.olingo.server.api.uri.queryoption.FilterOption;
@@ -53,6 +55,7 @@ import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl;
import org.apache.olingo.server.core.uri.parser.UriTokenizer.TokenKind;
import org.apache.olingo.server.core.uri.parser.search.SearchParser;
import org.apache.olingo.server.core.uri.queryoption.AliasQueryOptionImpl;
+import org.apache.olingo.server.core.uri.queryoption.ApplyOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl;
import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl;
@@ -206,6 +209,8 @@ public class Parser {
}
// Post-process system query options that need context information from the resource path.
+ parseApplyOption(contextUriInfo.getApplyOption(), contextType,
+ contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
parseFilterOption(contextUriInfo.getFilterOption(), contextType,
contextUriInfo.getEntitySetNames(), contextUriInfo.getAliasMap());
parseOrderByOption(contextUriInfo.getOrderByOption(), contextType,
@@ -226,7 +231,7 @@ public class Parser {
throw new UriParserSyntaxException("Unknown system query option!",
UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
}
- final SystemQueryOptionImpl systemOption;
+ SystemQueryOptionImpl systemOption;
switch (kind) {
case SEARCH:
SearchOption searchOption = new SearchParser().parse(optionValue);
@@ -293,6 +298,9 @@ public class Parser {
case LEVELS:
throw new UriParserSyntaxException("System query option '$levels' is allowed only inside '$expand'!",
UriParserSyntaxException.MessageKeys.SYSTEM_QUERY_OPTION_LEVELS_NOT_ALLOWED_HERE);
+ case APPLY:
+ systemOption = new ApplyOptionImpl();
+ break;
default:
throw new UriParserSyntaxException("System query option '" + kind + "' is not known!",
UriParserSyntaxException.MessageKeys.UNKNOWN_SYSTEM_QUERY_OPTION, optionName);
@@ -344,8 +352,8 @@ public class Parser {
}
private void parseExpandOption(ExpandOption expandOption, final EdmType contextType, final boolean isAll,
- final List<String> entitySetNames, final Map<String, AliasQueryOption> aliases) throws UriParserException,
- UriValidationException {
+ final List<String> entitySetNames, final Map<String, AliasQueryOption> aliases)
+ throws UriParserException, UriValidationException {
if (expandOption != null) {
if (!(contextType instanceof EdmStructuredType || isAll
|| (entitySetNames != null && !entitySetNames.isEmpty()))) {
@@ -377,6 +385,23 @@ public class Parser {
}
}
+ private void parseApplyOption(ApplyOption applyOption, final EdmType contextType,
+ final List<String> entitySetNames, final Map<String, AliasQueryOption> aliases)
+ throws UriParserException, UriValidationException {
+ if (applyOption != null) {
+ final String optionValue = applyOption.getText();
+ UriTokenizer applyTokenizer = new UriTokenizer(optionValue);
+ final ApplyOption option = new ApplyParser(edm, odata).parse(applyTokenizer,
+ contextType instanceof EdmStructuredType ? (EdmStructuredType) contextType : null,
+ entitySetNames,
+ aliases);
+ checkOptionEOF(applyTokenizer, applyOption.getName(), optionValue);
+ for (final ApplyItem item : option.getApplyItems()) {
+ ((ApplyOptionImpl) applyOption).add(item);
+ }
+ }
+ }
+
private void ensureLastSegment(final String segment, final int pos, final int size)
throws UriParserSyntaxException {
if (pos < size) {
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
index db33a6a..f2c4634 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriParserSemanticException.java
@@ -67,9 +67,15 @@ public class UriParserSemanticException extends UriParserException {
COMPLEX_PARAMETER_IN_RESOURCE_PATH,
/** parameters: left type, right type */
TYPES_NOT_COMPATIBLE,
- /** parameter: addressed resource name*/
- NOT_A_MEDIA_RESOURCE;
-
+ /** parameter: addressed resource name */
+ NOT_A_MEDIA_RESOURCE,
+ /** parameters: property name */
+ IS_PROPERTY,
+ /** parameter: expression */
+ ONLY_FOR_PRIMITIVE_TYPES,
+ /** parameter: function name */
+ FUNCTION_MUST_USE_COLLECTIONS;
+
@Override
public String getKey() {
return name();
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
index d218666..6654df9 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/parser/UriTokenizer.java
@@ -23,7 +23,8 @@ package org.apache.olingo.server.core.uri.parser;
* <p>As far as feasible, it tries to work on character basis, assuming this to be faster than string operations.
* Since only the index is "moved", backing out while parsing a token is easy and used throughout.
* There is intentionally no method to push back tokens (although it would be easy to add such a method)
- * because this tokenizer should behave like a classical token-consuming tokenizer.</p>
+ * because this tokenizer should behave like a classical token-consuming tokenizer.
+ * There is, however, the possibility to save the current state and return to it later.</p>
* <p>Whitespace is not an extra token but consumed with the tokens that require whitespace.
* Optional whitespace is not supported.</p>
*/
@@ -40,6 +41,7 @@ public class UriTokenizer {
ROOT,
IT,
+ APPLY, // for the aggregation extension
EXPAND,
FILTER,
LEVELS,
@@ -66,6 +68,13 @@ public class UriTokenizer {
NULL,
MAX,
+ AVERAGE, // for the aggregation extension
+ COUNTDISTINCT, // for the aggregation extension
+ IDENTITY, // for the aggregation extension
+ MIN, // for the aggregation extension
+ SUM, // for the aggregation extension
+ ROLLUP_ALL, // for the aggregation extension
+
// variable-value tokens (convention: mixed case)
ODataIdentifier,
QualifiedName,
@@ -125,6 +134,10 @@ public class UriTokenizer {
MinusOperator,
NotOperator,
+ AsOperator, // for the aggregation extension
+ FromOperator, // for the aggregation extension
+ WithOperator, // for the aggregation extension
+
CastMethod,
CeilingMethod,
ConcatMethod,
@@ -158,6 +171,23 @@ public class UriTokenizer {
TrimMethod,
YearMethod,
+ IsDefinedMethod, // for the aggregation extension
+
+ AggregateTrafo, // for the aggregation extension
+ BottomCountTrafo, // for the aggregation extension
+ BottomPercentTrafo, // for the aggregation extension
+ BottomSumTrafo, // for the aggregation extension
+ ComputeTrafo, // for the aggregation extension
+ ExpandTrafo, // for the aggregation extension
+ FilterTrafo, // for the aggregation extension
+ GroupByTrafo, // for the aggregation extension
+ SearchTrafo, // for the aggregation extension
+ TopCountTrafo, // for the aggregation extension
+ TopPercentTrafo, // for the aggregation extension
+ TopSumTrafo, // for the aggregation extension
+
+ RollUpSpec, // for the aggregation extension
+
AscSuffix,
DescSuffix
}
@@ -167,10 +197,31 @@ public class UriTokenizer {
private int startIndex = 0;
private int index = 0;
+ private int savedStartIndex;
+ private int savedIndex;
+
public UriTokenizer(final String parseString) {
this.parseString = parseString == null ? "" : parseString;
}
+ /**
+ * Save the current state.
+ * @see #returnToSavedState()
+ */
+ public void saveState() {
+ savedStartIndex = startIndex;
+ savedIndex = index;
+ }
+
+ /**
+ * Return to the previously saved state.
+ * @see #saveState()
+ */
+ public void returnToSavedState() {
+ startIndex = savedStartIndex;
+ index = savedIndex;
+ }
+
/** Returns the string value corresponding to the last successful {@link #next(TokenKind)} call. */
public String getText() {
return parseString.substring(startIndex, index);
@@ -218,6 +269,9 @@ public class UriTokenizer {
found = nextConstant("$it");
break;
+ case APPLY:
+ found = nextConstant("$apply");
+ break;
case EXPAND:
found = nextConstant("$expand");
break;
@@ -288,6 +342,26 @@ public class UriTokenizer {
found = nextConstant("max");
break;
+ case AVERAGE:
+ found = nextConstant("average");
+ break;
+ case COUNTDISTINCT:
+ found = nextConstant("countdistinct");
+ break;
+ case IDENTITY:
+ found = nextConstant("identity");
+ break;
+ case MIN:
+ found = nextConstant("min");
+ break;
+ case SUM:
+ found = nextConstant("sum");
+ break;
+
+ case ROLLUP_ALL:
+ found = nextConstant("$all");
+ break;
+
// Identifiers
case ODataIdentifier:
found = nextODataIdentifier();
@@ -456,6 +530,17 @@ public class UriTokenizer {
found = nextUnaryOperator("not");
break;
+ // Operators for the aggregation extension
+ case AsOperator:
+ found = nextBinaryOperator("as");
+ break;
+ case FromOperator:
+ found = nextBinaryOperator("from");
+ break;
+ case WithOperator:
+ found = nextBinaryOperator("with");
+ break;
+
// Methods
case CastMethod:
found = nextMethod("cast");
@@ -554,6 +639,54 @@ public class UriTokenizer {
found = nextMethod("year");
break;
+ // Method for the aggregation extension
+ case IsDefinedMethod:
+ found = nextMethod("isdefined");
+ break;
+
+ // Transformations for the aggregation extension
+ case AggregateTrafo:
+ found = nextMethod("aggregate");
+ break;
+ case BottomCountTrafo:
+ found = nextMethod("bottomcount");
+ break;
+ case BottomPercentTrafo:
+ found = nextMethod("bottompercent");
+ break;
+ case BottomSumTrafo:
+ found = nextMethod("bottomsum");
+ break;
+ case ComputeTrafo:
+ found = nextMethod("compute");
+ break;
+ case ExpandTrafo:
+ found = nextMethod("expand");
+ break;
+ case FilterTrafo:
+ found = nextMethod("filter");
+ break;
+ case GroupByTrafo:
+ found = nextMethod("groupby");
+ break;
+ case SearchTrafo:
+ found = nextMethod("search");
+ break;
+ case TopCountTrafo:
+ found = nextMethod("topcount");
+ break;
+ case TopPercentTrafo:
+ found = nextMethod("toppercent");
+ break;
+ case TopSumTrafo:
+ found = nextMethod("topsum");
+ break;
+
+ // Roll-up specification for the aggregation extension
+ case RollUpSpec:
+ found = nextMethod("rollup");
+ break;
+
// Suffixes
case AscSuffix:
found = nextSuffix("asc");
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java
new file mode 100644
index 0000000..066352d
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/ApplyOptionImpl.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.queryoption.ApplyItem;
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
+import org.apache.olingo.server.api.uri.queryoption.SystemQueryOptionKind;
+
+public class ApplyOptionImpl extends SystemQueryOptionImpl implements ApplyOption {
+
+ private List<ApplyItem> transformations = new ArrayList<ApplyItem>();
+
+ public ApplyOptionImpl() {
+ setKind(SystemQueryOptionKind.APPLY);
+ }
+
+ @Override
+ public List<ApplyItem> getApplyItems() {
+ return Collections.unmodifiableList(transformations);
+ }
+
+ public ApplyOptionImpl add(final ApplyItem transformation) {
+ transformations.add(transformation);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateExpressionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateExpressionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateExpressionImpl.java
new file mode 100644
index 0000000..1bacfe0
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateExpressionImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.queryoption.apply.AggregateExpression;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+
+/**
+ * Represents an aggregate expression.
+ */
+public class AggregateExpressionImpl implements AggregateExpression {
+
+ private UriInfo path;
+ private Expression expression;
+ private StandardMethod standardMethod;
+ private FullQualifiedName customMethod;
+ private String alias;
+ private AggregateExpression inlineAggregateExpression;
+ private List<AggregateExpression> from = new ArrayList<AggregateExpression>();
+
+ @Override
+ public List<UriResource> getPath() {
+ return path == null ? Collections.<UriResource> emptyList() : path.getUriResourceParts();
+ }
+
+ public AggregateExpressionImpl setPath(final UriInfo uriInfo) {
+ path = uriInfo;
+ return this;
+ }
+
+ @Override
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public AggregateExpressionImpl setExpression(final Expression expression) {
+ this.expression = expression;
+ return this;
+ }
+
+ @Override
+ public StandardMethod getStandardMethod() {
+ return standardMethod;
+ }
+
+ public AggregateExpressionImpl setStandardMethod(final StandardMethod standardMethod) {
+ this.standardMethod = standardMethod;
+ return this;
+ }
+
+ @Override
+ public FullQualifiedName getCustomMethod() {
+ return customMethod;
+ }
+
+ public AggregateExpressionImpl setCustomMethod(final FullQualifiedName customMethod) {
+ this.customMethod = customMethod;
+ return this;
+ }
+
+ @Override
+ public AggregateExpression getInlineAggregateExpression() {
+ return inlineAggregateExpression;
+ }
+
+ public AggregateExpressionImpl setInlineAggregateExpression(final AggregateExpression aggregateExpression) {
+ inlineAggregateExpression = aggregateExpression;
+ return this;
+ }
+
+ @Override
+ public List<AggregateExpression> getFrom() {
+ return Collections.unmodifiableList(from);
+ }
+
+ public AggregateExpressionImpl addFrom(final AggregateExpression from) {
+ this.from.add(from);
+ return this;
+ }
+
+ @Override
+ public String getAlias() {
+ return alias;
+ }
+
+ public AggregateExpressionImpl setAlias(final String alias) {
+ this.alias = alias;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateImpl.java
new file mode 100644
index 0000000..3414d2d
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/AggregateImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.queryoption.apply.Aggregate;
+import org.apache.olingo.server.api.uri.queryoption.apply.AggregateExpression;
+
+/**
+ * Represents the aggregate transformation.
+ */
+public class AggregateImpl implements Aggregate {
+
+ private List<AggregateExpression> expressions = new ArrayList<AggregateExpression>();
+
+ @Override
+ public Kind getKind() {
+ return Kind.AGGREGATE;
+ }
+
+ @Override
+ public List<AggregateExpression> getExpressions() {
+ return expressions;
+ }
+
+ public AggregateImpl addExpression(final AggregateExpression expression) {
+ expressions.add(expression);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/BottomTopImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/BottomTopImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/BottomTopImpl.java
new file mode 100644
index 0000000..3deb895
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/BottomTopImpl.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import org.apache.olingo.server.api.uri.queryoption.apply.BottomTop;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+
+/**
+ * Represents a transformation with one of the pre-defined methods
+ * <code>bottomcount</code>, <code>bottompercent</code>, <code>bottomsum</code>,
+ * <code>topcount</code>, <code>toppercent</code>, <code>topsum</code>.
+ */
+public class BottomTopImpl implements BottomTop {
+
+ private Method method;
+ private Expression number;
+ private Expression value;
+
+ @Override
+ public Kind getKind() {
+ return Kind.BOTTOM_TOP;
+ }
+
+ @Override
+ public Method getMethod() {
+ return method;
+ }
+
+ public BottomTopImpl setMethod(final Method method) {
+ this.method = method;
+ return this;
+ }
+
+ @Override
+ public Expression getNumber() {
+ return number;
+ }
+
+ public BottomTopImpl setNumber(final Expression number) {
+ this.number = number;
+ return this;
+ }
+
+ @Override
+ public Expression getValue() {
+ return value;
+ }
+
+ public BottomTopImpl setValue(final Expression value) {
+ this.value = value;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeExpressionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeExpressionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeExpressionImpl.java
new file mode 100644
index 0000000..c073aa3
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeExpressionImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import org.apache.olingo.server.api.uri.queryoption.apply.ComputeExpression;
+import org.apache.olingo.server.api.uri.queryoption.expression.Expression;
+
+/**
+ * Represents an aggregate expression.
+ */
+public class ComputeExpressionImpl implements ComputeExpression {
+
+ private Expression expression;
+ private String alias;
+
+ @Override
+ public Expression getExpression() {
+ return expression;
+ }
+
+ public ComputeExpressionImpl setExpression(final Expression expression) {
+ this.expression = expression;
+ return this;
+ }
+
+ @Override
+ public String getAlias() {
+ return alias;
+ }
+
+ public ComputeExpressionImpl setAlias(final String alias) {
+ this.alias = alias;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeImpl.java
new file mode 100644
index 0000000..8e57120
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ComputeImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.queryoption.apply.Compute;
+import org.apache.olingo.server.api.uri.queryoption.apply.ComputeExpression;
+
+/**
+ * Represents the compute transformation.
+ */
+public class ComputeImpl implements Compute {
+
+ private List<ComputeExpression> expressions = new ArrayList<ComputeExpression>();
+
+ @Override
+ public Kind getKind() {
+ return Kind.COMPUTE;
+ }
+
+ @Override
+ public List<ComputeExpression> getExpressions() {
+ return expressions;
+ }
+
+ public ComputeImpl addExpression(final ComputeExpressionImpl expression) {
+ expressions.add(expression);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ConcatImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ConcatImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ConcatImpl.java
new file mode 100644
index 0000000..0a3b919
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ConcatImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
+import org.apache.olingo.server.api.uri.queryoption.apply.Concat;
+
+/**
+ * Represents the concat transformation.
+ */
+public class ConcatImpl implements Concat {
+
+ private List<ApplyOption> options = new ArrayList<ApplyOption>();
+
+ @Override
+ public Kind getKind() {
+ return Kind.CONCAT;
+ }
+
+ @Override
+ public List<ApplyOption> getApplyOptions() {
+ return options;
+ }
+
+ public ConcatImpl addApplyOption(final ApplyOption option) {
+ options.add(option);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/CustomFunctionImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/CustomFunctionImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/CustomFunctionImpl.java
new file mode 100644
index 0000000..ba083dd
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/CustomFunctionImpl.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.commons.api.edm.EdmFunction;
+import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.queryoption.apply.CustomFunction;
+
+/**
+ * Represents a transformation with a custom function.
+ */
+public class CustomFunctionImpl implements CustomFunction {
+
+ private EdmFunction function = null;
+ private List<UriParameter> parameters;
+
+ @Override
+ public Kind getKind() {
+ return Kind.CUSTOM_FUNCTION;
+ }
+
+ @Override
+ public EdmFunction getFunction() {
+ return function;
+ }
+
+ public CustomFunctionImpl setFunction(final EdmFunction function) {
+ this.function = function;
+ return this;
+ }
+
+ @Override
+ public List<UriParameter> getParameters() {
+ return parameters == null ?
+ Collections.<UriParameter> emptyList() :
+ Collections.unmodifiableList(parameters);
+ }
+
+ public CustomFunctionImpl setParameters(final List<UriParameter> parameters) {
+ this.parameters = parameters;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java
new file mode 100644
index 0000000..d9fbde9
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicProperty.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.commons.api.edm.EdmAnnotation;
+import org.apache.olingo.commons.api.edm.EdmMapping;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmTerm;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.api.edm.geo.SRID;
+
+/** A dynamic EDM property containing an aggregation. */
+public class DynamicProperty implements EdmProperty {
+
+ private final String name;
+ private final EdmType propertyType;
+
+ /** Creates a dynamic property with a mandatory name and an optional type. */
+ public DynamicProperty(final String name, final EdmType type) {
+ this.name = name;
+ propertyType = type;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public EdmType getType() {
+ return propertyType;
+ }
+
+ @Override
+ public boolean isCollection() {
+ return false;
+ }
+
+ @Override
+ public EdmMapping getMapping() {
+ return null;
+ }
+
+ @Override
+ public String getMimeType() {
+ return null;
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public Integer getMaxLength() {
+ return null;
+ }
+
+ @Override
+ public Integer getPrecision() {
+ return null;
+ }
+
+ @Override
+ public Integer getScale() {
+ return null;
+ }
+
+ @Override
+ public SRID getSrid() {
+ return null;
+ }
+
+ @Override
+ public boolean isUnicode() {
+ return true;
+ }
+
+ @Override
+ public String getDefaultValue() {
+ return null;
+ }
+
+ @Override
+ public boolean isPrimitive() {
+ return propertyType != null && propertyType.getKind() == EdmTypeKind.PRIMITIVE;
+ }
+
+ @Override
+ public EdmAnnotation getAnnotation(final EdmTerm term, final String qualifier) {
+ return null;
+ }
+
+ @Override
+ public List<EdmAnnotation> getAnnotations() {
+ return Collections.emptyList();
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicStructuredType.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicStructuredType.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicStructuredType.java
new file mode 100644
index 0000000..f0ac5c6
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/DynamicStructuredType.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.commons.api.edm.EdmAnnotation;
+import org.apache.olingo.commons.api.edm.EdmElement;
+import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmStructuredType;
+import org.apache.olingo.commons.api.edm.EdmTerm;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+
+/** A dynamic structured type used to incorporate dynamic properties containing aggregations. */
+public class DynamicStructuredType implements EdmStructuredType, Cloneable {
+
+ private final EdmStructuredType startType;
+ private Map<String, EdmProperty> properties;
+
+ public DynamicStructuredType(final EdmStructuredType startType) {
+ this.startType = startType;
+ }
+
+ public DynamicStructuredType addProperty(final EdmProperty property) {
+ if (properties == null) {
+ properties = new LinkedHashMap<String, EdmProperty>();
+ }
+ properties.put(property.getName(), property);
+ return this;
+ }
+
+ @Override
+ public EdmElement getProperty(final String name) {
+ final EdmElement property = startType.getProperty(name);
+ return property == null ?
+ properties == null ? null : properties.get(name) :
+ property;
+ }
+
+ @Override
+ public List<String> getPropertyNames() {
+ if (properties == null || properties.isEmpty()) {
+ return startType.getPropertyNames();
+ } else {
+ List<String> names = new ArrayList<String>(startType.getPropertyNames());
+ names.addAll(properties.keySet());
+ return Collections.unmodifiableList(names);
+ }
+ }
+
+ @Override
+ public EdmProperty getStructuralProperty(final String name) {
+ final EdmProperty property = startType.getStructuralProperty(name);
+ return property == null ?
+ properties == null ? null : properties.get(name) :
+ property;
+ }
+
+ @Override
+ public EdmNavigationProperty getNavigationProperty(final String name) {
+ return startType.getNavigationProperty(name);
+ }
+
+ @Override
+ public List<String> getNavigationPropertyNames() {
+ return startType.getNavigationPropertyNames();
+ }
+
+ @Override
+ public String getNamespace() {
+ return startType.getNamespace();
+ }
+
+ @Override
+ public String getName() {
+ return startType.getName();
+ }
+
+ @Override
+ public FullQualifiedName getFullQualifiedName() {
+ return startType.getFullQualifiedName();
+ }
+
+ @Override
+ public EdmTypeKind getKind() {
+ return startType.getKind();
+ }
+
+ @Override
+ public EdmAnnotation getAnnotation(final EdmTerm term, final String qualifier) {
+ return startType.getAnnotation(term, qualifier);
+ }
+
+ @Override
+ public List<EdmAnnotation> getAnnotations() {
+ return startType.getAnnotations();
+ }
+
+ @Override
+ public EdmStructuredType getBaseType() {
+ return startType.getBaseType();
+ }
+
+ @Override
+ public boolean compatibleTo(final EdmType targetType) {
+ return startType.compatibleTo(targetType);
+ }
+
+ @Override
+ public boolean isOpenType() {
+ return startType.isOpenType();
+ }
+
+ @Override
+ public boolean isAbstract() {
+ return startType.isAbstract();
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ExpandImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ExpandImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ExpandImpl.java
new file mode 100644
index 0000000..a9992c5
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/ExpandImpl.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import org.apache.olingo.server.api.uri.queryoption.ExpandOption;
+import org.apache.olingo.server.api.uri.queryoption.apply.Expand;
+
+/**
+ * Represents the expand transformation.
+ */
+public class ExpandImpl implements Expand {
+
+ private ExpandOption expandOption = null;
+
+ @Override
+ public Kind getKind() {
+ return Kind.EXPAND;
+ }
+
+ @Override
+ public ExpandOption getExpandOption() {
+ return expandOption;
+ }
+
+ public ExpandImpl setExpandOption(final ExpandOption expandOption) {
+ this.expandOption = expandOption;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/FilterImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/FilterImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/FilterImpl.java
new file mode 100644
index 0000000..c356845
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/FilterImpl.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import org.apache.olingo.server.api.uri.queryoption.FilterOption;
+import org.apache.olingo.server.api.uri.queryoption.apply.Filter;
+
+/**
+ * Represents the filter transformation.
+ */
+public class FilterImpl implements Filter {
+
+ private FilterOption filterOption = null;
+
+ @Override
+ public Kind getKind() {
+ return Kind.FILTER;
+ }
+
+ @Override
+ public FilterOption getFilterOption() {
+ return filterOption;
+ }
+
+ public FilterImpl setFilterOption(final FilterOption filterOption) {
+ this.filterOption = filterOption;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByImpl.java
new file mode 100644
index 0000000..9946e17
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.queryoption.ApplyOption;
+import org.apache.olingo.server.api.uri.queryoption.apply.GroupBy;
+import org.apache.olingo.server.api.uri.queryoption.apply.GroupByItem;
+
+/**
+ * Represents the grouping transformation.
+ */
+public class GroupByImpl implements GroupBy {
+
+ private ApplyOption applyOption;
+ private List<GroupByItem> groupByItems = new ArrayList<GroupByItem>();
+
+ @Override
+ public Kind getKind() {
+ return Kind.GROUP_BY;
+ }
+
+ @Override
+ public ApplyOption getApplyOption() {
+ return applyOption;
+ }
+
+ public GroupByImpl setApplyOption(final ApplyOption applyOption) {
+ this.applyOption = applyOption;
+ return this;
+ }
+
+ @Override
+ public List<GroupByItem> getGroupByItems() {
+ return groupByItems;
+ }
+
+ public GroupByImpl addGroupByItem(final GroupByItem groupByItem) {
+ groupByItems.add(groupByItem);
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByItemImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByItemImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByItemImpl.java
new file mode 100644
index 0000000..0dd52b1
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/GroupByItemImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.queryoption.apply.GroupByItem;
+
+/**
+ * Represents a grouping property.
+ */
+public class GroupByItemImpl implements GroupByItem {
+
+ private UriInfo path;
+ private boolean isRollupAll;
+ private List<GroupByItem> rollup = new ArrayList<GroupByItem>();
+
+ @Override
+ public List<UriResource> getPath() {
+ return path == null ? Collections.<UriResource> emptyList() : path.getUriResourceParts();
+ }
+
+ public GroupByItemImpl setPath(final UriInfo uriInfo) {
+ path = uriInfo;
+ return this;
+ }
+
+ @Override
+ public List<GroupByItem> getRollup() {
+ return rollup;
+ }
+
+ public GroupByItemImpl addRollupItem(final GroupByItem groupByItem) {
+ rollup.add(groupByItem);
+ return this;
+ }
+
+ @Override
+ public boolean isRollupAll() {
+ return isRollupAll;
+ }
+
+ public GroupByItemImpl setIsRollupAll() {
+ this.isRollupAll = true;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/IdentityImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/IdentityImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/IdentityImpl.java
new file mode 100644
index 0000000..838d0b2
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/IdentityImpl.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import org.apache.olingo.server.api.uri.queryoption.apply.Identity;
+
+/**
+ * Represents the identity transformation.
+ */
+public class IdentityImpl implements Identity {
+
+ @Override
+ public Kind getKind() {
+ return Kind.IDENTITY;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/SearchImpl.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/SearchImpl.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/SearchImpl.java
new file mode 100644
index 0000000..9a588d9
--- /dev/null
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/queryoption/apply/SearchImpl.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.olingo.server.core.uri.queryoption.apply;
+
+import org.apache.olingo.server.api.uri.queryoption.SearchOption;
+import org.apache.olingo.server.api.uri.queryoption.apply.Search;
+
+/**
+ * Represents the search transformation.
+ */
+public class SearchImpl implements Search {
+
+ private SearchOption searchOption = null;
+
+ @Override
+ public Kind getKind() {
+ return Kind.SEARCH;
+ }
+
+ @Override
+ public SearchOption getSearchOption() {
+ return searchOption;
+ }
+
+ public SearchImpl setSearchOption(final SearchOption searchOption) {
+ this.searchOption = searchOption;
+ return this;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
index 0946b60..64c3cf7 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/uri/validator/UriValidator.java
@@ -45,27 +45,27 @@ public class UriValidator {
//CHECKSTYLE:OFF (Maven checkstyle)
private static final boolean[][] decisionMatrix =
{
- /* 0-FILTER 1-FORMAT 2-EXPAND 3-ID 4-COUNT 5-ORDERBY 6-SEARCH 7-SELECT 8-SKIP 9-SKIPTOKEN 10-TOP */
- /* all 0 */ { true , true , true , false, true , true , true , true , true , true , true },
- /* batch 1 */ { false, false, false, false, false, false, false, false, false, false, false },
- /* crossjoin 2 */ { true , true , true , false, true , true , true , true , true , true , true },
- /* entityId 3 */ { false, true , true , true , false, false, false, true , false, false, false },
- /* metadata 4 */ { false, true , false, false, false, false, false, false, false, false, false },
- /* service 5 */ { false, true , false, false, false, false, false, false, false, false, false },
- /* entitySet 6 */ { true , true , true , false, true , true , true , true , true , true , true },
- /* entitySetCount 7 */ { true , false, false, false, false, false, true , false, false, false, false },
- /* entity 8 */ { false, true , true , false, false, false, false, true , false, false, false },
- /* mediaStream 9 */ { false, false, false, false, false, false, false, false, false, false, false },
- /* references 10 */ { true , true , false, false, true , true , true , false, true , true , true },
- /* reference 11 */ { false, true , false, false, false, false, false, false, false, false, false },
- /* propertyComplex 12 */ { false, true , true , false, false, false, false, true , false, false, false },
- /* propertyComplexCollection 13 */ { true , true , true , false, true , true , false, true , true , true , true },
- /* propertyComplexCollectionCount 14 */ { true , false, false, false, false, false, false, false, false, false, false },
- /* propertyPrimitive 15 */ { false, true , false, false, false, false, false, false, false, false, false },
- /* propertyPrimitiveCollection 16 */ { true , true , false, false, true , true , false, false, true , true , true },
- /* propertyPrimitiveCollectionCount 17 */ { true , false, false, false, false, false, false, false, false, false, false },
- /* propertyPrimitiveValue 18 */ { false, true , false, false, false, false, false, false, false, false, false },
- /* none 19 */ { false, true , false, false, false, false, false, false, false, false, false }
+ /* 0-FILTER 1-FORMAT 2-EXPAND 3-ID 4-COUNT 5-ORDERBY 6-SEARCH 7-SELECT 8-SKIP 9-SKIPTOKEN 10-TOP 11-APPLY */
+ /* all 0 */ { true , true , true , false, true , true , true , true , true , true , true , true },
+ /* batch 1 */ { false, false, false, false, false, false, false, false, false, false, false, false },
+ /* crossjoin 2 */ { true , true , true , false, true , true , true , true , true , true , true , true },
+ /* entityId 3 */ { false, true , true , true , false, false, false, true , false, false, false, false },
+ /* metadata 4 */ { false, true , false, false, false, false, false, false, false, false, false, false },
+ /* service 5 */ { false, true , false, false, false, false, false, false, false, false, false, false },
+ /* entitySet 6 */ { true , true , true , false, true , true , true , true , true , true , true , true },
+ /* entitySetCount 7 */ { true , false, false, false, false, false, true , false, false, false, false, false },
+ /* entity 8 */ { false, true , true , false, false, false, false, true , false, false, false, false },
+ /* mediaStream 9 */ { false, false, false, false, false, false, false, false, false, false, false, false },
+ /* references 10 */ { true , true , false, false, true , true , true , false, true , true , true , false },
+ /* reference 11 */ { false, true , false, false, false, false, false, false, false, false, false, false },
+ /* propertyComplex 12 */ { false, true , true , false, false, false, false, true , false, false, false, false },
+ /* propertyComplexCollection 13 */ { true , true , true , false, true , true , false, true , true , true , true , true },
+ /* propertyComplexCollectionCount 14 */ { true , false, false, false, false, false, false, false, false, false, false, false },
+ /* propertyPrimitive 15 */ { false, true , false, false, false, false, false, false, false, false, false, false },
+ /* propertyPrimitiveCollection 16 */ { true , true , false, false, true , true , false, false, true , true , true , false },
+ /* propertyPrimitiveCollectionCount 17 */ { true , false, false, false, false, false, false, false, false, false, false, false },
+ /* propertyPrimitiveValue 18 */ { false, true , false, false, false, false, false, false, false, false, false, false },
+ /* none 19 */ { false, true , false, false, false, false, false, false, false, false, false, false }
};
//CHECKSTYLE:ON
//@formatter:on
@@ -118,6 +118,7 @@ public class UriValidator {
temp.put(SystemQueryOptionKind.SKIP, 8);
temp.put(SystemQueryOptionKind.SKIPTOKEN, 9);
temp.put(SystemQueryOptionKind.TOP, 10);
+ temp.put(SystemQueryOptionKind.APPLY, 11);
OPTION_INDEX = Collections.unmodifiableMap(temp);
}
@@ -255,7 +256,6 @@ public class UriValidator {
private UriType getUriTypeForFunction(final UriResource lastPathSegment) throws UriValidationException {
final UriResourceFunction uriFunction = (UriResourceFunction) lastPathSegment;
-
final boolean isCollection = uriFunction.isCollection();
final EdmTypeKind typeKind = uriFunction.getFunction().getReturnType().getType().getKind();
UriType uriType;
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index 3b63c1b..985bfe6 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -73,6 +73,9 @@ UriParserSemanticException.NAMESPACE_NOT_ALLOWED_AT_FIRST_ELEMENT=Namespace is n
UriParserSemanticException.COMPLEX_PARAMETER_IN_RESOURCE_PATH=Complex parameters must not appear in resource path segments; found: '%1$s'.
UriParserSemanticException.TYPES_NOT_COMPATIBLE=The types '%1$s' and '%2$s' are not compatible.
UriParserSemanticException.NOT_A_MEDIA_RESOURCE=The resource '%1$s' is not a media resource. $value can only be applied on media resources.
+UriParserSemanticException.IS_PROPERTY=The identifier '%1$s' is already used as a property.
+UriParserSemanticException.ONLY_FOR_PRIMITIVE_TYPES='%1$s' is only allowed for primitive-type expressions.
+UriParserSemanticException.FUNCTION_MUST_USE_COLLECTIONS=Only bound functions with collections of structural types as binding parameter and as return type are allowed; '%1$s' is not such a function.
UriValidationException.UNSUPPORTED_QUERY_OPTION=The query option '%1$s' is not supported.
UriValidationException.UNSUPPORTED_URI_KIND=The URI kind '%1$s' is not supported.
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
index 118e2ea..23bf1d1 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/uri/parser/UriTokenizerTest.java
@@ -97,6 +97,18 @@ public class UriTokenizerTest {
}
@Test
+ public void saveState() {
+ UriTokenizer tokenizer = new UriTokenizer("a*");
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ tokenizer.saveState();
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ tokenizer.returnToSavedState();
+ assertTrue(tokenizer.next(TokenKind.STAR));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+ }
+
+ @Test
public void systemQueryOptions() {
UriTokenizer tokenizer = new UriTokenizer("$expand=*;$filter=true;$levels=max;$orderby=false");
assertTrue(tokenizer.next(TokenKind.EXPAND));
@@ -642,6 +654,64 @@ public class UriTokenizerTest {
wrongToken(TokenKind.GeometryCollection, "geometry'SRID=0;Collection(Point(1 2),Point(3 4))'", 'x');
}
+ @Test
+ public void aggregation() {
+ UriTokenizer tokenizer = new UriTokenizer("$apply=aggregate(a with sum as s from x with average)");
+ assertTrue(tokenizer.next(TokenKind.APPLY));
+ assertTrue(tokenizer.next(TokenKind.EQ));
+ assertTrue(tokenizer.next(TokenKind.AggregateTrafo));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.WithOperator));
+ assertTrue(tokenizer.next(TokenKind.SUM));
+ assertTrue(tokenizer.next(TokenKind.AsOperator));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.FromOperator));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.WithOperator));
+ assertTrue(tokenizer.next(TokenKind.AVERAGE));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ tokenizer = new UriTokenizer("a with min as m");
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.WithOperator));
+ assertTrue(tokenizer.next(TokenKind.MIN));
+
+ tokenizer = new UriTokenizer("a with countdistinct as c");
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.WithOperator));
+ assertTrue(tokenizer.next(TokenKind.COUNTDISTINCT));
+
+ assertTrue(new UriTokenizer("identity").next(TokenKind.IDENTITY));
+ assertTrue(new UriTokenizer("bottomcount(1,x)").next(TokenKind.BottomCountTrafo));
+ assertTrue(new UriTokenizer("bottompercent(1,x)").next(TokenKind.BottomPercentTrafo));
+ assertTrue(new UriTokenizer("bottomsum(1,x)").next(TokenKind.BottomSumTrafo));
+ assertTrue(new UriTokenizer("topcount(1,x)").next(TokenKind.TopCountTrafo));
+ assertTrue(new UriTokenizer("toppercent(1,x)").next(TokenKind.TopPercentTrafo));
+ assertTrue(new UriTokenizer("topsum(1,x)").next(TokenKind.TopSumTrafo));
+ assertTrue(new UriTokenizer("compute(a mul b as m)").next(TokenKind.ComputeTrafo));
+
+ assertTrue(new UriTokenizer("search(a)").next(TokenKind.SearchTrafo));
+ assertTrue(new UriTokenizer("expand(a)").next(TokenKind.ExpandTrafo));
+ assertTrue(new UriTokenizer("filter(true)").next(TokenKind.FilterTrafo));
+
+ tokenizer = new UriTokenizer("groupby((rollup($all,x,y)))");
+ assertTrue(tokenizer.next(TokenKind.GroupByTrafo));
+ assertTrue(tokenizer.next(TokenKind.OPEN));
+ assertTrue(tokenizer.next(TokenKind.RollUpSpec));
+ assertTrue(tokenizer.next(TokenKind.ROLLUP_ALL));
+ assertTrue(tokenizer.next(TokenKind.COMMA));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.COMMA));
+ assertTrue(tokenizer.next(TokenKind.ODataIdentifier));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.CLOSE));
+ assertTrue(tokenizer.next(TokenKind.EOF));
+
+ assertTrue(new UriTokenizer("isdefined(x)").next(TokenKind.IsDefinedMethod));
+ }
+
private void wrongToken(final TokenKind kind, final String value, final char disturbCharacter) {
assertFalse(new UriTokenizer(disturbCharacter + value).next(kind));
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/6553e950/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
index 28cf63d..ddbfb1a 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java
@@ -233,7 +233,7 @@ public abstract class TechnicalProcessor implements Processor {
}
protected void validateOptions(final UriInfoResource uriInfo) throws ODataApplicationException {
- if (uriInfo.getIdOption() != null) {
+ if (uriInfo.getIdOption() != null || uriInfo.getApplyOption() != null) {
throw new ODataApplicationException("Not all of the specified options are supported.",
HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT);
}