/**
* 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.config;
import static org.hamcrest.Matchers.*;
import static org.jsonschema2pojo.integration.util.CodeGenerationHelper.config;
import static org.junit.Assert.*;
import static org.fest.util.Lists.newArrayList;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeDiagnosingMatcher;
import org.hamcrest.TypeSafeMatcher;
import org.jsonschema2pojo.integration.util.Jsonschema2PojoRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.Parameterized;
/**
* Checks general properties of includeAccessors and different configurations.
*
* @author Christian Trimble
*
*/
@SuppressWarnings({ "rawtypes" })
@RunWith(Parameterized.class)
public class IncludeAccessorsPropertiesIT {
public static final String PACKAGE = "com.example";
public static final String PRIMITIVE_JSON = "/schema/properties/primitiveProperties.json";
public static final String PRIMITIVE_TYPE = "com.example.PrimitiveProperties";
@Parameters
public static Collection<Object[]> parameters() {
return Arrays.asList(new Object[][] {
{ PRIMITIVE_JSON, PRIMITIVE_TYPE, config() },
{ PRIMITIVE_JSON, PRIMITIVE_TYPE, config("useJodaDates", true) },
{ PRIMITIVE_JSON, PRIMITIVE_TYPE, config("includeAdditionalProperties", false) }
});
}
@Rule public Jsonschema2PojoRule schemaRule = new Jsonschema2PojoRule();
private String path;
private String typeName;
private Map<String, Object> includeAccessorsFalse;
private Map<String, Object> includeAccessorsTrue;
public IncludeAccessorsPropertiesIT(String path, String typeName, Map<String, Object> config) {
this.path = path;
this.typeName = typeName;
this.includeAccessorsFalse = configWithIncludeAccessors(config, false);
this.includeAccessorsTrue = configWithIncludeAccessors(config, true);
}
@Test
public void noGettersOrSettersWhenFalse() throws ClassNotFoundException, SecurityException, NoSuchMethodException, NoSuchFieldException {
ClassLoader resultsClassLoader = schemaRule.generateAndCompile(path, PACKAGE, includeAccessorsFalse);
Class generatedType = resultsClassLoader.loadClass(typeName);
assertThat("getters and setters should not exist", generatedType.getDeclaredMethods(), everyItemInArray(anyOf(methodWhitelist(), not(fieldGetterOrSetter()))));
}
@Test
public void hasGettersOrSettersWhenTrue() throws ClassNotFoundException, SecurityException, NoSuchMethodException, NoSuchFieldException {
ClassLoader resultsClassLoader = schemaRule.generateAndCompile(path, PACKAGE, includeAccessorsTrue);
Class generatedType = resultsClassLoader.loadClass(typeName);
assertThat("a getter or setter should be found.", generatedType.getDeclaredMethods(), hasItemInArray(allOf(not(methodWhitelist()), fieldGetterOrSetter())));
}
@Test
public void onlyHasPublicInstanceFieldsWhenFalse() throws ClassNotFoundException, SecurityException, NoSuchMethodException, NoSuchFieldException {
ClassLoader resultsClassLoader = schemaRule.generateAndCompile(path, PACKAGE, includeAccessorsFalse);
Class generatedType = resultsClassLoader.loadClass(typeName);
assertThat("only public instance fields exist", generatedType.getDeclaredFields(), everyItemInArray(anyOf(hasModifiers(Modifier.STATIC), fieldWhitelist(), hasModifiers(Modifier.PUBLIC))));
}
@Test
public void noPublicInstanceFieldsWhenTrue() throws ClassNotFoundException, SecurityException, NoSuchMethodException, NoSuchFieldException {
ClassLoader resultsClassLoader = schemaRule.generateAndCompile(path, PACKAGE, includeAccessorsTrue);
Class generatedType = resultsClassLoader.loadClass(typeName);
assertThat("only public instance fields exist", generatedType.getDeclaredFields(), everyItemInArray(anyOf(not(hasModifiers(Modifier.PUBLIC)), fieldWhitelist())));
}
private static Map<String, Object> configWithIncludeAccessors(Map<String, Object> template, boolean includeAccessors) {
Map<String, Object> config = new HashMap<String, Object>(template);
config.put("includeAccessors", includeAccessors);
return config;
}
private static <M extends Member> Matcher<M> hasModifiers(final int modifiers) {
return new TypeSafeMatcher<M>() {
@Override
public void describeTo(Description description) {
description.appendText("has modifier ").appendValue(Modifier.toString(modifiers));
}
@Override
protected boolean matchesSafely(M item) {
int masked = item.getModifiers() & modifiers;
return masked == modifiers;
}
};
}
private static <M extends Member> Matcher<M> nameMatches(final Matcher<String> nameMatcher) {
return new TypeSafeMatcher<M>() {
@Override
public void describeTo(Description description) {
description.appendText("name ").appendDescriptionOf(nameMatcher);
}
@Override
protected boolean matchesSafely(M item) {
return nameMatcher.matches(item.getName());
}
};
}
private static <T> Matcher<T[]> everyItemInArray(final Matcher<T> itemMatcher) {
return new TypeSafeDiagnosingMatcher<T[]>() {
@Override
public void describeTo(Description description) {
description.appendText("every item in array is ").appendDescriptionOf(itemMatcher);
}
@Override
protected boolean matchesSafely(T[] items, Description mismatchDescription) {
for (T item : items) {
if (!itemMatcher.matches(item)) {
mismatchDescription.appendText("an item ");
itemMatcher.describeMismatch(item, mismatchDescription);
return false;
}
}
return true;
}
};
}
private static <M extends Member> Matcher<M> methodWhitelist() {
return nameMatches(isIn(newArrayList("setAdditionalProperty", "getAdditionalProperties")));
}
private static <M extends Member> Matcher<M> fieldWhitelist() {
return nameMatches(isIn(newArrayList("additionalProperties")));
}
private static <M extends Member> Matcher<M> fieldGetterOrSetter() {
return nameMatches(anyOf(startsWith("get"), startsWith("set")));
}
}