Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id DF910200C36 for ; Fri, 10 Mar 2017 17:51:07 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id DE0C6160B67; Fri, 10 Mar 2017 16:51:07 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id DCC16160B79 for ; Fri, 10 Mar 2017 17:51:05 +0100 (CET) Received: (qmail 36224 invoked by uid 500); 10 Mar 2017 16:51:04 -0000 Mailing-List: contact commits-help@juneau.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@juneau.incubator.apache.org Delivered-To: mailing list commits@juneau.incubator.apache.org Received: (qmail 36203 invoked by uid 99); 10 Mar 2017 16:51:04 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Mar 2017 16:51:04 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 2A947C6B50 for ; Fri, 10 Mar 2017 16:51:04 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -3.569 X-Spam-Level: X-Spam-Status: No, score=-3.569 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.001, SPF_NEUTRAL=0.652] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id v-elg5AxIZxF for ; Fri, 10 Mar 2017 16:51:00 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 4F6A85FCDA for ; Fri, 10 Mar 2017 16:50:58 +0000 (UTC) Received: (qmail 36116 invoked by uid 99); 10 Mar 2017 16:50:57 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 10 Mar 2017 16:50:57 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 4A935F171C; Fri, 10 Mar 2017 16:50:57 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: jamesbognar@apache.org To: commits@juneau.incubator.apache.org Date: Fri, 10 Mar 2017 16:51:08 -0000 Message-Id: <866d8c721ead409ab74cc00f3e94833d@git.apache.org> In-Reply-To: <050f6b9ffdd24b72a491377772392c83@git.apache.org> References: <050f6b9ffdd24b72a491377772392c83@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [12/34] incubator-juneau git commit: Add builder classes for all serializers and parsers. archived-at: Fri, 10 Mar 2017 16:51:08 -0000 http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java new file mode 100644 index 0000000..96bb20b --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java @@ -0,0 +1,570 @@ +// *************************************************************************************************************************** +// * 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.uon; + +import static org.apache.juneau.uon.UonSerializerContext.*; + +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.urlencoding.*; + +/** + * Builder class for building instances of UON serializers. + */ +public class UonSerializerBuilder extends SerializerBuilder { + + /** + * Constructor, default settings. + */ + public UonSerializerBuilder() { + super(); + } + + /** + * Constructor. + * @param propertyStore The initial configuration settings for this builder. + */ + public UonSerializerBuilder(PropertyStore propertyStore) { + super(propertyStore); + } + + @Override /* CoreObjectBuilder */ + public UonSerializer build() { + return new UonSerializer(propertyStore); + } + + + //-------------------------------------------------------------------------------- + // Properties + //-------------------------------------------------------------------------------- + + /** + * Configuration property: Encode non-valid URI characters. + *

+ *

    + *
  • Name: "UonSerializer.encodeChars" + *
  • Data type: Boolean + *
  • Default: false for {@link UonSerializer}, true for {@link UrlEncodingSerializer} + *
  • Session-overridable: true + *
+ *

+ * Encode non-valid URI characters with "%xx" constructs. + *

+ * If true, non-valid URI characters will be converted to "%xx" sequences. + * Set to false if parameter value is being passed to some other code that will already + * perform URL-encoding of non-valid URI characters. + *

+ *

Notes:
+ *
    + *
  • This is equivalent to calling property(UON_encodeChars, value). + *
  • This introduces a slight performance penalty. + *
