001/* 002 * ModeShape (http://www.modeshape.org) 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.modeshape.common.util; 017 018import static org.hamcrest.core.Is.is; 019import static org.hamcrest.core.IsNull.notNullValue; 020import static org.junit.Assert.assertThat; 021import java.lang.reflect.Method; 022import java.util.ArrayList; 023import java.util.List; 024import java.util.Map; 025import org.junit.Before; 026import org.junit.Test; 027import org.modeshape.common.CommonI18n; 028import org.modeshape.common.annotation.Category; 029import org.modeshape.common.annotation.Description; 030import org.modeshape.common.annotation.Label; 031import org.modeshape.common.collection.Problem; 032import org.modeshape.common.collection.Problem.Status; 033import org.modeshape.common.i18n.I18n; 034import org.modeshape.common.util.Reflection.Property; 035 036/** 037 * @author Randall Hauch 038 */ 039public class ReflectionTest { 040 041 private String string; 042 private List<String> stringList; 043 private Reflection stringReflection; 044 private Reflection stringListReflection; 045 046 @Before 047 public void setUp() { 048 string = "This is string #"; 049 stringList = new ArrayList<String>(); 050 for (int i = 0; i != 10; ++i) { 051 stringList.add(string + (i + 1)); 052 } 053 stringReflection = new Reflection(String.class); 054 stringListReflection = new Reflection(List.class); 055 } 056 057 @Test 058 public void shouldGetClassNameForClass() { 059 assertThat(Reflection.getClassName(String.class), is(String.class.getName())); 060 assertThat(Reflection.getClassName(ArrayList.class), is(ArrayList.class.getName())); 061 assertThat(Reflection.getClassName(StringUtil.class), is(StringUtil.class.getName())); 062 } 063 064 @Test 065 public void shouldGetClassNameOfInterface() { 066 assertThat(Reflection.getClassName(CharSequence.class), is(CharSequence.class.getName())); 067 assertThat(Reflection.getClassName(List.class), is(List.class.getName())); 068 } 069 070 @Test 071 public void shouldGetClassNameWithPrimitive() { 072 assertThat(Reflection.getClassName(Integer.TYPE), is("int")); 073 assertThat(Reflection.getClassName(Boolean.TYPE), is("boolean")); 074 assertThat(Reflection.getClassName(Long.TYPE), is("long")); 075 assertThat(Reflection.getClassName(Short.TYPE), is("short")); 076 assertThat(Reflection.getClassName(Float.TYPE), is("float")); 077 assertThat(Reflection.getClassName(Double.TYPE), is("double")); 078 assertThat(Reflection.getClassName(Character.TYPE), is("char")); 079 assertThat(Reflection.getClassName(Byte.TYPE), is("byte")); 080 assertThat(Reflection.getClassName(Void.TYPE), is("void")); 081 } 082 083 @Test 084 public void shouldGetClassNameWith1DPrimitiveArray() { 085 assertThat(Reflection.getClassName(new int[0].getClass()), is("int[]")); 086 assertThat(Reflection.getClassName(new boolean[0].getClass()), is("boolean[]")); 087 assertThat(Reflection.getClassName(new long[0].getClass()), is("long[]")); 088 assertThat(Reflection.getClassName(new short[0].getClass()), is("short[]")); 089 assertThat(Reflection.getClassName(new float[0].getClass()), is("float[]")); 090 assertThat(Reflection.getClassName(new double[0].getClass()), is("double[]")); 091 assertThat(Reflection.getClassName(new char[0].getClass()), is("char[]")); 092 assertThat(Reflection.getClassName(new byte[0].getClass()), is("byte[]")); 093 } 094 095 @Test 096 public void shouldGetClassNameWith2DPrimitiveArray() { 097 assertThat(Reflection.getClassName(new int[0][0].getClass()), is("int[][]")); 098 assertThat(Reflection.getClassName(new boolean[0][0].getClass()), is("boolean[][]")); 099 assertThat(Reflection.getClassName(new long[0][0].getClass()), is("long[][]")); 100 assertThat(Reflection.getClassName(new short[0][0].getClass()), is("short[][]")); 101 assertThat(Reflection.getClassName(new float[0][0].getClass()), is("float[][]")); 102 assertThat(Reflection.getClassName(new double[0][0].getClass()), is("double[][]")); 103 assertThat(Reflection.getClassName(new char[0][0].getClass()), is("char[][]")); 104 assertThat(Reflection.getClassName(new byte[0][0].getClass()), is("byte[][]")); 105 } 106 107 @Test 108 public void shouldGetClassNameWith3DPrimitiveArray() { 109 assertThat(Reflection.getClassName(new int[0][0][0].getClass()), is("int[][][]")); 110 assertThat(Reflection.getClassName(new boolean[0][0][0].getClass()), is("boolean[][][]")); 111 assertThat(Reflection.getClassName(new long[0][0][0].getClass()), is("long[][][]")); 112 assertThat(Reflection.getClassName(new short[0][0][0].getClass()), is("short[][][]")); 113 assertThat(Reflection.getClassName(new float[0][0][0].getClass()), is("float[][][]")); 114 assertThat(Reflection.getClassName(new double[0][0][0].getClass()), is("double[][][]")); 115 assertThat(Reflection.getClassName(new char[0][0][0].getClass()), is("char[][][]")); 116 assertThat(Reflection.getClassName(new byte[0][0][0].getClass()), is("byte[][][]")); 117 } 118 119 @Test 120 public void shouldGetClassNameWith8DPrimitiveArray() { 121 assertThat(Reflection.getClassName(new int[0][0][0][0][0][0][0][0].getClass()), is("int[][][][][][][][]")); 122 assertThat(Reflection.getClassName(new boolean[0][0][0][0][0][0][0][0].getClass()), is("boolean[][][][][][][][]")); 123 assertThat(Reflection.getClassName(new long[0][0][0][0][0][0][0][0].getClass()), is("long[][][][][][][][]")); 124 assertThat(Reflection.getClassName(new short[0][0][0][0][0][0][0][0].getClass()), is("short[][][][][][][][]")); 125 assertThat(Reflection.getClassName(new float[0][0][0][0][0][0][0][0].getClass()), is("float[][][][][][][][]")); 126 assertThat(Reflection.getClassName(new double[0][0][0][0][0][0][0][0].getClass()), is("double[][][][][][][][]")); 127 assertThat(Reflection.getClassName(new char[0][0][0][0][0][0][0][0].getClass()), is("char[][][][][][][][]")); 128 assertThat(Reflection.getClassName(new byte[0][0][0][0][0][0][0][0].getClass()), is("byte[][][][][][][][]")); 129 } 130 131 @Test 132 public void shouldHaveTargetClass() { 133 assertThat(stringReflection.getTargetClass() == String.class, is(true)); 134 assertThat(stringListReflection.getTargetClass() == List.class, is(true)); 135 } 136 137 @Test 138 public void shouldFindMethodsWithExactMatchingName() { 139 Method[] stringMethods = stringReflection.findMethods("indexOf", true); 140 assertThat(stringMethods.length, is(4)); 141 for (Method method : stringMethods) { 142 assertThat(method.getName(), is("indexOf")); 143 } 144 stringMethods = stringReflection.findMethods("length", true); 145 assertThat(stringMethods.length, is(1)); 146 for (Method method : stringMethods) { 147 assertThat(method.getName(), is("length")); 148 } 149 } 150 151 @Test 152 public void shouldFindMethodsWithNameMatchingRegularExpression() { 153 Method[] stringMethods = stringReflection.findMethods("indexO.", true); 154 assertThat(stringMethods.length, is(4)); 155 for (Method method : stringMethods) { 156 assertThat(method.getName(), is("indexOf")); 157 } 158 stringMethods = stringReflection.findMethods(".+gth", true); 159 assertThat(stringMethods.length, is(1)); 160 for (Method method : stringMethods) { 161 assertThat(method.getName(), is("length")); 162 } 163 } 164 165 @Test 166 public void shouldNotFindMethodsWhenThereAreNoMethodsWithThatName() { 167 assertThat(stringReflection.findMethods("size", true).length, is(0)); 168 assertThat(stringListReflection.findMethods("argleBargle", true).length, is(0)); 169 } 170 171 @Test 172 public void shouldGetAllPropertiesOnJavaBean() throws Exception { 173 Status status = Status.INFO; 174 int code = 121; 175 I18n msg = CommonI18n.argumentMayNotBeEmpty; 176 Object[] params = new Object[] {"argName"}; 177 String resource = "The source"; 178 String location = "The place to be"; 179 Throwable throwable = null; 180 Problem problem = new Problem(status, code, msg, params, resource, location, throwable); 181 Reflection reflection = new Reflection(Problem.class); 182 List<Property> props = reflection.getAllPropertiesOn(problem); 183 Map<String, Property> propsByName = reflection.getAllPropertiesByNameOn(problem); 184 185 assertThat(props.size(), is(8)); 186 assertThat(propsByName.size(), is(8)); 187 assertThat(props.containsAll(propsByName.values()), is(true)); 188 189 Property property = propsByName.remove("status"); 190 assertThat(property.getName(), is("status")); 191 assertThat(property.getLabel(), is("Status")); 192 assertThat(property.getType().equals(Status.class), is(true)); 193 assertThat(property.isReadOnly(), is(true)); 194 assertThat(property, is(findProperty(property.getName(), props))); 195 assertValue(reflection, problem, property, status); 196 197 property = propsByName.remove("code"); 198 assertThat(property.getName(), is("code")); 199 assertThat(property.getLabel(), is("Code")); 200 assertThat(property.getType().equals(Integer.TYPE), is(true)); 201 assertThat(property.isReadOnly(), is(true)); 202 assertValue(reflection, problem, property, code); 203 204 property = propsByName.remove("message"); 205 assertThat(property.getName(), is("message")); 206 assertThat(property.getLabel(), is("Message")); 207 assertThat(property.getType().equals(I18n.class), is(true)); 208 assertThat(property.isReadOnly(), is(true)); 209 assertValue(reflection, problem, property, msg); 210 211 property = propsByName.remove("messageString"); 212 assertThat(property.getName(), is("messageString")); 213 assertThat(property.getLabel(), is("Message String")); 214 assertThat(property.getType().equals(String.class), is(true)); 215 assertThat(property.isReadOnly(), is(true)); 216 assertValue(reflection, problem, property, msg.text(params)); 217 218 property = propsByName.remove("parameters"); 219 assertThat(property.getName(), is("parameters")); 220 assertThat(property.getLabel(), is("Parameters")); 221 assertThat(property.getType().equals(Object[].class), is(true)); 222 assertThat(property.isReadOnly(), is(true)); 223 assertValue(reflection, problem, property, params); 224 225 property = propsByName.remove("resource"); 226 assertThat(property.getName(), is("resource")); 227 assertThat(property.getLabel(), is("Resource")); 228 assertThat(property.getType().equals(String.class), is(true)); 229 assertThat(property.isReadOnly(), is(true)); 230 assertValue(reflection, problem, property, resource); 231 232 property = propsByName.remove("location"); 233 assertThat(property.getName(), is("location")); 234 assertThat(property.getLabel(), is("Location")); 235 assertThat(property.getType().equals(String.class), is(true)); 236 assertThat(property.isReadOnly(), is(true)); 237 assertValue(reflection, problem, property, location); 238 239 property = propsByName.remove("throwable"); 240 assertThat(property.getName(), is("throwable")); 241 assertThat(property.getLabel(), is("Throwable")); 242 assertThat(property.getType().equals(Throwable.class), is(true)); 243 assertThat(property.isReadOnly(), is(true)); 244 assertValue(reflection, problem, property, throwable); 245 246 assertThat(propsByName.isEmpty(), is(true)); 247 } 248 249 @Test 250 public void shouldUseAnnotationsOnClassFieldsForProperties() throws Exception { 251 SomeStructure structure = new SomeStructure(); 252 structure.setCount(33); 253 structure.setIdentifier("This is the identifier value"); 254 Reflection reflection = new Reflection(SomeStructure.class); 255 List<Property> props = reflection.getAllPropertiesOn(structure); 256 Map<String, Property> propsByName = reflection.getAllPropertiesByNameOn(structure); 257 258 assertThat(props.size(), is(3)); 259 assertThat(propsByName.size(), is(3)); 260 261 Property property = propsByName.remove("identifier"); 262 assertThat(property.getName(), is("identifier")); 263 assertThat(property.getLabel(), is(CommonI18n.noMoreContent.text())); 264 assertThat(property.getDescription(), is(CommonI18n.nullActivityMonitorTaskName.text())); 265 assertThat(property.getCategory(), is(CommonI18n.noMoreContent.text())); 266 assertThat(property.getType().equals(String.class), is(true)); 267 assertThat(property.isReadOnly(), is(false)); 268 assertThat(property, is(findProperty(property.getName(), props))); 269 assertValue(reflection, structure, property, structure.getIdentifier()); 270 271 property = propsByName.remove("count"); 272 assertThat(property.getName(), is("count")); 273 assertThat(property.getLabel(), is("Count")); 274 assertThat(property.getDescription(), is("This is the count")); 275 assertThat(property.getCategory(), is("")); 276 assertThat(property.getType().equals(Integer.TYPE), is(true)); 277 assertThat(property.isReadOnly(), is(false)); 278 assertValue(reflection, structure, property, structure.getCount()); 279 280 property = propsByName.remove("onFire"); 281 assertThat(property.getName(), is("onFire")); 282 assertThat(property.getLabel(), is("On Fire")); 283 assertThat(property.getDescription(), is("")); 284 assertThat(property.getCategory(), is("")); 285 assertThat(property.getType().equals(Boolean.TYPE), is(true)); 286 assertThat(property.isReadOnly(), is(true)); 287 assertValue(reflection, structure, property, structure.isOnFire()); 288 } 289 290 protected void assertValue( Reflection reflection, 291 Object target, 292 Property property, 293 Object expectedValue ) throws Exception { 294 Object actual = reflection.getProperty(target, property); 295 assertThat(actual, is(expectedValue)); 296 assertThat(reflection.getPropertyAsString(target, property), is(notNullValue())); 297 } 298 299 protected Property findProperty( String propertyName, 300 List<Property> properties ) { 301 for (Property prop : properties) { 302 if (prop.getName().equals(propertyName)) return prop; 303 } 304 return null; 305 } 306 307 protected static class SomeStructure { 308 @Category( i18n = CommonI18n.class, value = "noMoreContent" ) 309 @Label( i18n = CommonI18n.class, value = "noMoreContent" ) 310 @Description( i18n = CommonI18n.class, value = "nullActivityMonitorTaskName" ) 311 private String identifier; 312 @Description( value = "This is the count" ) 313 private int count; 314 private boolean onFire; 315 316 public int getCount() { 317 return count; 318 } 319 320 public String getIdentifier() { 321 return identifier; 322 } 323 324 public boolean isOnFire() { 325 return onFire; 326 } 327 328 public void setCount( int count ) { 329 this.count = count; 330 } 331 332 public void setIdentifier( String identifier ) { 333 this.identifier = identifier; 334 } 335 336 // public void setOnFire( boolean onFire ) { 337 // this.onFire = onFire; 338 // } 339 } 340}