001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.rest.converter; 018 019import org.apache.juneau.*; 020import org.apache.juneau.commons.lang.*; 021import org.apache.juneau.objecttools.*; 022import org.apache.juneau.rest.*; 023import org.apache.juneau.rest.httppart.*; 024 025/** 026 * Converter for enabling of search/view/sort/page support on response objects returned by a <c>@RestOp</c>-annotated method. 027 * 028 * <p> 029 * When enabled, objects in a POJO tree can be filtered using the functionality described in the {@link ObjectSearcher}, 030 * {@link ObjectViewer}, {@link ObjectSorter}, and {@link ObjectPaginator} classes. 031 * 032 * <p> 033 * The following HTTP request parameters are available for tabular data (e.g. {@code Collections} of {@code Maps}, 034 * arrays of beans, etc...): 035 * <ul class='spaced-list'> 036 * <li> 037 * <c>&s=</c> Search arguments. 038 * <br>Comma-delimited list of key/value pairs representing column names and search tokens. 039 * <br>Example: 040 * <p class='burlenc'> 041 * &s=name=Bill*,birthDate>2000 042 * </p> 043 * <li> 044 * <c>&v=</c> Visible columns. 045 * <br>Comma-delimited list of column names to display. 046 * <br>Example: 047 * <p class='burlenc'> 048 * &v=name,birthDate 049 * </p> 050 * <li> 051 * <c>&o=</c> Sort commands. 052 * <br>Comma-delimited list of columns to sort by. 053 * <br>Column names can be suffixed with <js>'+'</js> or <js>'-'</js> to indicate ascending or descending order. 054 * <br>The default is ascending order. 055 * <br>Example: 056 * <p class='burlenc'> 057 * &o=name,birthDate- 058 * </p> 059 * <li> 060 * <c>&i=</c> Case-insensitive parameter. 061 * <br>Boolean flag for case-insensitive matching on the search parameters. 062 * <li> 063 * <c>&p=</c> - Position parameter. 064 * <br>Only return rows starting at the specified index position (zero-indexed). 065 * <br>Default is {@code 0}. 066 * <li> 067 * <c>&l=</c> Limit parameter. 068 * <br>Only return the specified number of rows. 069 * <br>Default is {@code 0} (meaning return all rows). 070 * </ul> 071 * 072 * <h5 class='section'>See Also:</h5><ul> 073 * <li class='jc'>{@link ObjectSearcher} - Additional information on searching POJO models. 074 * <li class='jc'>{@link ObjectViewer} - Additional information on filtering POJO models. 075 * <li class='jc'>{@link ObjectSorter} - Additional information on sorting POJO models. 076 * <li class='jc'>{@link ObjectPaginator} - Additional information on paginating POJO models. 077 * <li class='jm'>{@link org.apache.juneau.rest.RestOpContext.Builder#converters()} - Registering converters with REST resources. 078 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Converters">Converters</a> 079 * </ul> 080 */ 081public class Queryable implements RestConverter { 082 083 /** 084 * Swagger parameters for this converter. 085 */ 086 public static final String SWAGGER_PARAMS = """ 087 { 088 in:'query', 089 name:'s', 090 description:'Search. 091 Key/value pairs representing column names and search tokens. 092 \\'*\\' and \\'?\\' can be used as meta-characters in string fields. 093 \\'>\\', \\'>=\\', \\'<\\', and \\'<=\\' can be used as limits on numeric and date fields. 094 Date fields can be matched with partial dates (e.g. \\'2018\\' to match any date in the year 2018).', 095 type:'array', 096 collectionFormat:'csv', 097 examples:{example:'?s=Bill*,birthDate>2000'} 098 },{ 099 in:'query', 100 name:'v', 101 description:'View. 102 Column names to display.', 103 type:'array', 104 collectionFormat:'csv', 105 examples:{example:'?v=name,birthDate'} 106 },{ 107 in:'query', 108 name:'o', 109 description:'Order by. 110 Columns to sort by. 111 Column names can be suffixed with \\'+\\' or \\'-\\' to indicate ascending or descending order. 112 The default is ascending order.', 113 type:'array', 114 collectionFormat:'csv', 115 examples:{example:'?o=name,birthDate-'} 116 },{ 117 in:'query', 118 name:'p', 119 description:'Position. 120 Only return rows starting at the specified index position (zero-indexed). 121 Default is 0', 122 type:'integer', 123 examples:{example:'?p=100'} 124 },{ 125 in:'query', 126 name:'l', 127 description:'Limit. 128 Only return the specified number of rows. 129 Default is 0 (meaning return all rows).', 130 type:'integer', 131 examples:{example:'?l=100'} 132 }"""; 133 134 @Override /* Overridden from RestConverter */ 135 public Object convert(RestRequest req, Object o) { 136 if (o == null) 137 return null; 138 139 Value<Object> v = Value.of(o); 140 RequestQueryParams params = req.getQueryParams(); 141 BeanSession bs = req.getBeanSession(); 142 143 params.getSearchArgs().ifPresent(x -> v.set(ObjectSearcher.create().run(bs, v.get(), x))); 144 params.getSortArgs().ifPresent(x -> v.set(ObjectSorter.create().run(bs, v.get(), x))); 145 params.getViewArgs().ifPresent(x -> v.set(ObjectViewer.create().run(bs, v.get(), x))); 146 params.getPageArgs().ifPresent(x -> v.set(ObjectPaginator.create().run(bs, v.get(), x))); 147 return v.get(); 148 } 149}