You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2015/12/06 18:45:57 UTC
[1/3] incubator-johnzon git commit: JOHNZON-61 bases for jsonb,
still a lot of tests to add but allows to review more efficiently the
early draft
Repository: incubator-johnzon
Updated Branches:
refs/heads/master 6443633f7 -> b65d149a5
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/config/PropertyOrderStrategy.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/config/PropertyOrderStrategy.java b/jsonb-api/src/main/java/javax/json/bind/config/PropertyOrderStrategy.java
new file mode 100644
index 0000000..5db8c0e
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/config/PropertyOrderStrategy.java
@@ -0,0 +1,29 @@
+/*
+ * 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 javax.json.bind.config;
+
+public final class PropertyOrderStrategy {
+ private PropertyOrderStrategy() {
+ // no-op
+ }
+
+ public static final String LEXICOGRAPHICAL = "LEXICOGRAPHICAL";
+ public static final String ANY = "ANY";
+ public static final String REVERSE = "REVERSE";
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/config/PropertyVisibilityStrategy.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/config/PropertyVisibilityStrategy.java b/jsonb-api/src/main/java/javax/json/bind/config/PropertyVisibilityStrategy.java
new file mode 100644
index 0000000..14f915e
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/config/PropertyVisibilityStrategy.java
@@ -0,0 +1,27 @@
+/*
+ * 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 javax.json.bind.config;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public interface PropertyVisibilityStrategy {
+ boolean isVisible(Field field);
+ boolean isVisible(Method method);
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/spi/JsonbProvider.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/spi/JsonbProvider.java b/jsonb-api/src/main/java/javax/json/bind/spi/JsonbProvider.java
new file mode 100644
index 0000000..8c75a4b
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/spi/JsonbProvider.java
@@ -0,0 +1,59 @@
+/*
+ * 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 javax.json.bind.spi;
+
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbException;
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+public abstract class JsonbProvider {
+ private static final String DEFAULT_PROVIDER = "org.apache.johnzon.jsonb.JohnzonProvider";
+
+ public static JsonbProvider provider() {
+ final Iterator<JsonbProvider> it = ServiceLoader.load(JsonbProvider.class).iterator();
+ if (it.hasNext()) {
+ return it.next();
+ }
+
+ try {
+ return JsonbProvider.class.cast(Thread.currentThread().getContextClassLoader().loadClass(DEFAULT_PROVIDER).newInstance());
+ } catch (final ClassNotFoundException cnfe) {
+ throw new JsonbException(DEFAULT_PROVIDER + " not found", cnfe);
+ } catch (final Exception x) {
+ throw new JsonbException(DEFAULT_PROVIDER + " couldn't be instantiated: " + x, x);
+ }
+ }
+
+ public static JsonbProvider provider(final String providerFqn) {
+ if (providerFqn == null) {
+ throw new IllegalArgumentException();
+ }
+ for (final JsonbProvider provider : ServiceLoader.load(JsonbProvider.class)) {
+ if (providerFqn.equals(provider.getClass().getName())) {
+ return provider;
+ }
+ }
+
+ final String msg = providerFqn + " not found";
+ throw new JsonbException(msg, new ClassNotFoundException(msg));
+ }
+
+ public abstract JsonbBuilder create();
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 5cb8afd..2355ab0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -47,6 +47,7 @@
<staging.directory>${project.build.directory}/site</staging.directory>
<felix.plugin.version>2.5.3</felix.plugin.version>
<bnd.version.policy>[$(version;==;$(@)),$(version;+;$(@)))</bnd.version.policy>
+ <java-compile.version>1.6</java-compile.version>
</properties>
<modules>
@@ -79,8 +80,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>1.6</source>
- <target>1.6</target>
+ <source>${java-compile.version}</source>
+ <target>${java-compile.version}</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
<showWarnings>true</showWarnings>
@@ -102,7 +103,7 @@
<exclude>*.iws</exclude>
<exclude>*.iml</exclude>
<exclude>*.ipr</exclude>
- <exclude>**/META-INF/services/javax.json.spi.JsonProvider</exclude>
+ <exclude>**/META-INF/services/javax.*</exclude>
<exclude>**/*.json</exclude>
<exclude>**/*.yml</exclude>
<exclude>**/bench/*.txt</exclude>
@@ -159,7 +160,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
- <version>2.13</version>
+ <version>2.17</version>
<executions>
<execution>
<id>verify-style</id>
@@ -302,7 +303,7 @@
<localCheckout>true</localCheckout>
<autoVersionSubmodules>true</autoVersionSubmodules>
</configuration>
- </plugin>
+ </plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
@@ -351,7 +352,7 @@
<version>[3.1,)</version>
</requireMavenVersion>
<requireJavaVersion>
- <version>[1.6,)</version>
+ <version>[${java-compile.version},)</version>
</requireJavaVersion>
</rules>
</configuration>
@@ -372,7 +373,7 @@
<url>${pubsub.url}</url>
</site>
</distributionManagement>
-
+
<scm>
<connection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-johnzon.git</connection>
<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-johnzon.git</developerConnection>
@@ -550,7 +551,7 @@
</otherArchives>
</mailingList>
</mailingLists>
-
+
<ciManagement>
<system>jenkins</system>
<url>https://builds.apache.org/job/johnzon/</url>
@@ -647,5 +648,16 @@
<module>johnzon-websocket</module>
</modules>
</profile>
+ <profile>
+ <!-- jsonb module needs java 1.8 or higher -->
+ <id>jdk1.8+</id>
+ <activation>
+ <jdk>[1.8,)</jdk>
+ </activation>
+ <modules>
+ <module>jsonb-api</module>
+ <module>johnzon-jsonb</module>
+ </modules>
+ </profile>
</profiles>
</project>
[2/3] incubator-johnzon git commit: JOHNZON-61 bases for jsonb,
still a lot of tests to add but allows to review more efficiently the
early draft
Posted by rm...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactoryTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactoryTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactoryTest.java
new file mode 100644
index 0000000..d9d14ed
--- /dev/null
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactoryTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+import javax.json.bind.config.PropertyNamingStrategy;
+
+import static org.junit.Assert.assertEquals;
+
+@RunWith(Theories.class)
+public class PropertyNamingStrategyFactoryTest {
+ @DataPoints()
+ public static String[][] points() {
+ return new String[][] {
+ new String[] { PropertyNamingStrategy.IDENTITY, "a", "a" },
+ new String[] { PropertyNamingStrategy.IDENTITY, "aBEOCBDJ4397dkabqWLCd", "aBEOCBDJ4397dkabqWLCd" },
+ new String[] { PropertyNamingStrategy.CASE_INSENSITIVE, "aBEOCBDJ4397dkabqWLCd", "aBEOCBDJ4397dkabqWLCd" }, // not really testable there
+ new String[] { PropertyNamingStrategy.LOWER_CASE_WITH_DASHES, "lower-dash", "lower-dash" },
+ new String[] { PropertyNamingStrategy.LOWER_CASE_WITH_DASHES, "lower_dash", "lower_dash" },
+ new String[] { PropertyNamingStrategy.LOWER_CASE_WITH_DASHES, "lowerDash", "lower-dash" },
+ new String[] { PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES, "lower_under", "lower_under" },
+ new String[] { PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES, "lowerUnder", "lower_under" },
+ new String[] { PropertyNamingStrategy.UPPER_CAMEL_CASE, "fooBar", "FooBar" },
+ new String[] { PropertyNamingStrategy.UPPER_CAMEL_CASE_WITH_SPACES, "fooBar", "Foo Bar" },
+ };
+ }
+
+ @Theory
+ public void valid(final String[] config) {
+ assertEquals(config[2], new PropertyNamingStrategyFactory(config[0]).create().translateName(config[1]));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
index 8d94bf9..20ac31f 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java
@@ -81,25 +81,25 @@ public class Mapper {
protected final boolean skipNull;
protected final boolean skipEmptyArray;
protected final boolean treatByteArrayAsBase64;
+ protected final boolean treatByteArrayAsBase64URL;
protected final Charset encoding;
// CHECKSTYLE:OFF
public Mapper(final JsonReaderFactory readerFactory, final JsonGeneratorFactory generatorFactory,
final boolean doClose, final Map<Type, Converter<?>> converters,
final int version, final Comparator<String> attributeOrder, final boolean skipNull, final boolean skipEmptyArray,
- final AccessMode accessMode, final boolean hiddenConstructorSupported, final boolean useConstructors,
- final boolean treatByteArrayAsBase64,
- final Charset encoding) {
+ final AccessMode accessMode, final boolean treatByteArrayAsBase64, final boolean treatByteArrayAsBase64URL, final Charset encoding) {
// CHECKSTYLE:ON
this.readerFactory = readerFactory;
this.generatorFactory = generatorFactory;
this.close = doClose;
this.converters = new ConcurrentHashMap<Type, Converter<?>>(converters);
this.version = version;
- this.mappings = new Mappings(attributeOrder, accessMode, hiddenConstructorSupported, useConstructors, version, this.converters);
+ this.mappings = new Mappings(attributeOrder, accessMode, version, this.converters);
this.skipNull = skipNull;
this.skipEmptyArray = skipEmptyArray;
this.treatByteArrayAsBase64 = treatByteArrayAsBase64;
+ this.treatByteArrayAsBase64URL = treatByteArrayAsBase64URL;
this.encoding = encoding;
}
@@ -370,7 +370,7 @@ public class Mapper {
}
if (value == null) {
- if (skipNull) {
+ if (skipNull && !getter.reader.isNillable()) {
continue;
} else {
gen.writeNull(getterEntry.getKey());
@@ -434,6 +434,9 @@ public class Mapper {
generator.write(key, base64EncodedByteArray);
return generator;
}
+ if(treatByteArrayAsBase64URL && (type == byte[].class /*|| type == Byte[].class*/)) {
+ return generator.write(key, Converter.class.cast(converters.get(byte[].class)).toString(value));
+ }
JsonGenerator gen = generator.writeStartArray(key);
for (int i = 0; i < length; i++) {
@@ -619,12 +622,8 @@ public class Mapper {
throw new MapperException("Can't map " + type);
}
- if (classMapping.constructor == null) {
- throw new IllegalArgumentException(classMapping.clazz.getName() + " can't be instantiated by Johnzon, this is a write only class");
- }
-
- final Object t = !classMapping.constructorHasArguments ?
- classMapping.constructor.newInstance() : classMapping.constructor.newInstance(createParameters(classMapping, object));
+ final Object t = classMapping.factory.getParameterTypes().length == 0 ?
+ classMapping.factory.create(null) : classMapping.factory.create(createParameters(classMapping, object));
for (final Map.Entry<String, Mappings.Setter> setter : classMapping.setters.entrySet()) {
final JsonValue jsonValue = object.get(setter.getKey());
if (jsonValue == null) {
@@ -650,11 +649,12 @@ public class Mapper {
}
private Object[] createParameters(final Mappings.ClassMapping mapping, final JsonObject object) throws Exception {
- final Object[] objects = new Object[mapping.constructorParameters.length];
- for (int i = 0; i < mapping.constructorParameters.length; i++) {
+ final int length = mapping.factory.getParameterTypes().length;
+ final Object[] objects = new Object[length];
+ for (int i = 0; i < length; i++) {
objects[i] = toValue(
- object.get(mapping.constructorParameters[i]), mapping.constructorParameterConverters[i],
- mapping.constructorItemParameterConverters[i], mapping.constructorParameterTypes[i]);
+ object.get(mapping.factory.getParameterNames()[i]), mapping.factory.getParameterConverter()[i],
+ mapping.factory.getParameterItemConverter()[i], mapping.factory.getParameterTypes()[i]);
}
return objects;
}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index cee2841..8f4f1db 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -92,11 +92,14 @@ public class MapperBuilder {
private boolean skipEmptyArray = false;
private boolean supportsComments = false;
protected boolean pretty;
- private AccessMode accessMode = new MethodAccessMode(false);
+ private AccessMode accessMode;
private boolean treatByteArrayAsBase64;
+ private boolean treatByteArrayAsBase64URL;
private final Map<Type, Converter<?>> converters = new HashMap<Type, Converter<?>>(DEFAULT_CONVERTERS);
private boolean supportConstructors;
private Charset encoding = Charset.forName(System.getProperty("johnzon.mapper.encoding", "UTF-8"));
+ private boolean useGetterForCollections;
+ private String accessModeName;
public Mapper build() {
if (readerFactory == null || generatorFactory == null) {
@@ -128,6 +131,20 @@ public class MapperBuilder {
}
}
+ if (accessMode == null) {
+ if ("field".equalsIgnoreCase(accessModeName)) {
+ this.accessMode = new FieldAccessMode(supportConstructors, supportHiddenAccess);
+ } else if ("method".equalsIgnoreCase(accessModeName)) {
+ this.accessMode = new MethodAccessMode(supportConstructors, supportHiddenAccess, true);
+ } else if ("strict-method".equalsIgnoreCase(accessModeName)) {
+ this.accessMode = new MethodAccessMode(supportConstructors, supportHiddenAccess, false);
+ } else if ("both".equalsIgnoreCase(accessModeName)) {
+ this.accessMode = new FieldAndMethodAccessMode(supportConstructors, supportHiddenAccess);
+ } else {
+ this.accessMode = new MethodAccessMode(supportConstructors, supportHiddenAccess, useGetterForCollections);
+ }
+ }
+
return new Mapper(
readerFactory, generatorFactory,
doCloseOnStreams,
@@ -136,9 +153,7 @@ public class MapperBuilder {
attributeOrder,
skipNull, skipEmptyArray,
accessMode,
- supportHiddenAccess,
- supportConstructors,
- treatByteArrayAsBase64,
+ treatByteArrayAsBase64, treatByteArrayAsBase64URL,
encoding);
}
@@ -156,7 +171,7 @@ public class MapperBuilder {
}
public MapperBuilder setSupportGetterForCollections(final boolean useGetterForCollections) {
- accessMode = new MethodAccessMode(useGetterForCollections);
+ this.useGetterForCollections = useGetterForCollections;
return this;
}
@@ -191,17 +206,11 @@ public class MapperBuilder {
}
public MapperBuilder setAccessModeName(final String mode) {
- if ("field".equalsIgnoreCase(mode)) {
- this.accessMode = new FieldAccessMode();
- } else if ("method".equalsIgnoreCase(mode)) {
- this.accessMode = new MethodAccessMode(true);
- } else if ("strict-method".equalsIgnoreCase(mode)) {
- this.accessMode = new MethodAccessMode(false);
- } else if ("both".equalsIgnoreCase(mode)) {
- this.accessMode = new FieldAndMethodAccessMode();
- } else {
+ if (!"field".equalsIgnoreCase(mode) && !"method".equalsIgnoreCase(mode) &&
+ !"strict-method".equalsIgnoreCase(mode) && !"both".equalsIgnoreCase(mode)) {
throw new IllegalArgumentException("Mode " + mode + " unsupported");
}
+ this.accessModeName = mode;
return this;
}
@@ -261,6 +270,11 @@ public class MapperBuilder {
return this;
}
+ public MapperBuilder setTreatByteArrayAsBase64URL(final boolean treatByteArrayAsBase64URL) {
+ this.treatByteArrayAsBase64URL = treatByteArrayAsBase64URL;
+ return this;
+ }
+
public MapperBuilder setSupportConstructors(final boolean supportConstructors) {
this.supportConstructors = supportConstructors;
return this;
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
index 37b675b..038c9a9 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java
@@ -18,6 +18,8 @@
*/
package org.apache.johnzon.mapper.access;
+import org.apache.johnzon.mapper.Converter;
+
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Map;
@@ -26,6 +28,8 @@ public interface AccessMode {
interface DecoratedType {
Type getType();
<T extends Annotation> T getAnnotation(Class<T> clazz);
+ Converter<?> findConverter();
+ boolean isNillable();
}
interface Writer extends DecoratedType {
@@ -36,6 +40,15 @@ public interface AccessMode {
Object read(Object instance);
}
+ interface Factory {
+ Object create(Object[] params);
+ Type[] getParameterTypes();
+ String[] getParameterNames();
+ Converter<?>[] getParameterConverter();
+ Converter<?>[] getParameterItemConverter();
+ }
+
+ Factory findFactory(Class<?> clazz);
Map<String, Reader> findReaders(Class<?> clazz);
Map<String, Writer> findWriters(Class<?> clazz);
}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
index 2260881..94642bf 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java
@@ -18,9 +18,16 @@
*/
package org.apache.johnzon.mapper.access;
+import org.apache.johnzon.mapper.Converter;
+import org.apache.johnzon.mapper.JohnzonConverter;
import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType;
+import java.beans.ConstructorProperties;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@@ -29,12 +36,21 @@ import java.util.HashMap;
import java.util.Map;
import static java.util.Arrays.asList;
+import static org.apache.johnzon.mapper.reflection.Converters.matches;
// handle some specific types
public abstract class BaseAccessMode implements AccessMode {
+ private static final Type[] NO_PARAMS = new Type[0];
+
private final Map<Class<?>, String[]> fieldsToRemove = new HashMap<Class<?>, String[]>();
+ private final boolean acceptHiddenConstructor;
+ private final boolean useConstructor;
+
+ protected BaseAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor) {
+ this.useConstructor = useConstructor;
+ this.acceptHiddenConstructor = acceptHiddenConstructor;
- public BaseAccessMode() { // mainly built it in the JVM types == user cant handle them
+ // mainly built it in the JVM types == user cant handle them
fieldsToRemove.put(Throwable.class, new String[]{"suppressedExceptions", "cause"});
}
@@ -56,6 +72,113 @@ public abstract class BaseAccessMode implements AccessMode {
return fieldsToRemove;
}
+ @Override
+ public Factory findFactory(final Class<?> clazz) {
+ Constructor<?> constructor = null;
+ for (final Constructor<?> c : clazz.getDeclaredConstructors()) {
+ if (c.getParameterTypes().length == 0) {
+ if (!Modifier.isPublic(c.getModifiers()) && acceptHiddenConstructor) {
+ c.setAccessible(true);
+ }
+ constructor = c;
+ if (!useConstructor) {
+ break;
+ }
+ } else if (c.getAnnotation(ConstructorProperties.class) != null) {
+ constructor = c;
+ break;
+ }
+ }
+ if (constructor == null) {
+ try {
+ constructor = clazz.getConstructor();
+ } catch (final NoSuchMethodException e) {
+ return null; // readOnly class
+ }
+ }
+
+ final boolean constructorHasArguments = constructor != null && constructor.getGenericParameterTypes().length > 0;
+ final Type[] factoryParameterTypes;
+ final String[] constructorParameters;
+ final Converter<?>[] constructorParameterConverters;
+ final Converter<?>[] constructorItemParameterConverters;
+ if (constructorHasArguments) {
+ factoryParameterTypes = constructor.getGenericParameterTypes();
+
+ constructorParameters = new String[constructor.getGenericParameterTypes().length];
+ final ConstructorProperties constructorProperties = constructor.getAnnotation(ConstructorProperties.class);
+ System.arraycopy(constructorProperties.value(), 0, constructorParameters, 0, constructorParameters.length);
+
+ constructorParameterConverters = new Converter<?>[constructor.getGenericParameterTypes().length];
+ constructorItemParameterConverters = new Converter<?>[constructorParameterConverters.length];
+ for (int i = 0; i < constructorParameters.length; i++) {
+ for (final Annotation a : constructor.getParameterAnnotations()[i]) {
+ if (a.annotationType() == JohnzonConverter.class) {
+ try {
+ final Converter<?> converter = JohnzonConverter.class.cast(a).value().newInstance();
+ if (matches(constructor.getParameterTypes()[i], converter)) {
+ constructorParameterConverters[i] = converter;
+ constructorItemParameterConverters[i] = null;
+ } else {
+ constructorParameterConverters[i] = null;
+ constructorItemParameterConverters[i] = converter;
+ }
+ } catch (final Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ }
+ }
+ } else {
+ factoryParameterTypes = NO_PARAMS;
+ constructorParameters = null;
+ constructorParameterConverters = null;
+ constructorItemParameterConverters = null;
+ }
+
+ final Constructor<?> cons = constructor;
+ if (cons != null && !cons.isAccessible()) {
+ cons.setAccessible(true);
+ }
+ return new Factory() {
+ @Override
+ public Object create(final Object[] params) {
+ if (cons == null) {
+ throw new IllegalArgumentException(clazz.getName() + " can't be instantiated by Johnzon, this is a write only class");
+ }
+ try {
+ return params == null ? cons.newInstance() : cons.newInstance(params);
+ } catch (final InstantiationException e) {
+ throw new IllegalStateException(e);
+ } catch (final IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ } catch (final InvocationTargetException e) {
+ throw new IllegalStateException(e.getCause());
+ }
+ }
+
+ @Override
+ public Type[] getParameterTypes() {
+ return factoryParameterTypes;
+ }
+
+ @Override
+ public String[] getParameterNames() {
+ return constructorParameters;
+ }
+
+ @Override
+ public Converter<?>[] getParameterConverter() {
+ return constructorParameterConverters;
+ }
+
+ @Override
+ public Converter<?>[] getParameterItemConverter() {
+ return constructorItemParameterConverters;
+ }
+ };
+ }
+
private <T> Map<String, T> sanitize(final Class<?> type, final Map<String, T> delegate) {
for (final Map.Entry<Class<?>, String[]> entry : fieldsToRemove.entrySet()) {
if (entry.getKey().isAssignableFrom(type)) {
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
index 3f1b54c..70c456a 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java
@@ -18,6 +18,7 @@
*/
package org.apache.johnzon.mapper.access;
+import org.apache.johnzon.mapper.Converter;
import org.apache.johnzon.mapper.JohnzonProperty;
import org.apache.johnzon.mapper.MapperException;
@@ -29,6 +30,10 @@ import java.util.HashMap;
import java.util.Map;
public class FieldAccessMode extends BaseAccessMode {
+ public FieldAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor) {
+ super(useConstructor, acceptHiddenConstructor);
+ }
+
@Override
public Map<String, Reader> doFindReaders(final Class<?> clazz) {
final Map<String, Reader> readers = new HashMap<String, Reader>();
@@ -68,7 +73,7 @@ public class FieldAccessMode extends BaseAccessMode {
return key.contains("$");
}
- private Map<String, Field> fields(final Class<?> clazz) {
+ protected Map<String, Field> fields(final Class<?> clazz) {
final Map<String, Field> fields = new HashMap<String, Field>();
Class<?> current = clazz;
while (current != null && current != Object.class) {
@@ -87,7 +92,7 @@ public class FieldAccessMode extends BaseAccessMode {
return fields;
}
- protected static abstract class FieldDecoratedType implements DecoratedType {
+ public static abstract class FieldDecoratedType implements DecoratedType {
protected final Field field;
protected final Type type;
@@ -100,6 +105,15 @@ public class FieldAccessMode extends BaseAccessMode {
}
@Override
+ public Converter<?> findConverter() {
+ return null;
+ }
+
+ public Field getField() {
+ return field;
+ }
+
+ @Override
public Type getType() {
return type;
}
@@ -108,6 +122,11 @@ public class FieldAccessMode extends BaseAccessMode {
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
return field.getAnnotation(clazz);
}
+
+ @Override
+ public boolean isNillable() {
+ return false;
+ }
}
public static class FieldWriter extends FieldDecoratedType implements Writer {
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
index 0c3a2da..1a27c52 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java
@@ -18,6 +18,8 @@
*/
package org.apache.johnzon.mapper.access;
+import org.apache.johnzon.mapper.Converter;
+
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.HashMap;
@@ -25,8 +27,14 @@ import java.util.Map;
// methods override fields
public class FieldAndMethodAccessMode extends BaseAccessMode {
- private final FieldAccessMode fields = new FieldAccessMode();
- private final MethodAccessMode methods = new MethodAccessMode(false);
+ private final FieldAccessMode fields;
+ private final MethodAccessMode methods;
+
+ public FieldAndMethodAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor) {
+ super(useConstructor, acceptHiddenConstructor);
+ this.fields = new FieldAccessMode(useConstructor, acceptHiddenConstructor);
+ this.methods = new MethodAccessMode(useConstructor, acceptHiddenConstructor, false);
+ }
@Override
public Map<String, Reader> doFindReaders(final Class<?> clazz) {
@@ -56,7 +64,7 @@ public class FieldAndMethodAccessMode extends BaseAccessMode {
return writers;
}
- private static abstract class CompositeDecoratedType implements DecoratedType {
+ public static abstract class CompositeDecoratedType implements DecoratedType {
protected final DecoratedType type1;
private final DecoratedType type2;
@@ -66,6 +74,12 @@ public class FieldAndMethodAccessMode extends BaseAccessMode {
}
@Override
+ public Converter<?> findConverter() {
+ final Converter<?> converter = type1.findConverter();
+ return converter != null ? converter : type2.findConverter();
+ }
+
+ @Override
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
final T found = type1.getAnnotation(clazz);
return found == null ? type2.getAnnotation(clazz) : found;
@@ -75,9 +89,22 @@ public class FieldAndMethodAccessMode extends BaseAccessMode {
public Type getType() {
return type1.getType();
}
+
+ @Override
+ public boolean isNillable() {
+ return type1.isNillable() || type2.isNillable();
+ }
+
+ public DecoratedType getType1() {
+ return type1;
+ }
+
+ public DecoratedType getType2() {
+ return type2;
+ }
}
- private static final class CompositeReader extends CompositeDecoratedType implements Reader {
+ public static final class CompositeReader extends CompositeDecoratedType implements Reader {
private final Reader reader;
private CompositeReader(final Reader type1, final DecoratedType type2) {
@@ -91,7 +118,7 @@ public class FieldAndMethodAccessMode extends BaseAccessMode {
}
}
- private static final class CompositeWriter extends CompositeDecoratedType implements Writer {
+ public static final class CompositeWriter extends CompositeDecoratedType implements Writer {
private final Writer writer;
private CompositeWriter(final Writer type1, final DecoratedType type2) {
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
index 69f1af5..df17a56 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java
@@ -18,6 +18,7 @@
*/
package org.apache.johnzon.mapper.access;
+import org.apache.johnzon.mapper.Converter;
import org.apache.johnzon.mapper.JohnzonProperty;
import org.apache.johnzon.mapper.MapperException;
@@ -34,7 +35,8 @@ import java.util.Map;
public class MethodAccessMode extends BaseAccessMode {
private final boolean supportGetterAsWritter;
- public MethodAccessMode(final boolean supportGetterAsWritter) {
+ public MethodAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor, final boolean supportGetterAsWritter) {
+ super(useConstructor, acceptHiddenConstructor);
this.supportGetterAsWritter = supportGetterAsWritter;
}
@@ -94,7 +96,7 @@ public class MethodAccessMode extends BaseAccessMode {
return propertyDescriptors;
}
- protected static abstract class MethodDecoratedType implements DecoratedType {
+ public static abstract class MethodDecoratedType implements DecoratedType {
protected final Method method;
protected final Type type;
@@ -107,6 +109,15 @@ public class MethodAccessMode extends BaseAccessMode {
}
@Override
+ public Converter<?> findConverter() {
+ return null;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ @Override
public Type getType() {
return type;
}
@@ -115,6 +126,11 @@ public class MethodAccessMode extends BaseAccessMode {
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
return method.getAnnotation(clazz);
}
+
+ @Override
+ public boolean isNillable() {
+ return false;
+ }
}
public static class MethodWriter extends MethodDecoratedType implements Writer {
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Converters.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Converters.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Converters.java
new file mode 100644
index 0000000..bfdbaa6
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Converters.java
@@ -0,0 +1,78 @@
+/*
+ * 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.johnzon.mapper.reflection;
+
+import org.apache.johnzon.mapper.Converter;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Map;
+
+public class Converters {
+ private Converters() {
+ // no-op
+ }
+
+ // TODO: more ParameterizedType and maybe TypeClosure support
+ public static boolean matches(final Type type, final Converter<?> converter) {
+ Type convertType = null;
+ if (Converter.TypeAccess.class.isInstance(converter)) {
+ convertType = Converter.TypeAccess.class.cast(converter).type();
+ } else {
+ for (final Type pt : converter.getClass().getGenericInterfaces()) {
+ if (ParameterizedType.class.isInstance(pt) && ParameterizedType.class.cast(pt).getRawType() == Converter.class) {
+ convertType = ParameterizedType.class.cast(pt).getActualTypeArguments()[0];
+ break;
+ }
+ }
+ }
+
+ if (convertType == null) { // compatibility, previously nested converter were not supported
+ return true;
+ }
+
+ if (ParameterizedType.class.isInstance(type)) {
+ final ParameterizedType parameterizedType = ParameterizedType.class.cast(type);
+ final Type rawType = parameterizedType.getRawType();
+ if (Class.class.isInstance(rawType)) {
+ final Class<?> clazz = Class.class.cast(rawType);
+ if (Collection.class.isAssignableFrom(clazz) && parameterizedType.getActualTypeArguments().length == 1) {
+ final Type argType = parameterizedType.getActualTypeArguments()[0];
+ if (Class.class.isInstance(argType) && Class.class.isInstance(convertType)) {
+ return !Class.class.cast(convertType).isAssignableFrom(Class.class.cast(argType));
+ }
+ } else if (Map.class.isAssignableFrom(clazz) && parameterizedType.getActualTypeArguments().length == 2) {
+ final Type argType = parameterizedType.getActualTypeArguments()[1];
+ if (Class.class.isInstance(argType) && Class.class.isInstance(convertType)) {
+ return !Class.class.cast(convertType).isAssignableFrom(Class.class.cast(argType));
+ }
+ }
+ return true; // actually here we suppose we dont know
+ }
+ }
+ if (Class.class.isInstance(type)) {
+ final Class<?> clazz = Class.class.cast(type);
+ if (clazz.isArray()) {
+ return !Class.class.cast(convertType).isAssignableFrom(clazz.getComponentType());
+ }
+ }
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
index b75823c..49c5d88 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Mappings.java
@@ -27,11 +27,8 @@ import org.apache.johnzon.mapper.access.AccessMode;
import org.apache.johnzon.mapper.converter.DateWithCopyConverter;
import org.apache.johnzon.mapper.converter.EnumConverter;
-import java.beans.ConstructorProperties;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@@ -53,88 +50,22 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static java.util.Arrays.asList;
+import static org.apache.johnzon.mapper.reflection.Converters.matches;
public class Mappings {
public static class ClassMapping {
public final Class<?> clazz;
+ public final AccessMode.Factory factory;
public final Map<String, Getter> getters;
public final Map<String, Setter> setters;
- public final Constructor<?> constructor;
- public final boolean constructorHasArguments;
- public final String[] constructorParameters;
- public final Converter<?>[] constructorParameterConverters;
- public final Converter<?>[] constructorItemParameterConverters;
- public final Type[] constructorParameterTypes;
-
- protected ClassMapping(final Class<?> clazz,
- final Map<String, Getter> getters, final Map<String, Setter> setters,
- final boolean acceptHiddenConstructor, final boolean useConstructor) {
+
+
+ protected ClassMapping(final Class<?> clazz, final AccessMode.Factory factory,
+ final Map<String, Getter> getters, final Map<String, Setter> setters) {
this.clazz = clazz;
+ this.factory = factory;
this.getters = getters;
this.setters = setters;
- this.constructor = findConstructor(acceptHiddenConstructor, useConstructor);
-
- this.constructorHasArguments = this.constructor != null && this.constructor.getGenericParameterTypes().length > 0;
- if (this.constructorHasArguments) {
- this.constructorParameterTypes = this.constructor.getGenericParameterTypes();
-
- // TODO: java 8 gives access to it without annotation
- this.constructorParameters = new String[this.constructor.getGenericParameterTypes().length];
- final ConstructorProperties constructorProperties = this.constructor.getAnnotation(ConstructorProperties.class);
- System.arraycopy(constructorProperties.value(), 0, this.constructorParameters, 0, this.constructorParameters.length);
-
- this.constructorParameterConverters = new Converter<?>[this.constructor.getGenericParameterTypes().length];
- this.constructorItemParameterConverters = new Converter<?>[this.constructorParameterConverters.length];
- for (int i = 0; i < this.constructorParameters.length; i++) {
- for (final Annotation a : this.constructor.getParameterAnnotations()[i]) {
- if (a.annotationType() == JohnzonConverter.class) {
- try {
- final Converter<?> converter = JohnzonConverter.class.cast(a).value().newInstance();
- if (matches(this.constructor.getParameterTypes()[i], converter)) {
- this.constructorParameterConverters[i] = converter;
- this.constructorItemParameterConverters[i] = null;
- } else {
- this.constructorParameterConverters[i] = null;
- this.constructorItemParameterConverters[i] = converter;
- }
- } catch (final Exception e) {
- throw new IllegalArgumentException(e);
- }
- }
- }
- }
- } else {
- this.constructorParameterTypes = null;
- this.constructorParameters = null;
- this.constructorParameterConverters = null;
- this.constructorItemParameterConverters = null;
- }
- }
-
- private Constructor<?> findConstructor(final boolean acceptHiddenConstructor, final boolean useConstructor) {
- Constructor<?> found = null;
- for (final Constructor<?> c : clazz.getDeclaredConstructors()) {
- if (c.getParameterTypes().length == 0) {
- if (!Modifier.isPublic(c.getModifiers()) && acceptHiddenConstructor) {
- c.setAccessible(true);
- }
- found = c;
- if (!useConstructor) {
- break;
- }
- } else if (c.getAnnotation(ConstructorProperties.class) != null) {
- found = c;
- break;
- }
- }
- if (found != null) {
- return found;
- }
- try {
- return clazz.getConstructor();
- } catch (final NoSuchMethodException e) {
- return null; // readOnly class
- }
}
}
@@ -241,70 +172,19 @@ public class Mappings {
}
}
- // TODO: more ParameterizedType and maybe TypeClosure support
- private static boolean matches(final Type type, final Converter<?> converter) {
- Type convertType = null;
- if (Converter.TypeAccess.class.isInstance(converter)) {
- convertType = Converter.TypeAccess.class.cast(converter).type();
- } else {
- for (final Type pt : converter.getClass().getGenericInterfaces()) {
- if (ParameterizedType.class.isInstance(pt) && ParameterizedType.class.cast(pt).getRawType() == Converter.class) {
- convertType = ParameterizedType.class.cast(pt).getActualTypeArguments()[0];
- break;
- }
- }
- }
-
- if (convertType == null) { // compatibility, previously nested converter were not supported
- return true;
- }
-
- if (ParameterizedType.class.isInstance(type)) {
- final ParameterizedType parameterizedType = ParameterizedType.class.cast(type);
- final Type rawType = parameterizedType.getRawType();
- if (Class.class.isInstance(rawType)) {
- final Class<?> clazz = Class.class.cast(rawType);
- if (Collection.class.isAssignableFrom(clazz) && parameterizedType.getActualTypeArguments().length == 1) {
- final Type argType = parameterizedType.getActualTypeArguments()[0];
- if (Class.class.isInstance(argType) && Class.class.isInstance(convertType)) {
- return !Class.class.cast(convertType).isAssignableFrom(Class.class.cast(argType));
- }
- } else if (Map.class.isAssignableFrom(clazz) && parameterizedType.getActualTypeArguments().length == 2) {
- final Type argType = parameterizedType.getActualTypeArguments()[1];
- if (Class.class.isInstance(argType) && Class.class.isInstance(convertType)) {
- return !Class.class.cast(convertType).isAssignableFrom(Class.class.cast(argType));
- }
- }
- return true; // actually here we suppose we dont know
- }
- }
- if (Class.class.isInstance(type)) {
- final Class<?> clazz = Class.class.cast(type);
- if (clazz.isArray()) {
- return !Class.class.cast(convertType).isAssignableFrom(clazz.getComponentType());
- }
- }
- return true;
- }
-
private static final JohnzonParameterizedType VIRTUAL_TYPE = new JohnzonParameterizedType(Map.class, String.class, Object.class);
protected final ConcurrentMap<Type, ClassMapping> classes = new ConcurrentHashMap<Type, ClassMapping>();
protected final ConcurrentMap<Type, CollectionMapping> collections = new ConcurrentHashMap<Type, CollectionMapping>();
protected final Comparator<String> fieldOrdering;
protected final ConcurrentMap<Type, Converter<?>> converters;
- private final boolean supportHiddenConstructors;
- private final boolean supportConstructors;
private final AccessMode accessMode;
private final int version;
public Mappings(final Comparator<String> attributeOrder, final AccessMode accessMode,
- final boolean supportHiddenConstructors, final boolean supportConstructors,
final int version, final ConcurrentMap<Type, Converter<?>> converters) {
this.fieldOrdering = attributeOrder;
this.accessMode = accessMode;
- this.supportHiddenConstructors = supportHiddenConstructors;
- this.supportConstructors = supportConstructors;
this.version = version;
this.converters = converters;
}
@@ -396,7 +276,7 @@ public class Mappings {
return classMapping;
}
- private ClassMapping createClassMapping(final Class<?> inClazz) {
+ protected ClassMapping createClassMapping(final Class<?> inClazz) {
boolean copyDate = false;
for (final Class<?> itf : inClazz.getInterfaces()) {
if ("org.apache.openjpa.enhance.PersistenceCapable".equals(itf.getName())) {
@@ -442,7 +322,7 @@ public class Mappings {
}
addSetterIfNeeded(setters, key, writer.getValue(), copyDate);
}
- return new ClassMapping(clazz, getters, setters, supportHiddenConstructors, supportConstructors);
+ return new ClassMapping(clazz, accessMode.findFactory(clazz), getters, setters);
}
protected Class<?> findModelClass(final Class<?> inClazz) {
@@ -550,20 +430,23 @@ public class Mappings {
setters.put(key, new Setter(newSetter == null ? newWriter : new CompositeWriter(newSetter.writer, newWriter), false, false, VIRTUAL_TYPE, null, -1));
}
- private Converter findConverter(final boolean copyDate, final AccessMode.DecoratedType method) {
- Converter converter = null;
- final JohnzonConverter annotation = method.getAnnotation(JohnzonConverter.class);
+ private Converter findConverter(final boolean copyDate, final AccessMode.DecoratedType decoratedType) {
+ Converter converter = decoratedType.findConverter();
+ if (converter != null) {
+ return converter;
+ }
+ final JohnzonConverter annotation = decoratedType.getAnnotation(JohnzonConverter.class);
- Type typeToTest = method.getType();
+ Type typeToTest = decoratedType.getType();
if (annotation != null) {
try {
converter = annotation.value().newInstance();
} catch (final Exception e) {
throw new IllegalArgumentException(e);
}
- } else if (ParameterizedType.class.isInstance(method.getType())) {
- final ParameterizedType type = ParameterizedType.class.cast(method.getType());
+ } else if (ParameterizedType.class.isInstance(decoratedType.getType())) {
+ final ParameterizedType type = ParameterizedType.class.cast(decoratedType.getType());
final Type rawType = type.getRawType();
if (Class.class.isInstance(rawType)
&& Collection.class.isAssignableFrom(Class.class.cast(rawType))
@@ -638,6 +521,16 @@ public class Mappings {
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
}
+
+ @Override
+ public Converter<?> findConverter() {
+ return null;
+ }
+
+ @Override
+ public boolean isNillable() {
+ return false;
+ }
}
private static class MapUnwrapperWriter implements AccessMode.Writer {
@@ -697,6 +590,16 @@ public class Mappings {
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
}
+
+ @Override
+ public Converter<?> findConverter() {
+ return null;
+ }
+
+ @Override
+ public boolean isNillable() {
+ return false;
+ }
}
private static class CompositeReader implements AccessMode.Reader {
@@ -742,6 +645,27 @@ public class Mappings {
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
}
+
+ @Override
+ public Converter<?> findConverter() {
+ for (final AccessMode.Reader r : delegates) {
+ final Converter<?> converter = r.findConverter();
+ if (converter != null) {
+ return converter;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isNillable() {
+ for (final AccessMode.Reader r : delegates) {
+ if (r.isNillable()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
private static class CompositeWriter implements AccessMode.Writer {
@@ -775,5 +699,26 @@ public class Mappings {
public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
throw new UnsupportedOperationException("getAnnotation shouldn't get called for virtual fields");
}
+
+ @Override
+ public Converter<?> findConverter() {
+ for (final AccessMode.Writer r : delegates) {
+ final Converter<?> converter = r.findConverter();
+ if (converter != null) {
+ return converter;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isNillable() {
+ for (final AccessMode.Writer r : delegates) {
+ if (r.isNillable()) {
+ return true;
+ }
+ }
+ return false;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
----------------------------------------------------------------------
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
index f5817bb..a6c3267 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperTest.java
@@ -545,7 +545,7 @@ public class MapperTest {
public int compare(final String o1, final String o2) {
return o1.compareTo(o2);
}
- }).setAccessMode(new FieldAccessMode()).build();
+ }).setAccessMode(new FieldAccessMode(true, false)).build();
final String asString = mapper.writeObjectAsString(source);
assertEquals("{\"children\":[\"5\",\"6\"],\"nested\":{\"b\":2,\"sub\":{\"a\":1,\"c\":[\"3\",\"4\"]}}}", asString);
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/pom.xml
----------------------------------------------------------------------
diff --git a/jsonb-api/pom.xml b/jsonb-api/pom.xml
new file mode 100644
index 0000000..942ec3a
--- /dev/null
+++ b/jsonb-api/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>johnzon</artifactId>
+ <groupId>org.apache.johnzon</groupId>
+ <version>0.9.3-incubating-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>jsonb-api</artifactId>
+ <version>1.0-early-draft</version>
+ <name>Johnzon :: JSON-B API</name>
+
+ <properties>
+ <java-compile.version>1.8</java-compile.version>
+ </properties>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/Jsonb.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/Jsonb.java b/jsonb-api/src/main/java/javax/json/bind/Jsonb.java
new file mode 100644
index 0000000..9bccc4b
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/Jsonb.java
@@ -0,0 +1,49 @@
+/*
+ * 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 javax.json.bind;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Type;
+
+public interface Jsonb {
+ <T> T fromJson(String str, Class<T> type) throws JsonbException;
+
+ <T> T fromJson(String str, Type runtimeType) throws JsonbException;
+
+ <T> T fromJson(Readable readable, Class<T> type) throws JsonbException;
+
+ <T> T fromJson(Readable readable, Type runtimeType) throws JsonbException;
+
+ <T> T fromJson(InputStream stream, Class<T> type) throws JsonbException;
+
+ <T> T fromJson(InputStream stream, Type runtimeType) throws JsonbException;
+
+ String toJson(Object object) throws JsonbException;
+
+ String toJson(Object object, Type runtimeType) throws JsonbException;
+
+ void toJson(Object object, Appendable appendable) throws JsonbException;
+
+ void toJson(Object object, Type runtimeType, Appendable appendable) throws JsonbException;
+
+ void toJson(Object object, OutputStream stream) throws JsonbException;
+
+ void toJson(Object object, Type runtimeType, OutputStream stream) throws JsonbException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/JsonbBuilder.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/JsonbBuilder.java b/jsonb-api/src/main/java/javax/json/bind/JsonbBuilder.java
new file mode 100644
index 0000000..77e4a8c
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/JsonbBuilder.java
@@ -0,0 +1,50 @@
+/*
+ * 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 javax.json.bind;
+
+import javax.json.bind.spi.JsonbProvider;
+import javax.json.spi.JsonProvider;
+
+public interface JsonbBuilder {
+ JsonbBuilder withConfig(final JsonbConfig config);
+
+ JsonbBuilder withProvider(final JsonProvider jsonpProvider);
+
+ Jsonb build();
+
+ static Jsonb create() {
+ return JsonbProvider.provider().create().build();
+ }
+
+ static Jsonb create(final JsonbConfig config) {
+ return JsonbProvider.provider().create().withConfig(config).build();
+ }
+
+ static JsonbBuilder newBuilder() {
+ return JsonbProvider.provider().create();
+ }
+
+ static JsonbBuilder newBuilder(final String providerName) {
+ return JsonbProvider.provider(providerName).create();
+ }
+
+ static JsonbBuilder newBuilder(final JsonbProvider provider) {
+ return provider.create();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java b/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java
new file mode 100644
index 0000000..7d880b3
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java
@@ -0,0 +1,94 @@
+/*
+ * 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 javax.json.bind;
+
+import javax.json.bind.adapter.JsonbAdapter;
+import javax.json.bind.config.PropertyNamingStrategy;
+import javax.json.bind.config.PropertyVisibilityStrategy;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class JsonbConfig {
+ private final Map<String, Object> configuration = new HashMap<>();
+
+ public static final String FORMATTING = "jsonb.formatting";
+ public static final String ENCODING = "jsonb.encoding";
+ public static final String PROPERTY_NAMING_STRATEGY = "jsonb.property-naming-strategy";
+ public static final String PROPERTY_ORDER_STRATEGY = "jsonb.property-order-strategy";
+ public static final String NULL_VALUES = "jsonb.null-values";
+ public static final String STRICT_IJSON = "jsonb.strict-ijson";
+ public static final String PROPERTY_VISIBILITY_STRATEGY = "jsonb.property-visibility-strategy";
+ public static final String ADAPTERS = "jsonb.adapters";
+ public static final String BINARY_DATA_STRATEGY = "jsonb.binary-data-strategy";
+
+ public final JsonbConfig setProperty(final String name, final Object value) {
+ configuration.put(name, value);
+ return this;
+ }
+
+ public final Optional<Object> getProperty(final String name) {
+ return Optional.ofNullable(configuration.get(name));
+ }
+
+ public final Map<String, Object> getAsMap() {
+ return Collections.unmodifiableMap(configuration);
+ }
+
+ public final JsonbConfig withFormatting(final Boolean formatted) {
+ return setProperty(FORMATTING, formatted);
+ }
+
+ public final JsonbConfig withNullValues(final Boolean serializeNullValues) {
+ return setProperty(NULL_VALUES, serializeNullValues);
+ }
+
+ public final JsonbConfig withEncoding(final String encoding) {
+ return setProperty(ENCODING, encoding);
+ }
+
+ public final JsonbConfig withStrictIJSON(final Boolean enabled) {
+ return setProperty(STRICT_IJSON, enabled);
+ }
+
+ public final JsonbConfig withPropertyNamingStrategy(final PropertyNamingStrategy propertyNamingStrategy) {
+ return setProperty(PROPERTY_NAMING_STRATEGY, propertyNamingStrategy);
+ }
+
+ public final JsonbConfig withPropertyNamingStrategy(final String propertyNamingStrategy) {
+ return setProperty(PROPERTY_NAMING_STRATEGY, propertyNamingStrategy);
+ }
+
+ public final JsonbConfig withPropertyOrderStrategy(final String propertyOrderStrategy) {
+ return setProperty(PROPERTY_ORDER_STRATEGY, propertyOrderStrategy);
+ }
+
+ public final JsonbConfig withPropertyVisibilityStrategy(final PropertyVisibilityStrategy propertyVisibilityStrategy) {
+ return setProperty(PROPERTY_VISIBILITY_STRATEGY, propertyVisibilityStrategy);
+ }
+
+ public final JsonbConfig withAdapters(final JsonbAdapter... adapters) {
+ return setProperty(ADAPTERS, adapters);
+ }
+
+ public final JsonbConfig withBinaryDataStrategy(final String binaryDataStrategy) {
+ return setProperty(BINARY_DATA_STRATEGY, binaryDataStrategy);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/JsonbException.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/JsonbException.java b/jsonb-api/src/main/java/javax/json/bind/JsonbException.java
new file mode 100644
index 0000000..6cf0cdd
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/JsonbException.java
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.json.bind;
+
+public class JsonbException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public JsonbException(final String message) {
+ super(message);
+ }
+
+ public JsonbException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/adapter/JsonbAdapter.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/adapter/JsonbAdapter.java b/jsonb-api/src/main/java/javax/json/bind/adapter/JsonbAdapter.java
new file mode 100644
index 0000000..eb364fe
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/adapter/JsonbAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * 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 javax.json.bind.adapter;
+
+import java.lang.reflect.Type;
+
+// under discussion
+public interface JsonbAdapter {
+ default <ValueType> ValueType adaptTo(Object obj) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ default <BoundType> BoundType adaptFrom(Object obj) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ default Class<?> getValueType() {
+ return null;
+ }
+
+ default Class<?> getBoundType() {
+ return null;
+ }
+
+ default Type getRuntimeValueType() {
+ return null;
+ }
+
+ default Type getRuntimeBoundType() {
+ return null;
+ }
+
+ default boolean handlesNullValue() {
+ return false;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbAnnotation.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbAnnotation.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbAnnotation.java
new file mode 100644
index 0000000..743fd07
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbAnnotation.java
@@ -0,0 +1,26 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JsonbAnnotation {
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbCreator.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbCreator.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbCreator.java
new file mode 100644
index 0000000..9502320
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbCreator.java
@@ -0,0 +1,30 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})
+public @interface JsonbCreator {
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbDateFormat.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbDateFormat.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbDateFormat.java
new file mode 100644
index 0000000..3f7c2ec
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbDateFormat.java
@@ -0,0 +1,40 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+ ElementType.ANNOTATION_TYPE, ElementType.FIELD,
+ ElementType.METHOD, ElementType.TYPE,
+ ElementType.PARAMETER, ElementType.PACKAGE
+})
+public @interface JsonbDateFormat {
+ String DEFAULT_LOCALE = "##default";
+ String DEFAULT_FORMAT = "##default";
+ String TIME_IN_MILLIS = "##time-in-millis";
+
+ String value() default DEFAULT_FORMAT;
+ String locale() default DEFAULT_LOCALE;
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNillable.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNillable.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNillable.java
new file mode 100644
index 0000000..a2a70c6
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNillable.java
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.PACKAGE})
+public @interface JsonbNillable {
+ boolean value() default true;
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNumberFormat.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNumberFormat.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNumberFormat.java
new file mode 100644
index 0000000..06bfa9a
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbNumberFormat.java
@@ -0,0 +1,40 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+ ElementType.ANNOTATION_TYPE, ElementType.FIELD,
+ ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER,
+ ElementType.PACKAGE
+})
+public @interface JsonbNumberFormat {
+ String DEFAULT_LOCALE = "##default";
+
+ String value() default "";
+
+ String locale() default DEFAULT_LOCALE;
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbProperty.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbProperty.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbProperty.java
new file mode 100644
index 0000000..b8234ba
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbProperty.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+ ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER
+})
+public @interface JsonbProperty {
+ String value() default "";
+
+ boolean nillable() default false;
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbPropertyOrder.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbPropertyOrder.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbPropertyOrder.java
new file mode 100644
index 0000000..b06a868
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbPropertyOrder.java
@@ -0,0 +1,31 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+public @interface JsonbPropertyOrder {
+ String[] value();
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTransient.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTransient.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTransient.java
new file mode 100644
index 0000000..9b708dd
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTransient.java
@@ -0,0 +1,32 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
+public @interface JsonbTransient {
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeAdapter.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeAdapter.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeAdapter.java
new file mode 100644
index 0000000..6e9f281
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeAdapter.java
@@ -0,0 +1,32 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import javax.json.bind.adapter.JsonbAdapter;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD})
+public @interface JsonbTypeAdapter {
+ Class<? extends JsonbAdapter> value();
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbValue.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbValue.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbValue.java
new file mode 100644
index 0000000..7b44286
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbValue.java
@@ -0,0 +1,32 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+ ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER
+})
+public @interface JsonbValue {
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbVisibility.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbVisibility.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbVisibility.java
new file mode 100644
index 0000000..69265f8
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbVisibility.java
@@ -0,0 +1,34 @@
+/*
+ * 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 javax.json.bind.annotation;
+
+import javax.json.bind.config.PropertyVisibilityStrategy;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@JsonbAnnotation
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.PACKAGE
+})
+public @interface JsonbVisibility {
+ Class<? extends PropertyVisibilityStrategy> value();
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/config/BinaryDataStrategy.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/config/BinaryDataStrategy.java b/jsonb-api/src/main/java/javax/json/bind/config/BinaryDataStrategy.java
new file mode 100644
index 0000000..1871826
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/config/BinaryDataStrategy.java
@@ -0,0 +1,29 @@
+/*
+ * 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 javax.json.bind.config;
+
+public final class BinaryDataStrategy {
+ private BinaryDataStrategy() {
+ // no-op
+ }
+
+ public static final String BYTE = "BYTE";
+ public static final String BASE_64 = "BASE_64";
+ public static final String BASE_64_URL = "BASE_64_URL";
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/jsonb-api/src/main/java/javax/json/bind/config/PropertyNamingStrategy.java
----------------------------------------------------------------------
diff --git a/jsonb-api/src/main/java/javax/json/bind/config/PropertyNamingStrategy.java b/jsonb-api/src/main/java/javax/json/bind/config/PropertyNamingStrategy.java
new file mode 100644
index 0000000..218e087
--- /dev/null
+++ b/jsonb-api/src/main/java/javax/json/bind/config/PropertyNamingStrategy.java
@@ -0,0 +1,30 @@
+/*
+ * 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 javax.json.bind.config;
+
+public interface PropertyNamingStrategy {
+ String IDENTITY = "IDENTITY";
+ String LOWER_CASE_WITH_DASHES = "LOWER_CASE_WITH_DASHES";
+ String LOWER_CASE_WITH_UNDERSCORES = "LOWER_CASE_WITH_UNDERSCORES";
+ String UPPER_CAMEL_CASE = "UPPER_CAMEL_CASE";
+ String UPPER_CAMEL_CASE_WITH_SPACES = "UPPER_CAMEL_CASE_WITH_SPACES";
+ String CASE_INSENSITIVE = "CASE_INSENSITIVE";
+
+ String translateName(String propertyName);
+}
[3/3] incubator-johnzon git commit: JOHNZON-61 bases for jsonb,
still a lot of tests to add but allows to review more efficiently the
early draft
Posted by rm...@apache.org.
JOHNZON-61 bases for jsonb, still a lot of tests to add but allows to review more efficiently the early draft
Project: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/commit/b65d149a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/tree/b65d149a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/diff/b65d149a
Branch: refs/heads/master
Commit: b65d149a50bcd16ce71f6969ae46d9311fc9ce36
Parents: 6443633
Author: Romain Manni-Bucau <rm...@gmail.com>
Authored: Sun Dec 6 18:46:31 2015 +0100
Committer: Romain Manni-Bucau <rm...@gmail.com>
Committed: Sun Dec 6 18:46:31 2015 +0100
----------------------------------------------------------------------
.../java/org/apache/johnzon/core/HStack.java | 34 +-
johnzon-distribution/pom.xml | 18 +
johnzon-jsonb/pom.xml | 52 +++
.../org/apache/johnzon/jsonb/JohnsonJsonb.java | 211 +++++++++
.../apache/johnzon/jsonb/JohnzonBuilder.java | 178 ++++++++
.../apache/johnzon/jsonb/JohnzonProvider.java | 29 ++
.../apache/johnzon/jsonb/JsonbAccessMode.java | 454 +++++++++++++++++++
.../jsonb/PropertyNamingStrategyFactory.java | 98 ++++
.../johnzon/jsonb/converter/JsonbConverter.java | 51 +++
.../jsonb/converter/JsonbDateConverter.java | 41 ++
.../jsonb/converter/JsonbDateConverterBase.java | 35 ++
.../converter/JsonbLocalDateConverter.java | 39 ++
.../converter/JsonbLocalDateTimeConverter.java | 40 ++
.../JsonbLocaleParserConverterBase.java | 35 ++
.../jsonb/converter/JsonbNumberConverter.java | 77 ++++
.../jsonb/converter/JsonbValueConverter.java | 34 ++
.../converter/JsonbZonedDateTimeConverter.java | 42 ++
.../services/javax.json.bind.spi.JsonbProvider | 1 +
.../johnzon/jsonb/JohnzonProviderTest.java | 37 ++
.../org/apache/johnzon/jsonb/JsonbReadTest.java | 102 +++++
.../apache/johnzon/jsonb/JsonbWriteTest.java | 132 ++++++
.../PropertyNamingStrategyFactoryTest.java | 52 +++
.../java/org/apache/johnzon/mapper/Mapper.java | 30 +-
.../apache/johnzon/mapper/MapperBuilder.java | 42 +-
.../johnzon/mapper/access/AccessMode.java | 13 +
.../johnzon/mapper/access/BaseAccessMode.java | 125 ++++-
.../johnzon/mapper/access/FieldAccessMode.java | 23 +-
.../mapper/access/FieldAndMethodAccessMode.java | 37 +-
.../johnzon/mapper/access/MethodAccessMode.java | 20 +-
.../johnzon/mapper/reflection/Converters.java | 78 ++++
.../johnzon/mapper/reflection/Mappings.java | 215 ++++-----
.../org/apache/johnzon/mapper/MapperTest.java | 2 +-
jsonb-api/pom.xml | 39 ++
.../src/main/java/javax/json/bind/Jsonb.java | 49 ++
.../main/java/javax/json/bind/JsonbBuilder.java | 50 ++
.../main/java/javax/json/bind/JsonbConfig.java | 94 ++++
.../java/javax/json/bind/JsonbException.java | 31 ++
.../javax/json/bind/adapter/JsonbAdapter.java | 52 +++
.../json/bind/annotation/JsonbAnnotation.java | 26 ++
.../json/bind/annotation/JsonbCreator.java | 30 ++
.../json/bind/annotation/JsonbDateFormat.java | 40 ++
.../json/bind/annotation/JsonbNillable.java | 31 ++
.../json/bind/annotation/JsonbNumberFormat.java | 40 ++
.../json/bind/annotation/JsonbProperty.java | 35 ++
.../bind/annotation/JsonbPropertyOrder.java | 31 ++
.../json/bind/annotation/JsonbTransient.java | 32 ++
.../json/bind/annotation/JsonbTypeAdapter.java | 32 ++
.../javax/json/bind/annotation/JsonbValue.java | 32 ++
.../json/bind/annotation/JsonbVisibility.java | 34 ++
.../json/bind/config/BinaryDataStrategy.java | 29 ++
.../bind/config/PropertyNamingStrategy.java | 30 ++
.../json/bind/config/PropertyOrderStrategy.java | 29 ++
.../bind/config/PropertyVisibilityStrategy.java | 27 ++
.../java/javax/json/bind/spi/JsonbProvider.java | 59 +++
pom.xml | 28 +-
55 files changed, 3058 insertions(+), 199 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java
----------------------------------------------------------------------
diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java b/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java
index 94f07ae..b2d57bd 100644
--- a/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java
+++ b/johnzon-core/src/main/java/org/apache/johnzon/core/HStack.java
@@ -20,15 +20,15 @@ package org.apache.johnzon.core;
import java.io.Serializable;
-public class HStack<T> implements Serializable{
+public class HStack<T> implements Serializable {
private Node<T> topElement = null;
private int size;
-
-
- private static final class Node<T> implements Serializable{
- final Node<T> previous;
- final T object;
+
+
+ private static final class Node<T> implements Serializable {
+ private final Node<T> previous;
+ private final T object;
private Node(final Node<T> previous, final T object) {
super();
@@ -36,29 +36,31 @@ public class HStack<T> implements Serializable{
this.object = object;
}
}
-
-
+
+
void push(T object) {
topElement = new Node<T>(topElement, object);
size++;
}
-
+
T pop() {
-
- if(topElement == null) { return null; }
-
+
+ if (topElement == null) {
+ return null;
+ }
+
T tmp = topElement.object;
topElement = topElement.previous;
size--;
return tmp;
}
-
+
T peek() {
- return topElement == null?null:topElement.object;
+ return topElement == null ? null : topElement.object;
}
-
+
int size() {
return size;
}
-
+
}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-distribution/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-distribution/pom.xml b/johnzon-distribution/pom.xml
index 3f2c10f..7f92fa2 100644
--- a/johnzon-distribution/pom.xml
+++ b/johnzon-distribution/pom.xml
@@ -139,6 +139,24 @@
<version>${project.version}</version>
<classifier>javadoc</classifier>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>johnzon-jsonb</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>johnzon-jsonb</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>johnzon-jsonb</artifactId>
+ <version>${project.version}</version>
+ <classifier>javadoc</classifier>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/pom.xml
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/pom.xml b/johnzon-jsonb/pom.xml
new file mode 100644
index 0000000..8c36b72
--- /dev/null
+++ b/johnzon-jsonb/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://maven.apache.org/POM/4.0.0
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>johnzon</artifactId>
+ <groupId>org.apache.johnzon</groupId>
+ <version>0.9.3-incubating-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>johnzon-jsonb</artifactId>
+ <name>Johnzon :: JSON-B Implementation</name>
+
+ <properties>
+ <java-compile.version>1.8</java-compile.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>jsonb-api</artifactId>
+ <version>1.0-early-draft</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.johnzon</groupId>
+ <artifactId>johnzon-mapper</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
new file mode 100644
index 0000000..85f9bd1
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnsonJsonb.java
@@ -0,0 +1,211 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.apache.johnzon.mapper.Mapper;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbException;
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.nio.CharBuffer;
+import java.util.Collection;
+
+public class JohnsonJsonb implements Jsonb {
+ private final Mapper delegate;
+
+ public JohnsonJsonb(final Mapper build) {
+ this.delegate = build;
+ }
+
+ @Override
+ public <T> T fromJson(final String str, final Class<T> type) throws JsonbException {
+ return delegate.readObject(str, type);
+ }
+
+ @Override
+ public <T> T fromJson(final String str, final Type runtimeType) throws JsonbException {
+ if (isArray(runtimeType)) {
+ return (T) delegate.readArray(new StringReader(str), Class.class.cast(runtimeType).getComponentType());
+ } else if (isCollection(runtimeType)) {
+ return (T) delegate.readCollection(new StringReader(str), ParameterizedType.class.cast(runtimeType));
+ }
+ return delegate.readObject(str, runtimeType);
+ }
+
+ @Override
+ public <T> T fromJson(final Readable readable, final Class<T> type) throws JsonbException {
+ return delegate.readObject(toReader(readable), type);
+ }
+
+ @Override
+ public <T> T fromJson(final Readable readable, final Type runtimeType) throws JsonbException {
+ if (isArray(runtimeType)) {
+ return (T) delegate.readArray(toReader(readable), Class.class.cast(runtimeType).getComponentType());
+ } else if (isCollection(runtimeType)) {
+ return (T) delegate.readCollection(toReader(readable), ParameterizedType.class.cast(runtimeType));
+ }
+ return delegate.readObject(toReader(readable), runtimeType);
+ }
+
+ @Override
+ public <T> T fromJson(final InputStream stream, final Class<T> type) throws JsonbException {
+ return delegate.readObject(stream, type);
+ }
+
+ @Override
+ public <T> T fromJson(final InputStream stream, final Type runtimeType) throws JsonbException {
+ if (isArray(runtimeType)) {
+ return (T) delegate.readArray(stream, Class.class.cast(runtimeType).getComponentType());
+ } else if (isCollection(runtimeType)) {
+ return (T) delegate.readCollection(stream, ParameterizedType.class.cast(runtimeType));
+ }
+ return delegate.readObject(stream, runtimeType);
+ }
+
+ @Override
+ public String toJson(final Object object) throws JsonbException {
+ if (isArray(object.getClass())) {
+ return delegate.writeArrayAsString((Object[]) object);
+ } else if (Collection.class.isInstance(object)) {
+ return delegate.writeArrayAsString(Collection.class.cast(object));
+ }
+ return delegate.writeObjectAsString(object);
+ }
+
+ @Override
+ public String toJson(final Object object, final Type runtimeType) throws JsonbException {
+ if (isArray(runtimeType)) {
+ return delegate.writeArrayAsString((Object[]) object);
+ } else if (isCollection(runtimeType)) {
+ return delegate.writeArrayAsString(Collection.class.cast(object));
+ }
+ return delegate.writeObjectAsString(object);
+ }
+
+ @Override
+ public void toJson(final Object object, final Appendable appendable) throws JsonbException {
+ if (isArray(object.getClass())) {
+ delegate.writeArray((Object[]) object, toWriter(appendable));
+ } else if (Collection.class.isInstance(object)) {
+ delegate.writeArray(Collection.class.cast(object), toWriter(appendable));
+ } else {
+ delegate.writeObject(object, toWriter(appendable));
+ }
+ }
+
+ @Override
+ public void toJson(final Object object, final Type runtimeType, final Appendable appendable) throws JsonbException {
+ if (isArray(runtimeType)) {
+ delegate.writeArray((Object[]) object, toWriter(appendable));
+ } else if (isCollection(runtimeType)) {
+ delegate.writeArray(Collection.class.cast(object), toWriter(appendable));
+ } else {
+ delegate.writeObject(object, toWriter(appendable));
+ }
+ }
+
+ @Override
+ public void toJson(final Object object, final OutputStream stream) throws JsonbException {
+ if (isArray(object.getClass())) {
+ delegate.writeArray((Object[]) object, stream);
+ } else if (Collection.class.isInstance(object)) {
+ delegate.writeArray(Collection.class.cast(object), stream);
+ } else {
+ delegate.writeObject(object, stream);
+ }
+ }
+
+ @Override
+ public void toJson(final Object object, final Type runtimeType, final OutputStream stream) throws JsonbException {
+ if (isArray(runtimeType)) {
+ delegate.writeArray((Object[]) object, stream);
+ } else if (isCollection(runtimeType)) {
+ delegate.writeArray(Collection.class.cast(object), stream);
+ } else {
+ delegate.writeObject(object, stream);
+ }
+ }
+
+ private boolean isArray(final Type runtimeType) {
+ return Class.class.isInstance(runtimeType) && Class.class.cast(runtimeType).isArray();
+ }
+
+ private boolean isCollection(final Type runtimeType) {
+ if (!ParameterizedType.class.isInstance(runtimeType)) {
+ return false;
+ }
+ final Type rawType = ParameterizedType.class.cast(runtimeType).getRawType();
+ return Class.class.isInstance(rawType) && Collection.class.isAssignableFrom(Class.class.cast(rawType));
+ }
+
+ private Writer toWriter(final Appendable appendable) {
+ return Writer.class.isInstance(appendable) ? Writer.class.cast(appendable) :
+ new Writer() {
+ @Override
+ public void write(final char[] cbuf, final int off, final int len) throws IOException {
+ appendable.append(new String(cbuf, off, len));
+ }
+
+ @Override
+ public void flush() throws IOException {
+ if (Flushable.class.isInstance(appendable)) {
+ Flushable.class.cast(appendable);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (Closeable.class.isInstance(appendable)) {
+ Closeable.class.cast(appendable);
+ }
+ }
+ };
+ }
+
+ private Reader toReader(final Readable readable) {
+ return Reader.class.isInstance(readable) ? Reader.class.cast(readable) :
+ new Reader() {
+ @Override
+ public int read(final char[] cbuf, final int off, final int len) throws IOException {
+ int r;
+ final CharBuffer cb = CharBuffer.allocate(len);
+ while ((r = readable.read(cb)) >= 0) {
+ System.arraycopy(cb.array(), 0, cbuf, off, r);
+ }
+ return readable.read(CharBuffer.allocate(len));
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (Closeable.class.isInstance(readable)) {
+ Closeable.class.cast(readable);
+ }
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
new file mode 100644
index 0000000..9b2c47d
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -0,0 +1,178 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.apache.johnzon.core.AbstractJsonFactory;
+import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
+import org.apache.johnzon.jsonb.converter.JsonbConverter;
+import org.apache.johnzon.mapper.Converter;
+import org.apache.johnzon.mapper.MapperBuilder;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.adapter.JsonbAdapter;
+import javax.json.bind.annotation.JsonbVisibility;
+import javax.json.bind.config.BinaryDataStrategy;
+import javax.json.bind.config.PropertyNamingStrategy;
+import javax.json.bind.config.PropertyVisibilityStrategy;
+import javax.json.spi.JsonProvider;
+import javax.json.stream.JsonGenerator;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Optional.ofNullable;
+import static javax.json.bind.config.PropertyNamingStrategy.IDENTITY;
+import static javax.json.bind.config.PropertyOrderStrategy.ANY;
+
+public class JohnzonBuilder implements JsonbBuilder {
+ private final MapperBuilder builder = new MapperBuilder();
+ private JsonProvider jsonp;
+ private JsonbConfig config;
+
+ @Override
+ public JsonbBuilder withConfig(final JsonbConfig config) {
+ this.config = config;
+ return this;
+ }
+
+ @Override
+ public JsonbBuilder withProvider(final JsonProvider jsonpProvider) {
+ this.jsonp = jsonpProvider;
+ return this;
+ }
+
+ @Override
+ public Jsonb build() {
+ if (jsonp != null) {
+ builder.setGeneratorFactory(jsonp.createGeneratorFactory(generatorConfig()));
+ builder.setReaderFactory(jsonp.createReaderFactory(emptyMap()));
+ }
+
+ if (config == null) {
+ config = new JsonbConfig();
+ }
+
+ if (config.getProperty(JsonbConfig.FORMATTING).map(Boolean.class::cast).orElse(false)) {
+ builder.setPretty(true);
+ }
+
+ config.getProperty(JsonbConfig.ENCODING).ifPresent(encoding -> builder.setEncoding(String.valueOf(encoding)));
+ config.getProperty(JsonbConfig.NULL_VALUES).ifPresent(serNulls -> builder.setSkipNull(!Boolean.class.cast(serNulls)));
+
+ final Optional<Object> namingStrategyValue = config.getProperty(JsonbConfig.PROPERTY_NAMING_STRATEGY);
+
+ final PropertyNamingStrategy propertyNamingStrategy = new PropertyNamingStrategyFactory(namingStrategyValue.orElse(IDENTITY)).create();
+ final String orderValue = config.getProperty(JsonbConfig.PROPERTY_ORDER_STRATEGY).map(String::valueOf).orElse(ANY);
+ final PropertyVisibilityStrategy visibilityStrategy = config.getProperty(JsonbConfig.PROPERTY_VISIBILITY_STRATEGY)
+ .map(PropertyVisibilityStrategy.class::cast).orElse(new PropertyVisibilityStrategy() {
+ @Override
+ public boolean isVisible(final Field field) {
+ return true;
+ }
+
+ @Override
+ public boolean isVisible(final Method method) {
+ return true;
+ }
+
+ private PropertyVisibilityStrategy visibilityStrategy(final Class<?> type) { // can be cached
+ Package p = type.getPackage();
+ while (p != null) {
+ final JsonbVisibility visibility = p.getAnnotation(JsonbVisibility.class);
+ if (visibility != null) {
+ try {
+ return visibility.value().newInstance();
+ } catch (final InstantiationException | IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ final String name = p.getName();
+ final int end = name.lastIndexOf('.');
+ if (end < 0) {
+ break;
+ }
+ p = Package.getPackage(name.substring(0, end));
+ }
+ return this;
+ }
+ });
+
+ builder.setAccessMode(
+ new JsonbAccessMode(propertyNamingStrategy, orderValue, visibilityStrategy, !namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE)));
+
+ config.getProperty(JsonbConfig.ADAPTERS).ifPresent(adapters -> Stream.of(JsonbAdapter[].class.cast(adapters)).forEach(adapter ->
+ builder.addConverter(ofNullable(adapter.getRuntimeBoundType()).orElse(adapter.getBoundType()), new JsonbConverter(adapter))
+ ));
+
+ // TODO:
+ // - Converters for setter/getter
+ // - check adapters when type is not String (breaks our Converter API it seems)
+
+ config.getProperty(JsonbConfig.STRICT_IJSON).map(Boolean.class::cast).ifPresent(ijson -> {
+ // no-op: https://tools.ietf.org/html/rfc7493 the only MUST of the spec sould be fine by default
+ });
+
+ config.getProperty(JsonbConfig.BINARY_DATA_STRATEGY).map(String.class::cast).ifPresent(bin -> {
+ switch (bin) {
+ case BinaryDataStrategy.BYTE:
+ // no-op: our default
+ break;
+ case BinaryDataStrategy.BASE_64:
+ builder.setTreatByteArrayAsBase64(true);
+ break;
+ case BinaryDataStrategy.BASE_64_URL: // needs j8
+ builder.addConverter(byte[].class, new Converter<byte[]>() {
+ @Override
+ public String toString(final byte[] instance) {
+ return Base64.getUrlEncoder().encodeToString(instance);
+ }
+
+ @Override
+ public byte[] fromString(final String text) {
+ return Base64.getUrlDecoder().decode(text.getBytes(StandardCharsets.UTF_8));
+ }
+ });
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported binary configuration: " + bin);
+ }
+ });
+
+ return new JohnsonJsonb(builder.build());
+ }
+
+ private Map<String, ?> generatorConfig() {
+ final Map<String, Object> map = new HashMap<>();
+ if (config == null) {
+ return map;
+ }
+ config.getProperty(JsonGeneratorFactoryImpl.GENERATOR_BUFFER_LENGTH).ifPresent(b -> map.put(JsonGeneratorFactoryImpl.GENERATOR_BUFFER_LENGTH, b));
+ config.getProperty(AbstractJsonFactory.BUFFER_STRATEGY).ifPresent(b -> map.put(AbstractJsonFactory.BUFFER_STRATEGY, b));
+ config.getProperty(JsonbConfig.FORMATTING).ifPresent(b -> map.put(JsonGenerator.PRETTY_PRINTING, b));
+ return map;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonProvider.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonProvider.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonProvider.java
new file mode 100644
index 0000000..d21b915
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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.johnzon.jsonb;
+
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.spi.JsonbProvider;
+
+public class JohnzonProvider extends JsonbProvider {
+ @Override
+ public JsonbBuilder create() {
+ return new JohnzonBuilder();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
new file mode 100644
index 0000000..0bd3443
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java
@@ -0,0 +1,454 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.apache.johnzon.jsonb.converter.JsonbConverter;
+import org.apache.johnzon.jsonb.converter.JsonbDateConverter;
+import org.apache.johnzon.jsonb.converter.JsonbLocalDateConverter;
+import org.apache.johnzon.jsonb.converter.JsonbLocalDateTimeConverter;
+import org.apache.johnzon.jsonb.converter.JsonbNumberConverter;
+import org.apache.johnzon.jsonb.converter.JsonbValueConverter;
+import org.apache.johnzon.jsonb.converter.JsonbZonedDateTimeConverter;
+import org.apache.johnzon.mapper.Converter;
+import org.apache.johnzon.mapper.access.AccessMode;
+import org.apache.johnzon.mapper.access.FieldAccessMode;
+import org.apache.johnzon.mapper.access.FieldAndMethodAccessMode;
+import org.apache.johnzon.mapper.access.MethodAccessMode;
+
+import javax.json.bind.JsonbException;
+import javax.json.bind.annotation.JsonbAnnotation;
+import javax.json.bind.annotation.JsonbCreator;
+import javax.json.bind.annotation.JsonbDateFormat;
+import javax.json.bind.annotation.JsonbNillable;
+import javax.json.bind.annotation.JsonbNumberFormat;
+import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.annotation.JsonbPropertyOrder;
+import javax.json.bind.annotation.JsonbTransient;
+import javax.json.bind.annotation.JsonbTypeAdapter;
+import javax.json.bind.annotation.JsonbValue;
+import javax.json.bind.config.PropertyNamingStrategy;
+import javax.json.bind.config.PropertyOrderStrategy;
+import javax.json.bind.config.PropertyVisibilityStrategy;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Parameter;
+import java.lang.reflect.Type;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.stream.Stream;
+
+import static java.util.Arrays.asList;
+import static org.apache.johnzon.mapper.reflection.Converters.matches;
+
+public class JsonbAccessMode implements AccessMode {
+ private final PropertyNamingStrategy naming;
+ private final String order;
+ private final PropertyVisibilityStrategy visibility;
+ private final FieldAndMethodAccessMode delegate;
+ private final boolean caseSensitive;
+
+ public JsonbAccessMode(final PropertyNamingStrategy propertyNamingStrategy, final String orderValue,
+ final PropertyVisibilityStrategy visibilityStrategy, final boolean caseSensitive) {
+ this.naming = propertyNamingStrategy;
+ this.order = orderValue;
+ this.visibility = visibilityStrategy;
+ this.caseSensitive = caseSensitive;
+ this.delegate = new FieldAndMethodAccessMode(true, false);
+ }
+
+ @Override
+ public Factory findFactory(final Class<?> clazz) {
+ Constructor<?> constructor = null;
+ Method factory = null;
+ for (final Constructor<?> c : clazz.getConstructors()) {
+ if (c.isAnnotationPresent(JsonbCreator.class)) {
+ if (constructor != null) {
+ throw new IllegalArgumentException("Only one constructor or method can have @JsonbCreator");
+ }
+ constructor = c;
+ }
+ }
+ for (final Method m : clazz.getMethods()) {
+ final int modifiers = m.getModifiers();
+ if (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers) && m.isAnnotationPresent(JsonbCreator.class)) {
+ if (constructor != null || factory != null) {
+ throw new IllegalArgumentException("Only one constructor or method can have @JsonbCreator");
+ }
+ factory = m;
+ }
+ }
+ final Constructor<?> finalConstructor = constructor;
+ final Method finalFactory = factory;
+ final Type[] types;
+ final String[] params;
+ final Converter<?>[] converters;
+ final Converter<?>[] itemConverters;
+ if (finalConstructor != null || finalFactory != null) {
+ types = finalConstructor != null ? finalConstructor.getGenericParameterTypes() : finalFactory.getGenericParameterTypes();
+ params = new String[types.length];
+ converters = new Converter[types.length];
+ itemConverters = new Converter[types.length];
+ int i = 0;
+ for (final Parameter parameter : (finalConstructor == null ? finalFactory : finalConstructor).getParameters()) {
+ final JsonbProperty property = parameter.getAnnotation(JsonbProperty.class);
+ params[i] = property != null ? property.value() : parameter.getName();
+
+ final JsonbTypeAdapter adapter = parameter.getAnnotation(JsonbTypeAdapter.class);
+ final JsonbDateFormat dateFormat = parameter.getAnnotation(JsonbDateFormat.class);
+ final JsonbNumberFormat numberFormat = parameter.getAnnotation(JsonbNumberFormat.class);
+ final JsonbValue value = parameter.getAnnotation(JsonbValue.class);
+ if (adapter == null && dateFormat == null && numberFormat == null && value == null) {
+ converters[i] = null;
+ itemConverters[i] = null;
+ } else {
+ validateAnnotations(parameter, adapter, dateFormat, numberFormat, value);
+
+ try {
+ final Converter<?> converter = toConverter(parameter.getType(), adapter, dateFormat, numberFormat);
+ if (matches(parameter.getParameterizedType(), converter)) {
+ converters[i] = converter;
+ itemConverters[i] = null;
+ } else {
+ converters[i] = null;
+ itemConverters[i] = converter;
+ }
+ } catch (final InstantiationException | IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ }
+ i++;
+ }
+ } else {
+ types = null;
+ params = null;
+ converters = null;
+ itemConverters = null;
+ }
+
+ return constructor == null && factory == null ? delegate.findFactory(clazz) : (
+ constructor != null ?
+ new Factory() {
+ @Override
+ public Object create(final Object[] params) {
+ try {
+ return finalConstructor.newInstance(params);
+ } catch (final InstantiationException | IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ } catch (final InvocationTargetException e) {
+ throw new IllegalStateException(e.getCause());
+ }
+ }
+
+ @Override
+ public Type[] getParameterTypes() {
+ return types;
+ }
+
+ @Override
+ public String[] getParameterNames() {
+ return params;
+ }
+
+ @Override
+ public Converter<?>[] getParameterConverter() {
+ return converters;
+ }
+
+ @Override
+ public Converter<?>[] getParameterItemConverter() {
+ return itemConverters;
+ }
+ } :
+ new Factory() {
+ @Override
+ public Object create(final Object[] params) {
+ try {
+ final Object invoke = finalFactory.invoke(null, params);
+ if (!clazz.isInstance(invoke)) {
+ throw new IllegalArgumentException(invoke + " is not a " + clazz.getName());
+ }
+ return invoke;
+ } catch (final IllegalAccessException e) {
+ throw new IllegalStateException(e);
+ } catch (final InvocationTargetException e) {
+ throw new IllegalStateException(e.getCause());
+ }
+ }
+
+ @Override
+ public Type[] getParameterTypes() {
+ return types;
+ }
+
+ @Override
+ public String[] getParameterNames() {
+ return params;
+ }
+
+ @Override
+ public Converter<?>[] getParameterConverter() {
+ return converters;
+ }
+
+ @Override
+ public Converter<?>[] getParameterItemConverter() {
+ return itemConverters;
+ }
+ });
+ }
+
+ private void validateAnnotations(final Object parameter,
+ final JsonbTypeAdapter adapter, final JsonbDateFormat dateFormat,
+ final JsonbNumberFormat numberFormat, final JsonbValue value) {
+ int notNull = adapter != null ? 1 : 0;
+ notNull += dateFormat != null ? 1 : 0;
+ notNull += numberFormat != null ? 1 : 0;
+ notNull += value != null ? 1 : 0;
+ if (notNull > 1) {
+ throw new IllegalArgumentException("Conflicting @JsonbXXX on " + parameter);
+ }
+ }
+
+ private Converter<?> toConverter(final Type type,
+ final JsonbTypeAdapter adapter, final JsonbDateFormat dateFormat,
+ final JsonbNumberFormat numberFormat) throws InstantiationException, IllegalAccessException {
+ final Converter<?> converter;
+ if (adapter != null) {
+ converter = new JsonbConverter(adapter.value().newInstance());
+ } else if (dateFormat != null) { // TODO: support lists, LocalDate?
+ if (Date.class == type) {
+ converter = new JsonbDateConverter(dateFormat);
+ } else if (LocalDateTime.class == type) {
+ converter = new JsonbLocalDateTimeConverter(dateFormat);
+ } else if (LocalDate.class == type) {
+ converter = new JsonbLocalDateConverter(dateFormat);
+ } else if (ZonedDateTime.class == type) {
+ converter = new JsonbZonedDateTimeConverter(dateFormat);
+ } else {
+ throw new IllegalArgumentException(type + " not a supported date type");
+ }
+ } else if (numberFormat != null) { // TODO: support lists?
+ converter = new JsonbNumberConverter(numberFormat);
+ } else {
+ converter = new JsonbValueConverter();
+ }
+ return converter;
+ }
+
+ @Override
+ public Map<String, Reader> findReaders(final Class<?> clazz) {
+ final Map<String, Reader> readers = delegate.findReaders(clazz);
+
+ final Comparator<String> orderComparator = orderComparator(clazz);
+ final Comparator<String> keyComparator = caseSensitive ?
+ orderComparator :
+ (o1, o2) -> o1.equalsIgnoreCase(o2) ? 0 : orderComparator.compare(o1, o2);
+
+ final Map<String, Reader> result = keyComparator == null ? new HashMap<>() : new TreeMap<>(keyComparator);
+ for (final Map.Entry<String, Reader> entry : readers.entrySet()) {
+ final Reader value = entry.getValue();
+ if (shouldSkip(visibility, value)) {
+ continue;
+ }
+
+ // we are visible
+ final JsonbProperty property = value.getAnnotation(JsonbProperty.class);
+ final JsonbNillable nillable = value.getAnnotation(JsonbNillable.class);
+ final boolean isNillable = nillable != null || (property != null && property.nillable());
+ final JsonbTypeAdapter adapter = value.getAnnotation(JsonbTypeAdapter.class);
+ final JsonbDateFormat dateFormat = value.getAnnotation(JsonbDateFormat.class);
+ final JsonbNumberFormat numberFormat = value.getAnnotation(JsonbNumberFormat.class);
+ final JsonbValue jsonbValue = value.getAnnotation(JsonbValue.class);
+ validateAnnotations(value, adapter, dateFormat, numberFormat, jsonbValue);
+
+ final Converter<?> converter;
+ try {
+ converter = adapter == null && dateFormat == null && numberFormat == null && jsonbValue == null ? null :
+ toConverter(value.getType(), adapter, dateFormat, numberFormat);
+ } catch (final InstantiationException | IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ result.put(property == null || property.value().isEmpty() ? naming.translateName(entry.getKey()) : property.value(), new Reader() {
+ @Override
+ public Object read(final Object instance) {
+ return value.read(instance);
+ }
+
+ @Override
+ public Type getType() {
+ return value.getType();
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
+ return value.getAnnotation(clazz);
+ }
+
+ @Override
+ public Converter<?> findConverter() {
+ return converter;
+ }
+
+ @Override
+ public boolean isNillable() {
+ return isNillable;
+ }
+ });
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, Writer> findWriters(final Class<?> clazz) {
+ final Map<String, Writer> writers = delegate.findWriters(clazz);
+
+ final Comparator<String> keyComparator = orderComparator(clazz);
+ final Map<String, Writer> result = keyComparator == null ? new HashMap<>() : new TreeMap<>(keyComparator);
+ for (final Map.Entry<String, Writer> entry : writers.entrySet()) {
+ final Writer value = entry.getValue();
+ if (shouldSkip(visibility, value)) {
+ continue;
+ }
+
+ // we are visible
+ final JsonbProperty property = value.getAnnotation(JsonbProperty.class);
+ final JsonbNillable nillable = value.getAnnotation(JsonbNillable.class);
+ final boolean isNillable = nillable != null || (property != null && property.nillable());
+ final JsonbTypeAdapter adapter = value.getAnnotation(JsonbTypeAdapter.class);
+ final JsonbDateFormat dateFormat = value.getAnnotation(JsonbDateFormat.class);
+ final JsonbNumberFormat numberFormat = value.getAnnotation(JsonbNumberFormat.class);
+ final JsonbValue jsonbValue = value.getAnnotation(JsonbValue.class);
+ validateAnnotations(value, adapter, dateFormat, numberFormat, jsonbValue);
+
+ final Converter<?> converter;
+ try {
+ converter = adapter == null && dateFormat == null && numberFormat == null && jsonbValue == null ? null :
+ toConverter(value.getType(), adapter, dateFormat, numberFormat);
+ } catch (final InstantiationException | IllegalAccessException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ result.put(property == null || property.value().isEmpty() ? naming.translateName(entry.getKey()) : property.value(), new Writer() {
+ @Override
+ public void write(final Object instance, final Object val) {
+ value.write(instance, val);
+ }
+
+ @Override
+ public Type getType() {
+ return value.getType();
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(final Class<T> clazz) {
+ return value.getAnnotation(clazz);
+ }
+
+ @Override
+ public Converter<?> findConverter() {
+ return converter;
+ }
+
+ @Override
+ public boolean isNillable() {
+ return isNillable;
+ }
+ });
+ }
+ return result;
+ }
+
+ private boolean isTransient(final DecoratedType dt, final PropertyVisibilityStrategy visibility) {
+ return shouldSkip(visibility, dt) ||
+ (FieldAndMethodAccessMode.CompositeDecoratedType.class.isInstance(dt) &&
+ Stream.of(FieldAndMethodAccessMode.CompositeDecoratedType.class.cast(dt).getType1(), FieldAndMethodAccessMode.CompositeDecoratedType.class.cast(dt).getType2())
+ .map(t -> shouldSkip(visibility, t))
+ .filter(a -> a)
+ .findAny()
+ .isPresent());
+ }
+
+ private boolean shouldSkip(final PropertyVisibilityStrategy visibility, final DecoratedType t) {
+ return t.getAnnotation(JsonbTransient.class) != null ||
+ (FieldAccessMode.FieldDecoratedType.class.isInstance(t) && !visibility.isVisible(FieldAccessMode.FieldDecoratedType.class.cast(t).getField())) ||
+ (MethodAccessMode.MethodDecoratedType.class.isInstance(t) && !visibility.isVisible(MethodAccessMode.MethodDecoratedType.class.cast(t).getMethod()));
+ }
+
+ private boolean checkTransient(final Annotation[] annotations) {
+ boolean hasTransient = false;
+ boolean hasJsonb = false;
+ for (final Annotation a : annotations) {
+ if (a.annotationType() == JsonbTransient.class) {
+ hasTransient = true;
+ } else if (a.annotationType().isAnnotationPresent(JsonbAnnotation.class)) {
+ hasJsonb = true;
+ }
+ }
+ if (hasJsonb && hasTransient) {
+ throw new JsonbException("@JsonbTransient doesnt work with other @JsonbXXX: " + asList(annotations));
+ }
+ return hasTransient;
+ }
+
+ private Comparator<String> orderComparator(final Class<?> clazz) {
+ final Comparator<String> keyComparator;
+ final JsonbPropertyOrder orderAnnotation = clazz.getAnnotation(JsonbPropertyOrder.class);
+ if (orderAnnotation != null) {
+ final List<String> indexed = new ArrayList<>(asList(orderAnnotation.value()));
+ keyComparator = (o1, o2) -> {
+ final int i1 = indexed.indexOf(o1);
+ final int i2 = indexed.indexOf(o2);
+ if (i1 < 0) {
+ return 1;
+ }
+ return i1 - i2;
+ };
+ } else if (order != null) {
+ switch (order) {
+ case PropertyOrderStrategy.ANY:
+ keyComparator = null;
+ break;
+ case PropertyOrderStrategy.LEXICOGRAPHICAL:
+ keyComparator = String::compareTo;
+ break;
+ case PropertyOrderStrategy.REVERSE:
+ keyComparator = (o1, o2) -> o2.compareTo(o1);
+ break;
+ default:
+ keyComparator = null;
+ }
+ } else {
+ keyComparator = null;
+ }
+ return keyComparator;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactory.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactory.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactory.java
new file mode 100644
index 0000000..badfc15
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/PropertyNamingStrategyFactory.java
@@ -0,0 +1,98 @@
+/*
+ * 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.johnzon.jsonb;
+
+import javax.json.bind.config.PropertyNamingStrategy;
+import java.util.function.Function;
+
+public class PropertyNamingStrategyFactory {
+ private final Object value;
+
+ public PropertyNamingStrategyFactory(final Object value) {
+ this.value = value;
+ }
+
+ public PropertyNamingStrategy create() {
+ if (String.class.isInstance(value)) {
+ final String val = value.toString();
+ switch (val) {
+ case PropertyNamingStrategy.IDENTITY:
+ return propertyName -> propertyName;
+ case PropertyNamingStrategy.LOWER_CASE_WITH_DASHES:
+ return new ConfigurableNamingStrategy(Character::toLowerCase, '-');
+ case PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES:
+ return new ConfigurableNamingStrategy(Character::toLowerCase, '_');
+ case PropertyNamingStrategy.UPPER_CAMEL_CASE:
+ return camelCaseStrategy();
+ case PropertyNamingStrategy.UPPER_CAMEL_CASE_WITH_SPACES:
+ final PropertyNamingStrategy camelCase = camelCaseStrategy();
+ final PropertyNamingStrategy space = new ConfigurableNamingStrategy(Function.identity(), ' ');
+ return propertyName -> camelCase.translateName(space.translateName(propertyName));
+ case PropertyNamingStrategy.CASE_INSENSITIVE:
+ return propertyName -> propertyName;
+ default:
+ throw new IllegalArgumentException(val + " unknown as PropertyNamingStrategy");
+ }
+ }
+ if (PropertyNamingStrategy.class.isInstance(value)) {
+ return PropertyNamingStrategy.class.cast(value);
+ }
+ throw new IllegalArgumentException(value + " not supported as PropertyNamingStrategy");
+ }
+
+ private PropertyNamingStrategy camelCaseStrategy() {
+ return propertyName -> Character.toUpperCase(propertyName.charAt(0)) + (propertyName.length() > 1 ? propertyName.substring(1) : "");
+ }
+
+ private static class ConfigurableNamingStrategy implements PropertyNamingStrategy {
+ private final Function<Character, Character> converter;
+ private final char separator;
+
+ public ConfigurableNamingStrategy(final Function<Character, Character> wordConverter, final char sep) {
+ this.converter = wordConverter;
+ this.separator = sep;
+ }
+
+ @Override
+ public String translateName(final String propertyName) {
+ final StringBuilder global = new StringBuilder();
+
+ final StringBuilder current = new StringBuilder();
+ for (int i = 0; i < propertyName.length(); i++) {
+ final char c = propertyName.charAt(i);
+ if (Character.isUpperCase(c)) {
+ final char transformed = converter.apply(c);
+ if (current.length() > 0) {
+ global.append(current).append(separator);
+ current.setLength(0);
+ }
+ current.append(transformed);
+ } else {
+ current.append(c);
+ }
+ }
+ if (current.length() > 0) {
+ global.append(current);
+ } else {
+ global.setLength(global.length() - 1); // remove last sep
+ }
+ return global.toString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbConverter.java
new file mode 100644
index 0000000..9758d6e
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbConverter.java
@@ -0,0 +1,51 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import org.apache.johnzon.mapper.Converter;
+
+import javax.json.bind.JsonbException;
+import javax.json.bind.adapter.JsonbAdapter;
+
+// TODO
+public class JsonbConverter implements Converter<Object> {
+ private final JsonbAdapter adapter;
+
+ public JsonbConverter(final JsonbAdapter adapter) {
+ this.adapter = adapter;
+ }
+
+ @Override
+ public String toString(final Object instance) {
+ try {
+ return adapter.adaptTo(instance);
+ } catch (final Exception e) {
+ throw new JsonbException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public Object fromString(String text) {
+ try {
+ return adapter.adaptFrom(text);
+ } catch (final Exception e) {
+ throw new JsonbException(e.getMessage(), e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverter.java
new file mode 100644
index 0000000..813009c
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.Date;
+
+public class JsonbDateConverter extends JsonbDateConverterBase<Date> {
+ public JsonbDateConverter(final JsonbDateFormat dateFormat) {
+ super(dateFormat);
+ }
+
+ @Override
+ public String toString(final Date instance) {
+ return formatter == null ? Long.toString(instance.getTime()) : formatter.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(instance.getTime()), ZoneOffset.UTC));
+ }
+
+ @Override
+ public Date fromString(final String text) {
+ return formatter == null ? new Date(Long.parseLong(text)) : Date.from(LocalDateTime.parse(text, formatter).toInstant(ZoneOffset.UTC));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverterBase.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverterBase.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverterBase.java
new file mode 100644
index 0000000..8d961c4
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbDateConverterBase.java
@@ -0,0 +1,35 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import java.time.format.DateTimeFormatter;
+
+public abstract class JsonbDateConverterBase<T> extends JsonbLocaleParserConverterBase<T> {
+ protected final DateTimeFormatter formatter;
+
+ protected JsonbDateConverterBase(final JsonbDateFormat dateFormat) {
+ final String value = dateFormat.value();
+ final String locale = dateFormat.locale();
+ final boolean ms = value.equals(JsonbDateFormat.TIME_IN_MILLIS);
+ formatter = ms ? null :
+ (!locale.equals(JsonbDateFormat.DEFAULT_LOCALE) ?
+ DateTimeFormatter.ofPattern(value).withLocale(newLocale(locale)) : DateTimeFormatter.ofPattern(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateConverter.java
new file mode 100644
index 0000000..fa8578d
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import java.time.LocalDate;
+import java.util.concurrent.TimeUnit;
+
+public class JsonbLocalDateConverter extends JsonbDateConverterBase<LocalDate> {
+ public JsonbLocalDateConverter(final JsonbDateFormat dateFormat) {
+ super(dateFormat);
+ }
+
+ @Override
+ public String toString(final LocalDate instance) {
+ return formatter == null ? Long.toString(TimeUnit.DAYS.toMillis(instance.toEpochDay())) : instance.format(formatter);
+ }
+
+ @Override
+ public LocalDate fromString(final String text) {
+ return formatter == null ? LocalDate.ofEpochDay(TimeUnit.MILLISECONDS.toDays(Long.parseLong(text))) : LocalDate.parse(text, formatter);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateTimeConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateTimeConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateTimeConverter.java
new file mode 100644
index 0000000..b0c3018
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocalDateTimeConverter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+public class JsonbLocalDateTimeConverter extends JsonbDateConverterBase<LocalDateTime> {
+ public JsonbLocalDateTimeConverter(final JsonbDateFormat dateFormat) {
+ super(dateFormat);
+ }
+
+ @Override
+ public String toString(final LocalDateTime instance) {
+ return formatter == null ? Long.toString(instance.toInstant(ZoneOffset.UTC).toEpochMilli()) : instance.format(formatter);
+ }
+
+ @Override
+ public LocalDateTime fromString(final String text) {
+ return formatter == null ? LocalDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(text)), ZoneOffset.UTC) : LocalDateTime.parse(text, formatter);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocaleParserConverterBase.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocaleParserConverterBase.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocaleParserConverterBase.java
new file mode 100644
index 0000000..414a7a5
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbLocaleParserConverterBase.java
@@ -0,0 +1,35 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import org.apache.johnzon.mapper.Converter;
+
+import java.util.Locale;
+
+public abstract class JsonbLocaleParserConverterBase<T> implements Converter<T> {
+ protected Locale newLocale(final String locale) {
+ final String[] parts = locale.split("-");
+ switch (parts.length) {
+ case 1: return new Locale(locale);
+ case 2: return new Locale(parts[0], parts[1]);
+ case 3: return new Locale(parts[0], parts[1], parts[2]);
+ default: throw new IllegalArgumentException(locale);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbNumberConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbNumberConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbNumberConverter.java
new file mode 100644
index 0000000..563968e
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbNumberConverter.java
@@ -0,0 +1,77 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import javax.json.bind.annotation.JsonbNumberFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.text.ParseException;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class JsonbNumberConverter extends JsonbLocaleParserConverterBase<Number> {
+ private final Supplier<NumberFormat> delegateFactory; // NumberFormat is not thread safe
+ private final Queue<NumberFormat> pool = new ArrayBlockingQueue<>(30); // configurable?
+
+ public JsonbNumberConverter(final JsonbNumberFormat numberFormat) {
+ final String locale = numberFormat.locale();
+ final String format = numberFormat.value();
+ final boolean customLocale = !JsonbNumberFormat.DEFAULT_LOCALE.equals(locale);
+ if (format.isEmpty() && customLocale) {
+ delegateFactory = () -> NumberFormat.getInstance(newLocale(locale));
+ } else if (format.isEmpty()) {
+ delegateFactory = NumberFormat::getInstance;
+ } else if (customLocale) {
+ delegateFactory = () -> new DecimalFormat(format, DecimalFormatSymbols.getInstance(newLocale(locale)));
+ } else {
+ delegateFactory = () -> new DecimalFormat(format);
+ }
+ }
+
+ @Override
+ public String toString(final Number instance) {
+ return execute(f -> f.format(instance));
+ }
+
+ @Override
+ public Number fromString(final String text) {
+ return execute(f -> {
+ try {
+ return f.parse(text);
+ } catch (final ParseException e) {
+ throw new IllegalArgumentException(e);
+ }
+ });
+ }
+
+ private <T> T execute(final Function<NumberFormat, T> function) {
+ NumberFormat format = pool.poll();
+ if (format == null) {
+ format = delegateFactory.get();
+ }
+ try {
+ return function.apply(format);
+ } finally {
+ pool.add(format);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbValueConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbValueConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbValueConverter.java
new file mode 100644
index 0000000..a4b6ec3
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbValueConverter.java
@@ -0,0 +1,34 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import org.apache.johnzon.mapper.Converter;
+
+// TODO?
+public class JsonbValueConverter implements Converter<Object> {
+ @Override
+ public String toString(final Object instance) {
+ return String.valueOf(instance);
+ }
+
+ @Override
+ public Object fromString(final String text) {
+ return text;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbZonedDateTimeConverter.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbZonedDateTimeConverter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbZonedDateTimeConverter.java
new file mode 100644
index 0000000..d5ce9fc
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JsonbZonedDateTimeConverter.java
@@ -0,0 +1,42 @@
+/*
+ * 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.johnzon.jsonb.converter;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+
+public class JsonbZonedDateTimeConverter extends JsonbDateConverterBase<ZonedDateTime> {
+ private static final ZoneId UTC = ZoneId.of("UTC");
+
+ public JsonbZonedDateTimeConverter(final JsonbDateFormat dateFormat) {
+ super(dateFormat);
+ }
+
+ @Override
+ public String toString(final ZonedDateTime instance) {
+ return formatter == null ? Long.toString(instance.toInstant().toEpochMilli()) : instance.format(formatter);
+ }
+
+ @Override
+ public ZonedDateTime fromString(final String text) {
+ return formatter == null ? ZonedDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(text)), UTC) : ZonedDateTime.parse(text, formatter);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/main/resources/META-INF/services/javax.json.bind.spi.JsonbProvider
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/main/resources/META-INF/services/javax.json.bind.spi.JsonbProvider b/johnzon-jsonb/src/main/resources/META-INF/services/javax.json.bind.spi.JsonbProvider
new file mode 100644
index 0000000..4edadc5
--- /dev/null
+++ b/johnzon-jsonb/src/main/resources/META-INF/services/javax.json.bind.spi.JsonbProvider
@@ -0,0 +1 @@
+org.apache.johnzon.jsonb.JohnzonProvider
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonProviderTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonProviderTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonProviderTest.java
new file mode 100644
index 0000000..b35bd2d
--- /dev/null
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonProviderTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.junit.Test;
+
+import javax.json.bind.spi.JsonbProvider;
+
+import static org.junit.Assert.assertNotNull;
+
+public class JohnzonProviderTest {
+ @Test
+ public void provider() {
+ assertNotNull(JsonbProvider.provider());
+ }
+
+ @Test
+ public void create() {
+ assertNotNull(JsonbProvider.provider().create());
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
new file mode 100644
index 0000000..4b19cff
--- /dev/null
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.junit.Test;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.spi.JsonbProvider;
+import java.io.StringReader;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+
+import static org.junit.Assert.assertEquals;
+
+public class JsonbReadTest {
+ @Test
+ public void simple() {
+ assertEquals("test", JsonbProvider.provider().create().build().fromJson(new StringReader("{\"value\":\"test\"}"), Simple.class).value);
+ }
+
+ @Test
+ public void propertyMapping() {
+ assertEquals("test", JsonbProvider.provider().create().build().fromJson(new StringReader("{\"simple\":\"test\"}"), SimpleProperty.class).value);
+ }
+
+ @Test
+ public void date() { // ok, can fail at midnight, acceptable risk
+ final String date = DateTimeFormatter.ofPattern("d. LLLL yyyy").format(LocalDate.now());
+ assertEquals(
+ LocalDate.now().getYear(),
+ JsonbProvider.provider().create().build().fromJson(new StringReader("{\"date\":\"" + date + "\"}"), DateFormatting.class).date.getYear());
+ }
+
+ public static class Simple {
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class SimpleProperty {
+ @JsonbProperty("simple")
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class SimplePropertyNillable {
+ @JsonbProperty(nillable = true)
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class DateFormatting {
+ @JsonbDateFormat(value = "d. LLLL yyyy")
+ @JsonbProperty(nillable = true)
+ private LocalDate date;
+
+ public LocalDate getDate() {
+ return date;
+ }
+
+ public void setDate(final LocalDate value) {
+ this.date = value;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/b65d149a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
----------------------------------------------------------------------
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
new file mode 100644
index 0000000..273c7fc
--- /dev/null
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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.johnzon.jsonb;
+
+import org.junit.Test;
+
+import javax.json.bind.annotation.JsonbDateFormat;
+import javax.json.bind.annotation.JsonbProperty;
+import javax.json.bind.spi.JsonbProvider;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+
+public class JsonbWriteTest {
+ @Test
+ public void simple() {
+ final Simple simple = new Simple();
+ simple.setValue("test");
+ assertEquals("{\"value\":\"test\"}", JsonbProvider.provider().create().build().toJson(simple));
+ }
+
+ @Test
+ public void propertyMapping() {
+ final SimpleProperty simple = new SimpleProperty();
+ simple.setValue("test");
+ assertEquals("{\"simple\":\"test\"}", JsonbProvider.provider().create().build().toJson(simple));
+ }
+
+ @Test
+ public void map() {
+ final Map<String, String> map = new HashMap<>();
+ map.put("a", "b");
+ assertEquals("{\"a\":\"b\"}", JsonbProvider.provider().create().build().toJson(map));
+ }
+
+ @Test
+ public void list() {
+ final Collection<String> map = asList("a", "b");
+ assertEquals("[\"a\",\"b\"]", JsonbProvider.provider().create().build().toJson(map));
+ }
+
+ @Test
+ public void propertyMappingNotNillable() {
+ final SimpleProperty simple = new SimpleProperty();
+ assertEquals("{}", JsonbProvider.provider().create().build().toJson(simple));
+ }
+
+ @Test
+ public void propertyNillable() {
+ final SimplePropertyNillable simple = new SimplePropertyNillable();
+ assertEquals("{\"value\":null}", JsonbProvider.provider().create().build().toJson(simple));
+ }
+
+ @Test
+ public void date() {
+ final DateFormatting simple = new DateFormatting();
+ simple.setDate(LocalDateTime.now());
+ assertEquals("{\"date\":\"" + LocalDateTime.now().getYear() + "\"}", JsonbProvider.provider().create().build().toJson(simple));
+ }
+
+ public static class Simple {
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class SimpleProperty {
+ @JsonbProperty("simple")
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class SimplePropertyNillable {
+ @JsonbProperty(nillable = true)
+ private String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(final String value) {
+ this.value = value;
+ }
+ }
+
+ public static class DateFormatting {
+ @JsonbDateFormat(value = "yyyy")
+ @JsonbProperty(nillable = true)
+ private LocalDateTime date;
+
+ public LocalDateTime getDate() {
+ return date;
+ }
+
+ public void setDate(final LocalDateTime value) {
+ this.date = value;
+ }
+ }
+}