/*
* ModeShape (http://www.modeshape.org)
*
* 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.modeshape.common.util;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.core.IsNull.notNullValue;
import static org.junit.Assert.assertThat;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.modeshape.common.CommonI18n;
import org.modeshape.common.annotation.Category;
import org.modeshape.common.annotation.Description;
import org.modeshape.common.annotation.Label;
import org.modeshape.common.collection.Problem;
import org.modeshape.common.collection.Problem.Status;
import org.modeshape.common.i18n.I18n;
import org.modeshape.common.util.Reflection.Property;
/**
* @author Randall Hauch
*/
public class ReflectionTest {
private String string;
private List<String> stringList;
private Reflection stringReflection;
private Reflection stringListReflection;
@Before
public void setUp() {
string = "This is string #";
stringList = new ArrayList<String>();
for (int i = 0; i != 10; ++i) {
stringList.add(string + (i + 1));
}
stringReflection = new Reflection(String.class);
stringListReflection = new Reflection(List.class);
}
@Test
public void shouldGetClassNameForClass() {
assertThat(Reflection.getClassName(String.class), is(String.class.getName()));
assertThat(Reflection.getClassName(ArrayList.class), is(ArrayList.class.getName()));
assertThat(Reflection.getClassName(StringUtil.class), is(StringUtil.class.getName()));
}
@Test
public void shouldGetClassNameOfInterface() {
assertThat(Reflection.getClassName(CharSequence.class), is(CharSequence.class.getName()));
assertThat(Reflection.getClassName(List.class), is(List.class.getName()));
}
@Test
public void shouldGetClassNameWithPrimitive() {
assertThat(Reflection.getClassName(Integer.TYPE), is("int"));
assertThat(Reflection.getClassName(Boolean.TYPE), is("boolean"));
assertThat(Reflection.getClassName(Long.TYPE), is("long"));
assertThat(Reflection.getClassName(Short.TYPE), is("short"));
assertThat(Reflection.getClassName(Float.TYPE), is("float"));
assertThat(Reflection.getClassName(Double.TYPE), is("double"));
assertThat(Reflection.getClassName(Character.TYPE), is("char"));
assertThat(Reflection.getClassName(Byte.TYPE), is("byte"));
assertThat(Reflection.getClassName(Void.TYPE), is("void"));
}
@Test
public void shouldGetClassNameWith1DPrimitiveArray() {
assertThat(Reflection.getClassName(new int[0].getClass()), is("int[]"));
assertThat(Reflection.getClassName(new boolean[0].getClass()), is("boolean[]"));
assertThat(Reflection.getClassName(new long[0].getClass()), is("long[]"));
assertThat(Reflection.getClassName(new short[0].getClass()), is("short[]"));
assertThat(Reflection.getClassName(new float[0].getClass()), is("float[]"));
assertThat(Reflection.getClassName(new double[0].getClass()), is("double[]"));
assertThat(Reflection.getClassName(new char[0].getClass()), is("char[]"));
assertThat(Reflection.getClassName(new byte[0].getClass()), is("byte[]"));
}
@Test
public void shouldGetClassNameWith2DPrimitiveArray() {
assertThat(Reflection.getClassName(new int[0][0].getClass()), is("int[][]"));
assertThat(Reflection.getClassName(new boolean[0][0].getClass()), is("boolean[][]"));
assertThat(Reflection.getClassName(new long[0][0].getClass()), is("long[][]"));
assertThat(Reflection.getClassName(new short[0][0].getClass()), is("short[][]"));
assertThat(Reflection.getClassName(new float[0][0].getClass()), is("float[][]"));
assertThat(Reflection.getClassName(new double[0][0].getClass()), is("double[][]"));
assertThat(Reflection.getClassName(new char[0][0].getClass()), is("char[][]"));
assertThat(Reflection.getClassName(new byte[0][0].getClass()), is("byte[][]"));
}
@Test
public void shouldGetClassNameWith3DPrimitiveArray() {
assertThat(Reflection.getClassName(new int[0][0][0].getClass()), is("int[][][]"));
assertThat(Reflection.getClassName(new boolean[0][0][0].getClass()), is("boolean[][][]"));
assertThat(Reflection.getClassName(new long[0][0][0].getClass()), is("long[][][]"));
assertThat(Reflection.getClassName(new short[0][0][0].getClass()), is("short[][][]"));
assertThat(Reflection.getClassName(new float[0][0][0].getClass()), is("float[][][]"));
assertThat(Reflection.getClassName(new double[0][0][0].getClass()), is("double[][][]"));
assertThat(Reflection.getClassName(new char[0][0][0].getClass()), is("char[][][]"));
assertThat(Reflection.getClassName(new byte[0][0][0].getClass()), is("byte[][][]"));
}
@Test
public void shouldGetClassNameWith8DPrimitiveArray() {
assertThat(Reflection.getClassName(new int[0][0][0][0][0][0][0][0].getClass()), is("int[][][][][][][][]"));
assertThat(Reflection.getClassName(new boolean[0][0][0][0][0][0][0][0].getClass()), is("boolean[][][][][][][][]"));
assertThat(Reflection.getClassName(new long[0][0][0][0][0][0][0][0].getClass()), is("long[][][][][][][][]"));
assertThat(Reflection.getClassName(new short[0][0][0][0][0][0][0][0].getClass()), is("short[][][][][][][][]"));
assertThat(Reflection.getClassName(new float[0][0][0][0][0][0][0][0].getClass()), is("float[][][][][][][][]"));
assertThat(Reflection.getClassName(new double[0][0][0][0][0][0][0][0].getClass()), is("double[][][][][][][][]"));
assertThat(Reflection.getClassName(new char[0][0][0][0][0][0][0][0].getClass()), is("char[][][][][][][][]"));
assertThat(Reflection.getClassName(new byte[0][0][0][0][0][0][0][0].getClass()), is("byte[][][][][][][][]"));
}
@Test
public void shouldHaveTargetClass() {
assertThat(stringReflection.getTargetClass() == String.class, is(true));
assertThat(stringListReflection.getTargetClass() == List.class, is(true));
}
@Test
public void shouldFindMethodsWithExactMatchingName() {
Method[] stringMethods = stringReflection.findMethods("indexOf", true);
assertThat(stringMethods.length, is(4));
for (Method method : stringMethods) {
assertThat(method.getName(), is("indexOf"));
}
stringMethods = stringReflection.findMethods("length", true);
assertThat(stringMethods.length, is(1));
for (Method method : stringMethods) {
assertThat(method.getName(), is("length"));
}
}
@Test
public void shouldFindMethodsWithNameMatchingRegularExpression() {
Method[] stringMethods = stringReflection.findMethods("indexO.", true);
assertThat(stringMethods.length, is(4));
for (Method method : stringMethods) {
assertThat(method.getName(), is("indexOf"));
}
stringMethods = stringReflection.findMethods(".+gth", true);
assertThat(stringMethods.length, is(1));
for (Method method : stringMethods) {
assertThat(method.getName(), is("length"));
}
}
@Test
public void shouldNotFindMethodsWhenThereAreNoMethodsWithThatName() {
assertThat(stringReflection.findMethods("size", true).length, is(0));
assertThat(stringListReflection.findMethods("argleBargle", true).length, is(0));
}
@Test
public void shouldGetAllPropertiesOnJavaBean() throws Exception {
Status status = Status.INFO;
int code = 121;
I18n msg = CommonI18n.argumentMayNotBeEmpty;
Object[] params = new Object[] {"argName"};
String resource = "The source";
String location = "The place to be";
Throwable throwable = null;
Problem problem = new Problem(status, code, msg, params, resource, location, throwable);
Reflection reflection = new Reflection(Problem.class);
List<Property> props = reflection.getAllPropertiesOn(problem);
Map<String, Property> propsByName = reflection.getAllPropertiesByNameOn(problem);
assertThat(props.size(), is(8));
assertThat(propsByName.size(), is(8));
assertThat(props.containsAll(propsByName.values()), is(true));
Property property = propsByName.remove("status");
assertThat(property.getName(), is("status"));
assertThat(property.getLabel(), is("Status"));
assertThat(property.getType().equals(Status.class), is(true));
assertThat(property.isReadOnly(), is(true));
assertThat(property, is(findProperty(property.getName(), props)));
assertValue(reflection, problem, property, status);
property = propsByName.remove("code");
assertThat(property.getName(), is("code"));
assertThat(property.getLabel(), is("Code"));
assertThat(property.getType().equals(Integer.TYPE), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, code);
property = propsByName.remove("message");
assertThat(property.getName(), is("message"));
assertThat(property.getLabel(), is("Message"));
assertThat(property.getType().equals(I18n.class), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, msg);
property = propsByName.remove("messageString");
assertThat(property.getName(), is("messageString"));
assertThat(property.getLabel(), is("Message String"));
assertThat(property.getType().equals(String.class), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, msg.text(params));
property = propsByName.remove("parameters");
assertThat(property.getName(), is("parameters"));
assertThat(property.getLabel(), is("Parameters"));
assertThat(property.getType().equals(Object[].class), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, params);
property = propsByName.remove("resource");
assertThat(property.getName(), is("resource"));
assertThat(property.getLabel(), is("Resource"));
assertThat(property.getType().equals(String.class), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, resource);
property = propsByName.remove("location");
assertThat(property.getName(), is("location"));
assertThat(property.getLabel(), is("Location"));
assertThat(property.getType().equals(String.class), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, location);
property = propsByName.remove("throwable");
assertThat(property.getName(), is("throwable"));
assertThat(property.getLabel(), is("Throwable"));
assertThat(property.getType().equals(Throwable.class), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, problem, property, throwable);
assertThat(propsByName.isEmpty(), is(true));
}
@Test
public void shouldUseAnnotationsOnClassFieldsForProperties() throws Exception {
SomeStructure structure = new SomeStructure();
structure.setCount(33);
structure.setIdentifier("This is the identifier value");
Reflection reflection = new Reflection(SomeStructure.class);
List<Property> props = reflection.getAllPropertiesOn(structure);
Map<String, Property> propsByName = reflection.getAllPropertiesByNameOn(structure);
assertThat(props.size(), is(3));
assertThat(propsByName.size(), is(3));
Property property = propsByName.remove("identifier");
assertThat(property.getName(), is("identifier"));
assertThat(property.getLabel(), is(CommonI18n.noMoreContent.text()));
assertThat(property.getDescription(), is(CommonI18n.nullActivityMonitorTaskName.text()));
assertThat(property.getCategory(), is(CommonI18n.noMoreContent.text()));
assertThat(property.getType().equals(String.class), is(true));
assertThat(property.isReadOnly(), is(false));
assertThat(property, is(findProperty(property.getName(), props)));
assertValue(reflection, structure, property, structure.getIdentifier());
property = propsByName.remove("count");
assertThat(property.getName(), is("count"));
assertThat(property.getLabel(), is("Count"));
assertThat(property.getDescription(), is("This is the count"));
assertThat(property.getCategory(), is(""));
assertThat(property.getType().equals(Integer.TYPE), is(true));
assertThat(property.isReadOnly(), is(false));
assertValue(reflection, structure, property, structure.getCount());
property = propsByName.remove("onFire");
assertThat(property.getName(), is("onFire"));
assertThat(property.getLabel(), is("On Fire"));
assertThat(property.getDescription(), is(""));
assertThat(property.getCategory(), is(""));
assertThat(property.getType().equals(Boolean.TYPE), is(true));
assertThat(property.isReadOnly(), is(true));
assertValue(reflection, structure, property, structure.isOnFire());
}
protected void assertValue( Reflection reflection,
Object target,
Property property,
Object expectedValue ) throws Exception {
Object actual = reflection.getProperty(target, property);
assertThat(actual, is(expectedValue));
assertThat(reflection.getPropertyAsString(target, property), is(notNullValue()));
}
protected Property findProperty( String propertyName,
List<Property> properties ) {
for (Property prop : properties) {
if (prop.getName().equals(propertyName)) return prop;
}
return null;
}
protected static class SomeStructure {
@Category( i18n = CommonI18n.class, value = "noMoreContent" )
@Label( i18n = CommonI18n.class, value = "noMoreContent" )
@Description( i18n = CommonI18n.class, value = "nullActivityMonitorTaskName" )
private String identifier;
@Description( value = "This is the count" )
private int count;
private boolean onFire;
public int getCount() {
return count;
}
public String getIdentifier() {
return identifier;
}
public boolean isOnFire() {
return onFire;
}
public void setCount( int count ) {
this.count = count;
}
public void setIdentifier( String identifier ) {
this.identifier = identifier;
}
// public void setOnFire( boolean onFire ) {
// this.onFire = onFire;
// }
}
}