/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2016, 2017 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://oss.oracle.com/licenses/CDDL+GPL-1.1
* or LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package javax.json.bind;
import javax.json.bind.adapter.
JsonbAdapter;
import javax.json.bind.config.
PropertyNamingStrategy;
import javax.json.bind.config.
PropertyVisibilityStrategy;
import javax.json.bind.serializer.
JsonbDeserializer;
import javax.json.bind.serializer.
JsonbSerializer;
import java.lang.reflect.
Array;
import java.util.
Collections;
import java.util.
HashMap;
import java.util.
Locale;
import java.util.
Map;
import java.util.
Optional;
/**
* <p>
* <a name="supportedProps"></a>
* <b>Supported Properties</b><br>
* <blockquote>
* <p>
* All JSON Binding providers are required to support the following set of properties.
* Some providers may support additional properties.
* <dl>
* <dt><tt>jsonb.to.json.formatted</tt> - java.lang.Boolean
* <dd>Controls whether or not the {@link javax.json.bind.Jsonb Jsonb} {@code toJson()}
* methods will format the resulting JSON data with line breaks and indentation. A
* true value for this property indicates human readable indented
* data, while a false value indicates unformatted data.
* Default value is false (unformatted) if this property is not specified.
* </dl>
* <dl>
* <dt><tt>jsonb.to.json.encoding</tt> - java.lang.String
* <dd>The {@link javax.json.bind.Jsonb Jsonb} serialization {@code toJson()} methods
* will default to this property for encoding of output JSON data. Default
* value is 'UTF-8' if this property is not specified.
* </dl>
* <dl>
* <dt><tt>jsonb.from.json.encoding</tt> - java.lang.String
* <dd>The {@link javax.json.bind.Jsonb Jsonb} deserialization {@code fromJson()}
* methods will default to this property encoding of input JSON data if the
* encoding cannot be detected.
* </dl>
* </blockquote>
*
* This object is not thread safe. Implementations are expected to make a defensive copy
* of the object before applying the configuration.
*
* @since JSON Binding 1.0
*/
public class
JsonbConfig {
private final
Map<
String,
Object>
configuration = new
HashMap<>();
/**
* Property used to specify whether or not the serialized
* JSON data is formatted with line feeds and indentation.
*/
public static final
String FORMATTING = "jsonb.formatting";
/**
* The Jsonb serialization {@code toJson()} methods will default to this property
* for encoding of output JSON data. Default value is 'UTF-8'.
*
* The Jsonb deserialization {@code fromJson()} methods will default to this
* property encoding of input JSON data if the encoding cannot be detected
* automatically.
*/
public static final
String ENCODING = "jsonb.encoding";
/**
* Property used to specify custom naming strategy.
*/
public static final
String PROPERTY_NAMING_STRATEGY = "jsonb.property-naming-strategy";
/**
* Property used to specify custom order strategy.
*/
public static final
String PROPERTY_ORDER_STRATEGY = "jsonb.property-order-strategy";
/**
* Property used to specify null values serialization behavior.
*/
public static final
String NULL_VALUES = "jsonb.null-values";
/**
* Property used to specify strict I-JSON serialization compliance.
*/
public static final
String STRICT_IJSON = "jsonb.strict-ijson";
/**
* Property used to specify custom visibility strategy.
*/
public static final
String PROPERTY_VISIBILITY_STRATEGY = "jsonb.property-visibility-strategy";
/**
* Property used to specify custom mapping adapters for generic types.
*/
public static final
String ADAPTERS = "jsonb.adapters";
/**
* Property used to specify custom serializers.
*/
public static final
String SERIALIZERS = "jsonb.serializers";
/**
* Property used to specify custom deserializers.
*/
public static final
String DESERIALIZERS = "jsonb.derializers";
/**
* Property used to specify custom binary data strategy.
*/
public static final
String BINARY_DATA_STRATEGY = "jsonb.binary-data-strategy";
/**
* Property used to specify custom date format globally.
*/
public static final
String DATE_FORMAT = "jsonb.date-format";
/**
* Property used to specify locale globally.
*/
public static final
String LOCALE = "jsonb.locale";
/**
* Set the particular configuration property to a new value. The method can
* only be used to set one of the standard JSON Binding properties defined in
* this class or a provider specific property.
*
* @param name
* The name of the property to be set. This value can either
* be specified using one of the constant fields or a user supplied
* string.
* @param value
* The value of the property to be set
*
* @return This JsonbConfig instance.
*
* @throws NullPointerException if the name parameter is null.
*/
public final
JsonbConfig setProperty(final
String name, final
Object value) {
configuration.
put(
name,
value);
return this;
}
/**
* Return value of particular configuration property. The method can
* only be used to retrieve one of the standard JSON Binding properties defined
* in this class or a provider specific property. Attempting to get an undefined
* property will result in an empty Optional value.
* See <a href="#supportedProps"> Supported Properties</a>.
*
* @param name
* The name of the property to retrieve
*
* @return The value of the requested property
*
* @throws NullPointerException if the name parameter is null.
*/
public final
Optional<
Object>
getProperty(final
String name) {
return
Optional.
ofNullable(
configuration.
get(
name));
}
/**
* Return all configuration properties as an unmodifiable map.
*
* @return All configuration properties as an unmodifiable map
*/
public final
Map<
String,
Object>
getAsMap() {
return
Collections.
unmodifiableMap(
configuration);
}
/**
* Property used to specify whether or not the serialized JSON data is formatted
* with linefeeds and indentation.
*
* Configures value of {@code FORMATTING} property.
*
* @param formatted
* True means serialized data is formatted, false (default)
* means no formatting.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withFormatting(final
Boolean formatted) {
return
setProperty(
FORMATTING,
formatted);
}
/**
* Property used to specify whether null values should be serialized to JSON document or skipped.
*
* Configures value of {@code NULL_VALUES} property.
*
* @param serializeNullValues
* True means that null values will be serialized into JSON document,
* otherwise they will be effectively skipped.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withNullValues(final
Boolean serializeNullValues) {
return
setProperty(
NULL_VALUES,
serializeNullValues);
}
/**
* The binding operations will default to this property
* for encoding of JSON data. For input data (fromJson), selected encoding is used if
* the encoding cannot be detected automatically. Default value is 'UTF-8'.
*
* Configures value of {@code ENCODING} property.
*
* @param encoding
* Valid character encoding as defined in the
* <a href="http://tools.ietf.org/html/rfc7159">RFC 7159</a> and supported by
* Java Platform.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withEncoding(final
String encoding) {
return
setProperty(
ENCODING,
encoding);
}
/**
* Property used to specify whether strict I-JSON serialization compliance should be enforced.
*
* Configures value of {@code STRICT_IJSON} property.
*
* @param enabled
* True means data is serialized in strict compliance according to RFC 7493.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withStrictIJSON(final
Boolean enabled) {
return
setProperty(
STRICT_IJSON,
enabled);
}
/**
* Property used to specify custom naming strategy.
*
* Configures value of {@code JSONB_PROPERTY_NAMING_STRATEGY} property.
*
* @param propertyNamingStrategy
* Custom naming strategy which affects serialization and deserialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withPropertyNamingStrategy(final
PropertyNamingStrategy propertyNamingStrategy) {
return
setProperty(
PROPERTY_NAMING_STRATEGY,
propertyNamingStrategy);
}
/**
* Property used to specify custom naming strategy.
*
* Configures value of {@code JSONB_PROPERTY_NAMING_STRATEGY} property.
*
* @param propertyNamingStrategy
* Predefined naming strategy which affects serialization and deserialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withPropertyNamingStrategy(final
String propertyNamingStrategy) {
return
setProperty(
PROPERTY_NAMING_STRATEGY,
propertyNamingStrategy);
}
/**
* Property used to specify property order strategy.
*
* Configures values of {@code JSONB_PROPERTY_ORDER_STRATEGY} property.
*
* @param propertyOrderStrategy
* Predefined property order strategy which affects serialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withPropertyOrderStrategy(final
String propertyOrderStrategy) {
return
setProperty(
PROPERTY_ORDER_STRATEGY,
propertyOrderStrategy);
}
/**
* Property used to specify custom property visibility strategy.
*
* Configures value of {@code PROPERTY_VISIBILITY_STRATEGY} property.
*
* @param propertyVisibilityStrategy
* Custom property visibility strategy which affects serialization and deserialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withPropertyVisibilityStrategy(final
PropertyVisibilityStrategy
propertyVisibilityStrategy) {
return
setProperty(
PROPERTY_VISIBILITY_STRATEGY,
propertyVisibilityStrategy);
}
/**
* Property used to specify custom mapping adapters.
*
* Configures value of {@code ADAPTERS} property.
*
* Calling withAdapters more than once will merge the adapters with previous value.
*
* @param adapters
* Custom mapping adapters which affects serialization and deserialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withAdapters(final
JsonbAdapter...
adapters) {
mergeProperties(
ADAPTERS,
adapters,
JsonbAdapter.class);
return this;
}
/**
* Property used to specify custom serializers.
*
* Configures value of {@code SERIALIZERS} property.
*
* Calling withSerializers more than once will merge the serializers with previous value.
*
* @param serializers
* Custom serializers which affects serialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withSerializers(final
JsonbSerializer...
serializers) {
mergeProperties(
SERIALIZERS,
serializers,
JsonbSerializer.class);
return this;
}
/**
* Property used to specify custom deserializers.
*
* Configures value of {@code DESERIALIZERS} property.
*
* Calling withDeserializers more than once will merge the deserializers with previous value.
*
* @param deserializers
* Custom deserializers which affects deserialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withDeserializers(final
JsonbDeserializer...
deserializers) {
mergeProperties(
DESERIALIZERS,
deserializers,
JsonbDeserializer.class);
return this;
}
/**
* Property used to specify custom binary data strategy.
*
* Configures value of {@code BINARY_DATA_STRATEGY} property.
*
* @param binaryDataStrategy
* Custom binary data strategy which affects serialization and deserialization.
*
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withBinaryDataStrategy(final
String binaryDataStrategy) {
return
setProperty(
BINARY_DATA_STRATEGY,
binaryDataStrategy);
}
/**
* Property used to specify custom date format. This format will be used by default for all date classes
* serialization and deserialization.
*
* @param dateFormat
* Custom date format as specified in {@link java.time.format.DateTimeFormatter}.
* @param locale
* Locale, default is null.
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withDateFormat(final
String dateFormat, final
Locale locale) {
return
setProperty(
DATE_FORMAT,
dateFormat)
.
setProperty(
LOCALE,
locale != null ?
locale :
Locale.
getDefault());
}
/**
* Property used to specify custom locale.
*
* @param locale
* Locale, must not be null.
* @return This JsonbConfig instance.
*/
public final
JsonbConfig withLocale(final
Locale locale) {
return
setProperty(
LOCALE,
locale);
}
@
SuppressWarnings("unchecked")
private <T> void
mergeProperties(final
String propertyKey, final T[]
values, final
Class<T>
tClass) {
final
Optional<
Object>
property =
getProperty(
propertyKey);
if (!
property.
isPresent()) {
setProperty(
propertyKey,
values);
return;
}
T[]
storedValues = (T[])
property.
get();
T[]
newValues = (T[])
Array.
newInstance(
tClass,
storedValues.length +
values.length);
System.
arraycopy(
storedValues, 0,
newValues, 0,
storedValues.length);
System.
arraycopy(
values, 0,
newValues,
storedValues.length,
values.length);
setProperty(
propertyKey,
newValues);
}
}