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); }
