Coverage Report - org.seasar.cubby.spi.beans.impl.DefaultBeanDescProvider
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultBeanDescProvider
92%
49/53
95%
19/20
0
DefaultBeanDescProvider$BeanDescImpl
100%
11/11
100%
4/4
0
DefaultBeanDescProvider$ParameterizedClassDescImpl
83%
10/12
50%
1/2
0
DefaultBeanDescProvider$PropertyDescImpl
72%
63/88
63%
33/52
0
 
 1  
 /*
 2  
  * Copyright 2004-2009 the Seasar Foundation and the Others.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 13  
  * either express or implied. See the License for the specific language
 14  
  * governing permissions and limitations under the License.
 15  
  */
 16  
 package org.seasar.cubby.spi.beans.impl;
 17  
 
 18  
 import java.beans.BeanInfo;
 19  
 import java.beans.IntrospectionException;
 20  
 import java.beans.Introspector;
 21  
 import java.beans.PropertyDescriptor;
 22  
 import java.lang.annotation.Annotation;
 23  
 import java.lang.reflect.Array;
 24  
 import java.lang.reflect.GenericArrayType;
 25  
 import java.lang.reflect.InvocationTargetException;
 26  
 import java.lang.reflect.Method;
 27  
 import java.lang.reflect.ParameterizedType;
 28  
 import java.lang.reflect.Type;
 29  
 import java.util.Collections;
 30  
 import java.util.HashMap;
 31  
 import java.util.LinkedHashMap;
 32  
 import java.util.Map;
 33  
 import java.util.concurrent.ConcurrentHashMap;
 34  
 
 35  
 import org.seasar.cubby.spi.BeanDescProvider;
 36  
 import org.seasar.cubby.spi.beans.BeanDesc;
 37  
 import org.seasar.cubby.spi.beans.IllegalPropertyException;
 38  
 import org.seasar.cubby.spi.beans.ParameterizedClassDesc;
 39  
 import org.seasar.cubby.spi.beans.PropertyDesc;
 40  
 import org.seasar.cubby.spi.beans.PropertyNotFoundException;
 41  
 
 42  
 /**
 43  
  * {@link BeanDesc} のプロバイダの標準的な実装です。
 44  
  * <p>
 45  
  * {@link Introspector} によって生成されるメタ情報を元に {@link BeanDesc} を構築します。
 46  
  * </p>
 47  
  * 
 48  
  * @author baba
 49  
  * @since 2.0.0
 50  
  */
 51  383
 public class DefaultBeanDescProvider implements BeanDescProvider {
 52  
 
 53  
         /** プリミティブ型のデフォルト値の <code>Map</code>。 */
 54  
         private static final Map<Class<?>, Object> PRIMITIVE_TYPE_DEFAULT_VALUES;
 55  
         static {
 56  1
                 final Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();
 57  1
                 map.put(boolean.class, Boolean.FALSE);
 58  1
                 map.put(char.class, Character.valueOf('\u0000'));
 59  1
                 map.put(byte.class, Byte.valueOf((byte) 0));
 60  1
                 map.put(short.class, Short.valueOf((short) 0));
 61  1
                 map.put(int.class, Integer.valueOf(0));
 62  1
                 map.put(long.class, Long.valueOf(0L));
 63  1
                 map.put(float.class, Float.valueOf(0F));
 64  1
                 map.put(double.class, Double.valueOf(0D));
 65  1
                 PRIMITIVE_TYPE_DEFAULT_VALUES = Collections.unmodifiableMap(map);
 66  1
         }
 67  
 
 68  
         /** <code>BeanDesc</code> のキャッシュ。 */
 69  86
         private final Map<Class<?>, BeanDesc> beanDescCache = new ConcurrentHashMap<Class<?>, BeanDesc>(
 70  
                         1024);
 71  
 
 72  
         /**
 73  
          * {@inheritDoc}
 74  
          */
 75  
         public BeanDesc getBeanDesc(final Class<?> clazz) {
 76  78
                 if (beanDescCache.containsKey(clazz)) {
 77  43
                         return beanDescCache.get(clazz);
 78  
                 }
 79  
 
 80  35
                 synchronized (clazz) {
 81  35
                         if (beanDescCache.containsKey(clazz)) {
 82  0
                                 return beanDescCache.get(clazz);
 83  
                         }
 84  
 
 85  
                         try {
 86  35
                                 final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
 87  35
                                 final BeanDesc beanDesc = new BeanDescImpl(clazz, beanInfo);
 88  35
                                 beanDescCache.put(clazz, beanDesc);
 89  35
                                 return beanDesc;
 90  0
                         } catch (final IntrospectionException e) {
 91  0
                                 throw new IllegalStateException(e);
 92  
                         }
 93  0
                 }
 94  
         }
 95  
 
 96  
         /**
 97  
          * {@link BeanDesc} の実装です。
 98  
          * <p>
 99  
          * {@link Introspector} に処理を委譲します。
 100  
          * </p>
 101  
          * 
 102  
          * @author baba
 103  
          * @since 2.0.0
 104  
          */
 105  
         private static class BeanDescImpl implements BeanDesc {
 106  
 
 107  
                 /** JavaBean のクラス。 */
 108  
                 private final Class<?> clazz;
 109  
 
 110  
                 /** {@link PropertyDesc} のキャッシュ。 */
 111  35
                 private final Map<String, PropertyDesc> propertyDescMap = new LinkedHashMap<String, PropertyDesc>();
 112  
 
 113  
                 /**
 114  
                  * インスタンス化します。
 115  
                  * 
 116  
                  * @param clazz
 117  
                  *            JavaBean のクラス
 118  
                  * @param beanInfo
 119  
                  *            JavaBean の情報
 120  
                  */
 121  35
                 public BeanDescImpl(final Class<?> clazz, final BeanInfo beanInfo) {
 122  35
                         this.clazz = clazz;
 123  325
                         for (final PropertyDescriptor propertyDescriptor : beanInfo
 124  
                                         .getPropertyDescriptors()) {
 125  290
                                 propertyDescMap.put(propertyDescriptor.getName(),
 126  
                                                 new PropertyDescImpl(clazz, propertyDescriptor));
 127  
                         }
 128  35
                 }
 129  
 
 130  
                 /**
 131  
                  * {@inheritDoc}
 132  
                  */
 133  
                 public boolean hasPropertyDesc(final String propertyName) {
 134  8
                         return propertyDescMap.containsKey(propertyName);
 135  
                 }
 136  
 
 137  
                 /**
 138  
                  * {@inheritDoc}
 139  
                  */
 140  
                 public PropertyDesc getPropertyDesc(final String propertyName)
 141  
                                 throws PropertyNotFoundException {
 142  48
                         if (!propertyDescMap.containsKey(propertyName)) {
 143  2
                                 throw new PropertyNotFoundException(clazz, propertyName);
 144  
                         }
 145  46
                         return propertyDescMap.get(propertyName);
 146  
                 }
 147  
 
 148  
                 /**
 149  
                  * {@inheritDoc}
 150  
                  */
 151  
                 public PropertyDesc[] getPropertyDescs() {
 152  30
                         return propertyDescMap.values().toArray(new PropertyDesc[0]);
 153  
                 }
 154  
 
 155  
         }
 156  
 
 157  
         /**
 158  
          * {@link PropertyDesc} の実装です。
 159  
          * <p>
 160  
          * {@link PropertyDescriptor} に処理を委譲します。
 161  
          * </p>
 162  
          * 
 163  
          * @author baba
 164  
          * @since 2.0.0
 165  
          */
 166  
         private static class PropertyDescImpl implements PropertyDesc {
 167  
 
 168  
                 /** JavaBean のクラス。 */
 169  
                 private final Class<?> clazz;
 170  
 
 171  
                 /** プロパティの記述。 */
 172  
                 private final PropertyDescriptor propertyDescriptor;
 173  
 
 174  
                 /** パラメタ化されたクラスの記述。 */
 175  
                 private final ParameterizedClassDesc parameterizedClassDesc;
 176  
 
 177  
                 /** アノテーションのキャッシュ。 */
 178  290
                 private final Map<Class<? extends Annotation>, Annotation> annotationCache = new HashMap<Class<? extends Annotation>, Annotation>();
 179  
 
 180  
                 /**
 181  
                  * インスタンス化します。
 182  
                  * 
 183  
                  * @param clazz
 184  
                  *            JavaBean のクラス
 185  
                  * @param propertyDescriptor
 186  
                  *            プロパティの記述
 187  
                  */
 188  
                 PropertyDescImpl(final Class<?> clazz,
 189  290
                                 final PropertyDescriptor propertyDescriptor) {
 190  290
                         this.clazz = clazz;
 191  290
                         this.propertyDescriptor = propertyDescriptor;
 192  
 
 193  290
                         if (propertyDescriptor.getReadMethod() != null) {
 194  273
                                 parameterizedClassDesc = createParameterizedClassDesc(propertyDescriptor
 195  
                                                 .getReadMethod().getGenericReturnType());
 196  17
                         } else if (propertyDescriptor.getWriteMethod() != null) {
 197  17
                                 parameterizedClassDesc = createParameterizedClassDesc(propertyDescriptor
 198  
                                                 .getWriteMethod().getParameterTypes()[0]);
 199  
                         } else {
 200  0
                                 parameterizedClassDesc = null;
 201  
                         }
 202  290
                 }
 203  
 
 204  
                 /**
 205  
                  * {@inheritDoc}
 206  
                  */
 207  
                 public String getPropertyName() {
 208  214
                         return propertyDescriptor.getName();
 209  
                 }
 210  
 
 211  
                 /**
 212  
                  * {@inheritDoc}
 213  
                  */
 214  
                 public Class<?> getPropertyType() {
 215  104
                         return propertyDescriptor.getPropertyType();
 216  
                 }
 217  
 
 218  
                 /**
 219  
                  * {@inheritDoc}
 220  
                  */
 221  
                 public Method getReadMethod() {
 222  211
                         return propertyDescriptor.getReadMethod();
 223  
                 }
 224  
 
 225  
                 /**
 226  
                  * {@inheritDoc}
 227  
                  */
 228  
                 public boolean hasReadMethod() {
 229  0
                         return this.getReadMethod() != null;
 230  
                 }
 231  
 
 232  
                 /**
 233  
                  * {@inheritDoc}
 234  
                  */
 235  
                 public Method getWriteMethod() {
 236  266
                         return propertyDescriptor.getWriteMethod();
 237  
                 }
 238  
 
 239  
                 /**
 240  
                  * {@inheritDoc}
 241  
                  */
 242  
                 public boolean hasWriteMethod() {
 243  0
                         return this.getWriteMethod() != null;
 244  
                 }
 245  
 
 246  
                 /**
 247  
                  * {@inheritDoc}
 248  
                  */
 249  
                 public boolean isReadable() {
 250  7
                         return propertyDescriptor.getReadMethod() != null;
 251  
                 }
 252  
 
 253  
                 /**
 254  
                  * {@inheritDoc}
 255  
                  */
 256  
                 public boolean isWritable() {
 257  0
                         return propertyDescriptor.getWriteMethod() != null;
 258  
                 }
 259  
 
 260  
                 /**
 261  
                  * {@inheritDoc}
 262  
                  */
 263  
                 public Object getValue(final Object target)
 264  
                                 throws IllegalPropertyException {
 265  51
                         final Method method = this.getReadMethod();
 266  51
                         if (method == null) {
 267  2
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 268  
                                                 .getName(), new IllegalStateException(
 269  
                                                 propertyDescriptor.getName() + " is not readable."));
 270  
                         }
 271  
                         try {
 272  49
                                 return method.invoke(target);
 273  0
                         } catch (final IllegalAccessException e) {
 274  0
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 275  
                                                 .getName(), e);
 276  0
                         } catch (final InvocationTargetException e) {
 277  0
                                 final Throwable t = e.getTargetException();
 278  0
                                 if (t instanceof Error) {
 279  0
                                         throw (Error) t;
 280  
                                 }
 281  0
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 282  
                                                 .getName(), e);
 283  
                         }
 284  
                 }
 285  
 
 286  
                 /**
 287  
                  * {@inheritDoc}
 288  
                  */
 289  
                 public void setValue(final Object target, final Object value)
 290  
                                 throws IllegalPropertyException {
 291  106
                         final Method method = this.getWriteMethod();
 292  106
                         if (method == null) {
 293  2
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 294  
                                                 .getName(), new IllegalStateException(
 295  
                                                 propertyDescriptor.getName() + " is not writable."));
 296  
                         }
 297  
                         try {
 298  104
                                 final Class<?> propertyType = propertyDescriptor
 299  
                                                 .getPropertyType();
 300  104
                                 if (value == null && propertyType.isPrimitive()) {
 301  7
                                         method.invoke(target, PRIMITIVE_TYPE_DEFAULT_VALUES
 302  
                                                         .get(propertyType));
 303  
                                 } else {
 304  97
                                         method.invoke(target, value);
 305  
                                 }
 306  1
                         } catch (final IllegalArgumentException e) {
 307  1
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 308  
                                                 .getName(), e);
 309  0
                         } catch (final IllegalAccessException e) {
 310  0
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 311  
                                                 .getName(), e);
 312  0
                         } catch (final InvocationTargetException e) {
 313  0
                                 final Throwable t = e.getTargetException();
 314  0
                                 if (t instanceof Error) {
 315  0
                                         throw (Error) t;
 316  
                                 }
 317  0
                                 throw new IllegalPropertyException(clazz, propertyDescriptor
 318  
                                                 .getName(), e);
 319  103
                         }
 320  103
                 }
 321  
 
 322  
                 /**
 323  
                  * {@inheritDoc}
 324  
                  */
 325  
                 public boolean isParameterized() {
 326  4
                         return parameterizedClassDesc != null
 327  
                                         && parameterizedClassDesc.isParameterizedClass();
 328  
                 }
 329  
 
 330  
                 /**
 331  
                  * {@inheritDoc}
 332  
                  */
 333  
                 public ParameterizedClassDesc getParameterizedClassDesc() {
 334  4
                         return parameterizedClassDesc;
 335  
                 }
 336  
 
 337  
                 /**
 338  
                  * {@inheritDoc}
 339  
                  */
 340  
                 public <T extends Annotation> T getAnnotation(
 341  
                                 final Class<T> annotationClass) {
 342  250
                         if (annotationCache.containsKey(annotationClass)) {
 343  93
                                 return annotationClass.cast(annotationCache
 344  
                                                 .get(annotationClass));
 345  
                         }
 346  
 
 347  157
                         final Method readMethod = this.getReadMethod();
 348  157
                         if (readMethod != null) {
 349  157
                                 final T annotation = findAnnotation(annotationClass, readMethod);
 350  157
                                 if (annotation != null) {
 351  0
                                         annotationCache.put(annotationClass, annotation);
 352  0
                                         return annotation;
 353  
                                 }
 354  
                         }
 355  
 
 356  157
                         final Method writeMethod = this.getWriteMethod();
 357  157
                         if (writeMethod != null) {
 358  143
                                 final T annotation = findAnnotation(annotationClass,
 359  
                                                 writeMethod);
 360  143
                                 if (annotation != null) {
 361  8
                                         annotationCache.put(annotationClass, annotation);
 362  8
                                         return annotation;
 363  
                                 }
 364  
                         }
 365  
 
 366  149
                         annotationCache.put(annotationClass, null);
 367  149
                         return null;
 368  
                 }
 369  
 
 370  
                 /**
 371  
                  * 指定されたメソッドのアノテーションを検索します。
 372  
                  * <p>
 373  
                  * インターフェイスやスーパークラスに定義されたメソッドの定義からもアノテーションが見つかるまで検索します。
 374  
                  * アノテーションが見つからなかった場合は <code>null</code> を返します。
 375  
                  * </p>
 376  
                  * 
 377  
                  * @param <T>
 378  
                  *            アノテーションの型
 379  
                  * @param annotationClass
 380  
                  *            アノテーションの型
 381  
                  * @param method
 382  
                  *            メソッド
 383  
                  * @return アノテーションが見つかった場合はそのアノテーション、見つからなかった場合は <code>null</code>
 384  
                  */
 385  
                 private static <T extends Annotation> T findAnnotation(
 386  
                                 final Class<T> annotationClass, final Method method) {
 387  300
                         final String methodName = method.getName();
 388  300
                         final Class<?>[] parameterTypes = method.getParameterTypes();
 389  300
                         for (Class<?> target = method.getDeclaringClass(); !target
 390  278
                                         .equals(Object.class); target = target.getSuperclass()) {
 391  286
                                 final T annotation = getAnnotation(annotationClass, target,
 392  
                                                 methodName, parameterTypes);
 393  286
                                 if (annotation != null) {
 394  8
                                         return annotation;
 395  
                                 }
 396  278
                                 final T annotationOfInterfaces = getAnnotationOfInterfaces(
 397  
                                                 annotationClass, target, methodName, parameterTypes);
 398  278
                                 if (annotationOfInterfaces != null) {
 399  0
                                         return annotationOfInterfaces;
 400  
                                 }
 401  
                         }
 402  292
                         return null;
 403  
                 }
 404  
 
 405  
                 /**
 406  
                  * 指定されたクラスが実装するインターフェイスにメソッド名、パラメータ型でシグニチャを指定されたメソッドが定義されていれば、
 407  
                  * そのメソッドに定義されたアノテーションを返します。
 408  
                  * 
 409  
                  * @param <T>
 410  
                  *            アノテーションの型
 411  
                  * @param annotationClass
 412  
                  *            アノテーションの型
 413  
                  * @param clazz
 414  
                  *            クラス
 415  
                  * @param methodName
 416  
                  *            メソッド名
 417  
                  * @param parameterTypes
 418  
                  *            パラメータの型
 419  
                  * @return アノテーション
 420  
                  */
 421  
                 private static <T extends Annotation> T getAnnotationOfInterfaces(
 422  
                                 final Class<T> annotationClass, final Class<?> clazz,
 423  
                                 final String methodName, final Class<?>[] parameterTypes) {
 424  278
                         for (final Class<?> interfaceClass : clazz.getInterfaces()) {
 425  0
                                 final T annotation = getAnnotation(annotationClass,
 426  
                                                 interfaceClass, methodName, parameterTypes);
 427  0
                                 if (annotation != null) {
 428  0
                                         return annotation;
 429  
                                 }
 430  
                         }
 431  278
                         return null;
 432  
                 }
 433  
 
 434  
                 /**
 435  
                  * 指定されたクラスにメソッド名、パラメータ型でシグニチャを指定されたメソッドが定義されていれば、
 436  
                  * そのメソッドに定義されたアノテーションを返します。
 437  
                  * 
 438  
                  * @param <T>
 439  
                  *            アノテーションの型
 440  
                  * @param annotationClass
 441  
                  *            アノテーションの型
 442  
                  * @param clazz
 443  
                  *            クラス
 444  
                  * @param methodName
 445  
                  *            メソッド名
 446  
                  * @param parameterTypes
 447  
                  *            パラメータの型
 448  
                  * @return アノテーション
 449  
                  */
 450  
                 private static <T extends Annotation> T getAnnotation(
 451  
                                 final Class<T> annotationClass, final Class<?> clazz,
 452  
                                 final String methodName,
 453  
                                 @SuppressWarnings("unchecked") final Class[] parameterTypes) {
 454  
                         try {
 455  286
                                 final Method method = clazz.getDeclaredMethod(methodName,
 456  
                                                 parameterTypes);
 457  286
                                 if (method.isAnnotationPresent(annotationClass)) {
 458  8
                                         return method.getAnnotation(annotationClass);
 459  
                                 }
 460  0
                         } catch (final NoSuchMethodException e) {
 461  
                                 // do nothing
 462  278
                         }
 463  
 
 464  278
                         return null;
 465  
                 }
 466  
 
 467  
                 /**
 468  
                  * {@inheritDoc}
 469  
                  */
 470  
                 public boolean isAnnotationPresent(
 471  
                                 final Class<? extends Annotation> annotationClass) {
 472  98
                         return this.getAnnotation(annotationClass) != null;
 473  
                 }
 474  
 
 475  
         }
 476  
 
 477  
         /**
 478  
          * {@link ParameterizedClassDesc}の実装クラスです。
 479  
          * 
 480  
          * @since 2.0.0
 481  
          * @author baba
 482  
          */
 483  86
         private static class ParameterizedClassDescImpl implements
 484  
                         ParameterizedClassDesc {
 485  
 
 486  
                 /** 原型となるクラス */
 487  
                 protected Class<?> rawClass;
 488  
 
 489  
                 /** 型引数を表す{@link ParameterizedClassDesc}の配列 */
 490  
                 protected ParameterizedClassDesc[] arguments;
 491  
 
 492  
                 /**
 493  
                  * インスタンスを構築します。
 494  
                  */
 495  0
                 public ParameterizedClassDescImpl() {
 496  0
                 }
 497  
 
 498  
                 /**
 499  
                  * インスタンスを構築します。
 500  
                  * 
 501  
                  * @param rawClass
 502  
                  *            原型となるクラス
 503  
                  */
 504  258
                 public ParameterizedClassDescImpl(final Class<?> rawClass) {
 505  258
                         this.rawClass = rawClass;
 506  258
                 }
 507  
 
 508  
                 /**
 509  
                  * インスタンスを構築します。
 510  
                  * 
 511  
                  * @param rawClass
 512  
                  *            原型となるクラス
 513  
                  * @param arguments
 514  
                  *            型引数を表す{@link ParameterizedClassDesc}の配列
 515  
                  */
 516  
                 public ParameterizedClassDescImpl(final Class<?> rawClass,
 517  46
                                 final ParameterizedClassDesc[] arguments) {
 518  46
                         this.rawClass = rawClass;
 519  46
                         this.arguments = arguments;
 520  46
                 }
 521  
 
 522  
                 /**
 523  
                  * {@inheritDoc}
 524  
                  */
 525  
                 public boolean isParameterizedClass() {
 526  4
                         return arguments != null;
 527  
                 }
 528  
 
 529  
                 /**
 530  
                  * {@inheritDoc}
 531  
                  */
 532  
                 public Class<?> getRawClass() {
 533  4
                         return rawClass;
 534  
                 }
 535  
 
 536  
                 /**
 537  
                  * {@inheritDoc}
 538  
                  */
 539  
                 public ParameterizedClassDesc[] getArguments() {
 540  4
                         return arguments;
 541  
                 }
 542  
 
 543  
         }
 544  
 
 545  
         /**
 546  
          * {@link Type}を表現する{@link ParameterizedClassDesc}を作成して返します。
 547  
          * 
 548  
          * @param type
 549  
          *            型
 550  
          * @return 型を表現する{@link ParameterizedClassDesc}
 551  
          */
 552  
         private static ParameterizedClassDesc createParameterizedClassDesc(
 553  
                         final Type type) {
 554  339
                 final Class<?> rowClass = getRawClass(type);
 555  339
                 if (rowClass == null) {
 556  35
                         return null;
 557  
                 }
 558  304
                 final Type[] parameterTypes = getGenericParameter(type);
 559  304
                 if (parameterTypes == null) {
 560  258
                         final ParameterizedClassDescImpl desc = new ParameterizedClassDescImpl(
 561  
                                         rowClass);
 562  258
                         return desc;
 563  
                 } else {
 564  46
                         final ParameterizedClassDesc[] parameterDescs = new ParameterizedClassDesc[parameterTypes.length];
 565  95
                         for (int i = 0; i < parameterTypes.length; ++i) {
 566  49
                                 parameterDescs[i] = createParameterizedClassDesc(parameterTypes[i]);
 567  
                         }
 568  46
                         final ParameterizedClassDescImpl desc = new ParameterizedClassDescImpl(
 569  
                                         rowClass, parameterDescs);
 570  46
                         return desc;
 571  
                 }
 572  
         }
 573  
 
 574  
         /**
 575  
          * <code>type</code>の原型を返します。
 576  
          * <p>
 577  
          * <code>type</code>が原型でもパラメータ化された型でもない場合は<code>null</code>を返します。
 578  
          * </p>
 579  
          * 
 580  
          * @param type
 581  
          *            タイプ
 582  
          * @return <code>type</code>の原型
 583  
          */
 584  
         private static Class<?> getRawClass(final Type type) {
 585  386
                 if (Class.class.isInstance(type)) {
 586  304
                         return Class.class.cast(type);
 587  
                 }
 588  82
                 if (ParameterizedType.class.isInstance(type)) {
 589  46
                         final ParameterizedType parameterizedType = ParameterizedType.class
 590  
                                         .cast(type);
 591  46
                         return getRawClass(parameterizedType.getRawType());
 592  
                 }
 593  36
                 if (GenericArrayType.class.isInstance(type)) {
 594  1
                         final GenericArrayType genericArrayType = GenericArrayType.class
 595  
                                         .cast(type);
 596  1
                         final Class<?> rawClass = getRawClass(genericArrayType
 597  
                                         .getGenericComponentType());
 598  1
                         return Array.newInstance(rawClass, 0).getClass();
 599  
                 }
 600  35
                 return null;
 601  
         }
 602  
 
 603  
         /**
 604  
          * <code>type</code>の型引数の配列を返します。
 605  
          * <p>
 606  
          * <code>type</code>がパラメータ化された型でない場合は<code>null</code>を返します。
 607  
          * </p>
 608  
          * 
 609  
          * @param type
 610  
          *            タイプ
 611  
          * @return <code>type</code>の型引数の配列
 612  
          */
 613  
         private static Type[] getGenericParameter(final Type type) {
 614  305
                 if (ParameterizedType.class.isInstance(type)) {
 615  46
                         return ParameterizedType.class.cast(type).getActualTypeArguments();
 616  
                 }
 617  259
                 if (GenericArrayType.class.isInstance(type)) {
 618  1
                         return getGenericParameter(GenericArrayType.class.cast(type)
 619  
                                         .getGenericComponentType());
 620  
                 }
 621  258
                 return null;
 622  
         }
 623  
 
 624  
 }