diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index 74cdd51f1..923bf293e 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -67,6 +67,7 @@ import org.apache.olingo.server.tecsvc.processor.queryoptions.ExpandSystemQueryO import org.apache.olingo.server.tecsvc.processor.queryoptions.options.CountHandler; import org.apache.olingo.server.tecsvc.processor.queryoptions.options.FilterHandler; import org.apache.olingo.server.tecsvc.processor.queryoptions.options.OrderByHandler; +import org.apache.olingo.server.tecsvc.processor.queryoptions.options.SearchHandler; import org.apache.olingo.server.tecsvc.processor.queryoptions.options.ServerSidePagingHandler; import org.apache.olingo.server.tecsvc.processor.queryoptions.options.SkipHandler; import org.apache.olingo.server.tecsvc.processor.queryoptions.options.TopHandler; @@ -486,6 +487,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor OrderByHandler.applyOrderByOption(uriInfo.getOrderByOption(), entitySet, uriInfo, serviceMetadata.getEdm()); SkipHandler.applySkipSystemQueryHandler(uriInfo.getSkipOption(), entitySet); TopHandler.applyTopSystemQueryOption(uriInfo.getTopOption(), entitySet); + SearchHandler.applySearchSystemQueryOption(uriInfo.getSearchOption(), entitySet); final Integer pageSize = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getMaxPageSize(); final Integer serverPageSize = ServerSidePagingHandler.applyServerSidePaging(uriInfo.getSkipTokenOption(), 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 b63bdd899..28cf63def 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,8 +233,7 @@ public abstract class TechnicalProcessor implements Processor { } protected void validateOptions(final UriInfoResource uriInfo) throws ODataApplicationException { - if (uriInfo.getIdOption() != null - || uriInfo.getSearchOption() != null) { + if (uriInfo.getIdOption() != null) { throw new ODataApplicationException("Not all of the specified options are supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SearchHandler.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SearchHandler.java new file mode 100644 index 000000000..5ce4530b8 --- /dev/null +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/queryoptions/options/SearchHandler.java @@ -0,0 +1,92 @@ +/* + * 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.tecsvc.processor.queryoptions.options; + +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.queryoption.SearchOption; +import org.apache.olingo.server.api.uri.queryoption.search.SearchBinary; +import org.apache.olingo.server.api.uri.queryoption.search.SearchBinaryOperatorKind; +import org.apache.olingo.server.api.uri.queryoption.search.SearchExpression; +import org.apache.olingo.server.api.uri.queryoption.search.SearchTerm; + +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +public class SearchHandler { + public static void applySearchSystemQueryOption(final SearchOption searchOption, final EntityCollection entitySet) + throws ODataApplicationException { + + if (searchOption != null) { + Iterator it = entitySet.getEntities().iterator(); + while(it.hasNext()) { + boolean keep = false; + Entity next = it.next(); + List propertyList = next.getProperties(); + for (Property property : propertyList) { + SearchExpression se = searchOption.getSearchExpression(); + if(isTrue(se, property)) { + keep = true; + break; + } + } + if(!keep) { + it.remove(); + } + } + } + } + + private static boolean isTrue(SearchTerm term, Property property) { + if(property.isPrimitive()) { + String propertyString = property.asPrimitive().toString(); + return propertyString != null && propertyString.contains(term.getSearchTerm()); + } + return false; + } + + private static boolean isTrue(SearchBinary binary, Property property) throws ODataApplicationException { + SearchExpression left = binary.getLeftOperand(); + SearchExpression right = binary.getRightOperand(); + if(binary.getOperator() == SearchBinaryOperatorKind.AND) { + return isTrue(left, property) && isTrue(right, property); + } else if(binary.getOperator() == SearchBinaryOperatorKind.OR) { + return isTrue(left, property) || isTrue(right, property); + } else { + throw new ODataApplicationException("Found unknown SearchBinaryOperatorKind: " + binary.getOperator(), + HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT); + } + } + + private static boolean isTrue(SearchExpression searchExpression, Property property) throws ODataApplicationException { + if(searchExpression.isSearchBinary()) { + return isTrue(searchExpression.asSearchBinary(), property); + } else if(searchExpression.isSearchTerm()) { + return isTrue(searchExpression.asSearchTerm(), property); + } else if(searchExpression.isSearchUnary()) { + return !isTrue(searchExpression.asSearchUnary().getOperand(), property); + } + throw new ODataApplicationException("Found unknown SearchExpression: " + searchExpression, + HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ROOT); + } +}