Repository: incubator-juneau Updated Branches: refs/heads/master 95ee1b536 -> 35cb8461b
Add @RemoteMethod(returns) annotation. Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/35cb8461 Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/35cb8461 Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/35cb8461 Branch: refs/heads/master Commit: 35cb8461bf0b4dab5214cb74843f28636827d809 Parents: 95ee1b5 Author: JamesBognar <[email protected]> Authored: Mon Jun 19 21:29:23 2017 -0400 Committer: JamesBognar <[email protected]> Committed: Mon Jun 19 21:29:23 2017 -0400 ---------------------------------------------------------------------- .../main/java/org/apache/juneau/ClassMeta.java | 45 +--------- .../org/apache/juneau/internal/ClassUtils.java | 31 +++++++ .../apache/juneau/remoteable/RemoteMethod.java | 29 +++++- .../juneau/remoteable/RemoteableMethodMeta.java | 13 +++ .../apache/juneau/remoteable/ReturnValue.java | 25 ++++++ .../java/org/apache/juneau/utils/PojoQuery.java | 1 + juneau-core/src/main/javadoc/overview.html | 1 + .../apache/juneau/rest/client/RestClient.java | 17 +++- .../rest/test/ThirdPartyProxyResource.java | 14 +++ .../juneau/rest/test/ThirdPartyProxyTest.java | 75 ++++++++++++++++ .../java/org/apache/juneau/rest/CallMethod.java | 2 +- .../apache/juneau/rest/widget/QueryWidget.html | 92 ++++++++++++++------ 12 files changed, 271 insertions(+), 74 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java index 786d60a..1545511 100644 --- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java +++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java @@ -111,15 +111,6 @@ public final class ClassMeta<T> implements Type { private final BeanRegistry beanRegistry; // The bean registry of this class meta (if it has one). private final ClassMeta<?>[] args; // Arg types if this is an array of args. - private static final Boolean BOOLEAN_DEFAULT = false; - private static final Character CHARACTER_DEFAULT = (char)0; - private static final Short SHORT_DEFAULT = (short)0; - private static final Integer INTEGER_DEFAULT = 0; - private static final Long LONG_DEFAULT = 0l; - private static final Float FLOAT_DEFAULT = 0f; - private static final Double DOUBLE_DEFAULT = 0d; - private static final Byte BYTE_DEFAULT = (byte)0; - private ReadWriteLock lock = new ReentrantReadWriteLock(false); private Lock rLock = lock.readLock(), wLock = lock.writeLock(); @@ -521,41 +512,7 @@ public final class ClassMeta<T> implements Type { } } - if (c.isPrimitive()) { - if (c == Boolean.TYPE) - primitiveDefault = BOOLEAN_DEFAULT; - else if (c == Character.TYPE) - primitiveDefault = CHARACTER_DEFAULT; - else if (c == Short.TYPE) - primitiveDefault = SHORT_DEFAULT; - else if (c == Integer.TYPE) - primitiveDefault = INTEGER_DEFAULT; - else if (c == Long.TYPE) - primitiveDefault = LONG_DEFAULT; - else if (c == Float.TYPE) - primitiveDefault = FLOAT_DEFAULT; - else if (c == Double.TYPE) - primitiveDefault = DOUBLE_DEFAULT; - else if (c == Byte.TYPE) - primitiveDefault = BYTE_DEFAULT; - } else { - if (c == Boolean.class) - primitiveDefault = BOOLEAN_DEFAULT; - else if (c == Character.class) - primitiveDefault = CHARACTER_DEFAULT; - else if (c == Short.class) - primitiveDefault = SHORT_DEFAULT; - else if (c == Integer.class) - primitiveDefault = INTEGER_DEFAULT; - else if (c == Long.class) - primitiveDefault = LONG_DEFAULT; - else if (c == Float.class) - primitiveDefault = FLOAT_DEFAULT; - else if (c == Double.class) - primitiveDefault = DOUBLE_DEFAULT; - else if (c == Byte.class) - primitiveDefault = BYTE_DEFAULT; - } + primitiveDefault = ClassUtils.getPrimitiveDefault(c); for (Method m : c.getMethods()) if (isPublic(m) && isNotDeprecated(m)) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java index 0f52ed5..6a3e812 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/ClassUtils.java @@ -18,6 +18,7 @@ import java.lang.reflect.*; import java.util.*; import org.apache.juneau.*; +import org.apache.juneau.utils.*; /** * Class-related utility methods. @@ -923,4 +924,34 @@ public final class ClassUtils { } return l; } + + /** + * Returns the default value for the specified primitive class. + * + * @param primitiveClass The primitive class to get the default value for. + * @return The default value, or <jk>null</jk> if the specified class is not a primitive class. + */ + public static Object getPrimitiveDefault(Class<?> primitiveClass) { + return primitiveDefaultMap.get(primitiveClass); + } + + private static final Map<Class<?>,Object> primitiveDefaultMap = Collections.unmodifiableMap( + new AMap<Class<?>,Object>() + .append(Boolean.TYPE, false) + .append(Character.TYPE, (char)0) + .append(Short.TYPE, (short)0) + .append(Integer.TYPE, 0) + .append(Long.TYPE, 0l) + .append(Float.TYPE, 0f) + .append(Double.TYPE, 0d) + .append(Byte.TYPE, (byte)0) + .append(Boolean.class, false) + .append(Character.class, (char)0) + .append(Short.class, (short)0) + .append(Integer.class, 0) + .append(Long.class, 0l) + .append(Float.class, 0f) + .append(Double.class, 0d) + .append(Byte.class, (byte)0) + ); } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java index 97cd3be..0169033 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethod.java @@ -55,7 +55,7 @@ public @interface RemoteMethod { String path() default ""; /** - * Defines whether to use <code>GET</code> or <code>POST</code> for REST calls. + * Defines the HTTP method to use for REST calls. * <p> * Possible values: * <ul> @@ -66,4 +66,31 @@ public @interface RemoteMethod { * The default value is <js>"POST"</js>. */ String httpMethod() default "POST"; + + /** + * The value the remoteable method returns. + * <p> + * Possible values: + * <ul> + * <li>{@link ReturnValue#BODY} (default) - The body of the HTTP response converted to a POJO. + * <br>The return type on the Java method can be any of the following: + * <ul> + * <li><jk>void</jk> - Don't parse any response. Note that the method will still throw an exception if an + * error HTTP status is returned. + * <li>Any parsable POJO - The body of the response will be converted to the POJO using the parser defined + * on the <code>RestClient</code>. + * <li><code>HttpResponse</code> - Returns the raw <code>HttpResponse</code> returned by the inner + * <code>HttpClient</code>. + * <li>{@link Reader} - Returns access to the raw reader of the response. + * <li>{@link InputStream} - Returns access to the raw input stream of the response. + * </ul> + * <li>{@link ReturnValue#HTTP_STATUS} - The HTTP status code on the response. + * <br>The return type on the Java method can be any of the following: + * <ul> + * <li><jk>int</jk>/<code>Integer</code> - The HTTP response code. + * <li><jk>boolean</jk>/<code>Boolean</code> - <jk>true</jk> if the response code is <code><400</code> + * </ul> + * </ul> + */ + ReturnValue returns() default ReturnValue.BODY; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java index 8430ae8..2db986e 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteableMethodMeta.java @@ -37,6 +37,7 @@ public class RemoteableMethodMeta { private final RemoteMethodArg[] pathArgs, queryArgs, headerArgs, formDataArgs, requestBeanArgs; private final Integer[] otherArgs; private final Integer bodyArg; + private final ReturnValue returnValue; /** * Constructor. @@ -55,6 +56,7 @@ public class RemoteableMethodMeta { this.requestBeanArgs = b.requestBeanArgs.toArray(new RemoteMethodArg[b.requestBeanArgs.size()]); this.otherArgs = b.otherArgs.toArray(new Integer[b.otherArgs.size()]); this.bodyArg = b.bodyArg; + this.returnValue = b.returnValue; } private static class Builder { @@ -68,6 +70,7 @@ public class RemoteableMethodMeta { private List<Integer> otherArgs = new LinkedList<Integer>(); private Integer bodyArg; + private ReturnValue returnValue; private Builder(String restUrl, Method m) { Remoteable r = m.getDeclaringClass().getAnnotation(Remoteable.class); @@ -83,6 +86,8 @@ public class RemoteableMethodMeta { if (! isOneOf(methodPaths, "NAME", "SIGNATURE")) throw new RemoteableMetadataException(m, "Invalid value specified for @Remoteable.methodPaths() annotation. Valid values are [NAME,SIGNATURE]."); + returnValue = rm == null ? ReturnValue.BODY : rm.returns(); + url = trimSlashes(restUrl) + '/' @@ -206,4 +211,12 @@ public class RemoteableMethodMeta { public Integer getBodyArg() { return bodyArg; } + + /** + * Returns whether the method returns the HTTP response body or status code. + * @return Whether the method returns the HTTP response body or status code. + */ + public ReturnValue getReturns() { + return returnValue; + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java new file mode 100644 index 0000000..a6ebc3e --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/ReturnValue.java @@ -0,0 +1,25 @@ +// *************************************************************************************************************************** +// * 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.juneau.remoteable; + +/** + * Possible values for the {@link RemoteMethod#returns()} annotation. + */ +public enum ReturnValue { + + /** HTTP response body */ + BODY, + + /** HTTP status code */ + HTTP_STATUS; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java b/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java index 737fb32..17292ef 100644 --- a/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java +++ b/juneau-core/src/main/java/org/apache/juneau/utils/PojoQuery.java @@ -238,6 +238,7 @@ public final class PojoQuery { int limit = args.getLimit(); if (pos != 0 || limit != 0) { int end = (limit == 0 || limit+pos >= l.size()) ? l.size() : limit + pos; + pos = Math.min(pos, l.size()); ObjectList l2 = new DelegateList(((DelegateList)l).getClassMeta()); l2.addAll(l.subList(pos, end)); l = l2; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-core/src/main/javadoc/overview.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html index 12d6c29..15aa1eb 100644 --- a/juneau-core/src/main/javadoc/overview.html +++ b/juneau-core/src/main/javadoc/overview.html @@ -6183,6 +6183,7 @@ <li>{@link org.apache.juneau.utils.PojoQuery} improvements. <br>Search columns containing lists and maps. <br>Sort columns containing lists and maps. + <li>New {@link org.apache.juneau.remoteable.RemoteMethod#returns()} annotation. </ul> <h6 class='topic'>org.apache.juneau.rest</h6> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java ---------------------------------------------------------------------- diff --git a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java index 484d934..6d06825 100644 --- a/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java +++ b/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java @@ -30,6 +30,7 @@ import org.apache.http.client.utils.*; import org.apache.http.entity.*; import org.apache.http.impl.client.*; import org.apache.juneau.*; +import org.apache.juneau.internal.*; import org.apache.juneau.json.*; import org.apache.juneau.parser.*; import org.apache.juneau.remoteable.*; @@ -642,7 +643,21 @@ public class RestClient extends CoreObject { rc.input(otherArgs); } - return rc.getResponse(method.getGenericReturnType()); + if (rmm.getReturns() == ReturnValue.HTTP_STATUS) { + rc.ignoreErrors(); + int returnCode = rc.run(); + Class<?> rt = method.getReturnType(); + if (rt == Integer.class || rt == int.class) + return returnCode; + if (rt == Boolean.class || rt == boolean.class) + return returnCode < 400; + throw new RestCallException("Invalid return type on method annotated with @RemoteableMethod(returns=HTTP_STATUS). Only integer and booleans types are valid."); + } + + Object v = rc.getResponse(method.getGenericReturnType()); + if (v == null && method.getReturnType().isPrimitive()) + v = ClassUtils.getPrimitiveDefault(method.getReturnType()); + return v; } catch (RestCallException e) { // Try to throw original exception if possible. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java ---------------------------------------------------------------------- diff --git a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java index d613422..157e20d 100644 --- a/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java +++ b/juneau-rest-test/src/main/java/org/apache/juneau/rest/test/ThirdPartyProxyResource.java @@ -20,6 +20,7 @@ import static org.junit.Assert.*; import java.util.*; import org.apache.juneau.microservice.*; +import org.apache.juneau.rest.*; import org.apache.juneau.rest.annotation.*; import org.apache.juneau.rest.test.pojos.*; import org.apache.juneau.utils.*; @@ -1720,4 +1721,17 @@ public class ThirdPartyProxyResource extends ResourceJena { return "OK"; } + //-------------------------------------------------------------------------------- + // @RemoteableMethod(returns=HTTP_STATUS) + //-------------------------------------------------------------------------------- + + @RestMethod(name="GET", path="/httpStatusReturn200") + public void httpStatusReturn200(RestResponse res) { + res.setStatus(200); + } + + @RestMethod(name="GET", path="/httpStatusReturn404") + public void httpStatusReturn404(RestResponse res) { + res.setStatus(404); + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java ---------------------------------------------------------------------- diff --git a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java index fe02c60..b6c0e5b 100644 --- a/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java +++ b/juneau-rest-test/src/test/java/org/apache/juneau/rest/test/ThirdPartyProxyTest.java @@ -2147,6 +2147,55 @@ public class ThirdPartyProxyTest extends RestTestcase { assertEquals("OK", r); } + //-------------------------------------------------------------------------------- + // @RemoteableMethod(returns=HTTP_STATUS) + //-------------------------------------------------------------------------------- + @Test + public void i01a() throws Exception { + int r = proxy.httpStatusReturnInt200(); + assertEquals(200, r); + } + + @Test + public void i01b() throws Exception { + Integer r = proxy.httpStatusReturnInteger200(); + assertEquals(200, r.intValue()); + } + + @Test + public void i01c() throws Exception { + int r = proxy.httpStatusReturnInt404(); + assertEquals(404, r); + } + + @Test + public void i01d() throws Exception { + Integer r = proxy.httpStatusReturnInteger404(); + assertEquals(404, r.intValue()); + } + + @Test + public void i02a() throws Exception { + boolean r = proxy.httpStatusReturnBool200(); + assertEquals(true, r); + } + + @Test + public void i02b() throws Exception { + Boolean r = proxy.httpStatusReturnBoolean200(); + assertEquals(true, r); + } + + @Test + public void i02c() throws Exception { + boolean r = proxy.httpStatusReturnBool404(); + assertEquals(false, r); + } + + public void i02d() throws Exception { + Boolean r = proxy.httpStatusReturnBoolean404(); + assertEquals(false, r); + } //-------------------------------------------------------------------------------- // Proxy class @@ -3716,6 +3765,32 @@ public class ThirdPartyProxyTest extends RestTestcase { @RemoteMethod(httpMethod="POST", path="/setEnum1d3dListMap") void setEnum1d3dListMap(@Body Map<TestEnum,List<TestEnum[][][]>> x); + + // Method returns status code + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", returns=ReturnValue.HTTP_STATUS) + int httpStatusReturnInt200(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", returns=ReturnValue.HTTP_STATUS) + Integer httpStatusReturnInteger200(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", returns=ReturnValue.HTTP_STATUS) + int httpStatusReturnInt404(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", returns=ReturnValue.HTTP_STATUS) + Integer httpStatusReturnInteger404(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", returns=ReturnValue.HTTP_STATUS) + boolean httpStatusReturnBool200(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn200", returns=ReturnValue.HTTP_STATUS) + Boolean httpStatusReturnBoolean200(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", returns=ReturnValue.HTTP_STATUS) + boolean httpStatusReturnBool404(); + + @RemoteMethod(httpMethod="GET", path="/httpStatusReturn404", returns=ReturnValue.HTTP_STATUS) + Boolean httpStatusReturnBoolean404(); } // Bean for testing NE annotations. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java index 2563442..207e312 100644 --- a/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java +++ b/juneau-rest/src/main/java/org/apache/juneau/rest/CallMethod.java @@ -811,7 +811,7 @@ class CallMethod implements Comparable<CallMethod> { throw new RestException(SC_BAD_REQUEST, "Invalid argument type passed to the following method: ''{0}''.\n\tArgument types: {1}", method.toString(), getReadableClassNames(args) - ); + ).initCause(e); } catch (InvocationTargetException e) { Throwable e2 = e.getTargetException(); // Get the throwable thrown from the doX() method. if (e2 instanceof RestException) http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/35cb8461/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html ---------------------------------------------------------------------- diff --git a/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html b/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html index 02c4adf..d89516f 100644 --- a/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html +++ b/juneau-rest/src/main/resources/org/apache/juneau/rest/widget/QueryWidget.html @@ -63,71 +63,109 @@ .tooltiptext { white-space: nowrap; float: left; + border: 1px solid black; } </style> <form id='queryForm' style='display:inline'> <table id='query' class='queryInput hidden'> <tr> - <th> + <th>Search:</th> + <td> + <input name="s" size="50" value='$R{query.s}'> + </td> + <td> <div class="tooltip"> - Search <small>(?)</small>: + <small>(?)</small> <span class="tooltiptext"> Comma-delimited list of key/value pair search terms. - <br>Keys are column names. - <br>Values are search terms. - <br>Refer to the <code>Queryable</code> javadocs for a full explanation of possible search terms. - <br>Example: <code>column1=foo*, column2<100, column3=2013-2016.06.30</code> + <br> + <br>Keys are column names. Values are search terms. + <br> + <br><b>Example:</b> <code>[column1=foo*, column2<100, column3=2013-2016.06.30]</code> + <br> + <br><b>String fields:</b> + <br> - <code>'*'</code> represents any character + <br> - <code>'?'</code> represents one character + <br> - Use single or double quotes for phrases + <br> e.g. <code>[column='foo bar']</code> - The term 'foo bar' + <br> - Multiple search terms are ORed + <br> e.g. <code>[column=foo bar]</code> - 'foo' OR 'bar' + <br> - Prepend <code>'+'</code> on tokens that must match + <br> e.g. <code>[column=+foo* +*bar]</code> - Start with 'foo' AND end with 'bar'. + <br> - Prepend <code>'-'</code> on tokens that must not match + <br> e.g. <code>[column=+foo* -*bar]</code> - Start with 'foo' AND does not end with 'bar'. + <br> + <br><b>Numeric fields:</b> + <br><code>[column=123]</code> - A single number + <br><code>[column=1 2 3]</code> - Multiple numbers + <br><code>[column=1-100]</code> - Between two numbers + <br><code>[column=1-100 200-300]</code> - Two ranges of numbers + <br><code>[column>100]</code> - Greater than a number + <br><code>[column>=100]</code> - Greater than or equal to a number + <br><code>[column=!123]</code> - Not a specific number + <br> + <br><b>Date/Calendar fields:</b> + <br><code>[column=2001]</code> - A specific year + <br><code>[column=2001.01.01.10.50]</code> - A specific time + <br><code>[column=>2001]</code> - After a specific year + <br><code>[column=>=2001]</code> - During or after a specific year + <br><code>[column=2001-2003.06.30]</code> - A date range + <br><code>[column=2001 2003 2005]</code> - Multiple ORed dates </span> </div> - </th> - <td> - <input name="s" size="50" value='$R{query.s}'> </td> </tr> <tr> - <th> + <th>View:</th> + <td> + <input name="v" size="50" value='$R{query.v}'> + </td> + <td> <div class="tooltip"> - View <small>(?)</small>: + <small>(?)</small> <span class="tooltiptext"> Comma-delimited list of columns to display. - <br>Example: <code>column1, column2</code> + <br> + <br><b>Example:</b> <code>[column1, column2]</code> </span> </div> - </th> - <td> - <input name="v" size="50" value='$R{query.v}'> </td> </tr> <tr> - <th> + <th>Sort:</th> + <td> + <input name="o" size="50" value='$R{query.o}'> + </td> + <td> <div class="tooltip"> - Sort <small>(?)</small>: + <small>(?)</small> <span class="tooltiptext"> Comma-delimited list of columns to sort by. <br>Columns can be suffixed with '-' to indicate descending order. - <br>Example: <code>column1, column2-</code> + <br> + <br><b>Example:</b> <code>[column1, column2-]</code> + <br> + <br><b>Notes:</b> + <br> - Columns containing collections/arrays/lists are sorted by size. </span> </div> - </th> - <td> - <input name="o" size="50" value='$R{query.o}'> </td> </tr> <tr> - <th> - Page: - </th> + <th>Page:</th> <td> Position: <input name='p' type='number' style='width:50px' step=20 min=0 value='$R{query.p}'> Limit: <input name='l' type='number' style='width:50px' step=20 min=0 value='$R{query.l}'> - Ignore-case: <input name='i' type='checkbox' value='true'> + <span style='float:right'>Ignore-case: <input name='i' type='checkbox' value='true'></span> </td> - </tr> + <td> + </td> + </tr> <tr> <th> </th> - <td style='float:right'> + <td colspan='2' style='text-align:right'> <input type='reset' value='Reset'> <input type='button' value='Cancel' onclick='getElementById("query").classList.add("hidden")'> <input type="submit" value='Submit'>
