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