001/* 002 * Copyright 2015 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.search.query; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.Optional; 021 022/** 023 * Represents a search predicate. 024 */ 025@FunctionalInterface 026public interface Query 027{ 028 /** Constant for mandatory boolean clauses */ 029 public static final String BOOL_MUST = "must"; 030 031 /** Constant for prohibited boolean clauses */ 032 public static final String BOOL_MUST_NOT = "must_not"; 033 034 /** Constant for optional boolean clauses */ 035 public static final String BOOL_SHOULD = "should"; 036 037 /** Constant for mandatory, but not affecting score, boolean clauses */ 038 public static final String BOOL_FILTER = "filter"; 039 040 /** Enumeration of available operators in {@link Query} */ 041 public enum Operator 042 { 043 /** Operator testing the existence of a property. */ 044 EXISTS("exists"), 045 /** Constant of test's operator for textual search, on unstemmed terms. Works only for type String */ 046 SEARCH("search"), 047 /** Constant of test's operator for textual search, on stemmed terms. Works only for type String */ 048 SEARCH_STEMMED("searchStemmed"), 049 /** Constant of test's operator for 'like' comparison. Works only for type String */ 050 LIKE("like"), 051 /** Constant of test's operator for fuzzy search. Works only for type String */ 052 FUZZY("fuzzy"), 053 /** Constant of test's operator for phonetic comparison. Works only for type String */ 054 PHONETIC("phonetic"), 055 /** Constant of test's operator for 'less than' comparison. Works only for type String */ 056 NGRAM("ngram"), 057 /** Constant of test's operator for 'less than' comparison */ 058 LT("lt"), 059 /** Constant of test's operator for 'less than or equals to' comparison */ 060 LE("le"), 061 /** Constant of test's operator for 'greater than' comparison */ 062 GT("gt"), 063 /** Constant of test's operator for 'greater than or equals to' comparison */ 064 GE("ge"), 065 /** Constant of test's operator for 'equals to' comparison */ 066 EQ("eq"), 067 /** Constant of test's operator for 'not equals to' comparison */ 068 NE("ne"); 069 070 private static Map<String, Operator> _OP_NAMES = new HashMap<>(); 071 static 072 { 073 for (Operator op : values()) 074 { 075 _OP_NAMES.put(op.getName(), op); 076 } 077 } 078 079 private final String _name; 080 081 Operator(String name) 082 { 083 _name = name; 084 } 085 086 /** 087 * Get the operator name. 088 * @return the operator name. 089 */ 090 public String getName() 091 { 092 return _name; 093 } 094 095 /** 096 * Get an Operator object from its name. 097 * @param name the operator name. 098 * @return the operator object, or null if not found. 099 */ 100 public static Operator fromName(String name) 101 { 102 if (_OP_NAMES.containsKey(name)) 103 { 104 return _OP_NAMES.get(name); 105 } 106 throw new IllegalArgumentException("No operator with code '" + name + "'"); 107 } 108 } 109 110 /** Enumeration of available logical operators in {@link Query} */ 111 public enum LogicalOperator 112 { 113 /** Logical operator AND */ 114 AND, 115 /** Logical operator OR */ 116 OR 117 } 118 119 /** 120 * Build the solr query string representing the Query object. 121 * @return the solr query string representing the Query object. 122 * @throws QuerySyntaxException if the query can't be built because of a syntax error. 123 */ 124 String build() throws QuerySyntaxException; 125 126 /** 127 * Build the solr query representing the Query object.<br> 128 * The return type may be either String or Map<String, Object> following the Solr JSON Query DSL. 129 * @return the solr query representing the Query object. Can be empty in case of empty query. 130 * @throws QuerySyntaxException if the query can't be built because of a syntax error. 131 */ 132 default Optional<Object> buildAsJson() throws QuerySyntaxException 133 { 134 return Optional.of(build()); 135 } 136 137 /** 138 * Rewrite this Query to allow further optimisations. 139 * @return a rewritten Query, sementically identical. Can be empty in case of empty query 140 */ 141 default Optional<Query> rewrite() 142 { 143 return Optional.of(this); 144 } 145 146 /** 147 * Gets a representation of this {@link Query}, for pretty-printing for logging and debugging purposes 148 * @param indent The current indentation. Base indentation is 2 (for printing a sub-level) 149 * @return a representation of this {@link Query} 150 */ 151 default String toString(int indent) 152 { 153 return QueryDebugger.toDebugString(this, indent); 154 } 155}