+ * + * @param value The new value for this property. + * @return This object (for method chaining). + * @see UonSerializerContext#UON_encodeChars + */ + public UonSerializerBuilder encodeChars(boolean value) { + return property(UON_encodeChars, value); + } + + /** + * Shortcut for calling setEncodeChars(true). + * + * @return This object (for method chaining). + */ + public UonSerializerBuilder encoding() { + return encodeChars(true); + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder maxDepth(int value) { + super.maxDepth(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder initialDepth(int value) { + super.initialDepth(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder detectRecursions(boolean value) { + super.detectRecursions(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder ignoreRecursions(boolean value) { + super.ignoreRecursions(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder useWhitespace(boolean value) { + super.useWhitespace(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder ws() { + super.ws(); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder addBeanTypeProperties(boolean value) { + super.addBeanTypeProperties(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder quoteChar(char value) { + super.quoteChar(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder sq() { + super.sq(); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder trimNullProperties(boolean value) { + super.trimNullProperties(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder trimEmptyCollections(boolean value) { + super.trimEmptyCollections(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder trimEmptyMaps(boolean value) { + super.trimEmptyMaps(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder trimStrings(boolean value) { + super.trimStrings(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder relativeUriBase(String value) { + super.relativeUriBase(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder absolutePathUriBase(String value) { + super.absolutePathUriBase(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder sortCollections(boolean value) { + super.sortCollections(value); + return this; + } + + @Override /* SerializerBuilder */ + public UonSerializerBuilder sortMaps(boolean value) { + super.sortMaps(value); + return this; + } + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beansRequireDefaultConstructor(boolean value) { + super.beansRequireDefaultConstructor(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beansRequireSerializable(boolean value) { + super.beansRequireSerializable(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beansRequireSettersForGetters(boolean value) { + super.beansRequireSettersForGetters(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beansRequireSomeProperties(boolean value) { + super.beansRequireSomeProperties(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanMapPutReturnsOldValue(boolean value) { + super.beanMapPutReturnsOldValue(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanConstructorVisibility(Visibility value) { + super.beanConstructorVisibility(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanClassVisibility(Visibility value) { + super.beanClassVisibility(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanFieldVisibility(Visibility value) { + super.beanFieldVisibility(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder methodVisibility(Visibility value) { + super.methodVisibility(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder useJavaBeanIntrospector(boolean value) { + super.useJavaBeanIntrospector(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder useInterfaceProxies(boolean value) { + super.useInterfaceProxies(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder ignoreUnknownBeanProperties(boolean value) { + super.ignoreUnknownBeanProperties(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder ignoreUnknownNullBeanProperties(boolean value) { + super.ignoreUnknownNullBeanProperties(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder ignorePropertiesWithoutSetters(boolean value) { + super.ignorePropertiesWithoutSetters(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder ignoreInvocationExceptionsOnGetters(boolean value) { + super.ignoreInvocationExceptionsOnGetters(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder ignoreInvocationExceptionsOnSetters(boolean value) { + super.ignoreInvocationExceptionsOnSetters(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder sortProperties(boolean value) { + super.sortProperties(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder notBeanPackages(String...values) { + super.notBeanPackages(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder notBeanPackages(Collection values) { + super.notBeanPackages(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setNotBeanPackages(String...values) { + super.setNotBeanPackages(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setNotBeanPackages(Collection values) { + super.setNotBeanPackages(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeNotBeanPackages(String...values) { + super.removeNotBeanPackages(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeNotBeanPackages(Collection values) { + super.removeNotBeanPackages(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder notBeanClasses(Class...values) { + super.notBeanClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder notBeanClasses(Collection> values) { + super.notBeanClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setNotBeanClasses(Class...values) { + super.setNotBeanClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setNotBeanClasses(Collection> values) { + super.setNotBeanClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeNotBeanClasses(Class...values) { + super.removeNotBeanClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeNotBeanClasses(Collection> values) { + super.removeNotBeanClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanFilters(Class...values) { + super.beanFilters(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanFilters(Collection> values) { + super.beanFilters(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setBeanFilters(Class...values) { + super.setBeanFilters(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setBeanFilters(Collection> values) { + super.setBeanFilters(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeBeanFilters(Class...values) { + super.removeBeanFilters(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeBeanFilters(Collection> values) { + super.removeBeanFilters(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder pojoSwaps(Class...values) { + super.pojoSwaps(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder pojoSwaps(Collection> values) { + super.pojoSwaps(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setPojoSwaps(Class...values) { + super.setPojoSwaps(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setPojoSwaps(Collection> values) { + super.setPojoSwaps(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removePojoSwaps(Class...values) { + super.removePojoSwaps(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removePojoSwaps(Collection> values) { + super.removePojoSwaps(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder implClasses(Map,Class> values) { + super.implClasses(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder implClass(Class interfaceClass, Class implClass) { + super.implClass(interfaceClass, implClass); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanDictionary(Class...values) { + super.beanDictionary(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanDictionary(Collection> values) { + super.beanDictionary(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setBeanDictionary(Class...values) { + super.setBeanDictionary(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder setBeanDictionary(Collection> values) { + super.setBeanDictionary(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeFromBeanDictionary(Class...values) { + super.removeFromBeanDictionary(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeFromBeanDictionary(Collection> values) { + super.removeFromBeanDictionary(values); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder beanTypePropertyName(String value) { + super.beanTypePropertyName(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder defaultParser(Class value) { + super.defaultParser(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder locale(Locale value) { + super.locale(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder timeZone(TimeZone value) { + super.timeZone(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder mediaType(MediaType value) { + super.mediaType(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder debug(boolean value) { + super.debug(value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder property(String name, Object value) { + super.property(name, value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder properties(Map properties) { + super.properties(properties); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder addToProperty(String name, Object value) { + super.addToProperty(name, value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder putToProperty(String name, Object key, Object value) { + super.putToProperty(name, key, value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder putToProperty(String name, Object value) { + super.putToProperty(name, value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder removeFromProperty(String name, Object value) { + super.removeFromProperty(name, value); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder classLoader(ClassLoader classLoader) { + super.classLoader(classLoader); + return this; + } + + @Override /* CoreObjectBuilder */ + public UonSerializerBuilder apply(PropertyStore copyFrom) { + super.apply(copyFrom); + return this; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/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 new file mode 100644 index 0000000..b9ce464 --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerContext.java @@ -0,0 +1,100 @@ +// *************************************************************************************************************************** +// * 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.uon; + +import org.apache.juneau.*; +import org.apache.juneau.serializer.*; +import org.apache.juneau.urlencoding.*; + +/** + * Configurable properties on the {@link UonSerializer} class. + *

