| /* |
| * 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.parser; |
| |
| import org.antlr.v4.runtime.misc.NotNull; |
| import org.antlr.v4.runtime.misc.ParseCancellationException; |
| import org.antlr.v4.runtime.tree.ParseTree; |
| import org.apache.olingo.commons.api.edm.Edm; |
| import org.apache.olingo.commons.api.edm.EdmAction; |
| import org.apache.olingo.commons.api.edm.EdmActionImport; |
| import org.apache.olingo.commons.api.edm.EdmComplexType; |
| import org.apache.olingo.commons.api.edm.EdmElement; |
| import org.apache.olingo.commons.api.edm.EdmEntityContainer; |
| import org.apache.olingo.commons.api.edm.EdmEntitySet; |
| import org.apache.olingo.commons.api.edm.EdmEntityType; |
| import org.apache.olingo.commons.api.edm.EdmEnumType; |
| import org.apache.olingo.commons.api.edm.EdmFunction; |
| import org.apache.olingo.commons.api.edm.EdmFunctionImport; |
| import org.apache.olingo.commons.api.edm.EdmNavigationProperty; |
| import org.apache.olingo.commons.api.edm.EdmPrimitiveType; |
| import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; |
| import org.apache.olingo.commons.api.edm.EdmProperty; |
| import org.apache.olingo.commons.api.edm.EdmSingleton; |
| import org.apache.olingo.commons.api.edm.EdmStructuredType; |
| import org.apache.olingo.commons.api.edm.EdmType; |
| import org.apache.olingo.commons.api.edm.FullQualifiedName; |
| import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory; |
| import org.apache.olingo.server.api.uri.UriInfoKind; |
| import org.apache.olingo.server.api.uri.UriResource; |
| import org.apache.olingo.server.api.uri.UriResourcePartTyped; |
| import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind; |
| import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind; |
| import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind; |
| import org.apache.olingo.server.core.uri.UriInfoImpl; |
| import org.apache.olingo.server.core.uri.UriParameterImpl; |
| import org.apache.olingo.server.core.uri.UriResourceActionImpl; |
| import org.apache.olingo.server.core.uri.UriResourceComplexPropertyImpl; |
| import org.apache.olingo.server.core.uri.UriResourceCountImpl; |
| import org.apache.olingo.server.core.uri.UriResourceEntitySetImpl; |
| import org.apache.olingo.server.core.uri.UriResourceFunctionImpl; |
| import org.apache.olingo.server.core.uri.UriResourceImpl; |
| import org.apache.olingo.server.core.uri.UriResourceItImpl; |
| import org.apache.olingo.server.core.uri.UriResourceLambdaAllImpl; |
| import org.apache.olingo.server.core.uri.UriResourceLambdaAnyImpl; |
| import org.apache.olingo.server.core.uri.UriResourceLambdaVarImpl; |
| import org.apache.olingo.server.core.uri.UriResourceNavigationPropertyImpl; |
| import org.apache.olingo.server.core.uri.UriResourcePrimitivePropertyImpl; |
| import org.apache.olingo.server.core.uri.UriResourceRefImpl; |
| import org.apache.olingo.server.core.uri.UriResourceRootImpl; |
| import org.apache.olingo.server.core.uri.UriResourceSingletonImpl; |
| import org.apache.olingo.server.core.uri.UriResourceStartingTypeFilterImpl; |
| import org.apache.olingo.server.core.uri.UriResourceTypedImpl; |
| import org.apache.olingo.server.core.uri.UriResourceValueImpl; |
| import org.apache.olingo.server.core.uri.UriResourceWithKeysImpl; |
| import org.apache.olingo.server.core.uri.antlr.UriLexer; |
| import org.apache.olingo.server.core.uri.antlr.UriParserBaseVisitor; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AllExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAddContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAllContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAndContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltAnyContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltComparismContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltEqualityContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltHasContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltMultContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AltOrContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.AnyExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.BatchEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.BooleanNonCaseContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.CastExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.CeilingMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConcatMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ConstSegmentContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ContainsMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.CrossjoinEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.DateMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.DayMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.EndsWithMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.EntityEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.EnumLitContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandCountOptionContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandItemsContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandOptionContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandPathExtensionContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ExpandRefOptionContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.FilterExpressionEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.FloorMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.FractionalsecondsMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoDistanceMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoIntersectsMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.GeoLengthMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.HourMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.IndexOfMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.InlinecountContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.IsofExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.LengthMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.LevelsContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.MaxDateTimeMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.MemberExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.MetadataEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinDateTimeMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.MinuteMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.MonthMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValueOptListContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.NameValuePairContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.NamespaceContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.NaninfinityContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.NowMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.NullruleContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.OdataIdentifierContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderByItemContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.OrderListContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.PathSegmentsContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.PrimitiveLiteralContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.QueryOptionsContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.RootExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.RoundMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SecondMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectEOFContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectItemContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SelectSegmentContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkipContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SkiptokenContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.StartsWithMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.SubstringMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.TimeMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToLowerMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.ToUpperMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.TopContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalOffsetMinutesMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.TotalsecondsMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.TrimMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.antlr.UriParserParser.YearMethodCallExprContext; |
| import org.apache.olingo.server.core.uri.queryoption.CountOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.ExpandItemImpl; |
| import org.apache.olingo.server.core.uri.queryoption.ExpandOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.FilterOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.LevelsOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.OrderByItemImpl; |
| import org.apache.olingo.server.core.uri.queryoption.OrderByOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.QueryOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.SelectItemImpl; |
| import org.apache.olingo.server.core.uri.queryoption.SelectOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.SkipOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.SkipTokenOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.SystemQueryOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.TopOptionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.AliasImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.BinaryImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.EnumerationImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.ExpressionImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.LiteralImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.MemberImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.MethodImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.TypeLiteralImpl; |
| import org.apache.olingo.server.core.uri.queryoption.expression.UnaryImpl; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * UriVisitor |
| * |
| * Converts the URI parse tree the generated by ANTLR into an internal representation which maybe is given to the |
| * application. While converting the tree is only validated against the EDM if necessary. |
| * |
| * Attention: |
| * <li> This UriVisitor is at somes point more lax than the original ABNF |
| * <li> It is more tolerable against additional white spaces Currently not supported |
| * <li>Parsing the context of $metadata</li> |
| * <li>Parsing $search</li> |
| */ |
| public class UriParseTreeVisitor extends UriParserBaseVisitor<Object> { |
| |
| public class TypeInformation { |
| |
| boolean isCollection; |
| |
| EdmType type; |
| |
| TypeInformation(final EdmType type, final boolean isCollection) { |
| this.type = type; |
| this.isCollection = isCollection; |
| } |
| |
| public TypeInformation() {} |
| } |
| |
| public UriContext context = null; |
| |
| public Edm edm; |
| |
| public EdmEntityContainer edmEntityContainer; |
| |
| // --- class --- |
| public UriParseTreeVisitor(final Edm edm, final UriContext context) { |
| this.edm = edm; |
| this.context = context; |
| edmEntityContainer = edm.getEntityContainer(null); |
| } |
| |
| @Override |
| protected Object aggregateResult(final Object aggregate, final Object nextResult) { |
| if (aggregate != null) { |
| return aggregate; |
| } else { |
| return nextResult; |
| } |
| } |
| |
| private FullQualifiedName getFullNameFromContext(final NamespaceContext vNS, final String odi) { |
| String namespace = vNS.getText(); |
| namespace = namespace.substring(0, namespace.length() - 1); // vNS contains a trailing point that has to be removed |
| return new FullQualifiedName(namespace, odi); |
| } |
| |
| private UriContext.LambdaVariables getLambdaVar(final String odi) { |
| for (UriContext.LambdaVariables item : context.allowedLambdaVariables) { |
| if (item.name.equals(odi)) { |
| return item; |
| } |
| } |
| return null; |
| } |
| |
| TypeInformation getTypeInformation(final UriResource lastResourcePart) { |
| |
| TypeInformation typeInformation = new TypeInformation(); |
| if (lastResourcePart instanceof UriResourceWithKeysImpl) { |
| UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart; |
| |
| if (lastPartWithKeys.getTypeFilterOnEntry() != null) { |
| typeInformation.type = lastPartWithKeys.getTypeFilterOnEntry(); |
| } else if (lastPartWithKeys.getTypeFilterOnCollection() != null) { |
| typeInformation.type = lastPartWithKeys.getTypeFilterOnCollection(); |
| } else { |
| typeInformation.type = lastPartWithKeys.getType(); |
| } |
| typeInformation.isCollection = lastPartWithKeys.isCollection(); |
| |
| } else if (lastResourcePart instanceof UriResourceTypedImpl) { |
| UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart; |
| |
| if (lastPartTyped.getTypeFilter() != null) { |
| typeInformation.type = lastPartTyped.getTypeFilter(); |
| } else { |
| typeInformation.type = lastPartTyped.getType(); |
| } |
| |
| typeInformation.isCollection = lastPartTyped.isCollection(); |
| } |
| |
| return typeInformation; |
| } |
| |
| public UriResourceTypedImpl readResourcePathSegment(final PathSegmentContext ctx) { |
| |
| final boolean checkFirst = |
| context.contextUriInfo.getLastResourcePart() == null |
| || context.contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl; |
| |
| String odi = ctx.vODI.getText(); |
| |
| if (checkFirst && ctx.vNS == null) { |
| |
| // check EntitySet |
| EdmEntitySet edmEntitySet = edmEntityContainer.getEntitySet(odi); |
| if (edmEntitySet != null) { |
| UriResourceEntitySetImpl uriResource = new UriResourceEntitySetImpl() |
| .setEntitSet(edmEntitySet); |
| context.contextUriInfo.addResourcePart(uriResource); |
| return null; |
| } |
| |
| // check Singleton |
| EdmSingleton edmSingleton = edmEntityContainer.getSingleton(odi); |
| if (edmSingleton != null) { |
| UriResourceSingletonImpl uriResource = new UriResourceSingletonImpl() |
| .setSingleton(edmSingleton); |
| context.contextUriInfo.addResourcePart(uriResource); |
| return null; |
| } |
| |
| // check ActionImport |
| EdmActionImport edmActionImport = edmEntityContainer.getActionImport(odi); |
| if (edmActionImport != null) { |
| UriResourceActionImpl uriResource = new UriResourceActionImpl() |
| .setActionImport(edmActionImport); |
| context.contextUriInfo.addResourcePart(uriResource); |
| return null; |
| } |
| |
| // check FunctionImport |
| EdmFunctionImport edmFunctionImport = edmEntityContainer.getFunctionImport(odi); |
| if (edmFunctionImport != null) { |
| |
| // read the URI parameters |
| context.contextReadingFunctionParameters = true; |
| @SuppressWarnings("unchecked") |
| List<UriParameterImpl> parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this); |
| context.contextReadingFunctionParameters = false; |
| |
| // mark parameters as consumed |
| ctx.vlNVO.remove(0); |
| |
| UriResourceFunctionImpl uriResource = new UriResourceFunctionImpl() |
| .setFunctionImport(edmFunctionImport, parameters); |
| |
| // collect parameter names |
| List<String> names = new ArrayList<String>(); |
| for (UriParameterImpl item : parameters) { |
| names.add(item.getName()); |
| } |
| |
| // get function from function import |
| EdmFunction function = edmFunctionImport.getUnboundFunction(names); |
| if (function == null) { |
| String tmp = ""; |
| for (String name : names) { |
| tmp += (tmp.length() != 0 ? "," : "") + name; |
| } |
| throw wrap(new UriParserSemanticException("Function of functionimport '" + edmFunctionImport.getName() |
| + "' with parameters [" + tmp + "] not found", |
| UriParserSemanticException.MessageKeys.FUNCTION_NOT_FOUND, edmFunctionImport.getName(), tmp)); |
| } |
| |
| uriResource.setFunction(edmFunctionImport.getUnboundFunction(names)); |
| context.contextUriInfo.addResourcePart(uriResource); |
| return null; |
| } |
| } |
| |
| TypeInformation source = null; |
| UriResource lastResourcePart = context.contextUriInfo.getLastResourcePart(); |
| |
| if (lastResourcePart == null) { |
| if (context.contextTypes.size() == 0) { |
| if(checkFirst && ctx.vNS == null){ |
| throw wrap(new UriParserSemanticException( |
| "Cannot find EntitySet, Singleton, ActionImport or FunctionImport with name '" + odi + "'.", |
| UriParserSemanticException.MessageKeys.RESOURCE_NOT_FOUND, odi)); |
| } |
| throw wrap(new UriParserSemanticException("Resource part '" + odi + "' can only applied on typed " |
| + "resource parts", |
| UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi)); |
| } |
| source = context.contextTypes.peek(); |
| } else { |
| source = getTypeInformation(lastResourcePart); |
| |
| if (source.type == null) { |
| throw wrap(new UriParserSemanticException("Resource part '" + odi + "' can only be applied on typed " |
| + "resource parts.", UriParserSemanticException.MessageKeys.RESOURCE_PART_ONLY_FOR_TYPED_PARTS, odi)); |
| } |
| } |
| |
| if (ctx.vNS == null) { // without namespace |
| |
| // first check for lambda variable because a newly add property should not shadow a long used lambda variable |
| UriContext.LambdaVariables lVar = getLambdaVar(odi); |
| if (lVar != null) { |
| UriResourceLambdaVarImpl lambdaResource = new UriResourceLambdaVarImpl(); |
| lambdaResource.setVariableText(lVar.name); |
| lambdaResource.setType(lVar.type); |
| lambdaResource.setCollection(lVar.isCollection); |
| context.contextUriInfo.addResourcePart(lambdaResource); |
| return null; |
| } |
| |
| if (!(source.type instanceof EdmStructuredType)) { |
| throw wrap(new UriParserSemanticException("Cannot parse '" + odi |
| + "'; previous path segment is not a structural type.", |
| UriParserSemanticException.MessageKeys.RESOURCE_PART_MUST_BE_PRECEDED_BY_STRUCTURAL_TYPE, odi)); |
| } |
| |
| if (ctx.depth() <= 2 // path evaluation for the resource path |
| && source.isCollection) { |
| throw wrap(new UriParserSemanticException("Property '" + odi + "' is not allowed after collection.", |
| UriParserSemanticException.MessageKeys.PROPERTY_AFTER_COLLECTION, odi)); |
| } |
| |
| EdmStructuredType structType = (EdmStructuredType) source.type; |
| |
| EdmElement property = structType.getProperty(odi); |
| if (property == null) { |
| throw wrap(new UriParserSemanticException("Property '" + odi + "' not found in type '" |
| + structType.getNamespace() + "." + structType.getName() + "'", |
| ctx.depth() > 2 ? // path evaluation inside an expression or for the resource path? |
| UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE : |
| UriParserSemanticException.MessageKeys.PROPERTY_NOT_IN_TYPE, |
| structType.getFullQualifiedName().toString(), odi)); |
| } |
| |
| if (property instanceof EdmProperty) { |
| if (((EdmProperty) property).isPrimitive() == true) { |
| // create simple property |
| UriResourcePrimitivePropertyImpl simpleResource = new UriResourcePrimitivePropertyImpl() |
| .setProperty((EdmProperty) property); |
| context.contextUriInfo.addResourcePart(simpleResource); |
| return null; |
| } else { |
| // create complex property |
| UriResourceComplexPropertyImpl complexResource = new UriResourceComplexPropertyImpl() |
| .setProperty((EdmProperty) property); |
| context.contextUriInfo.addResourcePart(complexResource); |
| return null; |
| } |
| } else if (property instanceof EdmNavigationProperty) { |
| // create navigation property |
| UriResourceNavigationPropertyImpl navigationResource = new UriResourceNavigationPropertyImpl() |
| .setNavigationProperty((EdmNavigationProperty) property); |
| context.contextUriInfo.addResourcePart(navigationResource); |
| return null; |
| } else { |
| throw wrap(new UriParserSemanticException("Unkown type for property '" + property + "'", |
| UriParserSemanticException.MessageKeys.UNKNOWN_PROPERTY_TYPE, property.getName())); |
| } |
| |
| } else { // with namespace |
| |
| FullQualifiedName fullFilterName = getFullNameFromContext(ctx.vNS, odi); |
| |
| // EdmType lastType = getLastType(lastTyped); |
| if (source.type instanceof EdmEntityType) { |
| |
| EdmEntityType filterEntityType = edm.getEntityType(fullFilterName); |
| if (filterEntityType != null) { |
| // is entity type cast |
| if (!(filterEntityType.compatibleTo(source.type))) { |
| throw wrap(new UriParserSemanticException( |
| "Entity typefilter not compatible to previous path segment: " + fullFilterName.toString(), |
| UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, fullFilterName.toString())); |
| } |
| |
| if (lastResourcePart == null) { |
| // this may be the case if a member expression within a filter starts with a typeCast |
| UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl() |
| .setType(filterEntityType) |
| .setCollection(source.isCollection); |
| if (source.isCollection) { |
| uriResource.setCollectionTypeFilter(filterEntityType); |
| } else { |
| uriResource.setEntryTypeFilter(filterEntityType); |
| } |
| context.contextUriInfo.addResourcePart(uriResource); |
| return null; |
| } else { |
| |
| // check if last segment may contain key properties |
| if (lastResourcePart instanceof UriResourceWithKeysImpl) { |
| UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart; |
| |
| if (lastPartWithKeys.isCollection() == false) { |
| if (lastPartWithKeys.getTypeFilterOnEntry() != null) { |
| throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '" |
| + getName(filterEntityType) + "' behind '" |
| + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'", |
| UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE, |
| getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterEntityType))); |
| } |
| lastPartWithKeys.setEntryTypeFilter(filterEntityType); |
| return null; |
| } else { |
| if (lastPartWithKeys.getTypeFilterOnCollection() != null) { |
| throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '" |
| + getName(filterEntityType) + "' behind '" |
| + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'", |
| UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE, |
| getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterEntityType))); |
| } |
| lastPartWithKeys.setCollectionTypeFilter(filterEntityType); |
| return null; |
| } |
| } else if (lastResourcePart instanceof UriResourceTypedImpl) { |
| UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart; |
| if (lastPartTyped.getTypeFilter() != null) { |
| throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '" |
| + getName(filterEntityType) + "' behind '" |
| + getName(lastPartTyped.getTypeFilter()) + "'", |
| UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE, |
| getName(lastPartTyped.getTypeFilter()), getName(filterEntityType))); |
| } |
| |
| lastPartTyped.setTypeFilter(filterEntityType); |
| return null; |
| } else { |
| throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterEntityType) |
| + "' not typed", |
| UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterEntityType))); |
| } |
| } |
| } |
| |
| } else if (source.type instanceof EdmComplexType) { |
| |
| EdmComplexType filterComplexType = edm.getComplexType(fullFilterName); |
| |
| if (filterComplexType != null) { |
| |
| // is complex type cast |
| if (!(filterComplexType.compatibleTo(source.type))) { |
| throw wrap(new UriParserSemanticException( |
| "Complex typefilter '" + getName(source.type) + "'not compatible type of previous path segment '" |
| + getName(filterComplexType) + "'", |
| UriParserSemanticException.MessageKeys.INCOMPATIBLE_TYPE_FILTER, getName(source.type))); |
| } |
| |
| // is simple complex type cast |
| if (lastResourcePart == null) { |
| // this may be the case if a member expression within a filter starts with a typeCast |
| UriResourceStartingTypeFilterImpl uriResource = new UriResourceStartingTypeFilterImpl() |
| .setType(filterComplexType) |
| .setCollection(source.isCollection); |
| |
| if (source.isCollection) { |
| uriResource.setCollectionTypeFilter(filterComplexType); |
| } else { |
| uriResource.setEntryTypeFilter(filterComplexType); |
| } |
| context.contextUriInfo.addResourcePart(uriResource); |
| return null; |
| } else { |
| if (lastResourcePart instanceof UriResourceWithKeysImpl) { |
| // e.g. in case of function returning complex data or a list of complex data |
| UriResourceWithKeysImpl lastPartWithKeys = (UriResourceWithKeysImpl) lastResourcePart; |
| |
| if (lastPartWithKeys.isCollection() == false) { |
| if (lastPartWithKeys.getTypeFilterOnEntry() != null) { |
| throw wrap(new UriParserSemanticException("Entry typefilters are not chainable, used '" |
| + getName(filterComplexType) + "' behind '" |
| + getName(lastPartWithKeys.getTypeFilterOnEntry()) + "'", |
| UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE, |
| getName(lastPartWithKeys.getTypeFilterOnEntry()), getName(filterComplexType))); |
| } |
| lastPartWithKeys.setEntryTypeFilter(filterComplexType); |
| return null; |
| } else { |
| if (lastPartWithKeys.getTypeFilterOnCollection() != null) { |
| throw wrap(new UriParserSemanticException("Collection typefilters are not chainable, used '" |
| + getName(filterComplexType) + "' behind '" |
| + getName(lastPartWithKeys.getTypeFilterOnCollection()) + "'", |
| UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE, |
| getName(lastPartWithKeys.getTypeFilterOnCollection()), getName(filterComplexType))); |
| } |
| lastPartWithKeys.setCollectionTypeFilter(filterComplexType); |
| return null; |
| } |
| |
| } else if (lastResourcePart instanceof UriResourceTypedImpl) { |
| UriResourceTypedImpl lastPartTyped = (UriResourceTypedImpl) lastResourcePart; |
| if (lastPartTyped.getTypeFilter() != null) { |
| throw wrap(new UriParserSemanticException("Typefilters are not chainable, used '" |
| + getName(filterComplexType) + "' behind '" |
| + getName(lastPartTyped.getTypeFilter()) + "'", |
| UriParserSemanticException.MessageKeys.TYPE_FILTER_NOT_CHAINABLE, |
| getName(lastPartTyped.getTypeFilter()), getName(filterComplexType))); |
| } |
| |
| lastPartTyped.setTypeFilter(filterComplexType); |
| return null; |
| } else { |
| throw wrap(new UriParserSemanticException("Path segment before '" + getName(filterComplexType) |
| + "' not typed", |
| UriParserSemanticException.MessageKeys.PREVIOUS_PART_NOT_TYPED, getName(filterComplexType))); |
| } |
| } |
| } |
| } |
| |
| FullQualifiedName fullBindingTypeName = new FullQualifiedName(source.type.getNamespace(), source.type.getName()); |
| |
| // check for action |
| EdmAction action = edm.getBoundAction(fullFilterName, fullBindingTypeName, source.isCollection); |
| if (action != null) { |
| UriResourceActionImpl pathInfoAction = new UriResourceActionImpl(); |
| pathInfoAction.setAction(action); |
| context.contextUriInfo.addResourcePart(pathInfoAction); |
| return null; |
| } |
| |
| // do a check for bound functions (which requires a parameter list) |
| if (ctx.vlNVO.size() == 0) { |
| throw wrap(new UriParserSemanticException("Expected function parameters for '" + fullBindingTypeName.toString() |
| + "'", |
| UriParserSemanticException.MessageKeys.FUNCTION_PARAMETERS_EXPECTED, fullBindingTypeName.toString())); |
| } |
| |
| context.contextReadingFunctionParameters = true; |
| @SuppressWarnings("unchecked") |
| List<UriParameterImpl> parameters = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this); |
| context.contextReadingFunctionParameters = false; |
| |
| // get names of function parameters |
| List<String> names = new ArrayList<String>(); |
| for (UriParameterImpl item : parameters) { |
| names.add(item.getName()); |
| } |
| |
| EdmFunction function = edm.getBoundFunction(fullFilterName, fullBindingTypeName, source.isCollection, names); |
| |
| if (function != null) { |
| UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl() |
| .setFunction(function) |
| .setParameters(parameters); |
| context.contextUriInfo.addResourcePart(pathInfoFunction); |
| |
| // mark parameters as consumed |
| ctx.vlNVO.remove(0); |
| return null; |
| } |
| |
| // check for unbound function in the $filter case ( where the previous resource segment is a $it) |
| function = edm.getUnboundFunction(fullFilterName, names); |
| |
| if (function != null) { |
| UriResourceFunctionImpl pathInfoFunction = new UriResourceFunctionImpl() |
| .setFunction(function) |
| .setParameters(parameters); |
| context.contextUriInfo.addResourcePart(pathInfoFunction); |
| |
| // mark parameters as consumed |
| ctx.vlNVO.remove(0); |
| return null; |
| } |
| |
| throw wrap(new UriParserSemanticException("Unknown resource path segment:" + fullFilterName.toString(), |
| UriParserSemanticException.MessageKeys.UNKNOWN_PART, fullFilterName.toString())); |
| } |
| } |
| |
| private String getName(final EdmType type) { |
| return type.getFullQualifiedName().getFullQualifiedNameAsString(); |
| } |
| |
| @Override |
| public Object visitAllEOF(final AllEOFContext ctx) { |
| UriInfoImpl crossJoin = new UriInfoImpl().setKind(UriInfoKind.all); |
| context.contextUriInfo = crossJoin; |
| return null; |
| } |
| |
| @Override |
| public Object visitAllExpr(final AllExprContext ctx) { |
| UriResourceLambdaAllImpl all = new UriResourceLambdaAllImpl(); |
| |
| UriResource obj = context.contextUriInfo.getLastResourcePart(); |
| if (!(obj instanceof UriResourcePartTyped)) { |
| throw wrap(new UriParserSemanticException("all only allowed on typed path segments", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "all")); |
| } |
| |
| UriContext.LambdaVariables var = new UriContext.LambdaVariables(); |
| var.name = ctx.vLV.getText(); |
| var.type = getTypeInformation(obj).type; |
| var.isCollection = false; |
| |
| all.setLamdaVariable(ctx.vLV.getText()); |
| context.allowedLambdaVariables.push(var); |
| all.setExpression((ExpressionImpl) ctx.vLE.accept(this)); |
| context.allowedLambdaVariables.pop(); |
| return all; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltAdd(final AltAddContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| int tokenIndex = ctx.vO.getType(); |
| |
| if (tokenIndex == UriLexer.ADD) { |
| binary.setOperator(BinaryOperatorKind.ADD); |
| } else if (tokenIndex == UriLexer.SUB) { |
| binary.setOperator(BinaryOperatorKind.SUB); |
| } |
| |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| return binary; |
| } |
| |
| @Override |
| public Object visitAltAll(final AltAllContext ctx) { |
| |
| UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource); |
| |
| uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAll(ctx)); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath); |
| |
| MemberImpl ret = new MemberImpl(); |
| |
| ret.setResourcePath(uriInfoImplpath); |
| if (startType != null) { |
| ret.setTypeFilter(startType); |
| } |
| |
| return ret; |
| } |
| |
| private EdmType removeUriResourceStartingTypeFilterImpl(final UriInfoImpl uriInfoImplpath) { |
| |
| List<UriResource> segments = uriInfoImplpath.getUriResourceParts(); |
| if (segments.size() == 0) { |
| return null; |
| } |
| |
| UriResource segment = segments.get(0); |
| if (segment instanceof UriResourceStartingTypeFilterImpl) { |
| UriResourceStartingTypeFilterImpl startingTypeFilter = (UriResourceStartingTypeFilterImpl) segment; |
| |
| EdmType type = null; |
| if (startingTypeFilter.getTypeFilterOnEntry() != null) { |
| type = startingTypeFilter.getTypeFilterOnEntry(); |
| } else if (startingTypeFilter.getTypeFilterOnCollection() != null) { |
| type = startingTypeFilter.getTypeFilterOnCollection(); |
| } else { |
| type = startingTypeFilter.getType(); |
| } |
| |
| uriInfoImplpath.removeResourcePart(0); |
| return type; |
| } |
| |
| return null; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltAnd(final AltAndContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| binary.setOperator(BinaryOperatorKind.AND); |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| |
| return binary; |
| } |
| |
| @Override |
| public Object visitAltAny(final AltAnyContext ctx) { |
| UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource); |
| |
| uriInfoImplpath.addResourcePart((UriResourceImpl) super.visitAltAny(ctx)); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath); |
| |
| MemberImpl ret = new MemberImpl(); |
| ret.setResourcePath(uriInfoImplpath); |
| if (startType != null) { |
| ret.setTypeFilter(startType); |
| } |
| return ret; |
| } |
| |
| @Override |
| public Object visitBatchEOF(final BatchEOFContext ctx) { |
| context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.batch); |
| return null; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltComparism(final AltComparismContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| int tokenIndex = ctx.vO.getType(); |
| |
| if (tokenIndex == UriLexer.GT) { |
| binary.setOperator(BinaryOperatorKind.GT); |
| } else if (tokenIndex == UriLexer.GE) { |
| binary.setOperator(BinaryOperatorKind.GE); |
| } else if (tokenIndex == UriLexer.LT) { |
| binary.setOperator(BinaryOperatorKind.LT); |
| } else if (tokenIndex == UriLexer.LE) { |
| binary.setOperator(BinaryOperatorKind.LE); |
| } |
| |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| return binary; |
| } |
| |
| @Override |
| public Object visitEntityEOF(final EntityEOFContext ctx) { |
| String odi = ctx.vODI.getText(); |
| FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi); |
| |
| EdmEntityType type = edm.getEntityType(fullName); |
| if (type == null) { |
| throw wrap(new UriParserSemanticException("Expected EntityTypeName", |
| UriParserSemanticException.MessageKeys.UNKNOWN_ENTITY_TYPE, fullName.toString())); |
| } |
| context.contextUriInfo.setEntityTypeCast(type); |
| |
| // contextUriInfo = uriInfo; |
| context.contextTypes.push(new TypeInformation(context.contextUriInfo.getEntityTypeCast(), true)); |
| |
| // @SuppressWarnings("unchecked") |
| // List<QueryOptionImpl> list = (List<QueryOptionImpl>) ctx.vEO.accept(this); |
| // uriInfo.setQueryOptions(list); |
| return null; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltEquality(final AltEqualityContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| int tokenIndex = ctx.vO.getType(); |
| |
| if (tokenIndex == UriLexer.EQ_ALPHA) { |
| binary.setOperator(BinaryOperatorKind.EQ); |
| } else { |
| binary.setOperator(BinaryOperatorKind.NE); |
| } |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| |
| return binary; |
| } |
| |
| @Override |
| public Object visitAltHas(final AltHasContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| binary.setOperator(BinaryOperatorKind.HAS); |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| |
| return binary; |
| } |
| |
| @Override |
| public Object visitMetadataEOF(final MetadataEOFContext ctx) { |
| UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.metadata); |
| |
| context.contextUriInfo = uriInfo; |
| return null; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltMult(final AltMultContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| int tokenIndex = ctx.vO.getType(); |
| |
| if (tokenIndex == UriLexer.MUL) { |
| binary.setOperator(BinaryOperatorKind.MUL); |
| } else if (tokenIndex == UriLexer.DIV) { |
| binary.setOperator(BinaryOperatorKind.DIV); |
| } else { |
| binary.setOperator(BinaryOperatorKind.MOD); |
| } |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| |
| return binary; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltOr(final AltOrContext ctx) { |
| BinaryImpl binary = new BinaryImpl(); |
| |
| binary.setOperator(BinaryOperatorKind.OR); |
| binary.setLeftOperand((ExpressionImpl) ctx.vE1.accept(this)); |
| binary.setRightOperand((ExpressionImpl) ctx.vE2.accept(this)); |
| |
| return binary; |
| } |
| |
| @Override |
| public Object visitAnyExpr(final AnyExprContext ctx) { |
| UriResourceLambdaAnyImpl any = new UriResourceLambdaAnyImpl(); |
| if (ctx.vLV != null) { |
| UriResourceImpl lastResourcePart = (UriResourceImpl) context.contextUriInfo.getLastResourcePart(); |
| if (!(lastResourcePart instanceof UriResourcePartTyped)) { |
| throw wrap(new UriParserSemanticException("any only allowed on typed path segments", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "any")); |
| } |
| |
| UriContext.LambdaVariables var = new UriContext.LambdaVariables(); |
| var.name = ctx.vLV.getText(); |
| var.type = getTypeInformation(lastResourcePart).type; |
| var.isCollection = false; |
| |
| any.setLamdaVariable(ctx.vLV.getText()); |
| context.allowedLambdaVariables.push(var); |
| any.setExpression((ExpressionImpl) ctx.vLE.accept(this)); |
| context.allowedLambdaVariables.pop(); |
| } |
| return any; |
| } |
| |
| @Override |
| public Object visitBooleanNonCase(final BooleanNonCaseContext ctx) { |
| String text = ctx.getText().toLowerCase(); |
| |
| if (text.equals("false")) { |
| return new LiteralImpl().setText("false").setType( |
| EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)); |
| } |
| return new LiteralImpl().setText("true").setType( |
| EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Boolean)); |
| } |
| |
| @Override |
| public ExpressionImpl visitCastExpr(final CastExprContext ctx) { |
| MethodImpl method = new MethodImpl(); |
| if (ctx.vE1 != null) { |
| // is optional parameter |
| ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this); |
| method.addParameter(onExpression); |
| } |
| |
| String namespace = ctx.vNS.getText(); |
| namespace = namespace.substring(0, namespace.length() - 1); |
| |
| FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText()); |
| EdmType type = getType(fullName); |
| method.setMethod(MethodKind.CAST); |
| method.addParameter(new TypeLiteralImpl().setType(type)); |
| return method; |
| } |
| |
| private EdmType getType(final FullQualifiedName fullName) { |
| EdmType type = null; |
| |
| type = edm.getEntityType(fullName); |
| if (type != null) { |
| return type; |
| } |
| |
| type = edm.getComplexType(fullName); |
| if (type != null) { |
| return type; |
| } |
| |
| type = edm.getEnumType(fullName); |
| if (type != null) { |
| return type; |
| } |
| |
| if (fullName.getNamespace().equals(EdmPrimitiveType.EDM_NAMESPACE)) { |
| final EdmPrimitiveTypeKind typeKind = EdmPrimitiveTypeKind.valueOf(fullName.getName()); |
| type = EdmPrimitiveTypeFactory.getInstance(typeKind); |
| if (type != null) { |
| return type; |
| } |
| } |
| |
| return null; |
| |
| } |
| |
| @Override |
| public ExpressionImpl visitCeilingMethodCallExpr(final CeilingMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.CEILING) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitConcatMethodCallExpr(final ConcatMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.CONCAT) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public Object visitConstSegment(final ConstSegmentContext ctx) { |
| UriInfoImpl uriInfoResource = context.contextUriInfo; |
| UriResource pathInfo = uriInfoResource.getLastResourcePart(); |
| |
| if (ctx.vV != null) { |
| if (pathInfo instanceof UriResourcePartTyped) { |
| if (!((UriResourcePartTyped) pathInfo).isCollection()) { |
| context.contextUriInfo.addResourcePart(new UriResourceValueImpl()); |
| } else { |
| throw wrap(new UriParserSemanticException("$value only allowed on typed path segments", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value")); |
| } |
| return null; |
| } else { |
| throw wrap(new UriParserSemanticException("$value only allowed on typed path segments", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$value")); |
| } |
| |
| } else if (ctx.vC != null) { |
| if (pathInfo instanceof UriResourcePartTyped) { |
| if (((UriResourcePartTyped) pathInfo).isCollection()) { |
| context.contextUriInfo.addResourcePart(new UriResourceCountImpl()); |
| } else { |
| throw wrap(new UriParserSemanticException("$count only allowed on collection properties", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_COLLECTIONS, "$count")); |
| } |
| } else { |
| throw wrap(new UriParserSemanticException("$count only allowed on typed properties", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "$count")); |
| } |
| } else if (ctx.vR != null) { |
| if (pathInfo instanceof UriResourcePartTyped) { |
| EdmType type = ((UriResourcePartTyped) pathInfo).getType(); |
| if (type instanceof EdmEntityType) { |
| context.contextUriInfo.addResourcePart(new UriResourceRefImpl()); |
| } else { |
| throw wrap(new UriParserSemanticException("$ref only allowed on entity types", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_ENTITY_TYPES, "$ref")); |
| } |
| } else { |
| throw wrap(new UriParserSemanticException("$ref only allowed on typed properties", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PROPERTIES, "$ref")); |
| } |
| |
| } else if (ctx.vAll != null) { |
| context.contextUriInfo.addResourcePart((UriResourceLambdaAllImpl) ctx.vAll.accept(this)); |
| } else if (ctx.vAny != null) { |
| context.contextUriInfo.addResourcePart((UriResourceLambdaAnyImpl) ctx.vAny.accept(this)); |
| } |
| return null; |
| } |
| |
| @Override |
| public ExpressionImpl visitContainsMethodCallExpr(final ContainsMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.CONTAINS) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public Object visitCrossjoinEOF(final CrossjoinEOFContext ctx) { |
| UriInfoImpl crossJoin = new UriInfoImpl().setKind(UriInfoKind.crossjoin); |
| |
| for (OdataIdentifierContext obj : ctx.vlODI) { |
| crossJoin.addEntitySetName(obj.getText()); |
| } |
| |
| context.contextUriInfo = crossJoin; |
| return null; |
| } |
| |
| @Override |
| public Object visitDateMethodCallExpr(final DateMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.DATE) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitDayMethodCallExpr(final DayMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.DAY) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitGeoDistanceMethodCallExpr(final GeoDistanceMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.GEODISTANCE) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public Object visitEndsWithMethodCallExpr(final EndsWithMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.ENDSWITH) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public Object visitEnumLit(final EnumLitContext ctx) { |
| EnumerationImpl enum1 = new EnumerationImpl(); |
| |
| // get type |
| String odi = ctx.vODI.getText(); |
| |
| FullQualifiedName fullName = getFullNameFromContext(ctx.vNS, odi); |
| EdmEnumType edmEnumType = edm.getEnumType(fullName); |
| |
| enum1.setType(edmEnumType); |
| |
| String valueString = ctx.vValues.getText(); |
| valueString = valueString.substring(1, valueString.length() - 1); |
| |
| String[] values = valueString.split(","); |
| for (String item : values) { |
| enum1.addValue(item); |
| } |
| |
| return enum1; |
| } |
| |
| @Override |
| public Object visitExpandItems(final ExpandItemsContext ctx) { |
| ExpandOptionImpl expand = new ExpandOptionImpl(); |
| expand.setText(ctx.getText()); |
| for (ExpandItemContext eI : ctx.vlEI) { |
| expand.addExpandItem((ExpandItemImpl) eI.accept(this)); |
| } |
| |
| return expand; |
| } |
| |
| @Override |
| public Object visitExpandItem(final ExpandItemContext ctx) { |
| |
| ExpandItemImpl expandItem = null; |
| if (ctx.vS != null) { |
| expandItem = new ExpandItemImpl().setIsStar(true); |
| if (ctx.vR != null) { |
| expandItem.setIsRef(true); |
| } else if (ctx.vM != null) { |
| LevelsOptionImpl levels = new LevelsOptionImpl().setMax(); |
| levels.setText(ctx.vM.getText()); |
| expandItem.setSystemQueryOption(levels); |
| } else if (ctx.vL != null) { |
| LevelsOptionImpl levels = new LevelsOptionImpl(); |
| String text = ctx.vL.getText(); |
| levels.setText(text); |
| levels.setValue(Integer.parseInt(text)); |
| expandItem.setSystemQueryOption(levels); |
| } |
| |
| } else if (ctx.vEP != null) { |
| expandItem = (ExpandItemImpl) ctx.vEP.accept(this); |
| |
| if (ctx.vEPE != null) { |
| ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath; |
| context.contextExpandItemPath = expandItem; |
| |
| @SuppressWarnings("unchecked") |
| List<SystemQueryOptionImpl> list = (List<SystemQueryOptionImpl>) ctx.vEPE.accept(this); |
| for (SystemQueryOptionImpl option : list) { |
| expandItem.setSystemQueryOption(option); |
| } |
| context.contextExpandItemPath = contextExpandItemPathBU; |
| } |
| } |
| |
| return expandItem; |
| |
| } |
| |
| @Override |
| public Object visitExpandPath(final ExpandPathContext ctx) { |
| ExpandItemImpl expandItem = new ExpandItemImpl(); |
| |
| // UriResourceItImpl pathInfoIT = new UriResourceItImpl(); |
| context.contextUriInfo.getLastResourcePart(); |
| |
| // save context |
| ExpandItemImpl contextExpandItemPathBU = context.contextExpandItemPath; |
| UriInfoImpl uriInfoResourceBU = context.contextUriInfo; |
| |
| // set tmp context |
| context.contextExpandItemPath = expandItem; |
| context.contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); |
| // contextUriInfo.addPathInfo(pathInfoIT); |
| |
| super.visitExpandPath(ctx); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(context.contextUriInfo); |
| expandItem.setResourcePath(context.contextUriInfo); |
| if (startType != null) { |
| expandItem.setTypeFilter(startType); |
| } |
| |
| // reset context |
| context.contextUriInfo = uriInfoResourceBU; |
| context.contextExpandItemPath = contextExpandItemPathBU; |
| |
| return expandItem; |
| } |
| |
| @Override |
| public Object visitExpandPathExtension(final ExpandPathExtensionContext ctx) { |
| List<SystemQueryOptionImpl> list = new ArrayList<SystemQueryOptionImpl>(); |
| |
| EdmType targetType = null; |
| boolean isColl = false; |
| if (context.contextExpandItemPath == null) { |
| // use the type of the last resource path segement |
| UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart(); |
| targetType = getTypeInformation(lastSegment).type; |
| isColl = lastSegment.isCollection(); |
| } else { |
| if (context.contextExpandItemPath.getResourcePath() == null) { |
| // use the type of the last resource path segement |
| UriResourceTypedImpl lastSegment = (UriResourceTypedImpl) context.contextUriInfo.getLastResourcePart(); |
| targetType = getTypeInformation(lastSegment).type; |
| isColl = lastSegment.isCollection(); |
| } else { |
| // use the type of the last ''expand'' path segement |
| UriInfoImpl info = (UriInfoImpl) context.contextExpandItemPath.getResourcePath(); |
| targetType = getTypeInformation(info.getLastResourcePart()).type; |
| isColl = ((UriResourcePartTyped) info.getLastResourcePart()).isCollection(); |
| } |
| } |
| |
| context.contextTypes.push(new TypeInformation(targetType, isColl)); |
| |
| if (ctx.vC != null) { |
| UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath(); |
| resourcePath.addResourcePart(new UriResourceCountImpl()); |
| |
| for (ExpandCountOptionContext s : ctx.vlEOC) { |
| list.add((SystemQueryOptionImpl) s.accept(this)); |
| } |
| } else if (ctx.vR != null) { |
| UriInfoImpl resourcePath = (UriInfoImpl) context.contextExpandItemPath.getResourcePath(); |
| resourcePath.addResourcePart(new UriResourceRefImpl()); |
| |
| for (ExpandRefOptionContext s : ctx.vlEOR) { |
| list.add((SystemQueryOptionImpl) s.accept(this)); |
| } |
| } else { |
| for (ExpandOptionContext s : ctx.vlEO) { |
| list.add((SystemQueryOptionImpl) s.accept(this)); |
| } |
| } |
| |
| context.contextTypes.pop(); |
| return list; |
| |
| } |
| |
| @Override |
| public Object visitFilter(final FilterContext ctx) { |
| |
| FilterOptionImpl filter = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(2).accept(this)); |
| return filter; |
| } |
| |
| @Override |
| public Object visitFilterExpressionEOF(final FilterExpressionEOFContext ctx) { |
| |
| FilterOptionImpl filter = new FilterOptionImpl().setExpression((ExpressionImpl) ctx.children.get(0).accept(this)); |
| return filter; |
| } |
| |
| @Override |
| public ExpressionImpl visitFloorMethodCallExpr(final FloorMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.FLOOR) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitFractionalsecondsMethodCallExpr(final FractionalsecondsMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.FRACTIONALSECONDS) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitGeoLengthMethodCallExpr(final GeoLengthMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.GEOLENGTH) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitHourMethodCallExpr(final HourMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.HOUR) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitIndexOfMethodCallExpr(final IndexOfMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.INDEXOF) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public Object visitInlinecount(final InlinecountContext ctx) { |
| CountOptionImpl inlineCount = new CountOptionImpl(); |
| |
| String text = ctx.children.get(2).getText(); |
| |
| return inlineCount.setValue(text.toLowerCase().equals("true") ? true : false).setText(text); |
| } |
| |
| @Override |
| public ExpressionImpl visitGeoIntersectsMethodCallExpr(final GeoIntersectsMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.GEOINTERSECTS) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitIsofExpr(final IsofExprContext ctx) { |
| MethodImpl method = new MethodImpl(); |
| if (ctx.vE1 != null) { |
| ExpressionImpl onExpression = (ExpressionImpl) ctx.vE1.accept(this); |
| method.addParameter(onExpression); |
| } |
| |
| String namespace = ctx.vNS.getText(); |
| namespace = namespace.substring(0, namespace.length() - 1); |
| |
| FullQualifiedName fullName = new FullQualifiedName(namespace, ctx.vODI.getText()); |
| EdmType type = getType(fullName); |
| method.setMethod(MethodKind.ISOF); |
| method.addParameter(new TypeLiteralImpl().setType(type)); |
| |
| return method; |
| } |
| |
| @Override |
| public ExpressionImpl visitLengthMethodCallExpr(final LengthMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.LENGTH) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public Object visitLevels(final LevelsContext ctx) { |
| |
| LevelsOptionImpl levels = new LevelsOptionImpl(); |
| |
| String text = ctx.children.get(2).getText(); |
| |
| if (text.equals("max")) { |
| levels.setMax(); |
| } else { |
| levels.setValue(Integer.parseInt(text)); |
| } |
| levels.setText(text); |
| |
| return levels; |
| |
| } |
| |
| @Override |
| public ExpressionImpl visitMaxDateTimeMethodCallExpr(final MaxDateTimeMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.MAXDATETIME); |
| } |
| |
| @Override |
| public Object visitMemberExpr(final MemberExprContext ctx) { |
| |
| UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource); |
| |
| if (context.contextTypes.isEmpty()) { |
| throw wrap(new UriParserSemanticException("Expression '" + ctx.getText() + "' is not allowed as key value.", |
| UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, ctx.getText())); |
| } |
| TypeInformation lastTypeInfo = context.contextTypes.peek(); |
| |
| if (ctx.vIt != null || ctx.vIts != null) { |
| UriResourceItImpl pathInfoIT = new UriResourceItImpl(); |
| pathInfoIT.setType(lastTypeInfo.type); |
| pathInfoIT.setCollection(lastTypeInfo.isCollection); |
| uriInfoImplpath.addResourcePart(pathInfoIT); |
| } |
| |
| if (ctx.vPs != null) { |
| // save the context |
| UriInfoImpl backupUriInfoPath = context.contextUriInfo; |
| |
| // set temporary uriInfoPath |
| context.contextUriInfo = uriInfoImplpath; |
| |
| ctx.vPs.accept(this); |
| |
| // reset context |
| context.contextUriInfo = backupUriInfoPath; |
| } |
| |
| if (ctx.vALL != null) { |
| uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vALL.accept(this)); |
| } |
| if (ctx.vANY != null) { |
| uriInfoImplpath.addResourcePart((UriResourceImpl) ctx.vANY.accept(this)); |
| } |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfoImplpath); |
| |
| MemberImpl ret = new MemberImpl(); |
| ret.setResourcePath(uriInfoImplpath); |
| if (startType != null) { |
| ret.setTypeFilter(startType); |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public ExpressionImpl visitMinDateTimeMethodCallExpr(final MinDateTimeMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.MINDATETIME); |
| } |
| |
| @Override |
| public ExpressionImpl visitMinuteMethodCallExpr(final MinuteMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.MINUTE) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitMonthMethodCallExpr(final MonthMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.MONTH) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public Object visitNameValueOptList(final NameValueOptListContext ctx) { |
| if (ctx.vVO != null) { |
| |
| // is single key predicate without a name |
| String valueText = ctx.vVO.getText(); |
| ExpressionImpl expression = null; |
| try { |
| expression = (ExpressionImpl) ctx.vVO.accept(this); |
| } catch (final RuntimeException e) { |
| throw wrap(new UriParserSemanticException("Invalid key value: " + valueText, e, |
| UriParserSemanticException.MessageKeys.INVALID_KEY_VALUE, valueText)); |
| } |
| |
| // get type of last resource part |
| UriResource last = context.contextUriInfo.getLastResourcePart(); |
| if (!(last instanceof UriResourcePartTyped)) { |
| throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed", |
| UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS)); |
| } |
| EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType(); |
| |
| // get list of keys for lastType |
| List<String> lastKeyPredicates = lastType.getKeyPredicateNames(); |
| |
| // If there is exactly one key defined in the EDM, then this key is the key written in the URI, |
| // so fill the keylist with this key and return. |
| if (lastKeyPredicates.size() == 1) { |
| return Collections.singletonList(new UriParameterImpl() |
| .setName(lastKeyPredicates.get(0)) |
| .setText(valueText) |
| .setExpression(expression)); |
| } |
| |
| // There are more keys defined in the EDM, but only one is written in the URI. This is allowed only if |
| // referential constraints are defined on this navigation property which can be used to fill up all |
| // required keys. |
| // For using referential constraints the last resource part must be a navigation property. |
| if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) { |
| throw wrap(new UriParserSemanticException("Wrong number of key properties.", |
| UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, |
| Integer.toString(lastKeyPredicates.size()), "1")); |
| } |
| UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last; |
| |
| // get the partner of the navigation property |
| EdmNavigationProperty partner = lastNav.getProperty().getPartner(); |
| if (partner == null) { |
| throw wrap(new UriParserSemanticException("Wrong number of key properties.", |
| UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, |
| Integer.toString(lastKeyPredicates.size()), "1")); |
| } |
| |
| // create the keylist |
| List<UriParameterImpl> list = new ArrayList<UriParameterImpl>(); |
| |
| // Find the keys not filled by referential constraints |
| // and collect the other keys filled by referential constraints. |
| String missedKey = null; |
| for (String item : lastKeyPredicates) { |
| String property = partner.getReferencingPropertyName(item); |
| if (property != null) { |
| list.add(new UriParameterImpl().setName(item).setRefencedProperty(property)); |
| } else { |
| if (missedKey == null) { |
| missedKey = item; |
| } else { |
| // two of more keys are missing |
| throw wrap(new UriParserSemanticException("Not enough referential constraints defined", |
| UriParserSemanticException.MessageKeys.NOT_ENOUGH_REFERENTIAL_CONSTRAINTS)); |
| } |
| } |
| } |
| |
| // the missing key is the one which is defined in the URI |
| list.add(new UriParameterImpl().setName(missedKey).setText(valueText).setExpression(expression)); |
| |
| return list; |
| } else if (ctx.vNVL != null) { |
| |
| List<UriParameterImpl> list = new ArrayList<UriParameterImpl>(); |
| |
| for (ParseTree c : ctx.vNVL.vlNVP) { |
| list.add((UriParameterImpl) c.accept(this)); |
| } |
| |
| if (context.contextReadingFunctionParameters) { |
| return list; |
| } |
| |
| UriResource last = context.contextUriInfo.getLastResourcePart(); |
| // if the last resource part is a function |
| /* |
| * if (last instanceof UriResourceFunctionImpl) { |
| * UriResourceFunctionImpl function = (UriResourceFunctionImpl) last; |
| * if (!function.isParameterListFilled()) { |
| * return list; |
| * } |
| * } |
| */ |
| |
| // get type of last resource part |
| if (!(last instanceof UriResourcePartTyped)) { |
| throw wrap(new UriParserSemanticException("Parameters list on untyped resource path segment not allowed", |
| UriParserSemanticException.MessageKeys.PARAMETERS_LIST_ONLY_FOR_TYPED_PARTS)); |
| } |
| EdmEntityType lastType = (EdmEntityType) ((UriResourcePartTyped) last).getType(); |
| |
| // get list of keys for lastType |
| List<String> lastKeyPredicates = lastType.getKeyPredicateNames(); |
| |
| // check if all key are filled from the URI |
| if (list.size() == lastKeyPredicates.size()) { |
| return list; |
| } |
| |
| // if not, check if the missing key predicates can be satisfied with help of the defined |
| // referential constraints |
| // for using referential constraints the last resource part must be a navigation property |
| if (!(context.contextUriInfo.getLastResourcePart() instanceof UriResourceNavigationPropertyImpl)) { |
| throw wrap(new UriParserSemanticException("Wrong number of key properties.", |
| UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, |
| Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size()))); |
| } |
| UriResourceNavigationPropertyImpl lastNav = (UriResourceNavigationPropertyImpl) last; |
| |
| // get the partner of the navigation property |
| EdmNavigationProperty partner = lastNav.getProperty().getPartner(); |
| if (partner == null) { |
| throw wrap(new UriParserSemanticException("Wrong number of key properties.", |
| UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, |
| Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size()))); |
| } |
| |
| // fill missing keys from referential constraints |
| for (String key : lastKeyPredicates) { |
| boolean found = false; |
| for (UriParameterImpl item : list) { |
| if (item.getName().equals(key)) { |
| found = true; |
| break; |
| } |
| } |
| |
| if (!found) { |
| String property = partner.getReferencingPropertyName(key); |
| if (property != null) { |
| // store the key name as referenced property |
| list.add(0, new UriParameterImpl().setName(key).setRefencedProperty(property)); |
| } |
| } |
| } |
| |
| // check again if all key predicates are filled from the URI |
| if (list.size() == lastKeyPredicates.size()) { |
| return list; |
| } else { |
| throw wrap(new UriParserSemanticException("Wrong number of key properties.", |
| UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, |
| Integer.toString(lastKeyPredicates.size()), Integer.toString(list.size()))); |
| } |
| } else { |
| if (context.contextReadingFunctionParameters) { |
| return Collections.emptyList(); |
| } else { |
| final UriResource last = context.contextUriInfo.getLastResourcePart(); |
| final int number = last instanceof UriResourcePartTyped ? |
| ((EdmEntityType) ((UriResourcePartTyped) last).getType()).getKeyPredicateNames().size() : 0; |
| throw wrap(new UriParserSemanticException("Wrong number of key properties.", |
| UriParserSemanticException.MessageKeys.WRONG_NUMBER_OF_KEY_PROPERTIES, Integer.toString(number), "0")); |
| } |
| } |
| } |
| |
| @Override |
| public UriParameterImpl visitNameValuePair(final NameValuePairContext ctx) { |
| UriParameterImpl uriParameter = new UriParameterImpl(); |
| uriParameter.setName(ctx.vODI.getText()); |
| |
| if (ctx.vCOM != null) { |
| uriParameter.setText(ctx.vCOM.getText()); |
| uriParameter.setExpression((ExpressionImpl) ctx.vCOM.accept(this)); |
| } else { |
| uriParameter.setAlias("@" + ctx.vALI.getText()); |
| } |
| |
| return uriParameter; |
| } |
| |
| @Override |
| public Object visitNaninfinity(final NaninfinityContext ctx) { |
| return new LiteralImpl().setType(EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Decimal)). |
| setText(ctx.getText()); |
| } |
| |
| @Override |
| public ExpressionImpl visitNowMethodCallExpr(final NowMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.NOW); |
| } |
| |
| @Override |
| public Object visitNullrule(final NullruleContext ctx) { |
| return new LiteralImpl().setText("null"); |
| } |
| |
| /* |
| * @Override |
| * public Object visitOdataRelativeUriEOF(final OdataRelativeUriEOFContext ctx) { |
| * contextUriInfo = null; |
| * super.visitOdataRelativeUriEOF(ctx); |
| * return contextUriInfo; |
| * } |
| */ |
| @Override |
| public Object visitOrderBy(final OrderByContext ctx) { |
| |
| OrderByOptionImpl orderBy = new OrderByOptionImpl(); |
| |
| for (OrderByItemContext item : ((OrderListContext) ctx.getChild(2)).vlOI) { |
| OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this); |
| orderBy.addOrder(oItem); |
| } |
| |
| return orderBy; |
| } |
| |
| @Override |
| public Object visitOrderByEOF(final OrderByEOFContext ctx) { |
| |
| OrderByOptionImpl orderBy = new OrderByOptionImpl(); |
| |
| for (OrderByItemContext item : ((OrderListContext) ctx.getChild(0)).vlOI) { |
| OrderByItemImpl oItem = (OrderByItemImpl) item.accept(this); |
| orderBy.addOrder(oItem); |
| } |
| |
| return orderBy; |
| } |
| |
| @Override |
| public Object visitOrderByItem(final OrderByItemContext ctx) { |
| OrderByItemImpl oItem = new OrderByItemImpl(); |
| if (ctx.vD != null) { |
| oItem.setDescending(true); |
| } |
| |
| oItem.setExpression((ExpressionImpl) ctx.vC.accept(this)); |
| return oItem; |
| } |
| |
| @Override |
| public Object visitPathSegment(final PathSegmentContext ctx) { |
| readResourcePathSegment(ctx); |
| /* |
| * if (contextUriInfo.getLastResourcePart() == null || |
| * contextUriInfo.getLastResourcePart() instanceof UriResourceRootImpl) { |
| * |
| * } else { |
| * readNextPathInfoSegment(ctx); |
| * } |
| */ |
| UriResourceImpl pathInfoSegment = (UriResourceImpl) context.contextUriInfo.getLastResourcePart(); |
| |
| if (ctx.vlNVO.size() > 0) { |
| // check for keyPredicates |
| if (pathInfoSegment instanceof UriResourceWithKeysImpl) { |
| @SuppressWarnings("unchecked") |
| List<UriParameterImpl> list = (List<UriParameterImpl>) ctx.vlNVO.get(0).accept(this); |
| ((UriResourceWithKeysImpl) pathInfoSegment) |
| .setKeyPredicates(list); |
| } else { |
| throw wrap(new UriParserSemanticException("Key properties not allowed", |
| UriParserSemanticException.MessageKeys.KEY_NOT_ALLOWED)); |
| } |
| } |
| |
| return pathInfoSegment; |
| } |
| |
| @Override |
| public Object visitPathSegments(final PathSegmentsContext ctx) { |
| // path segment |
| for (PathSegmentContext it : ctx.vlPS) { |
| it.accept(this); |
| } |
| |
| // const segment |
| if (ctx.vCS != null) { |
| ctx.vCS.accept(this); |
| } |
| return null; |
| } |
| |
| @Override |
| public Object visitPrimitiveLiteral(final PrimitiveLiteralContext ctx) { |
| ParseTree child1 = ctx.children.get(0); |
| |
| if (child1 instanceof EnumLitContext |
| || child1 instanceof BooleanNonCaseContext |
| || child1 instanceof NullruleContext |
| || child1 instanceof NaninfinityContext) { |
| return child1.accept(this); |
| } |
| return new LiteralImpl().setText(ctx.getText()); |
| } |
| |
| @Override |
| public Object visitQueryOptions(final QueryOptionsContext ctx) { |
| |
| List<QueryOptionImpl> qpList = new ArrayList<QueryOptionImpl>(); |
| for (QueryOptionContext entityOption : ctx.vlQO) { |
| qpList.add((QueryOptionImpl) entityOption.accept(this)); |
| } |
| |
| return qpList; |
| } |
| |
| /* |
| * @Override |
| * public Object visitResourcePath(final ResourcePathContext ctx) { |
| * if (ctx.vAll != null) { |
| * contextUriInfo = new UriInfoImpl().setKind(UriInfoKind.all); |
| * } else if (ctx.vCJ != null) { |
| * ctx.vCJ.accept(this); |
| * } else if (ctx.vlPS != null) { |
| * UriInfoImpl uriInfoPath = new UriInfoImpl().setKind(UriInfoKind.resource); |
| * contextUriInfo = uriInfoPath; |
| * super.visitResourcePath(ctx); // visit all children of ctx |
| * } |
| * return contextUriInfo; |
| * } |
| */ |
| @Override |
| public Object visitRootExpr(final RootExprContext ctx) { |
| |
| UriResource lastResource = context.contextUriInfo.getLastResourcePart(); |
| |
| if (!(lastResource instanceof UriResourcePartTyped)) { |
| throw wrap(new UriParserSemanticException("Resource path not typed", |
| UriParserSemanticException.MessageKeys.RESOURCE_PATH_NOT_TYPED)); |
| } |
| |
| UriResourcePartTyped lastType = (UriResourcePartTyped) lastResource; |
| |
| UriResourceRootImpl pathInfoRoot = new UriResourceRootImpl(); |
| pathInfoRoot.setCollection(lastType.isCollection()); |
| pathInfoRoot.setType(getTypeInformation(lastType).type); |
| |
| UriInfoImpl uriInfoImplpath = new UriInfoImpl().setKind(UriInfoKind.resource); |
| uriInfoImplpath.addResourcePart(pathInfoRoot); |
| |
| if (ctx.vPs != null) { |
| // store the context uriInfoPath |
| UriInfoImpl backupUriInfoPath = context.contextUriInfo; |
| |
| // set temporary uriInfoPath to collect the path information of the memberExpression |
| context.contextUriInfo = uriInfoImplpath; |
| |
| ctx.vPs.accept(this); |
| |
| context.contextUriInfo = backupUriInfoPath; |
| |
| } |
| return new MemberImpl() |
| .setResourcePath(uriInfoImplpath); |
| |
| } |
| |
| @Override |
| public ExpressionImpl visitRoundMethodCallExpr(final RoundMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.ROUND) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitSecondMethodCallExpr(final SecondMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.SECOND) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public Object visitSelect(final SelectContext ctx) { |
| List<SelectItemImpl> selectItems = new ArrayList<SelectItemImpl>(); |
| |
| for (SelectItemContext si : ctx.vlSI) { |
| selectItems.add((SelectItemImpl) si.accept(this)); |
| } |
| |
| return new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.children.get(2).getText()); |
| } |
| |
| @Override |
| public Object visitSelectEOF(final SelectEOFContext ctx) { |
| List<SelectItemImpl> selectItems = new ArrayList<SelectItemImpl>(); |
| |
| for (SelectItemContext si : ctx.vlSI) { |
| selectItems.add((SelectItemImpl) si.accept(this)); |
| } |
| |
| return new SelectOptionImpl().setSelectItems(selectItems).setText(ctx.getText()); |
| } |
| |
| @Override |
| public Object visitSelectItem(final SelectItemContext ctx) { |
| SelectItemImpl selectItem = new SelectItemImpl(); |
| |
| context.contextSelectItem = selectItem; |
| for (SelectSegmentContext si : ctx.vlSS) { |
| si.accept(this); |
| } |
| context.contextSelectItem = null; |
| |
| return selectItem; |
| } |
| |
| @Override |
| public Object visitSelectSegment(final SelectSegmentContext ctx) { |
| |
| if (ctx.vS != null) { |
| if (ctx.vNS != null) { |
| String namespace = ctx.vNS.getText(); |
| namespace = namespace.substring(0, namespace.length() - 1); |
| FullQualifiedName fullName = new FullQualifiedName(namespace, "*"); |
| context.contextSelectItem.addAllOperationsInSchema(fullName); |
| } else { |
| context.contextSelectItem.setStar(true); |
| } |
| return null; |
| } |
| |
| String odi = ctx.vODI.getText(); |
| if (ctx.vNS == null) { |
| |
| EdmType prevType = null; |
| if (context.contextSelectItem.getResourcePath() == null) { |
| prevType = context.contextTypes.peek().type; |
| } else { |
| UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| UriResource last = uriInfo.getLastResourcePart(); |
| |
| prevType = getTypeInformation(last).type; |
| if (prevType == null) { |
| throw wrap(new UriParserSemanticException("prev segment not typed", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select")); |
| } |
| } |
| |
| if (!(prevType instanceof EdmStructuredType)) { |
| throw wrap(new UriParserSemanticException("Previous select item is not a structural type", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_STRUCTURAL_TYPES, "select")); |
| } |
| |
| EdmStructuredType structType = (EdmStructuredType) prevType; |
| EdmElement element = structType.getProperty(odi); |
| if (element == null) { |
| throw wrap(new UriParserSemanticException("Previous select item has not property: " + odi, |
| UriParserSemanticException.MessageKeys.EXPRESSION_PROPERTY_NOT_IN_TYPE, structType.getName(), odi)); |
| } |
| |
| // create new segment |
| // SelectSegmentImpl newSegment = new SelectSegmentImpl().setProperty(property); |
| // contextSelectItem.addSegment(newSegment); |
| if (element instanceof EdmProperty) { |
| EdmProperty property = (EdmProperty) element; |
| if (property.isPrimitive()) { |
| |
| UriResourcePrimitivePropertyImpl simple = new UriResourcePrimitivePropertyImpl(); |
| simple.setProperty(property); |
| |
| UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| if (uriInfo == null) { |
| uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); |
| uriInfo.addResourcePart(simple); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo); |
| if (startType != null) { |
| context.contextSelectItem.setTypeFilter(startType); |
| } |
| |
| context.contextSelectItem.setResourcePath(uriInfo); |
| } else { |
| uriInfo.addResourcePart(simple); |
| } |
| return this; |
| } else { |
| UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| |
| UriResourceComplexPropertyImpl complex = new UriResourceComplexPropertyImpl(); |
| complex.setProperty(property); |
| |
| if (uriInfo == null) { |
| uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); |
| uriInfo.addResourcePart(complex); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo); |
| if (startType != null) { |
| context.contextSelectItem.setTypeFilter(startType); |
| } |
| |
| context.contextSelectItem.setResourcePath(uriInfo); |
| } else { |
| uriInfo.addResourcePart(complex); |
| } |
| return this; |
| } |
| } else { |
| throw wrap(new UriParserSemanticException("Only Simple and Complex properties within select allowed", |
| UriParserSemanticException.MessageKeys.ONLY_SIMPLE_AND_COMPLEX_PROPERTIES_IN_SELECT)); |
| } |
| } else { |
| String namespace = ctx.vNS.getText(); |
| namespace = namespace.substring(0, namespace.length() - 1); |
| |
| FullQualifiedName fullName = new FullQualifiedName(namespace, odi); |
| // contextSelectItem.addQualifiedThing(fullName); |
| |
| if (context.contextSelectItem.getResourcePath() == null) { |
| EdmType prevType = context.contextTypes.peek().type; |
| |
| // check for complex type cast |
| if (prevType instanceof EdmComplexType) { |
| EdmComplexType ct = edm.getComplexType(fullName); |
| if (ct != null) { |
| if ((ct.compatibleTo(prevType))) { |
| UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); |
| resourcePart.setCollectionTypeFilter(ct); |
| |
| UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); |
| uriInfo.addResourcePart(resourcePart); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo); |
| if (startType != null) { |
| context.contextSelectItem.setTypeFilter(startType); |
| } |
| |
| context.contextSelectItem.setResourcePath(uriInfo); |
| return this; |
| } |
| } |
| } else if (prevType instanceof EdmEntityType) { |
| EdmEntityType et = edm.getEntityType(fullName); |
| if (et != null) { |
| if ((et.compatibleTo(prevType))) { |
| UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); |
| resourcePart.setCollectionTypeFilter(et); |
| |
| UriInfoImpl uriInfo = new UriInfoImpl().setKind(UriInfoKind.resource); |
| uriInfo.addResourcePart(resourcePart); |
| |
| EdmType startType = removeUriResourceStartingTypeFilterImpl(uriInfo); |
| if (startType != null) { |
| context.contextSelectItem.setTypeFilter(startType); |
| } |
| |
| context.contextSelectItem.setResourcePath(uriInfo); |
| return this; |
| } |
| } |
| } else { |
| throw wrap(new UriParserSemanticException("prev segment must be complex of entity type", |
| UriParserSemanticException.MessageKeys.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED)); |
| } |
| |
| } else { |
| UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| UriResource last = uriInfo.getLastResourcePart(); |
| if (!(last instanceof UriResourceTypedImpl)) { |
| throw wrap(new UriParserSemanticException("prev segment typed", |
| UriParserSemanticException.MessageKeys.ONLY_FOR_TYPED_PARTS, "select")); |
| } |
| EdmType prevType = getTypeInformation(last).type; |
| |
| if (prevType instanceof EdmComplexType) { |
| EdmComplexType ct = edm.getComplexType(fullName); |
| if (ct != null) { |
| if ((ct.compatibleTo(prevType))) { |
| UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); |
| resourcePart.setCollectionTypeFilter(ct); |
| |
| uriInfo.addResourcePart(resourcePart); |
| return this; |
| } |
| } |
| } else if (prevType instanceof EdmEntityType) { |
| throw wrap(new UriParserSemanticException("Error", |
| UriParserSemanticException.MessageKeys.NOT_FOR_ENTITY_TYPE)); |
| /* |
| * EdmEntityType et = edm.getEntityType(fullName); |
| * if (et != null) { |
| * if ((et.compatibleTo((EdmStructuralType) prevType))) { |
| * UriResourceStartingTypeFilterImpl resourcePart = new UriResourceStartingTypeFilterImpl(); |
| * resourcePart.setEntryTypeFilter(et); |
| * |
| * uriInfo.addResourcePart(resourcePart); |
| * return this; |
| * } |
| * } |
| */ |
| } else { |
| throw wrap(new UriParserSemanticException("prev segment must be complex of entity type", |
| UriParserSemanticException.MessageKeys.COMPLEX_PROPERTY_OF_ENTITY_TYPE_EXPECTED)); |
| } |
| } |
| |
| EdmType prevType = null; |
| if (context.contextSelectItem.getResourcePath() == null) { |
| prevType = context.contextTypes.peek().type; |
| } else { |
| UriInfoImpl uriInfo = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| UriResource last = uriInfo.getLastResourcePart(); |
| if (!(last instanceof UriResourceTypedImpl)) { |
| throw wrap(new UriParserSemanticException("prev segment typed", |
| UriParserSemanticException.MessageKeys.PREVIOUS_PART_TYPED)); |
| } |
| prevType = getTypeInformation(last).type; |
| } |
| |
| FullQualifiedName finalTypeName = new FullQualifiedName(prevType.getNamespace(), prevType.getName()); |
| |
| // check for action |
| EdmAction action = edm.getBoundAction(fullName, finalTypeName, null); |
| |
| if (action != null) { |
| UriResourceActionImpl uriAction = new UriResourceActionImpl(); |
| uriAction.setAction(action); |
| |
| UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| resourcePath.addResourcePart(uriAction); |
| } |
| |
| // check for function |
| EdmFunction function = edm.getBoundFunction(fullName, finalTypeName, null, null); |
| |
| if (function != null) { |
| UriResourceFunctionImpl uriFunction = new UriResourceFunctionImpl(); |
| uriFunction.setFunction(function); |
| |
| UriInfoImpl resourcePath = (UriInfoImpl) context.contextSelectItem.getResourcePath(); |
| resourcePath.addResourcePart(uriFunction); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public Object visitSkip(final SkipContext ctx) { |
| SkipOptionImpl skiptoken = new SkipOptionImpl(); |
| |
| String text = ctx.children.get(2).getText(); |
| |
| return skiptoken.setValue(Integer.parseInt(text)).setText(text); |
| } |
| |
| @Override |
| public Object visitSkiptoken(final SkiptokenContext ctx) { |
| SkipTokenOptionImpl skiptoken = new SkipTokenOptionImpl(); |
| |
| String text = ctx.children.get(2).getText(); |
| |
| return skiptoken.setValue(text).setText(text); |
| } |
| |
| @Override |
| public ExpressionImpl visitStartsWithMethodCallExpr(final StartsWithMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.STARTSWITH) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)) |
| .addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitSubstringMethodCallExpr(final SubstringMethodCallExprContext ctx) { |
| MethodImpl ret = new MethodImpl(); |
| ret.setMethod(MethodKind.SUBSTRING); |
| ret.addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| ret.addParameter((ExpressionImpl) ctx.vE2.accept(this)); |
| |
| if (ctx.vE3 != null) { |
| ret.addParameter((ExpressionImpl) ctx.vE3.accept(this)); |
| } |
| |
| return ret; |
| |
| } |
| |
| @Override |
| public ExpressionImpl visitTimeMethodCallExpr(final TimeMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.TIME) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public Object visitTop(final TopContext ctx) { |
| TopOptionImpl top = new TopOptionImpl(); |
| |
| String text = ctx.children.get(2).getText(); |
| |
| return top.setValue(Integer.parseInt(text)).setText(text); |
| } |
| |
| @Override |
| public ExpressionImpl visitToLowerMethodCallExpr(final ToLowerMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.TOLOWER) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitTotalOffsetMinutesMethodCallExpr(final TotalOffsetMinutesMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.TOTALOFFSETMINUTES) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitTotalsecondsMethodCallExpr(final TotalsecondsMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.TOTALSECONDS) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitToUpperMethodCallExpr(final ToUpperMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.TOUPPER) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitTrimMethodCallExpr(final TrimMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.TRIM) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| @Override |
| public ExpressionImpl visitYearMethodCallExpr(final YearMethodCallExprContext ctx) { |
| return new MethodImpl() |
| .setMethod(MethodKind.YEAR) |
| .addParameter((ExpressionImpl) ctx.vE1.accept(this)); |
| } |
| |
| private ParseCancellationException wrap(final UriParserException uriParserException) { |
| return new ParseCancellationException(uriParserException); |
| } |
| |
| @Override |
| public ExpressionImpl visitAltUnary(@NotNull UriParserParser.AltUnaryContext ctx) { |
| UnaryImpl unary = new UnaryImpl(); |
| unary.setOperator(ctx.unary().NOT() == null? UnaryOperatorKind.MINUS: UnaryOperatorKind.NOT); |
| unary.setOperand((ExpressionImpl) ctx.commonExpr().accept(this)); |
| return unary; |
| } |
| |
| @Override |
| public ExpressionImpl visitAltAlias(@NotNull UriParserParser.AltAliasContext ctx) { |
| AliasImpl alias = new AliasImpl(); |
| alias.setParameter("@"+ctx.odataIdentifier().getChild(0).getText()); |
| return alias; |
| } |
| } |