001package com.box.sdk; 002 003import static java.util.stream.Collectors.toList; 004 005import com.eclipsesource.json.Json; 006import com.eclipsesource.json.JsonArray; 007import com.eclipsesource.json.JsonObject; 008import com.eclipsesource.json.JsonValue; 009import java.util.ArrayList; 010import java.util.Arrays; 011import java.util.List; 012 013/** Represents Metadata Query. */ 014public class MetadataQuery { 015 static final String FROM = "from"; 016 static final String LIMIT = "limit"; 017 static final String QUERY = "query"; 018 static final String ANCESTOR_FOLDER_ID = "ancestor_folder_id"; 019 static final String MARKER = "marker"; 020 static final String ORDER_BY = "order_by"; 021 static final String FIELDS = "fields"; 022 static final String QUERY_PARAMS = "query_params"; 023 private final String from; 024 private final int limit; 025 private String query; 026 private JsonObject queryParameters = new JsonObject(); 027 private String ancestorFolderId = "0"; 028 private List<OrderBy> orderBy = new ArrayList<>(); 029 private String marker; 030 private List<String> fields = new ArrayList<>(); 031 032 /** 033 * Creates Metadata Query 034 * 035 * @param from The template used in the query. Must be in the form scope_enterpriseID.templateKey 036 * @param limit Max results to return for a single request (0-100 inclusive) 037 */ 038 public MetadataQuery(String from, int limit) { 039 this.from = from; 040 this.limit = limit; 041 } 042 043 /** 044 * Creates Metadata Query 045 * 046 * @param from The template used in the query. Must be in the form scope.templateKey 047 */ 048 public MetadataQuery(String from) { 049 this(from, 100); 050 } 051 052 /** 053 * The logical expression of the query 054 * 055 * @param query Query string 056 * @return Returns current MetadataQuery object 057 */ 058 public MetadataQuery setQuery(String query) { 059 this.query = query; 060 return this; 061 } 062 063 /** 064 * Sets the folder_id to which to restrain the query. If not set query starts at root level. 065 * 066 * @param ancestorFolderId The folder id 067 * @return Returns current MetadataQuery object 068 */ 069 public MetadataQuery setAncestorFolderId(String ancestorFolderId) { 070 this.ancestorFolderId = ancestorFolderId; 071 return this; 072 } 073 074 /** 075 * The marker to use for requesting the next page 076 * 077 * @param marker Marker string. 078 * @return Returns current MetadataQuery object 079 */ 080 public MetadataQuery setMarker(String marker) { 081 this.marker = marker; 082 return this; 083 } 084 085 /** 086 * The field_key(s) to order on and the corresponding direction(s) 087 * 088 * @param fields Fields with sort order 089 * @return Returns current MetadataQuery object 090 */ 091 public MetadataQuery setOrderBy(OrderBy... fields) { 092 this.orderBy = new ArrayList<>(); 093 this.orderBy.addAll(Arrays.asList(fields)); 094 return this; 095 } 096 097 MetadataQuery setOrderBy(JsonArray orderBy) { 098 if (orderBy != null) { 099 this.orderBy = orderBy.values().stream().map(OrderBy::fromJson).collect(toList()); 100 } 101 return this; 102 } 103 104 /** 105 * The fields to retrieve. 106 * 107 * @param fields Field names 108 * @return Returns current MetadataQuery object 109 */ 110 public MetadataQuery setFields(String... fields) { 111 this.fields = new ArrayList<>(); 112 this.fields.addAll(Arrays.asList(fields)); 113 return this; 114 } 115 116 /** 117 * Adds parameter to query 118 * 119 * @param name Parameter name 120 * @param value Parameter value 121 * @return Returns current MetadataQuery object 122 */ 123 public MetadataQuery addParameter(String name, String value) { 124 this.queryParameters.add(name, value); 125 return this; 126 } 127 128 /** 129 * Adds parameter to query 130 * 131 * @param name Parameter name 132 * @param value Parameter value 133 * @return Returns current MetadataQuery object 134 */ 135 public MetadataQuery addParameter(String name, int value) { 136 this.queryParameters.add(name, value); 137 return this; 138 } 139 140 /** 141 * Adds parameter to query 142 * 143 * @param name Parameter name 144 * @param value Parameter value 145 * @return Returns current MetadataQuery object 146 */ 147 public MetadataQuery addParameter(String name, boolean value) { 148 this.queryParameters.add(name, value); 149 return this; 150 } 151 152 /** 153 * Adds parameter to query 154 * 155 * @param name Parameter name 156 * @param value Parameter value 157 * @return Returns current MetadataQuery object 158 */ 159 public MetadataQuery addParameter(String name, float value) { 160 this.queryParameters.add(name, value); 161 return this; 162 } 163 164 /** 165 * Adds parameter to query 166 * 167 * @param name Parameter name 168 * @param value Parameter value 169 * @return Returns current MetadataQuery object 170 */ 171 public MetadataQuery addParameter(String name, long value) { 172 this.queryParameters.add(name, value); 173 return this; 174 } 175 176 /** 177 * Adds parameter to query 178 * 179 * @param name Parameter name 180 * @param value Parameter value 181 * @return Returns current MetadataQuery object 182 */ 183 public MetadataQuery addParameter(String name, double value) { 184 this.queryParameters.add(name, value); 185 return this; 186 } 187 188 /** 189 * Adds parameter to query 190 * 191 * @param name Parameter name 192 * @param value Parameter value 193 * @return Returns current MetadataQuery object 194 */ 195 public MetadataQuery addParameter(String name, JsonValue value) { 196 this.queryParameters.add(name, Json.parse(value.toString())); 197 return this; 198 } 199 200 MetadataQuery setQueryParams(JsonObject queryParameters) { 201 this.queryParameters = new JsonObject(queryParameters); 202 return this; 203 } 204 205 JsonObject toJsonObject() { 206 JsonObject jsonObject = new JsonObject().add(FROM, from).add(LIMIT, limit); 207 if (query != null) { 208 jsonObject.add(QUERY, query); 209 } 210 if (ancestorFolderId != null) { 211 jsonObject.add(ANCESTOR_FOLDER_ID, ancestorFolderId); 212 } 213 if (marker != null) { 214 jsonObject.add(MARKER, marker); 215 } 216 if (!orderBy.isEmpty()) { 217 JsonArray orderByJson = new JsonArray(); 218 orderBy.stream().map(OrderBy::toJsonObject).forEach(orderByJson::add); 219 jsonObject.add(ORDER_BY, orderByJson); 220 } 221 if (!fields.isEmpty()) { 222 JsonArray fieldsJson = new JsonArray(); 223 fields.forEach(fieldsJson::add); 224 jsonObject.add(FIELDS, fieldsJson); 225 } 226 if (queryParameters.iterator().hasNext()) { 227 jsonObject.add(QUERY_PARAMS, new JsonObject(queryParameters)); 228 } 229 return jsonObject; 230 } 231 232 int getLimit() { 233 return limit; 234 } 235 236 String getMarker() { 237 return marker; 238 } 239 240 public static final class OrderBy { 241 242 static final String FIELD_KEY = "field_key"; 243 static final String DIRECTION = "direction"; 244 static final String DIRECTION_ASCENDING = "asc"; 245 static final String DIRECTION_DESCENDING = "desc"; 246 private final String fieldName; 247 private final String direction; 248 249 private OrderBy(String fieldName, String direction) { 250 this.fieldName = fieldName; 251 this.direction = direction; 252 } 253 254 JsonObject toJsonObject() { 255 return new JsonObject().add(FIELD_KEY, fieldName).add(DIRECTION, direction); 256 } 257 258 /** 259 * Creates OrderBy for ascending sort with a specified field. 260 * 261 * @param fieldName Name of a field 262 * @return OrderBy instance 263 */ 264 public static OrderBy ascending(String fieldName) { 265 return new OrderBy(fieldName, DIRECTION_ASCENDING); 266 } 267 268 /** 269 * Creates OrderBy for descending sort with a specified field. 270 * 271 * @param fieldName Name of a field 272 * @return OrderBy instance 273 */ 274 public static OrderBy descending(String fieldName) { 275 return new OrderBy(fieldName, DIRECTION_DESCENDING); 276 } 277 278 static OrderBy fromJson(JsonValue jsonValue) { 279 if (jsonValue.isObject()) { 280 JsonObject object = jsonValue.asObject(); 281 String fieldName = object.get(FIELD_KEY).asString(); 282 String direction = object.get(DIRECTION).asString().toLowerCase(java.util.Locale.ROOT); 283 if (!DIRECTION_ASCENDING.equals(direction) && !DIRECTION_DESCENDING.equals(direction)) { 284 throw new RuntimeException( 285 String.format( 286 "Unsupported sort direction [%s] for field [%s]", direction, fieldName)); 287 } 288 return object.getString(DIRECTION, "").equals(DIRECTION_ASCENDING) 289 ? ascending(fieldName) 290 : descending(fieldName); 291 } 292 throw new RuntimeException("Unsupported json " + jsonValue); 293 } 294 } 295}