+ * Context properties are set by calling {@link PropertyStore#setProperty(String, Object)} on the property store + * passed into the constructor. + *

+ * See {@link PropertyStore} for more information about context properties. + * + *

Inherited configurable properties:
+ *
    + *
  • BeanContext - Properties associated with handling beans on serializers and parsers. + * + *
+ */ +public class UonSerializerContext extends SerializerContext { + + /** + * Configuration property: Encode non-valid URI characters. + *

+ *

    + *
  • Name: "UonSerializer.encodeChars" + *
  • Data type: Boolean + *
  • Default: false for {@link UonSerializer}, true for {@link UrlEncodingSerializer} + *
  • Session-overridable: true + *
+ *

+ * Encode non-valid URI characters with "%xx" constructs. + *

+ * If true, non-valid URI characters will be converted to "%xx" sequences. + * Set to false if parameter value is being passed to some other code that will already + * perform URL-encoding of non-valid URI characters. + */ + public static final String UON_encodeChars = "UonSerializer.encodeChars"; + + /** + * Configuration property: Add "_type" properties when needed. + *

+ *

    + *
  • Name: "UonSerializer.addBeanTypeProperties" + *
  • Data type: Boolean + *
  • Default: false + *
  • Session-overridable: true + *
+ *

+ * If true, then "_type" properties will be added to beans if their type cannot be inferred through reflection. + * This is used to recreate the correct objects during parsing if the object types cannot be inferred. + * For example, when serializing a {@code Map} field, where the bean class cannot be determined from the value type. + *

+ * When present, this value overrides the {@link SerializerContext#SERIALIZER_addBeanTypeProperties} setting and is + * provided to customize the behavior of specific serializers in a {@link SerializerGroup}. + */ + public static final String UON_addBeanTypeProperties = "UonSerializer.addBeanTypeProperties"; + + + final boolean + encodeChars, + addBeanTypeProperties; + + /** + * Constructor. + *

+ * Typically only called from {@link PropertyStore#getContext(Class)}. + * + * @param ps The property store that created this context. + */ + public UonSerializerContext(PropertyStore ps) { + super(ps); + encodeChars = ps.getProperty(UON_encodeChars, boolean.class, false); + addBeanTypeProperties = ps.getProperty(UON_addBeanTypeProperties, boolean.class, ps.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, true)); + } + + @Override /* Context */ + public ObjectMap asMap() { + return super.asMap() + .append("UonSerializerContext", new ObjectMap() + .append("encodeChars", encodeChars) + .append("addBeanTypeProperties", addBeanTypeProperties) + ); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/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 new file mode 100644 index 0000000..92fbe56 --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonSerializerSession.java @@ -0,0 +1,88 @@ +// *************************************************************************************************************************** +// * 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.uon; + +import static org.apache.juneau.msgpack.MsgPackSerializerContext.*; +import static org.apache.juneau.uon.UonSerializerContext.*; + +import java.lang.reflect.*; +import java.util.*; + +import org.apache.juneau.*; +import org.apache.juneau.json.*; +import org.apache.juneau.serializer.*; + +/** + * Session object that lives for the duration of a single use of {@link UonSerializer}. + *

+ * This class is NOT thread safe. It is meant to be discarded after one-time use. + */ +public class UonSerializerSession extends SerializerSession { + + private final boolean + encodeChars, + addBeanTypeProperties; + + /** + * Create a new session using properties specified in the context. + * + * @param ctx The context creating this session object. + * The context contains all the configuration settings for this object. + * @param output The output object. See {@link JsonSerializerSession#getWriter()} for valid class types. + * @param op The override properties. + * These override any context properties defined in the context. + * @param javaMethod The java method that called this serializer, usually the method in a REST servlet. + * @param locale The session locale. + * If null, then the locale defined on the context is used. + * @param timeZone The session timezone. + * If null, then the timezone defined on the context is used. + * @param mediaType The session media type (e.g. "application/json"). + */ + protected UonSerializerSession(UonSerializerContext ctx, ObjectMap op, Object output, Method javaMethod, Locale locale, TimeZone timeZone, MediaType mediaType) { + super(ctx, op, output, javaMethod, locale, timeZone, mediaType); + if (op == null || op.isEmpty()) { + encodeChars = ctx.encodeChars; + addBeanTypeProperties = ctx.addBeanTypeProperties; + } else { + encodeChars = op.getBoolean(UON_encodeChars, ctx.encodeChars); + addBeanTypeProperties = op.getBoolean(MSGPACK_addBeanTypeProperties, ctx.addBeanTypeProperties); + } + } + + /** + * Returns the {@link UonSerializerContext#UON_encodeChars} setting value for this session. + * + * @return The {@link UonSerializerContext#UON_encodeChars} setting value for this session. + */ + public final boolean isEncodeChars() { + return encodeChars; + } + + /** + * Returns the {@link UonSerializerContext#UON_addBeanTypeProperties} setting value for this session. + * + * @return The {@link UonSerializerContext#UON_addBeanTypeProperties} setting value for this session. + */ + @Override /* SerializerSession */ + public final boolean isAddBeanTypeProperties() { + return addBeanTypeProperties; + } + + @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(), getRelativeUriBase(), getAbsolutePathUriBase()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/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 new file mode 100644 index 0000000..96f2405 --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonWriter.java @@ -0,0 +1,281 @@ +// *************************************************************************************************************************** +// * 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.uon; + +import java.io.*; + +import org.apache.juneau.internal.*; +import org.apache.juneau.serializer.*; + +/** + * Specialized writer for serializing UON-encoded text. + *

+ *

Notes:
+ *
    + *
  • This class is not intended for external use. + *
+ */ +public final class UonWriter extends SerializerWriter { + + private final UonSerializerSession session; + private final boolean encodeChars; + + // Characters that do not need to be URL-encoded in strings. + private static final AsciiSet unencodedChars = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;/?:@-_.!*'$(),~="); + + // Characters that do not need to be URL-encoded in attribute names. + // Identical to unencodedChars, but excludes '='. + private static final AsciiSet unencodedCharsAttrName = new AsciiSet("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;/?:@-_.!*'$(),~"); + + // Characters that need to be preceeded with an escape character. + private static final AsciiSet escapedChars = new AsciiSet("~'"); + + private static final AsciiSet needsQuoteChars = new AsciiSet("),=\n\t\r\b\f "); + + private static final AsciiSet maybeNeedsQuotesFirstChar = new AsciiSet("),=\n\t\r\b\f tfn+-.#0123456789"); + + private static char[] hexArray = "0123456789ABCDEF".toCharArray(); + + /** + * Constructor. + * + * @param session The session that created this writer. + * @param out The writer being wrapped. + * @param useWhitespace If true, tabs will be used in output. + * @param encodeChars If true, special characters should be encoded. + * @param trimStrings If true, strings should be trimmed before they're serialized. + * @param relativeUriBase The base (e.g. https://localhost:9443/contextPath") for relative URIs (e.g. "my/path"). + * @param absolutePathUriBase The base (e.g. https://localhost:9443") for relative URIs with absolute paths (e.g. "/contextPath/my/path"). + */ + protected UonWriter(UonSerializerSession session, Writer out, boolean useWhitespace, boolean encodeChars, boolean trimStrings, String relativeUriBase, String absolutePathUriBase) { + super(out, useWhitespace, trimStrings, '\'', relativeUriBase, absolutePathUriBase); + this.session = session; + this.encodeChars = encodeChars; + } + + /** + * Serializes the specified simple object as a UON string value. + * + * @param o The object being serialized. + * @param isTopAttrName If this is a top-level attribute name we're serializing. + * @return This object (for method chaining). + * @throws IOException Should never happen. + */ + public final UonWriter appendObject(Object o, boolean isTopAttrName) throws IOException { + + if (o instanceof Boolean) + return appendBoolean(o); + if (o instanceof Number) + return appendNumber(o); + if (o == null) + return append("null"); + + String s = session.toString(o); + char c0 = s.isEmpty() ? 0 : s.charAt(0); + + boolean needsQuotes = + s.isEmpty() + || c0 == '@' + || c0 == '(' + || needsQuoteChars.contains(s) + || ( + maybeNeedsQuotesFirstChar.contains(c0) + && ( + "true".equals(s) + || "false".equals(s) + || "null".equals(s) + || StringUtils.isNumeric(s) + ) + ) + ; + + AsciiSet unenc = (isTopAttrName ? unencodedCharsAttrName : unencodedChars); + AsciiSet esc = escapedChars; + + if (needsQuotes) + append('\''); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (esc.contains(c)) + append('~'); + if ((!encodeChars) || unenc.contains(c)) + append(c); + else { + if (c == ' ') + append('+'); + else { + int p = s.codePointAt(i); + if (p < 0x0080) + appendHex(p); + else if (p < 0x0800) { + int p1=p>>>6; + appendHex(p1+192).appendHex((p&63)+128); + } else if (p < 0x10000) { + int p1=p>>>6, p2=p1>>>6; + appendHex(p2+224).appendHex((p1&63)+128).appendHex((p&63)+128); + } else { + i++; // Two-byte codepoint...skip past surrogate pair lower byte. + int p1=p>>>6, p2=p1>>>6, p3=p2>>>6; + appendHex(p3+240).appendHex((p2&63)+128).appendHex((p1&63)+128).appendHex((p&63)+128); + } + } + } + } + if (needsQuotes) + append('\''); + + return this; + } + + /** + * Appends a boolean value to the output. + * + * @param o The boolean value to append to the output. + * @return This object (for method chaining). + * @throws IOException + */ + protected UonWriter appendBoolean(Object o) throws IOException { + append(o.toString()); + return this; + } + + /** + * Appends a numeric value to the output. + * + * @param o The numeric value to append to the output. + * @return This object (for method chaining). + * @throws IOException + */ + protected UonWriter appendNumber(Object o) throws IOException { + append(o.toString()); + return this; + } + + /** + * Prints out a two-byte %xx sequence for the given byte value. + */ + private UonWriter appendHex(int b) throws IOException { + if (b > 255) + throw new IOException("Invalid value passed to appendHex. Must be in the range 0-255. Value=" + b); + append('%').append(hexArray[b>>>4]).append(hexArray[b&0x0F]); + return this; + } + + /** + * Appends a URI to the output. + * + * @param uri The URI to append to the output. + * @return This object (for method chaining). + * @throws IOException + */ + @Override + public SerializerWriter appendUri(Object uri) throws IOException { + String s = uri.toString(); + if (s.indexOf("://") == -1) { + if (StringUtils.startsWith(s, '/')) { + if (absolutePathUriBase != null) + append(absolutePathUriBase); + } else { + if (relativeUriBase != null) { + append(relativeUriBase); + if (! relativeUriBase.equals("/")) + append("/"); + } + } + } + return appendObject(s, false); + } + + + //-------------------------------------------------------------------------------- + // Overridden methods + //-------------------------------------------------------------------------------- + + @Override /* SerializerWriter */ + public UonWriter cr(int depth) throws IOException { + super.cr(depth); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter appendln(int indent, String text) throws IOException { + super.appendln(indent, text); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter appendln(String text) throws IOException { + super.appendln(text); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter append(int indent, String text) throws IOException { + super.append(indent, text); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter append(int indent, char c) throws IOException { + super.append(indent, c); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter q() throws IOException { + super.q(); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter i(int indent) throws IOException { + super.i(indent); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter nl() throws IOException { + super.nl(); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter append(Object text) throws IOException { + super.append(text); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter append(String text) throws IOException { + super.append(text); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter appendIf(boolean b, String text) throws IOException { + super.appendIf(b, text); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter appendIf(boolean b, char c) throws IOException { + super.appendIf(b, c); + return this; + } + + @Override /* SerializerWriter */ + public UonWriter append(char c) throws IOException { + super.append(c); + return this; + } +} http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png new file mode 100644 index 0000000..04dcf41 Binary files /dev/null and b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/Example_HTML.png differ http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/95e832e1/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt ---------------------------------------------------------------------- diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt new file mode 100644 index 0000000..7880064 --- /dev/null +++ b/juneau-core/src/main/java/org/apache/juneau/uon/doc-files/rfc_uon.txt @@ -0,0 +1,294 @@ +Network Working Group J. Bognar +Request for Comments: 9999 +Category: Informational Salesforce + Feb 2017 + + ***DRAFT*** + URI Object Notation (UON): Generic Syntax + + +About this document + + This memo provides information for the Internet community. It does + not specify an Internet standard of any kind. Distribution of this + memo is unlimited. + +Copyright Notice + + 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. + +Abstract + + This document describes a grammar that builds upon RFC2396 + (Uniform Resource Identifiers). Its purpose is to define a + generalized object notation for URI query parameter values similar in + concept to Javascript Object Notation (RFC4627). The goal is a + syntax that allows for array and map structures to be + such that any data structure defined in JSON can be losslessly + defined in an equivalent URI-based grammar, yet be fully compliant + with the RFC2396 specification. + + This grammar provides the ability to construct the following data + structures in URL parameter values: + + OBJECT + ARRAY + NUMBER + BOOLEAN + STRING + NULL + + Example: + + The following shows a sample object defined in Javascript: + + var x = { + id: 1, + name: 'John Smith', + uri: 'http://sample/addressBook/person/1', + addressBookUri: 'http://sample/addressBook', + birthDate: '1946-08-12T00:00:00Z', + otherIds: null, + addresses: [ + { + uri: 'http://sample/addressBook/address/1', + personUri: 'http://sample/addressBook/person/1', + id: 1, + street: '100 Main Street', + city: 'Anywhereville', + state: 'NY', + zip: 12345, + isCurrent: true, + } + ] + } + + Using the syntax defined in this document, the equivalent + UON notation would be as follows: + + x=(id=1,name='John+Smith',uri=http://sample/ + addressBook/person/1,addressBookUri=http://sample/ + addressBook,birthDate=1946-08-12T00:00:00Z,otherIds=null, + addresses=@((uri=http://sample/addressBook/ + address/1,personUri=http://sample/addressBook/ + person/1,id=1,street='100+Main+Street',city= + Anywhereville,state=NY,zip=12345,isCurrent=true))) + +1. Language constraints + + The grammar syntax is constrained to usage of characters allowed by + URI notation: + + uric = reserved | unreserved | escaped + reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | + "$" | "," + unreserved = alphanum | mark + mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" + + In particular, the URI specification disallows the following + characters in unencoded form: + + unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`" + delims = "<" | ">" | "#" | "%" | <"> + + The exclusion of {} and [] characters eliminates the possibility of + using JSON as parameter values. + + +2. Grammar constructs + + The grammar consists of the following language constructs: + + Objects - Values consisting of one or more child name/value pairs. + Arrays - Values consisting of zero or more child values. + Booleans - Values consisting of true/false values. + Numbers - Decimal and floating point values. + Strings - Everything else. + +2.1. Objects + + Objects are values consisting of one or more child name/value pairs. + The (...) construct is used to define an object. + + Example: A simple map with two key/value pairs: + + a1=(b1=x1,b2=x2) + + Example: A nested map: + + a1=(b1=(c1=x1,c2=x2)) + +2.2. Arrays + + Arrays are values consisting of zero or more child values. + The @(...) construct is used to define an array. + + Example: An array of two string values: + + a1=@(x1,x2) + + Example: A 2-dimensional array: + + a1=@(@(x1,x2),@(x3,x4)) + + Example: An array of objects: + + a1=@((b1=x1,b2=x2),(c1=x1,c2=x2)) + +2.3. Booleans + + Booleans are values that can only take on values "true" or "false". + + Example: Two boolean values: + + a1=true&a2=false + +2.4. Numbers + + Numbers are represented without constructs. + Both decimal and float numbers are supported. + + Example: Two numerical values, one decimal and one float: + + a1=123&a2=1.23e1 + +2.5. Null values + + Nulls are represented by the keyword 'null': + + a1=null + +2.6. Strings + + Strings are encapsulated in single quote (') characters. + + Example: Simple string values: + + a1='foobar'&a2='123'&a3='true' + + The quotes are optional when the string cannot be confused + with one of the constructs listed above (i.e. objects/arrays/ + booleans/numbers/null). + + Example: A simple string value, unquoted: + + a1=foobar + + Strings must be quoted for the following cases: + + - The string can be confused with a boolean or number. + - The string is empty. + - The string contains one or more whitespace characters. + - The string starts with one of the following characters: + @ ( + - The string contains any of the following characters: + ) , = + + For example, the string literal "(b1=x)" should be + represented as follows: + + a1='(b1=x)' + + The tilde character (~) is used for escaping characters to prevent + them from being confused with syntax characters. + + The following characters must be escaped in string literals: + + ' ~ + + Example: The string "foo'bar~baz" + + a1='foo~'bar~~baz' + +2.7. Top-level attribute names + + Top-level attribute names (e.g. "a1" in "&a1=foobar") are treated + as strings but for one exception. The '=' character must be + encoded so as not to be confused as a key/value separator. + Note that the '=' character must also be escaped per the UON + notation. + + For example, the UON equivalent of {"a=b":"a=b"} constructed as + a top-level query parameter string would be as follows: + + a~%3Db=a~=b + + Note that the '=' character is encoded in the attribute name, + but it is not necessary to have it encoded in the attribute value. + +2.8. URL-encoded characters + + UON notation allows for any character, even UON grammar + characters, to be URL-encoded. + + The following query strings are fully equivalent in structure: + + a1=(b1='x1',b2='x2') + %61%31=%79%6f%75%20%61%72%65%20%61%20%6e%65%72%64%21 + + +3. BNF + + The following BNF describes the syntax for top-level URI query + parameter values (e.g. ?=). + + attrname = (string | null) + value = (var | string | null) + + string = ("'" litchar* "'") | litchar* + null = "null" + + var = ovar | avar | nvar | boolean | number + ovar = "(" [pairs] ")" + avar = "@(" [values] ")" + + pairs = pair ["," pairs] + pair = key "=" value + values = value ["," values] + key = (string | null) + boolean = "true" | "false" + + escape_seq = "~" escaped + encode_seq = "%" digithex digithex + + number = [-] (decimal | float) [exp] + decimal = "0" | (digit19 digit*) + float = decimal "." digit+ + exp = "e" [("+" | "-")] digit+ + + litchar = unencoded | encode_seq | escape_seq + escaped = "@" | "," | "(" | ")" | "~" | "=" + unencoded = alpha | digit | + ";" | "/" | "?" | ":" | "@" | + "-" | "_" | "." | "!" | "*" | "'" + alpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | + "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | + "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z" | + "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | + "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | + "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z" + digit = "0" | digit19 + digit19 = "1" | "2" | "3" | "4" | "5" | "6" | "7" | + "8" | "9" + digithex = digit | + "A" | "B" | "C" | "D" | "E" | "F" | + "a" | "b" | "c" | "d" | "e" | "f" + + + +