Java tutorial
/** * Copyright 2010-2014 Nokia * * Licensed 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.jsonschema2pojo.integration; import static java.lang.reflect.Modifier.*; import static org.hamcrest.Matchers.*; import static org.jsonschema2pojo.integration.util.CodeGenerationHelper.config; import static org.junit.Assert.*; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.hamcrest.core.IsInstanceOf; import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule; import org.junit.BeforeClass; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @SuppressWarnings("rawtypes") public class EnumIT { @ClassRule public static Jsonschema2PojoRule classSchemaRule = new Jsonschema2PojoRule(); @Rule public Jsonschema2PojoRule schemaRule = new Jsonschema2PojoRule(); private static Class parentClass; private static Class<Enum> enumClass; @BeforeClass @SuppressWarnings("unchecked") public static void generateAndCompileEnum() throws ClassNotFoundException { ClassLoader resultsClassLoader = classSchemaRule.generateAndCompile( "/schema/enum/typeWithEnumProperty.json", "com.example", config("propertyWordDelimiters", "_")); parentClass = resultsClassLoader.loadClass("com.example.TypeWithEnumProperty"); enumClass = (Class<Enum>) resultsClassLoader.loadClass("com.example.TypeWithEnumProperty$EnumProperty"); } @Test public void enumPropertyCreatesAStaticInnerType() throws ClassNotFoundException { assertThat(enumClass.isEnum(), is(true)); assertThat(isPublic(enumClass.getModifiers()), is(true)); assertThat(isStatic(enumClass.getModifiers()), is(true)); } @Test public void enumClassIncludesCorrectlyNamedConstants() { assertThat(enumClass.getEnumConstants()[0].name(), is("ONE")); assertThat(enumClass.getEnumConstants()[1].name(), is("SECOND_ONE")); assertThat(enumClass.getEnumConstants()[2].name(), is("_3_RD_ONE")); assertThat(enumClass.getEnumConstants()[3].name(), is("_4_1")); } @Test public void enumContainsWorkingAnnotatedSerializationMethod() throws NoSuchMethodException { Method toString = enumClass.getMethod("value"); assertThat(enumClass.getEnumConstants()[0].toString(), is("one")); assertThat(enumClass.getEnumConstants()[1].toString(), is("secondOne")); assertThat(enumClass.getEnumConstants()[2].toString(), is("3rd one")); assertThat(toString.isAnnotationPresent(JsonValue.class), is(true)); } @Test public void enumContainsWorkingAnnotatedDeserializationMethod() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method fromValue = enumClass.getMethod("fromValue", String.class); assertThat((Enum) fromValue.invoke(enumClass, "one"), is(sameInstance(enumClass.getEnumConstants()[0]))); assertThat((Enum) fromValue.invoke(enumClass, "secondOne"), is(sameInstance(enumClass.getEnumConstants()[1]))); assertThat((Enum) fromValue.invoke(enumClass, "3rd one"), is(sameInstance(enumClass.getEnumConstants()[2]))); assertThat(fromValue.isAnnotationPresent(JsonCreator.class), is(true)); } @Test public void enumDeserializationMethodRejectsInvalidValues() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { Method fromValue = enumClass.getMethod("fromValue", String.class); try { fromValue.invoke(enumClass, "something invalid"); fail(); } catch (InvocationTargetException e) { assertThat(e.getCause(), is(instanceOf(IllegalArgumentException.class))); } } @Test @SuppressWarnings("unchecked") public void enumAtRootCreatesATopLevelType() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/enumAsRoot.json", "com.example"); Class<Enum> rootEnumClass = (Class<Enum>) resultsClassLoader.loadClass("com.example.enums.EnumAsRoot"); assertThat(rootEnumClass.isEnum(), is(true)); assertThat(isPublic(rootEnumClass.getModifiers()), is(true)); } @Test @SuppressWarnings("unchecked") public void intEnumAtRootCreatesIntBackedEnum() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/integerEnumAsRoot.json", "com.example"); Class<Enum> rootEnumClass = (Class<Enum>) resultsClassLoader .loadClass("com.example.enums.IntegerEnumAsRoot"); assertThat(rootEnumClass.isEnum(), is(true)); assertThat(rootEnumClass.getDeclaredMethod("fromValue", Integer.class), is(notNullValue())); assertThat(isPublic(rootEnumClass.getModifiers()), is(true)); } @Test @SuppressWarnings("unchecked") public void doubleEnumAtRootCreatesIntBackedEnum() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/doubleEnumAsRoot.json", "com.example"); Class<Enum> rootEnumClass = (Class<Enum>) resultsClassLoader .loadClass("com.example.enums.DoubleEnumAsRoot"); assertThat(rootEnumClass.isEnum(), is(true)); assertThat(rootEnumClass.getDeclaredMethod("fromValue", Double.class), is(notNullValue())); assertThat(isPublic(rootEnumClass.getModifiers()), is(true)); } @Test @SuppressWarnings("unchecked") public void enumWithEmptyStringAsValue() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/enumWithEmptyString.json", "com.example"); Class<Enum> emptyEnumClass = (Class<Enum>) resultsClassLoader.loadClass("com.example.EnumWithEmptyString"); assertThat(emptyEnumClass.isEnum(), is(true)); assertThat(emptyEnumClass.getEnumConstants()[0].name(), is("__EMPTY__")); } @Test @SuppressWarnings("unchecked") public void enumWithNullValue() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/enumWithNullValue.json", "com.example"); Class<Enum> nullEnumClass = (Class<Enum>) resultsClassLoader.loadClass("com.example.EnumWithNullValue"); assertThat(nullEnumClass.isEnum(), is(true)); assertThat(nullEnumClass.getEnumConstants().length, is(1)); } @Test public void enumWithUppercaseProperty() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule .generateAndCompile("/schema/enum/enumWithUppercaseProperty.json", "com.example"); resultsClassLoader.loadClass("com.example.EnumWithUppercaseProperty"); resultsClassLoader.loadClass("com.example.EnumWithUppercaseProperty$TimeFormat"); } @Test public void enumWithExtendedCharacters() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule .generateAndCompile("/schema/enum/enumWithExtendedCharacters.json", "com.example"); resultsClassLoader.loadClass("com.example.EnumWithExtendedCharacters"); } @Test @SuppressWarnings("unchecked") public void enumWithNoValidCharactersForIdentifier() throws Exception { ClassLoader resultsClassLoader = schemaRule .generateAndCompile("/schema/enum/enumWithNoValidCharactersForIdentifier.json", "com.example"); Class<Enum> enumClass = (Class<Enum>) resultsClassLoader .loadClass("com.example.EnumWithNoValidCharactersForIdentifier"); assertThat(enumClass.getEnumConstants()[0].name(), is("__EMPTY__")); assertThat(enumClass.getEnumConstants()[1].name(), is("__EMPTY___")); assertThat(enumClass.getEnumConstants()[2].name(), is("__EMPTY____")); assertThat(enumClass.getEnumConstants()[0].toString(), is(":")); assertThat(enumClass.getEnumConstants()[1].toString(), is("\u2265")); assertThat(enumClass.getEnumConstants()[2].toString(), is("<")); } @Test public void multipleEnumArraysWithSameName() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { ClassLoader resultsClassLoader = schemaRule .generateAndCompile("/schema/enum/multipleEnumArraysWithSameName.json", "com.example"); resultsClassLoader.loadClass("com.example.MultipleEnumArraysWithSameName"); resultsClassLoader.loadClass("com.example.Status"); resultsClassLoader.loadClass("com.example.Status_"); } @Test @SuppressWarnings({ "unchecked" }) public void enumWithCustomJavaNames() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/enumWithCustomJavaNames.json", "com.example"); Class<?> typeWithEnumProperty = resultsClassLoader.loadClass("com.example.EnumWithCustomJavaNames"); Class<Enum> enumClass = (Class<Enum>) resultsClassLoader .loadClass("com.example.EnumWithCustomJavaNames$EnumProperty"); Object valueWithEnumProperty = typeWithEnumProperty.newInstance(); Method enumSetter = typeWithEnumProperty.getMethod("setEnumProperty", enumClass); enumSetter.invoke(valueWithEnumProperty, enumClass.getEnumConstants()[2]); assertThat(enumClass.getEnumConstants()[0].name(), is("ONE")); assertThat(enumClass.getEnumConstants()[1].name(), is("TWO")); assertThat(enumClass.getEnumConstants()[2].name(), is("THREE")); assertThat(enumClass.getEnumConstants()[3].name(), is("FOUR")); ObjectMapper objectMapper = new ObjectMapper(); String jsonString = objectMapper.writeValueAsString(valueWithEnumProperty); JsonNode jsonTree = objectMapper.readTree(jsonString); assertThat(jsonTree.size(), is(1)); assertThat(jsonTree.has("enum_Property"), is(true)); assertThat(jsonTree.get("enum_Property").isTextual(), is(true)); assertThat(jsonTree.get("enum_Property").asText(), is("3")); } @Test @SuppressWarnings("unchecked") public void intEnumIsDeserializedCorrectly() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, JsonParseException, JsonMappingException, IOException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/integerEnumToSerialize.json", "com.example"); // the schema for a valid instance Class<?> typeWithEnumProperty = resultsClassLoader.loadClass("com.example.enums.IntegerEnumToSerialize"); Class<Enum> enumClass = (Class<Enum>) resultsClassLoader .loadClass("com.example.enums.IntegerEnumToSerialize$TestEnum"); // read the instance into the type ObjectMapper objectMapper = new ObjectMapper(); Object valueWithEnumProperty = objectMapper.readValue("{\"testEnum\" : 2}", typeWithEnumProperty); Method getEnumMethod = typeWithEnumProperty.getDeclaredMethod("getTestEnum"); Method getValueMethod = enumClass.getDeclaredMethod("value"); // call getTestEnum on the value assertThat(getEnumMethod, is(notNullValue())); Object enumObject = getEnumMethod.invoke(valueWithEnumProperty); // assert that the object returned is a) a TestEnum, and b) calling .value() on it returns 2 // as per the json snippet above assertThat(enumObject, IsInstanceOf.instanceOf(enumClass)); assertThat(getValueMethod, is(notNullValue())); assertThat((Integer) getValueMethod.invoke(enumObject), is(2)); } @Test @SuppressWarnings("unchecked") public void intEnumIsSerializedCorrectly() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, JsonParseException, JsonMappingException, IOException, InstantiationException { ClassLoader resultsClassLoader = schemaRule.generateAndCompile("/schema/enum/integerEnumToSerialize.json", "com.example"); // the schema for a valid instance Class<?> typeWithEnumProperty = resultsClassLoader.loadClass("com.example.enums.IntegerEnumToSerialize"); Class<Enum> enumClass = (Class<Enum>) resultsClassLoader .loadClass("com.example.enums.IntegerEnumToSerialize$TestEnum"); // create an instance Object valueWithEnumProperty = typeWithEnumProperty.newInstance(); Method enumSetter = typeWithEnumProperty.getMethod("setTestEnum", enumClass); // call setTestEnum(TestEnum.ONE) enumSetter.invoke(valueWithEnumProperty, enumClass.getEnumConstants()[0]); ObjectMapper objectMapper = new ObjectMapper(); // write our instance out to json String jsonString = objectMapper.writeValueAsString(valueWithEnumProperty); JsonNode jsonTree = objectMapper.readTree(jsonString); assertThat(jsonTree.size(), is(1)); assertThat(jsonTree.has("testEnum"), is(true)); assertThat(jsonTree.get("testEnum").isIntegralNumber(), is(true)); assertThat(jsonTree.get("testEnum").asInt(), is(1)); } @Test @SuppressWarnings("unchecked") public void jacksonCanMarshalEnums() throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, IOException { Object valueWithEnumProperty = parentClass.newInstance(); Method enumSetter = parentClass.getMethod("setEnumProperty", enumClass); enumSetter.invoke(valueWithEnumProperty, enumClass.getEnumConstants()[2]); ObjectMapper objectMapper = new ObjectMapper(); String jsonString = objectMapper.writeValueAsString(valueWithEnumProperty); JsonNode jsonTree = objectMapper.readTree(jsonString); assertThat(jsonTree.size(), is(1)); assertThat(jsonTree.has("enum_Property"), is(true)); assertThat(jsonTree.get("enum_Property").isTextual(), is(true)); assertThat(jsonTree.get("enum_Property").asText(), is("3rd one")); } @Test @SuppressWarnings("unchecked") public void jacksonCanUnmarshalEnums() throws IOException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException { String jsonString = "{\"enum_Property\" : \"3rd one\"}"; Object result = new ObjectMapper().readValue(jsonString, parentClass); Method enumGetter = parentClass.getMethod("getEnumProperty"); assertThat((Enum) enumGetter.invoke(result), is(equalTo(enumClass.getEnumConstants()[2]))); } }