##### Coverage Report - org.seasar.cubby.spi.impl.AbstractConverterProvider

Classes in this File | Line Coverage | Branch Coverage | Complexity
AbstractConverterProvider |
93% | 28/30
73% | 19/26
| 3.7142857142857144;3.714

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.impl;
17 |  |
18 |  |
     import static org.seasar.cubby.internal.util.LogMessages.format;
19 |  |
20 |  |
     import java.util.Collection;
21 |  |
     import java.util.Map;
22 |  |
     import java.util.TreeMap;
23 |  |
24 |  |
     import org.seasar.cubby.converter.Converter;
25 |  |
     import org.seasar.cubby.spi.ConverterProvider;
26 |  |
27 |  |
     /**
28 |  |
      * コンバータプロバイダのスケルトン実装です。
29 |  |
      *
30 |  |
      * @author baba
31 |  |
      */
32 | 19 |
     public abstract class AbstractConverterProvider implements ConverterProvider {
33 |  |
34 |  |
             /**
35 |  |
              * コンバータの一覧を返します。
36 |  |
              *
37 |  |
              * @return コンバータの一覧
38 |  |
              */
39 |  |
             protected abstract Collection<Converter> getConverters();
40 |  |
41 |  |
             /**
42 |  |
              * {@inheritDoc}
43 |  |
              */
44 |  |
             public Converter getConverter(final Class<? extends Converter> converterType) {
45 | 6 |
                     for (final Converter converter : getConverters()) {
46 | 108 |
                             if (converterType.isAssignableFrom(converter.getClass())) {
47 | 6 |
                                     return converter;
48 |  |
                             }
49 |  |
                     }
50 | 0 |
                     throw new IllegalArgumentException(format("ECUB0110", converterType));
51 |  |
             }
52 |  |
53 |  |
             /**
54 |  |
              * {@inheritDoc}
55 |  |
              */
56 |  |
             public Converter getConverter(final Class<?> parameterType,
57 |  |
                             final Class<?> objectType) {
58 | 129 |
                     final Class<?> destType = ConversionUtils
59 |  |
                                     .getWrapperClassIfPrimitive(objectType);
60 | 129 |
                     final Converter converter = getDistanceTable(parameterType, destType);
61 | 129 |
                     return converter;
62 |  |
             }
63 |  |
64 |  |
             private Converter getDistanceTable(final Class<?> parameterType,
65 |  |
                             final Class<?> objectType) {
66 | 129 |
                     final Map<Integer, Converter> distanceTable = new TreeMap<Integer, Converter>();
67 | 129 |
                     for (final Converter converter : getConverters()) {
68 | 2320 |
                             if (!converter.canConvert(parameterType, objectType)) {
69 | 2242 |
                                     continue;
70 |  |
                             }
71 | 78 |
                             final int distance = getDistance(converter.getObjectType(),
72 |  |
                                             objectType);
73 | 78 |
                             distanceTable.put(distance, converter);
74 | 78 |
                     }
75 | 129 |
                     if (distanceTable.isEmpty()) {
76 | 63 |
                             return null;
77 |  |
                     }
78 | 66 |
                     return distanceTable.values().iterator().next();
79 |  |
             }
80 |  |
81 |  |
             private int getDistance(final Class<?> assigner, final Class<?> assignee) {
82 | 78 |
                     return getDistance(assigner, assignee, 0);
83 |  |
             }
84 |  |
85 |  |
             private int getDistance(final Class<?> assigner, final Class<?> assignee,
86 |  |
                             final int distance) {
87 | 90 |
                     if (assignee.equals(assigner)) {
88 | 62 |
                             return distance;
89 |  |
                     }
90 | 28 |
                     if (Enum.class.equals(assigner) && assignee.isEnum()) {
91 | 4 |
                             return distance + 5;
92 |  |
                     }
93 | 24 |
                     if (isImplements(assigner, assignee)) {
94 | 0 |
                             return distance + 5;
95 |  |
                     }
96 |  |
97 | 24 |
                     final Class<?> superClass = assigner.getSuperclass();
98 | 24 |
                     if (superClass == null) {
99 | 12 |
                             return distance + 10;
100 |  |
                     }
101 | 12 |
                     return getDistance(superClass, assignee, distance + 10);
102 |  |
             }
103 |  |
104 |  |
             private boolean isImplements(final Class<?> assigner,
105 |  |
                             final Class<?> assignee) {
106 | 24 |
                     return !assigner.isInterface() && assignee.isInterface()
107 |  |
                                     && assignee.isAssignableFrom(assigner);
108 |  |
             }
109 |  |
110 |  |
     }