Improvements to @Query/@FormData/@Header/@Path remoteable annotations. Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/93aadae1 Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/93aadae1 Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/93aadae1
Branch: refs/heads/master Commit: 93aadae1d6c8da0b1ae81df461927ed16744576e Parents: 13f816f Author: JamesBognar <[email protected]> Authored: Thu Jun 1 20:00:25 2017 -0400 Committer: JamesBognar <[email protected]> Committed: Thu Jun 1 20:00:25 2017 -0400 ---------------------------------------------------------------------- .../apache/juneau/annotation/BeanProperty.java | 17 +- .../java/org/apache/juneau/http/package.html | 41 + .../org/apache/juneau/internal/ArrayUtils.java | 29 +- .../org/apache/juneau/internal/IOUtils.java | 30 + .../java/org/apache/juneau/json/package.html | 4 +- .../org/apache/juneau/remoteable/FormData.java | 150 +- .../apache/juneau/remoteable/FormDataIfNE.java | 22 +- .../org/apache/juneau/remoteable/Header.java | 139 +- .../apache/juneau/remoteable/HeaderIfNE.java | 22 +- .../java/org/apache/juneau/remoteable/Path.java | 134 +- .../org/apache/juneau/remoteable/Query.java | 151 +- .../org/apache/juneau/remoteable/QueryIfNE.java | 23 +- .../juneau/remoteable/RemoteMethodArg.java | 9 +- .../juneau/remoteable/RemoteableMethodMeta.java | 30 +- .../apache/juneau/remoteable/RequestBean.java | 16 +- .../juneau/serializer/PartSerializer.java | 1 + .../org/apache/juneau/uon/UonSerializer.java | 41 +- .../apache/juneau/uon/UonSerializerContext.java | 40 +- .../apache/juneau/uon/UonSerializerSession.java | 15 +- .../java/org/apache/juneau/uon/UonWriter.java | 11 +- .../java/org/apache/juneau/uon/package.html | 4 +- .../urlencoding/UrlEncodingSerializer.java | 47 +- .../UrlEncodingSerializerBuilder.java | 6 +- .../UrlEncodingSerializerContext.java | 31 +- .../UrlEncodingSerializerSession.java | 12 +- .../org/apache/juneau/urlencoding/package.html | 4 +- .../java/org/apache/juneau/xml/package.html | 4 +- juneau-core/src/main/javadoc/overview.html | 10 +- .../org/apache/juneau/rest/client/RestCall.java | 41 +- .../apache/juneau/rest/client/RestClient.java | 65 +- .../juneau/rest/client/RestClientBuilder.java | 25 +- .../rest/test/RequestBeanProxyResource.java | 50 + .../java/org/apache/juneau/rest/test/Root.java | 1 + .../apache/juneau/rest/test/FormDataTest.java | 2 +- .../juneau/rest/test/RequestBeanProxyTest.java | 1988 ++++++++++++++++++ .../apache/juneau/rest/test/RestTestcase.java | 6 +- .../org/apache/juneau/rest/test/_TestSuite.java | 1 + .../org/apache/juneau/rest/RequestFormData.java | 23 +- .../org/apache/juneau/rest/RequestHeaders.java | 43 + .../org/apache/juneau/rest/RequestQuery.java | 23 +- 40 files changed, 2986 insertions(+), 325 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/annotation/BeanProperty.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/annotation/BeanProperty.java b/juneau-core/src/main/java/org/apache/juneau/annotation/BeanProperty.java index f2461bb..f6472c0 100644 --- a/juneau-core/src/main/java/org/apache/juneau/annotation/BeanProperty.java +++ b/juneau-core/src/main/java/org/apache/juneau/annotation/BeanProperty.java @@ -127,21 +127,14 @@ public @interface BeanProperty { String name() default ""; /** - * A synonym for {@link #name()} + * A synonym for {@link #name()}. * <p> - * If you're only using the <code>BeanProperty</code> annotation to override the property name, this allows you - * to define it using shortened notation: - * <p class='bcode'> - * <ja>@BeanProperty</ja>(<js>"foo"</js>) - * <jk>public</jk> String getX(); - * } - * </p> + * The following annotations are equivalent: * <p> - * This is equivalent to the following notation: * <p class='bcode'> - * <ja>@BeanProperty</ja>(name=<js>"foo"</js>) - * <jk>public</jk> String getX(); - * } + * <ja>@BeanProperty</ja>(name=<js>"foo"</js>) + * + * <ja>@BeanProperty</ja>(<js>"foo"</js>) * </p> */ String value() default ""; http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/http/package.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/http/package.html b/juneau-core/src/main/java/org/apache/juneau/http/package.html new file mode 100644 index 0000000..23f63da --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/http/package.html @@ -0,0 +1,41 @@ +<!DOCTYPE HTML> +<!-- +/*************************************************************************************************************************** + * 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. + * + ***************************************************************************************************************************/ + --> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + <style type="text/css"> + /* For viewing in Page Designer */ + @IMPORT url("../../../../../../javadoc.css"); + + /* For viewing in REST interface */ + @IMPORT url("../htdocs/javadoc.css"); + body { + margin: 20px; + } + </style> + <script> + /* Replace all @code and @link tags. */ + window.onload = function() { + document.body.innerHTML = document.body.innerHTML.replace(/\{\@code ([^\}]+)\}/g, '<code>$1</code>'); + document.body.innerHTML = document.body.innerHTML.replace(/\{\@link (([^\}]+)\.)?([^\.\}]+)\}/g, '<code>$3</code>'); + } + </script> +</head> +<body> +<p>RFC2616 HTTP Headers</p> +</body> +</html> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java index 5199af1..176dbd5 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/ArrayUtils.java @@ -205,6 +205,31 @@ public final class ArrayUtils { } /** + * Returns <jk>true</jk> if the specified object is an array. + * @param array The array to test. + * @return <jk>true</jk> if the specified object is an array. + */ + public static boolean isArray(Object array) { + return array != null && array.getClass().isArray(); + } + + /** + * Converts the specified array to an <code>ArrayList</code> + * + * @param array The array to convert. + * @param componentType The type of objects in the array. + * It must match the actual component type in the array. + * @return A new {@link ArrayList} + */ + @SuppressWarnings("unchecked") + public static <T> List<T> toList(Object array, Class<T> componentType) { + List<T> l = new ArrayList<T>(Array.getLength(array)); + for (int i = 0; i < Array.getLength(array); i++) + l.add((T)Array.get(array, i)); + return l; + } + + /** * Shortcut for calling <code>myList.toArray(new T[myList.size()]);</code> * * @param c The collection being converted to an array. @@ -227,14 +252,16 @@ public final class ArrayUtils { * * @param array The array to copy into a list. * @param list The list to copy the values into. + * @return The same list passed in. */ @SuppressWarnings({"unchecked","rawtypes"}) - public static void copyToList(Object array, List list) { + public static List copyToList(Object array, List list) { if (array != null) { int length = Array.getLength(array); for (int i = 0; i < length; i++) list.add(Array.get(array, i)); } + return list; } /** http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/internal/IOUtils.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/IOUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/IOUtils.java index 1d0a5cc..516cd2e 100644 --- a/juneau-core/src/main/java/org/apache/juneau/internal/IOUtils.java +++ b/juneau-core/src/main/java/org/apache/juneau/internal/IOUtils.java @@ -53,6 +53,36 @@ public final class IOUtils { } /** + * Reads the specified object to a <code>String</code>. + * <p> + * Can be any of the following object types: + * <ul> + * <li>{@link CharSequence} + * <li>{@link File} + * <li>{@link Reader} + * <li>{@link InputStream} + * <li><code><jk>byte</jk>[]</code> + * </ul> + * + * @param o The object to read. + * @return The object serialized to a string, or <jk>null</jk> if it wasn't a supported type. + * @throws IOException + */ + public static String read(Object o) throws IOException { + if (o instanceof CharSequence) + return o.toString(); + if (o instanceof File) + return read((File)o); + if (o instanceof Reader) + return read((Reader)o); + if (o instanceof InputStream) + return read((InputStream)o); + if (o instanceof byte[]) + return read(new ByteArrayInputStream((byte[])o)); + return null; + } + + /** * Writes the contents of the specified <code>Reader</code> to the specified file. * * @param out The file to write the output to. http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/json/package.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/json/package.html b/juneau-core/src/main/java/org/apache/juneau/json/package.html index b6decc1..960ea0b 100644 --- a/juneau-core/src/main/java/org/apache/juneau/json/package.html +++ b/juneau-core/src/main/java/org/apache/juneau/json/package.html @@ -359,12 +359,12 @@ <p> Another useful feature is the {@link org.apache.juneau.annotation.Bean#propertyNamer()} annotation that allows you to plug in your own logic for determining bean property names.<br> - The {@link org.apache.juneau.PropertyNamerDashedLC} is an example of an alternate property namer. + The {@link org.apache.juneau.PropertyNamerDLC} is an example of an alternate property namer. It converts bean property names to lowercase-dashed format. </p> <h6 class='topic'>Example:</h6> <p class='bcode'> - <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>) + <ja>@Bean</ja>(propertyNamer=PropertyNamerDLC.<jk>class</jk>) <jk>public class</jk> Person { ... </p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/FormData.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/FormData.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/FormData.java index 83389b8..0bd91ad 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/FormData.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/FormData.java @@ -17,7 +17,6 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.*; -import org.apache.juneau.annotation.*; import org.apache.juneau.serializer.*; import org.apache.juneau.urlencoding.*; @@ -29,27 +28,39 @@ import org.apache.juneau.urlencoding.*; * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) * <jk>public interface</jk> MyProxy { * + * <jc>// Explicit names specified for form data parameters.</jc> + * <jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1"</js>) * String myProxyMethod1(<ja>@FormData</ja>(<js>"foo"</js>)</ja> String foo, <ja>@FormData</ja>(<js>"bar"</js>)</ja> MyPojo pojo); * + * <jc>// Multiple values pulled from a NameValuePairs object.</jc> + * <jc>// Same as @FormData("*").</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod2"</js>) - * String myProxyMethod2(<ja>@FormData</ja> NameValuePairs form); + * String myProxyMethod2(<ja>@FormData</ja> NameValuePairs nameValuePairs); * + * <jc>// Multiple values pulled from a Map.</jc> + * <jc>// Same as @FormData("*").</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod3"</js>) - * String myProxyMethod2(<ja>@FormData</ja> Map<String,Object> form); + * String myProxyMethod3(<ja>@FormData</ja> Map<String,Object> map); + * + * <jc>// Multiple values pulled from a bean.</jc> + * <jc>// Same as @FormData("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod4"</js>) + * String myProxyMethod4(<ja>@FormData</ja> MyBean myBean); + * + * <jc>// An entire form-data HTTP body as a String.</jc> + * <jc>// Same as @FormData("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod5"</js>) + * String myProxyMethod5(<ja>@FormData</ja> String string); + * + * <jc>// An entire form-data HTTP body as a Reader.</jc> + * <jc>// Sames as @FormData("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod6"</js>) + * String myProxyMethod6(<ja>@FormData</ja> Reader reader); + * * } * </p> * <p> - * The argument can be any of the following types: - * <ul class='spaced-list'> - * <li>Any serializable POJO - Converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li><code>NameValuePairs</code> - Individual name-value pairs. - * <li><code>Map<String,Object></code> - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li>A bean - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * </ul> - * <p> * The annotation can also be applied to a bean property field or getter when the argument is annotated with * {@link RequestBean @RequestBean}: * <p> @@ -63,18 +74,52 @@ import org.apache.juneau.urlencoding.*; * } * * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Name explicitly specified.</jc> + * <ja>@FormData</ja>(<js>"foo"</js>) + * String getX(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @FormData("bar")</jc> + * <ja>@FormData</ja> + * String getBar(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @FormData("baz")</jc> + * <ja>@FormData</ja> + * <ja>@BeanProperty</ja>(<js>"baz"</js>) + * String getY(); + * + * <jc>// Multiple values pulled from NameValuePairs object.</jc> + * <jc>// Same as @FormData("*")</jc> + * <ja>@FormData</ja> + * NameValuePairs getNameValuePairs(); + * + * <jc>// Multiple values pulled from Map.</jc> + * <jc>// Same as @FormData("*")</jc> + * <ja>@FormData</ja> + * Map<String,Object> getMap(); + * + * <jc>// Multiple values pulled from bean.</jc> + * <jc>// Same as @FormData("*")</jc> * <ja>@FormData</ja> - * String getFoo(); + * MyBean getMyBean(); * + * <jc>// An entire form-data HTTP body as a Reader.</jc> + * <jc>// Same as @FormData("*")</jc> * <ja>@FormData</ja> - * MyPojo getBar(); + * Reader getReader(); * } * </p> * <p> - * When used in a request bean, the {@link #value()} can be used to override the form data parameter name. - * It can also be overridden via the {@link BeanProperty#name @BeanProperty.name()} annotation. - * A name of <js>"*"</js> where the bean property value is a map or bean will cause the individual entries in the - * map or bean to be expanded to form data parameters. + * The {@link #name()} and {@link #value()} elements are synonyms for specifying the parameter name. Only one should be used. + * <br>The following annotations are fully equivalent: + * <p> + * <p class='bcode'> + * <ja>@FormData</ja>(name=<js>"foo"</js>) + * + * <ja>@FormData</ja>(<js>"foo"</js>) + * </p> */ @Documented @Target({PARAMETER,FIELD,METHOD}) @@ -85,22 +130,71 @@ public @interface FormData { /** * The form post parameter name. * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean + * Note that {@link #name()} and {@link #value()} are synonyms. + * <p> + * The value should be either <js>"*"</js> to represent multiple name/value pairs, or a label that defines the + * form data parameter name. + * <p> + * A blank value (the default) has the following behavior: + * <ul class='spaced-list'> + * <li>If the data type is <code>NameValuePairs</code>, <code>Map</code>, or a bean, + * then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jc>// When used on a remote method parameter</jc> + * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) + * <jk>public interface</jk> MyProxy { + * + * <jc>// Equivalent to @FormData("*")</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod"</js>) + * String myProxyMethod1(<ja>@FormData</ja> Map<String,Object> formData); + * } + * + * <jc>// When used on a request bean method</jc> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @FormData("*")</jc> + * <ja>@FormData</ja> + * Map<String,Object> getFoo(); + * } + * </p> + * <br> + * <li>If used on a request bean method, uses the bean property name. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @FormData("foo")</jc> + * <ja>@FormData</ja> + * String getFoo(); + * } + * </p> + * </ul> * </ul> */ - String value() default "*"; + String name() default ""; + + /** + * A synonym for {@link #name()}. + * <p> + * Allows you to use shortened notation if you're only specifying the name. + */ + String value() default ""; + + /** + * Skips this value if it's an empty string or empty collection/array. + * <p> + * Note that <jk>null</jk> values are already ignored. + */ + boolean skipIfEmpty() default false; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/FormDataIfNE.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/FormDataIfNE.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/FormDataIfNE.java index 2d0b3ab..494a2cf 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/FormDataIfNE.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/FormDataIfNE.java @@ -31,23 +31,23 @@ public @interface FormDataIfNE { /** * The form post parameter name. - * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean - * </ul> + * @see FormData#name() + */ + String name() default ""; + + /** + * A synonym for {@link #name()}. + * @see FormData#value() */ - String value() default "*"; + String value() default ""; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/Header.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/Header.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/Header.java index 6eaf870..d733e0d 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/Header.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/Header.java @@ -17,7 +17,6 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.*; -import org.apache.juneau.annotation.*; import org.apache.juneau.serializer.*; import org.apache.juneau.urlencoding.*; @@ -29,24 +28,28 @@ import org.apache.juneau.urlencoding.*; * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) * <jk>public interface</jk> MyProxy { * + * <jc>// Explicit names specified for HTTP headers.</jc> + * <jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1"</js>) * String myProxyMethod1(<ja>@Header</ja>(<js>"Foo"</js>)</ja> String foo, <ja>@Header</ja>(<js>"Bar"</js>)</ja> MyPojo pojo); * + * <jc>// Multiple values pulled from a NameValuePairs object.</jc> + * <jc>// Same as @Header("*").</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod2"</js>) - * String myProxyMethod2(<ja>@Header</ja> Map<String,Object> headers); + * String myProxyMethod2(<ja>@Header</ja> NameValuePairs nameValuePairs); + * + * <jc>// Multiple values pulled from a Map.</jc> + * <jc>// Same as @Header("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod3"</js>) + * String myProxyMethod3(<ja>@Header</ja> Map<String,Object> map); + * + * <jc>// Multiple values pulled from a bean.</jc> + * <jc>// Same as @Header("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod4"</js>) + * String myProxyMethod4(<ja>@Header</ja> MyBean myBean); * } * </p> * <p> - * The argument can be any of the following types: - * <ul class='spaced-list'> - * <li><code>NameValuePairs</code> - Individual name-value pairs. - * <li>Any serializable POJO - Converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li><code>Map<String,Object></code> - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li>A bean - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * </ul> - * <p> * The annotation can also be applied to a bean property field or getter when the argument is annotated with * {@link RequestBean @RequestBean}: * <p> @@ -60,18 +63,47 @@ import org.apache.juneau.urlencoding.*; * } * * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Name explicitly specified.</jc> * <ja>@Header</ja>(<js>"Foo"</js>) - * String getFoo(); + * String getX(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @Header("bar")</jc> + * <ja>@Header</ja> + * String getBar(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @Header("Baz")</jc> + * <ja>@Header</ja> + * <ja>@BeanProperty</ja>(<js>"Baz"</js>) + * String getY(); * - * <ja>@Header</ja>(<js>"Bar"</js>) - * MyPojo getBar(); + * <jc>// Multiple values pulled from NameValuePairs object.</jc> + * <jc>// Same as @Header("*")</jc> + * <ja>@Header</ja> + * NameValuePairs getNameValuePairs(); + * + * <jc>// Multiple values pulled from Map.</jc> + * <jc>// Same as @Header("*")</jc> + * <ja>@Header</ja> + * Map<String,Object> getMap(); + * + * <jc>// Multiple values pulled from bean.</jc> + * <jc>// Same as @Header("*")</jc> + * <ja>@Header</ja> + * MyBean getBean(); * } * </p> * <p> - * When used in a request bean, the {@link #value()} can be used to override the header name. - * It can also be overridden via the {@link BeanProperty#name @BeanProperty.name()} annotation. - * A name of <js>"*"</js> where the bean property value is a map or bean will cause the individual entries in the - * map or bean to be expanded to headers. + * The {@link #name()} and {@link #value()} elements are synonyms for specifying the header name. Only one should be used. + * <br>The following annotations are fully equivalent: + * <p> + * <p class='bcode'> + * <ja>@Header</ja>(name=<js>"Foo"</js>) + * + * <ja>@Header</ja>(<js>"Foo"</js>) + * </p> */ @Documented @Target({PARAMETER,FIELD,METHOD}) @@ -82,22 +114,73 @@ public @interface Header { /** * The HTTP header name. * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean + * A blank value (the default) indicates to reuse the bean property name when used on a request bean property. + * <p> + * <p> + * The value should be either <js>"*"</js> to represent multiple name/value pairs, or a label that defines the + * header name. + * <p> + * A blank value (the default) has the following behavior: + * <ul class='spaced-list'> + * <li>If the data type is <code>NameValuePairs</code>, <code>Map</code>, or a bean, + * then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jc>// When used on a remote method parameter</jc> + * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) + * <jk>public interface</jk> MyProxy { + * + * <jc>// Equivalent to @Header("*")</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod"</js>) + * String myProxyMethod1(<ja>@Header</ja> Map<String,Object> headers); + * } + * + * <jc>// When used on a request bean method</jc> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @Header("*")</jc> + * <ja>@Header</ja> + * Map<String,Object> getFoo(); + * } + * </p> + * <br> + * <li>If used on a request bean method, uses the bean property name. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @Header("Foo")</jc> + * <ja>@Header</ja> + * <ja>@BeanProperty</ja>(<js>"Foo"</js>) + * String getFoo(); + * } + * </p> + * </ul> * </ul> */ - String value() default "*"; + String name() default ""; + + /** + * A synonym for {@link #name()}. + * <p> + * Allows you to use shortened notation if you're only specifying the name. + */ + String value() default ""; + + /** + * Skips this value if it's an empty string or empty collection/array. + * <p> + * Note that <jk>null</jk> values are already ignored. + */ + boolean skipIfEmpty() default false; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/HeaderIfNE.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/HeaderIfNE.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/HeaderIfNE.java index 4839ff0..eb81015 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/HeaderIfNE.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/HeaderIfNE.java @@ -31,23 +31,23 @@ public @interface HeaderIfNE { /** * The HTTP header name. - * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean - * </ul> + * @see Header#name() + */ + String name() default ""; + + /** + * A synonym for {@link #name()}. + * @see Header#value() */ - String value() default "*"; + String value() default ""; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/Path.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/Path.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/Path.java index 919615e..3f5874d 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/Path.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/Path.java @@ -17,7 +17,6 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.*; -import org.apache.juneau.annotation.*; import org.apache.juneau.serializer.*; import org.apache.juneau.urlencoding.*; @@ -29,21 +28,28 @@ import org.apache.juneau.urlencoding.*; * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) * <jk>public interface</jk> MyProxy { * - * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1/{foo}"</js>) - * String myProxyMethod1(<ja>@Path</ja>(<js>"foo"</js>)</ja> String foo); + * <jc>// Explicit names specified for path parameters.</jc> + * <jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1/{foo}/{bar}"</js>) + * String myProxyMethod1(<ja>@Path</ja>(<js>"foo"</js>)</ja> String foo, <ja>@Path</ja>(<js>"bar"</js>)</ja> MyPojo pojo); + * + * <jc>// Multiple values pulled from a NameValuePairs object.</jc> + * <jc>// Same as @Path("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod2/{foo}/{bar}/{baz}"</js>) + * String myProxyMethod2(<ja>@Path</ja> NameValuePairs nameValuePairs); + * + * <jc>// Multiple values pulled from a Map.</jc> + * <jc>// Same as @Path("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod3/{foo}/{bar}/{baz}"</js>) + * String myProxyMethod3(<ja>@Path</ja> Map<String,Object> map); + * + * <jc>// Multiple values pulled from a bean.</jc> + * <jc>// Same as @Path("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod4/{foo}/{bar}/{baz}"</js>) + * String myProxyMethod4(<ja>@Path</ja> MyBean myBean); * } * </p> * <p> - * The argument can be any of the following types: - * <ul class='spaced-list'> - * <li><code>NameValuePairs</code> - Individual name-value pairs. - * <li>Any serializable POJO - Converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li><code>Map<String,Object></code> - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li>A bean - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * </ul> - * <p> * The annotation can also be applied to a bean property field or getter when the argument is annotated with * {@link RequestBean @RequestBean}: * <p> @@ -52,20 +58,52 @@ import org.apache.juneau.urlencoding.*; * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) * <jk>public interface</jk> MyProxy { * - * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1/{foo}"</js>) + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod/{foo}/{bar}/{baz}"</js>) * String myProxyMethod(<ja>@RequestBean</ja> MyRequestBean bean); * } * * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Name explicitly specified.</jc> + * <ja>@Path</ja>(<js>"foo"</js>) + * String getX(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @Path("bar")</jc> + * <ja>@Path</ja> + * String getBar(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @Path("baz")</jc> + * <ja>@Path</ja> + * <ja>@BeanProperty</ja>(<js>"baz"</js>) + * String getY(); + * + * <jc>// Multiple values pulled from NameValuePairs object.</jc> + * <jc>// Same as @Path("*")</jc> + * <ja>@Path</ja> + * NameValuePairs getNameValuePairs(); + * + * <jc>// Multiple values pulled from Map.</jc> + * <jc>// Same as @Path("*")</jc> * <ja>@Path</ja> - * String getFoo(); + * Map<String,Object> getMap(); + * + * <jc>// Multiple values pulled from bean.</jc> + * <jc>// Same as @Path("*")</jc> + * <ja>@Path</ja> + * MyBean getMyBean(); * } * </p> * <p> - * When used in a request bean, the {@link #value()} can be used to override the path variable name. - * It can also be overridden via the {@link BeanProperty#name @BeanProperty.name()} annotation. - * A name of <js>"*"</js> where the bean property value is a map or bean will cause the individual entries in the - * map or bean to be expanded to path variables. + * The {@link #name()} and {@link #value()} elements are synonyms for specifying the path variable name. Only one should be used. + * <br>The following annotations are fully equivalent: + * <p> + * <p class='bcode'> + * <ja>@Path</ja>(name=<js>"foo"</js>) + * + * <ja>@Path</ja>(<js>"foo"</js>) + * </p> */ @Documented @Target({PARAMETER,FIELD,METHOD}) @@ -76,22 +114,62 @@ public @interface Path { /** * The path parameter name. * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean + * Note that {@link #name()} and {@link #value()} are synonyms. + * <p> + * The value should be either <js>"*"</js> to represent multiple name/value pairs, or a label that defines the + * path variable name. + * <p> + * A blank value (the default) has the following behavior: + * <ul class='spaced-list'> + * <li>If the data type is <code>NameValuePairs</code>, <code>Map</code>, or a bean, + * then it's the equivalent to <js>"*"</js> which will cause the value to be treated as name/value pairs. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jc>// When used on a remote method parameter</jc> + * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) + * <jk>public interface</jk> MyProxy { + * + * <jc>// Equivalent to @Path("*")</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod/{foo}/{bar}"</js>) + * String myProxyMethod1(<ja>@FormData</ja> Map<String,Object> pathVars); + * } + * + * <jc>// When used on a request bean method</jc> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @Path("*")</jc> + * <ja>@Path</ja> + * Map<String,Object> getPathVars(); + * } + * </p> + * <br> + * <li>If used on a request bean method, uses the bean property name. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @Path("foo")</jc> + * <ja>@Path</ja> + * String getFoo(); + * } * </ul> */ - String value() default "*"; + String name() default ""; + + /** + * A synonym for {@link #name()}. + * <p> + * Allows you to use shortened notation if you're only specifying the name. + */ + String value() default ""; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/Query.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/Query.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/Query.java index 7738468..35540e5 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/Query.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/Query.java @@ -17,7 +17,6 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.*; -import org.apache.juneau.annotation.*; import org.apache.juneau.serializer.*; import org.apache.juneau.urlencoding.*; @@ -29,28 +28,38 @@ import org.apache.juneau.urlencoding.*; * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) * <jk>public interface</jk> MyProxy { * + * <jc>// Explicit names specified for query parameters.</jc> + * <jc>// pojo will be converted to UON notation (unless plain-text parts enabled).</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod1"</js>) * String myProxyMethod1(<ja>@Query</ja>(<js>"foo"</js>)</ja> String foo, <ja>@Query</ja>(<js>"bar"</js>)</ja> MyPojo pojo); * + * <jc>// Multiple values pulled from a NameValuePairs object.</jc> + * <jc>// Same as @Query("*").</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod2"</js>) - * String myProxyMethod2(<ja>@Query</ja> Map<String,Object> query); + * String myProxyMethod2(<ja>@Query</ja> NameValuePairs nameValuePairs); * + * <jc>// Multiple values pulled from a Map.</jc> + * <jc>// Same as @Query("*").</jc> * <ja>@RemoteMethod</ja>(path=<js>"/mymethod3"</js>) - * String myProxyMethod2(<ja>@Query</ja> String queryString); + * String myProxyMethod3(<ja>@Query</ja> Map<String,Object> map); + * + * <jc>// Multiple values pulled from a bean.</jc> + * <jc>// Same as @Query("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod4"</js>) + * String myProxyMethod4(<ja>@Query</ja> MyBean myBean); + * + * <jc>// An entire query string as a String.</jc> + * <jc>// Same as @FQuery("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod5"</js>) + * String myProxyMethod5(<ja>@Query</ja> String string); + * + * <jc>// An entire query string as a Reader.</jc> + * <jc>// Same as @Query("*").</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod6"</js>) + * String myProxyMethod6(<ja>@Query</ja> Reader reader); * } * </p> * <p> - * The argument can be any of the following types: - * <ul class='spaced-list'> - * <li><code>NameValuePairs</code> - Individual name-value pairs. - * <li>Any serializable POJO - Converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li><code>Map<String,Object></code> - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li>A bean - Individual name-value pairs. - * Values are converted to text using {@link UrlEncodingSerializer#serialize(PartType,Object)}. - * <li>{@link String} - Treated as a query string. - * </ul> - * <p> * The annotation can also be applied to a bean property field or getter when the argument is annotated with * {@link RequestBean @RequestBean}: * <p> @@ -64,18 +73,52 @@ import org.apache.juneau.urlencoding.*; * } * * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Name explicitly specified.</jc> + * <ja>@Query</ja>(<js>"foo"</js>) + * String getX(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @Query("bar")</jc> + * <ja>@Query</ja> + * String getBar(); + * + * <jc>// Name inherited from bean property.</jc> + * <jc>// Same as @Query("baz")</jc> + * <ja>@Query</ja> + * <ja>@BeanProperty</ja>(<js>"baz"</js>) + * String getY(); + * + * <jc>// Multiple values pulled from NameValuePairs object.</jc> + * <jc>// Same as @Query("*")</jc> + * <ja>@Query</ja> + * NameValuePairs getNameValuePairs(); + * + * <jc>// Multiple values pulled from Map.</jc> + * <jc>// Same as @Query("*")</jc> + * <ja>@Query</ja> + * Map<String,Object> getMap(); + * + * <jc>// Multiple values pulled from bean.</jc> + * <jc>// Same as @Query("*")</jc> * <ja>@Query</ja> - * String getFoo(); + * MyBean getMyBean(); * + * <jc>// An entire query string as a Reader.</jc> + * <jc>// Same as @Query("*")</jc> * <ja>@Query</ja> - * MyPojo getBar(); + * Reader getReader(); * } * </p> * <p> - * When used in a request bean, the {@link #value()} can be used to override the query parameter name. - * It can also be overridden via the {@link BeanProperty#name @BeanProperty.name()} annotation. - * A name of <js>"*"</js> where the bean property value is a map or bean will cause the individual entries in the - * map or bean to be expanded to query parameters. + * The {@link #name()} and {@link #value()} elements are synonyms for specifying the parameter name. Only one should be used. + * <br>The following annotations are fully equivalent: + * <p> + * <p class='bcode'> + * <ja>@Query</ja>(name=<js>"foo"</js>) + * + * <ja>@Query</ja>(<js>"foo"</js>) + * </p> */ @Documented @Target({PARAMETER,FIELD,METHOD}) @@ -86,23 +129,71 @@ public @interface Query { /** * The query parameter name. * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>String</code> - A complete query string. - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean + * Note that {@link #name()} and {@link #value()} are synonyms. + * <p> + * The value should be either <js>"*"</js> to represent multiple name/value pairs, or a label that defines the + * query parameter name. + * <p> + * A blank value (the default) has the following behavior: + * <ul class='spaced-list'> + * <li>If the data type is <code>NameValuePairs</code>, <code>Map</code>, or a bean, + * then it's the equivalent to <js>"*"</js> which will cause the value to be serialized as name/value pairs. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jc>// When used on a remote method parameter</jc> + * <ja>@Remoteable</ja>(path=<js>"/myproxy"</js>) + * <jk>public interface</jk> MyProxy { + * + * <jc>// Equivalent to @Query("*")</jc> + * <ja>@RemoteMethod</ja>(path=<js>"/mymethod"</js>) + * String myProxyMethod1(<ja>@Query</ja> Map<String,Object> formData); + * } + * + * <jc>// When used on a request bean method</jc> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @Query("*")</jc> + * <ja>@Query</ja> + * Map<String,Object> getFoo(); + * } + * </p> + * <br> + * <li>If used on a request bean method, uses the bean property name. + * <h6 class='figure'>Example:</h6> + * <p class='bcode'> + * <jk>public interface</jk> MyRequestBean { + * + * <jc>// Equivalent to @Query("foo")</jc> + * <ja>@Query</ja> + * String getFoo(); + * } + * </p> + * </ul> * </ul> */ - String value() default "*"; + String name() default ""; + + /** + * A synonym for {@link #name()}. + * <p> + * Allows you to use shortened notation if you're only specifying the name. + */ + String value() default ""; + + /** + * Skips this value if it's an empty string or empty collection/array. + * <p> + * Note that <jk>null</jk> values are already ignored. + */ + boolean skipIfEmpty() default false; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/QueryIfNE.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/QueryIfNE.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/QueryIfNE.java index 8d38510..968c974 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/QueryIfNE.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/QueryIfNE.java @@ -31,24 +31,23 @@ public @interface QueryIfNE { /** * The query parameter name. - * <p> - * A value of <js>"*"</js> indicates the value should be serialized as name/value pairs and is applicable - * for the following data types: - * <ul> - * <li><code>String</code> - A complete query string. - * <li><code>NameValuePairs</code> - * <li><code>Map<String,Object></code> - * <li>A bean - * </ul> + * @see Query#name() + */ + String name() default ""; + + /** + * A synonym for {@link #name()}. + * @see Query#value() */ - String value() default "*"; + String value() default ""; /** * Specifies the {@link PartSerializer} class used for serializing values to strings. * <p> - * The default serializer converters values to UON notation. + * The default value defaults to the using the part serializer defined on the {@link RequestBean} annotation, + * then on the client which by default is {@link UrlEncodingSerializer}. * <p> * This annotation is provided to allow values to be custom serialized. */ - Class<? extends PartSerializer> serializer() default UrlEncodingSerializer.class; + Class<? extends PartSerializer> serializer() default PartSerializer.class; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java index ab9a44c..97a4af3 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RemoteMethodArg.java @@ -35,19 +35,20 @@ public class RemoteMethodArg { /** * Constructor. * - * @param name The argument name. Can be blank. + * @param name The argument name pulled from name(). + * @param name2 The argument name pulled from value(). * @param index The zero-based index of the argument on the Java method. * @param skipIfNE The value is skipped if it's null/empty. * @param serializer The class to use for serializing headers, query paramters, form-data parameters, and * path variables. * If {@link UrlEncodingSerializer}, then the url-encoding serializer defined on the client will be used. */ - protected RemoteMethodArg(String name, int index, boolean skipIfNE, Class<? extends PartSerializer> serializer) { - this.name = name; + protected RemoteMethodArg(String name, String name2, int index, boolean skipIfNE, Class<? extends PartSerializer> serializer) { + this.name = name.isEmpty() ? name2 : name; this.index = index; this.skipIfNE = skipIfNE; try { - this.serializer = (serializer == UrlEncodingSerializer.class ? null : serializer.newInstance()); + this.serializer = (serializer == PartSerializer.class ? null : serializer.newInstance()); } catch (Exception e) { throw new RuntimeException(e); } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/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 13b96b4..772cb4f 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 @@ -29,8 +29,8 @@ public class RemoteableMethodMeta { private final String httpMethod; private final String url; - private final RemoteMethodArg[] pathArgs, queryArgs, headerArgs, formDataArgs; - private final Integer[] requestBeanArgs, otherArgs; + private final RemoteMethodArg[] pathArgs, queryArgs, headerArgs, formDataArgs, requestBeanArgs; + private final Integer[] otherArgs; private final Integer bodyArg; /** @@ -47,7 +47,7 @@ public class RemoteableMethodMeta { this.queryArgs = b.queryArgs.toArray(new RemoteMethodArg[b.queryArgs.size()]); this.formDataArgs = b.formDataArgs.toArray(new RemoteMethodArg[b.formDataArgs.size()]); this.headerArgs = b.headerArgs.toArray(new RemoteMethodArg[b.headerArgs.size()]); - this.requestBeanArgs = b.requestBeanArgs.toArray(new Integer[b.requestBeanArgs.size()]); + this.requestBeanArgs = b.requestBeanArgs.toArray(new RemoteMethodArg[b.requestBeanArgs.size()]); this.otherArgs = b.otherArgs.toArray(new Integer[b.otherArgs.size()]); this.bodyArg = b.bodyArg; } @@ -58,9 +58,9 @@ public class RemoteableMethodMeta { pathArgs = new LinkedList<RemoteMethodArg>(), queryArgs = new LinkedList<RemoteMethodArg>(), headerArgs = new LinkedList<RemoteMethodArg>(), - formDataArgs = new LinkedList<RemoteMethodArg>(); + formDataArgs = new LinkedList<RemoteMethodArg>(), + requestBeanArgs = new LinkedList<RemoteMethodArg>(); private List<Integer> - requestBeanArgs = new LinkedList<Integer>(), otherArgs = new LinkedList<Integer>(); private Integer bodyArg; @@ -90,28 +90,28 @@ public class RemoteableMethodMeta { Class<?> ca = a.annotationType(); if (ca == Path.class) { Path p = (Path)a; - annotated = pathArgs.add(new RemoteMethodArg(p.value(), index, false, p.serializer())); + annotated = pathArgs.add(new RemoteMethodArg(p.name(), p.value(), index, false, p.serializer())); } else if (ca == Query.class) { Query q = (Query)a; - annotated = queryArgs.add(new RemoteMethodArg(q.value(), index, false, q.serializer())); + annotated = queryArgs.add(new RemoteMethodArg(q.name(), q.value(), index, q.skipIfEmpty(), q.serializer())); } else if (ca == QueryIfNE.class) { QueryIfNE q = (QueryIfNE)a; - annotated = queryArgs.add(new RemoteMethodArg(q.value(), index, true, q.serializer())); + annotated = queryArgs.add(new RemoteMethodArg(q.name(), q.value(), index, true, q.serializer())); } else if (ca == FormData.class) { FormData f = (FormData)a; - annotated = formDataArgs.add(new RemoteMethodArg(f.value(), index, false, f.serializer())); + annotated = formDataArgs.add(new RemoteMethodArg(f.name(), f.value(), index, f.skipIfEmpty(), f.serializer())); } else if (ca == FormDataIfNE.class) { FormDataIfNE f = (FormDataIfNE)a; - annotated = formDataArgs.add(new RemoteMethodArg(f.value(), index, true, f.serializer())); + annotated = formDataArgs.add(new RemoteMethodArg(f.name(), f.value(), index, true, f.serializer())); } else if (ca == Header.class) { Header h = (Header)a; - annotated = headerArgs.add(new RemoteMethodArg(h.value(), index, false, h.serializer())); + annotated = headerArgs.add(new RemoteMethodArg(h.name(), h.value(), index, h.skipIfEmpty(), h.serializer())); } else if (ca == HeaderIfNE.class) { HeaderIfNE h = (HeaderIfNE)a; - annotated = headerArgs.add(new RemoteMethodArg(h.value(), index, true, h.serializer())); + annotated = headerArgs.add(new RemoteMethodArg(h.name(), h.value(), index, true, h.serializer())); } else if (ca == RequestBean.class) { - annotated = true; - requestBeanArgs.add(index); + RequestBean rb = (RequestBean)a; + annotated = requestBeanArgs.add(new RemoteMethodArg("", "", index, false, rb.serializer())); } else if (ca == Body.class) { annotated = true; if (bodyArg == null) @@ -182,7 +182,7 @@ public class RemoteableMethodMeta { * Returns the {@link RequestBean @RequestBean} annotated arguments on this Java method. * @return A list of zero-indexed argument indices. */ - public Integer[] getRequestBeanArgs() { + public RemoteMethodArg[] getRequestBeanArgs() { return requestBeanArgs; } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/remoteable/RequestBean.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/remoteable/RequestBean.java b/juneau-core/src/main/java/org/apache/juneau/remoteable/RequestBean.java index 3da7f6c..0c18874 100644 --- a/juneau-core/src/main/java/org/apache/juneau/remoteable/RequestBean.java +++ b/juneau-core/src/main/java/org/apache/juneau/remoteable/RequestBean.java @@ -17,6 +17,9 @@ import static java.lang.annotation.RetentionPolicy.*; import java.lang.annotation.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.urlencoding.*; + /** * Annotation applied to Java method arguments of interface proxies to denote a bean with remoteable annotations. * <p> @@ -82,4 +85,15 @@ import java.lang.annotation.*; @Target(PARAMETER) @Retention(RUNTIME) @Inherited -public @interface RequestBean {} +public @interface RequestBean { + + /** + * Specifies the {@link PartSerializer} class used for serializing values to strings. + * <p> + * The default value defaults to the using the part serializer defined on the client which by default is + * {@link UrlEncodingSerializer}. + * <p> + * This annotation is provided to allow values to be custom serialized. + */ + Class<? extends PartSerializer> serializer() default PartSerializer.class; +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/serializer/PartSerializer.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/PartSerializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/PartSerializer.java index 0063b9e..37d0fc5 100644 --- a/juneau-core/src/main/java/org/apache/juneau/serializer/PartSerializer.java +++ b/juneau-core/src/main/java/org/apache/juneau/serializer/PartSerializer.java @@ -31,6 +31,7 @@ import org.apache.juneau.urlencoding.*; * <li>{@link Header#serializer()} * <li>{@link HeaderIfNE#serializer()} * <li>{@link Path#serializer()} + * <li>{@link RequestBean#serializer()} * <li><code>RestClientBuilder.partSerializer(Class)</code> * </ul> * <p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java index b358920..8eed75b 100644 --- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializer.java @@ -204,17 +204,16 @@ public class UonSerializer extends WriterSerializer { * @param eType The expected type of the object if this is a bean property. * @param attrName The bean property name if this is a bean property. <jk>null</jk> if this isn't a bean property being serialized. * @param pMeta The bean property metadata. - * @param plainTextParams <jk>true</jk> if this is a top level parameter key or value and paramFormat is PLAINTEXT. * * @return The same writer passed in. * @throws Exception */ @SuppressWarnings({ "rawtypes", "unchecked" }) protected SerializerWriter serializeAnything(UonSerializerSession session, UonWriter out, Object o, ClassMeta<?> eType, - String attrName, BeanPropertyMeta pMeta, boolean plainTextParams) throws Exception { + String attrName, BeanPropertyMeta pMeta) throws Exception { if (o == null) { - out.appendObject(null, false, plainTextParams); + out.appendObject(null, false); return out; } @@ -249,7 +248,7 @@ public class UonSerializer extends WriterSerializer { // '\0' characters are considered null. if (o == null || (sType.isChar() && ((Character)o).charValue() == 0)) - out.appendObject(null, false, plainTextParams); + out.appendObject(null, false); else if (sType.isBoolean()) out.appendBoolean(o); else if (sType.isNumber()) @@ -271,7 +270,7 @@ public class UonSerializer extends WriterSerializer { serializeCollection(session, out, toList(sType.getInnerClass(), o), eType); } else { - out.appendObject(o, false, plainTextParams); + out.appendObject(o, false); } if (! isRecursion) @@ -287,7 +286,9 @@ public class UonSerializer extends WriterSerializer { ClassMeta<?> keyType = type.getKeyType(), valueType = type.getValueType(); int depth = session.getIndent(); - out.append('('); + + if (! session.isPlainTextParams()) + out.append('('); Iterator mapEntries = m.entrySet().iterator(); @@ -295,15 +296,17 @@ public class UonSerializer extends WriterSerializer { Map.Entry e = (Map.Entry) mapEntries.next(); Object value = e.getValue(); Object key = session.generalize(e.getKey(), keyType); - out.cr(depth).appendObject(key, false, false).append('='); - serializeAnything(session, out, value, valueType, (key == null ? null : session.toString(key)), null, false); + out.cr(depth).appendObject(key, false).append('='); + serializeAnything(session, out, value, valueType, (key == null ? null : session.toString(key)), null); if (mapEntries.hasNext()) out.append(','); } if (m.size() > 0) out.cr(depth-1); - out.append(')'); + + if (! session.isPlainTextParams()) + out.append(')'); return out; } @@ -311,7 +314,8 @@ public class UonSerializer extends WriterSerializer { private SerializerWriter serializeBeanMap(UonSerializerSession session, UonWriter out, BeanMap<?> m, String typeName) throws Exception { int depth = session.getIndent(); - out.append('('); + if (! session.isPlainTextParams()) + out.append('('); boolean addComma = false; @@ -331,16 +335,17 @@ public class UonSerializer extends WriterSerializer { if (addComma) out.append(','); - out.cr(depth).appendObject(key, false, false).append('='); + out.cr(depth).appendObject(key, false).append('='); - serializeAnything(session, out, value, cMeta, key, pMeta, false); + serializeAnything(session, out, value, cMeta, key, pMeta); addComma = true; } if (m.size() > 0) out.cr(depth-1); - out.append(')'); + if (! session.isPlainTextParams()) + out.append(')'); return out; } @@ -352,20 +357,22 @@ public class UonSerializer extends WriterSerializer { c = session.sort(c); - out.append('@').append('('); + if (! session.isPlainTextParams()) + out.append('@').append('('); int depth = session.getIndent(); for (Iterator i = c.iterator(); i.hasNext();) { out.cr(depth); - serializeAnything(session, out, i.next(), elementType, "<iterator>", null, false); + serializeAnything(session, out, i.next(), elementType, "<iterator>", null); if (i.hasNext()) out.append(','); } if (c.size() > 0) out.cr(depth-1); - out.append(')'); + if (! session.isPlainTextParams()) + out.append(')'); return out; } @@ -383,6 +390,6 @@ public class UonSerializer extends WriterSerializer { @Override /* Serializer */ protected void doSerialize(SerializerSession session, Object o) throws Exception { UonSerializerSession s = (UonSerializerSession)session; - serializeAnything(s, s.getWriter(), o, s.getExpectedRootType(o), "root", null, false); + serializeAnything(s, s.getWriter(), o, s.getExpectedRootType(o), "root", null); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java index b9ce464..ab2f931 100644 --- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java @@ -71,10 +71,38 @@ public class UonSerializerContext extends SerializerContext { */ public static final String UON_addBeanTypeProperties = "UonSerializer.addBeanTypeProperties"; + /** + * <b>Configuration property:</b> Format to use for query/form-data/header values. + * <p> + * <ul> + * <li><b>Name:</b> <js>"UrlEncodingSerializer.paramFormat"</js> + * <li><b>Data type:</b> <code>String</code> + * <li><b>Default:</b> <js>"UON"</js> + * <li><b>Session-overridable:</b> <jk>true</jk> + * </ul> + * <p> + * Specifies the format to use for URL GET parameter keys and values. + * <p> + * The possible values are: + * <ul> + * <li><js>"UON"</js> (default) - Use UON notation for values. + * <br>String values such as <js>"(foo='bar')"</js> will end up being quoted and escaped to <js>"'(foo=bar~'baz~')'"</js>. + * <br>Boolean strings (<js>"true"</js>/<js>"false"</js>) and numeric values (<js>"123"</js>) will also end up + * quoted (<js>"'true'"</js>, <js>"'false'"</js>, <js>"'123'"</js>. + * <li><js>"PLAINTEXT"</js> (default) - Serialize as plain text. + * <br>Strings will never be quoted or escaped. + * <br>Note that this can cause errors during parsing if you're using the URL-encoding parser to parse + * the results since UON constructs won't be differentiatable. + * <br>However, this is not an issue if you're simply creating queries or form posts against 3rd-party interfaces. + * </ul> + */ + public static final String UON_paramFormat = "UonSerializer.paramFormat"; + final boolean encodeChars, - addBeanTypeProperties; + addBeanTypeProperties, + plainTextParams; /** * Constructor. @@ -87,6 +115,7 @@ public class UonSerializerContext extends SerializerContext { super(ps); encodeChars = ps.getProperty(UON_encodeChars, boolean.class, false); addBeanTypeProperties = ps.getProperty(UON_addBeanTypeProperties, boolean.class, ps.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, true)); + plainTextParams = ps.getProperty(UON_paramFormat, String.class, "UON").equals("PLAINTEXT"); } @Override /* Context */ @@ -95,6 +124,15 @@ public class UonSerializerContext extends SerializerContext { .append("UonSerializerContext", new ObjectMap() .append("encodeChars", encodeChars) .append("addBeanTypeProperties", addBeanTypeProperties) + .append("plainTextParams", plainTextParams) ); } + + /** + * Returns <jk>true</jk> if the {@link UonSerializerContext#UON_paramFormat} is <js>"PLAINTEXT"</js>. + * @return <jk>true</jk> if the {@link UonSerializerContext#UON_paramFormat} is <js>"PLAINTEXT"</js>. + */ + public boolean plainTextParams() { + return plainTextParams; + } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java index e9f9659..b7c6c66 100644 --- a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java @@ -32,7 +32,8 @@ public class UonSerializerSession extends SerializerSession { private final boolean encodeChars, - addBeanTypeProperties; + addBeanTypeProperties, + plainTextParams; /** * Create a new session using properties specified in the context. @@ -57,9 +58,11 @@ public class UonSerializerSession extends SerializerSession { if (op == null || op.isEmpty()) { encodeChars = encode == null ? ctx.encodeChars : encode; addBeanTypeProperties = ctx.addBeanTypeProperties; + plainTextParams = ctx.plainTextParams; } else { encodeChars = encode == null ? op.getBoolean(UON_encodeChars, ctx.encodeChars) : encode; addBeanTypeProperties = op.getBoolean(MSGPACK_addBeanTypeProperties, ctx.addBeanTypeProperties); + plainTextParams = op.getString(UonSerializerContext.UON_paramFormat, "UON").equals("PLAINTEXT"); } } @@ -82,11 +85,19 @@ public class UonSerializerSession extends SerializerSession { return addBeanTypeProperties; } + /** + * Returns <jk>true</jk> if the {@link UonSerializerContext#UON_paramFormat} is <js>"PLAINTEXT"</js>. + * @return <jk>true</jk> if the {@link UonSerializerContext#UON_paramFormat} is <js>"PLAINTEXT"</js>. + */ + public boolean isPlainTextParams() { + return plainTextParams; + } + @Override /* SerializerSession */ public final UonWriter getWriter() throws Exception { Object output = getOutput(); if (output instanceof UonWriter) return (UonWriter)output; - return new UonWriter(this, super.getWriter(), isUseWhitespace(), isEncodeChars(), isTrimStrings(), getUriResolver()); + return new UonWriter(this, super.getWriter(), isUseWhitespace(), isEncodeChars(), isTrimStrings(), isPlainTextParams(), getUriResolver()); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java index 2844e62..1aafc74 100644 --- a/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java @@ -29,7 +29,7 @@ import org.apache.juneau.serializer.*; public final class UonWriter extends SerializerWriter { private final UonSerializerSession session; - private final boolean encodeChars; + private final boolean encodeChars, plainTextParams; // Characters that do not need to be URL-encoded in strings. private static final AsciiSet unencodedChars = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;/?:@-_.!*'$(),~="); @@ -53,12 +53,14 @@ public final class UonWriter extends SerializerWriter { * @param useWhitespace If <jk>true</jk>, tabs will be used in output. * @param encodeChars If <jk>true</jk>, special characters should be encoded. * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized. + * @param plainTextParams If <jk>true</jk>, don't use UON notation for values. * @param uriResolver The URI resolver for resolving URIs to absolute or root-relative form. */ - protected UonWriter(UonSerializerSession session, Writer out, boolean useWhitespace, boolean encodeChars, boolean trimStrings, UriResolver uriResolver) { + protected UonWriter(UonSerializerSession session, Writer out, boolean useWhitespace, boolean encodeChars, boolean trimStrings, boolean plainTextParams, UriResolver uriResolver) { super(out, useWhitespace, trimStrings, '\'', uriResolver); this.session = session; this.encodeChars = encodeChars; + this.plainTextParams = plainTextParams; } /** @@ -66,11 +68,10 @@ public final class UonWriter extends SerializerWriter { * * @param o The object being serialized. * @param isTopAttrName If this is a top-level attribute name we're serializing. - * @param plainTextParams This is a top-level name or parameter we're serializing and the parameter format is PLAINTEXT. * @return This object (for method chaining). * @throws IOException Should never happen. */ - public final UonWriter appendObject(Object o, boolean isTopAttrName, boolean plainTextParams) throws IOException { + public final UonWriter appendObject(Object o, boolean isTopAttrName) throws IOException { if (o instanceof Boolean) return appendBoolean(o); @@ -164,7 +165,7 @@ public final class UonWriter extends SerializerWriter { */ @Override public SerializerWriter appendUri(Object uri) throws IOException { - return appendObject(uriResolver.resolve(uri), false, false); + return appendObject(uriResolver.resolve(uri), false); } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/uon/package.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/package.html b/juneau-core/src/main/java/org/apache/juneau/uon/package.html index 1794466..440f5b2 100644 --- a/juneau-core/src/main/java/org/apache/juneau/uon/package.html +++ b/juneau-core/src/main/java/org/apache/juneau/uon/package.html @@ -467,12 +467,12 @@ <p> Another useful feature is the {@link org.apache.juneau.annotation.Bean#propertyNamer()} annotation that allows you to plug in your own logic for determining bean property names.<br> - The {@link org.apache.juneau.PropertyNamerDashedLC} is an example of an alternate property namer. + The {@link org.apache.juneau.PropertyNamerDLC} is an example of an alternate property namer. It converts bean property names to lowercase-dashed format. </p> <h6 class='figure'>Example:</h6> <p class='bcode'> - <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>) + <ja>@Bean</ja>(propertyNamer=PropertyNamerDLC.<jk>class</jk>) <jk>public class</jk> Person { ... </p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java index 2ab697a..df35f9a 100644 --- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java +++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java @@ -137,6 +137,9 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ /** Reusable instance of {@link UrlEncodingSerializer}, all default settings. */ public static final UrlEncodingSerializer DEFAULT = new UrlEncodingSerializer(PropertyStore.create()); + /** Reusable instance of {@link UrlEncodingSerializer.PlainText}. */ + public static final UrlEncodingSerializer DEFAULT_PLAINTEXT = new PlainText(PropertyStore.create()); + /** Reusable instance of {@link UrlEncodingSerializer.Expanded}. */ public static final UrlEncodingSerializer DEFAULT_EXPANDED = new Expanded(PropertyStore.create()); @@ -182,6 +185,24 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ } } + /** + * Equivalent to <code><jk>new</jk> UrlEncodingSerializerBuilder().plainTextParts().build();</code>. + */ + public static class PlainText extends UrlEncodingSerializer { + + /** + * Constructor. + * @param propertyStore The property store containing all the settings for this object. + */ + public PlainText(PropertyStore propertyStore) { + super(propertyStore); + } + + @Override /* CoreObject */ + protected ObjectMap getOverrideProperties() { + return super.getOverrideProperties().append(UonSerializerContext.UON_paramFormat, "PLAINTEXT"); + } + } private final UrlEncodingSerializerContext ctx; @@ -247,7 +268,7 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ // All other types can't be serialized as key/value pairs, so we create a // mock key/value pair with a "_value" key. out.append("_value="); - super.serializeAnything(session, out, o, null, null, null, session.plainTextParams()); + super.serializeAnything(session, out, o, null, null, null); } session.pop(); @@ -278,7 +299,6 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ @SuppressWarnings({ "rawtypes", "unchecked" }) private SerializerWriter serializeMap(UrlEncodingSerializerSession session, UonWriter out, Map m, ClassMeta<?> type) throws Exception { - boolean plainTextParams = session.plainTextParams(); m = session.sort(m); ClassMeta<?> keyType = type.getKeyType(), valueType = type.getValueType(); @@ -295,15 +315,15 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ while (i.hasNext()) { if (addAmp) out.cr(depth).append('&'); - out.appendObject(key, true, plainTextParams).append('='); - super.serializeAnything(session, out, i.next(), null, (key == null ? null : key.toString()), null, plainTextParams); + out.appendObject(key, true).append('='); + super.serializeAnything(session, out, i.next(), null, (key == null ? null : key.toString()), null); addAmp = true; } } else { if (addAmp) out.cr(depth).append('&'); - out.appendObject(key, true, plainTextParams).append('='); - super.serializeAnything(session, out, value, valueType, (key == null ? null : key.toString()), null, plainTextParams); + out.appendObject(key, true).append('='); + super.serializeAnything(session, out, value, valueType, (key == null ? null : key.toString()), null); addAmp = true; } } @@ -323,7 +343,7 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ if (addAmp) out.cr(depth).append('&'); out.append(e.getKey()).append('='); - super.serializeAnything(session, out, e.getValue(), valueType, null, null, session.plainTextParams()); + super.serializeAnything(session, out, e.getValue(), valueType, null, null); addAmp = true; } @@ -333,7 +353,6 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ @SuppressWarnings({ "rawtypes" }) private SerializerWriter serializeBeanMap(UrlEncodingSerializerSession session, UonWriter out, BeanMap<?> m, String typeName) throws Exception { int depth = session.getIndent(); - boolean plainTextParams = session.plainTextParams(); boolean addAmp = false; @@ -358,9 +377,9 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ if (addAmp) out.cr(depth).append('&'); - out.appendObject(key, true, plainTextParams).append('='); + out.appendObject(key, true).append('='); - super.serializeAnything(session, out, i.next(), cMeta.getElementType(), key, pMeta, plainTextParams); + super.serializeAnything(session, out, i.next(), cMeta.getElementType(), key, pMeta); addAmp = true; } @@ -368,9 +387,9 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ if (addAmp) out.cr(depth).append('&'); - out.appendObject(key, true, plainTextParams).append('='); + out.appendObject(key, true).append('='); - super.serializeAnything(session, out, value, cMeta, key, pMeta, plainTextParams); + super.serializeAnything(session, out, value, cMeta, key, pMeta); addAmp = true; } @@ -405,8 +424,8 @@ public class UrlEncodingSerializer extends UonSerializer implements PartSerializ return o.toString(); if (cm.isCharSequence()) { String s = o.toString(); - boolean ptt = (plainTextParams != null ? plainTextParams : ctx.plainTextParams); - if (ptt || ! UonUtils.needsQuotes(s)) + boolean ptt = (plainTextParams != null ? plainTextParams : ctx.plainTextParams()); + if (ptt || s.isEmpty() || ! UonUtils.needsQuotes(s)) return (urlEncode ? StringUtils.urlEncode(s) : s); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java index 7c79631..e7ff61e 100644 --- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java +++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerBuilder.java @@ -124,17 +124,17 @@ public class UrlEncodingSerializerBuilder extends UonSerializerBuilder { * * @param paramFormat The new value for this property. * @return This object (for method chaining). - * @see UrlEncodingSerializerContext#URLENC_paramFormat + * @see UonSerializerContext#UON_paramFormat */ public UrlEncodingSerializerBuilder paramFormat(String paramFormat) { - return property(UrlEncodingSerializerContext.URLENC_paramFormat, paramFormat); + return property(UonSerializerContext.UON_paramFormat, paramFormat); } /** * Shortcut for calling <code>paramFormat(<js>"PLAINTEXT"</js>)</code>. * * @return This object (for method chaining). - * @see UrlEncodingSerializerContext#URLENC_paramFormat + * @see UonSerializerContext#UON_paramFormat */ public UrlEncodingSerializerBuilder plainTextParams() { return paramFormat("PLAINTEXT"); http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerContext.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerContext.java index 1894b0a..d7ff160 100644 --- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerContext.java +++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerContext.java @@ -25,36 +25,9 @@ import org.apache.juneau.uon.*; */ public class UrlEncodingSerializerContext extends UonSerializerContext { - /** - * <b>Configuration property:</b> Format to use for top-level query names and simple parameters. - * <p> - * <ul> - * <li><b>Name:</b> <js>"UrlEncodingSerializer.paramFormat"</js> - * <li><b>Data type:</b> <code>String</code> - * <li><b>Default:</b> <js>"UON"</js> - * <li><b>Session-overridable:</b> <jk>true</jk> - * </ul> - * <p> - * Specifies the format to use for URL GET parameter keys and values. - * <p> - * The possible values are: - * <ul> - * <li><js>"UON"</js> (default) - Use UON notation for values. - * <br>String values such as <js>"(foo='bar')"</js> will end up being quoted and escaped to <js>"'(foo=bar~'baz~')'"</js>. - * <br>Similarly, boolean and numeric values will also end up quoted. - * <li><js>"PLAINTEXT"</js> (default) - Serialize as plain text. - * <br>Strings will never be quoted or escaped. - * <br>Note that this can cause errors during parsing if you're using the URL-encoding parser to parse - * the results since UON constructs won't be differentiatable. - * <br>However, this is not an issue if you're simply creating queries or form posts against 3rd-party interfaces. - * </ul> - */ - public static final String URLENC_paramFormat = "UrlEncodingSerializer.paramFormat"; - final boolean - expandedParams, - plainTextParams; + expandedParams; /** * Constructor. @@ -66,7 +39,6 @@ public class UrlEncodingSerializerContext extends UonSerializerContext { public UrlEncodingSerializerContext(PropertyStore ps) { super(ps); this.expandedParams = ps.getProperty(UrlEncodingContext.URLENC_expandedParams, boolean.class, false); - this.plainTextParams = ps.getProperty(UrlEncodingSerializerContext.URLENC_paramFormat, String.class, "UON").equals("PLAINTEXT"); } @Override /* Context */ @@ -74,7 +46,6 @@ public class UrlEncodingSerializerContext extends UonSerializerContext { return super.asMap() .append("UrlEncodingSerializerContext", new ObjectMap() .append("expandedParams", expandedParams) - .append("plainTextParams", plainTextParams) ); } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java index a7a93e3..d9c39d9 100644 --- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java +++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java @@ -27,7 +27,7 @@ import org.apache.juneau.uon.*; */ public class UrlEncodingSerializerSession extends UonSerializerSession { - private final boolean expandedParams, plainTextParams; + private final boolean expandedParams; /** * Create a new session using properties specified in the context. @@ -51,10 +51,8 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { super(ctx, encode, op, output, javaMethod, locale, timeZone, mediaType, uriContext); if (op == null || op.isEmpty()) { expandedParams = ctx.expandedParams; - plainTextParams = ctx.plainTextParams; } else { expandedParams = op.getBoolean(UrlEncodingContext.URLENC_expandedParams, false); - plainTextParams = op.getString(UrlEncodingSerializerContext.URLENC_paramFormat, "UON").equals("PLAINTEXT"); } } @@ -91,12 +89,4 @@ public class UrlEncodingSerializerSession extends UonSerializerSession { } return false; } - - /** - * Returns <jk>true</jk> if the {@link UrlEncodingSerializerContext#URLENC_paramFormat} is <js>"PLAINTEXT"</js>. - * @return <jk>true</jk> if the {@link UrlEncodingSerializerContext#URLENC_paramFormat} is <js>"PLAINTEXT"</js>. - */ - protected boolean plainTextParams() { - return plainTextParams; - } } http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html b/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html index ce7f90e..88349fc 100644 --- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html +++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/package.html @@ -467,12 +467,12 @@ <p> Another useful feature is the {@link org.apache.juneau.annotation.Bean#propertyNamer()} annotation that allows you to plug in your own logic for determining bean property names.<br> - The {@link org.apache.juneau.PropertyNamerDashedLC} is an example of an alternate property namer. + The {@link org.apache.juneau.PropertyNamerDLC} is an example of an alternate property namer. It converts bean property names to lowercase-dashed format. </p> <h6 class='figure'>Example:</h6> <p class='bcode'> - <ja>@Bean</ja>(propertyNamer=PropertyNamerDashedLC.<jk>class</jk>) + <ja>@Bean</ja>(propertyNamer=PropertyNamerDLC.<jk>class</jk>) <jk>public class</jk> Person { ... </p> http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/93aadae1/juneau-core/src/main/java/org/apache/juneau/xml/package.html ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/package.html b/juneau-core/src/main/java/org/apache/juneau/xml/package.html index 3b2647e..68257e9 100644 --- a/juneau-core/src/main/java/org/apache/juneau/xml/package.html +++ b/juneau-core/src/main/java/org/apache/juneau/xml/package.html @@ -2178,13 +2178,13 @@ <p> Another useful feature is the {@link org.apache.juneau.annotation.Bean#propertyNamer()} annotation that allows you to plug in your own logic for determining bean property names.<br> - The {@link org.apache.juneau.PropertyNamerDashedLC} is an example of an alternate property namer. + The {@link org.apache.juneau.PropertyNamerDLC} is an example of an alternate property namer. It converts bean property names to lowercase-dashed format. </p> <h6 class='figure'>Example</h6> <p class='bcode'> <ja>@Xml</ja>(prefix=<js>"per"</js>) - <ja>@Bean</ja>(typeName=<js>"person"</js>,propertyNamer=PropertyNamerDashedLC.<jk>class</jk>) + <ja>@Bean</ja>(typeName=<js>"person"</js>,propertyNamer=PropertyNamerDLC.<jk>class</jk>) <jk>public class</jk> Person { ... </p>
