1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.properties.internal

File DefaultConverterManager.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

32
53
5
1
230
122
26
0.49
10.6
5
5.2

Classes

Class Line # Actions
DefaultConverterManager 56 53 0% 26 6
0.9333333493.3%
 

Contributing tests

This file is covered by 845 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.properties.internal;
21   
22    import java.lang.reflect.ParameterizedType;
23    import java.lang.reflect.Type;
24    import java.lang.reflect.WildcardType;
25   
26    import javax.inject.Inject;
27    import javax.inject.Named;
28    import javax.inject.Provider;
29    import javax.inject.Singleton;
30   
31    import org.slf4j.Logger;
32    import org.xwiki.component.annotation.Component;
33    import org.xwiki.component.manager.ComponentLookupException;
34    import org.xwiki.component.manager.ComponentManager;
35    import org.xwiki.component.util.DefaultParameterizedType;
36    import org.xwiki.component.util.ReflectionUtils;
37    import org.xwiki.properties.ConverterManager;
38    import org.xwiki.properties.converter.ConversionException;
39    import org.xwiki.properties.converter.Converter;
40   
41    /**
42    * Default implementation for {@link ConverterManager}.
43    * <p>
44    * It try to find a {@link Converter} for the provided target type. If it can't find:
45    * <ul>
46    * <li>if the type is an {@link Enum}, it use the {@link Converter} with component hint "enum"</li>
47    * <li>then it use the default {@link Converter} (which is based on {@link org.apache.commons.beanutils.ConvertUtils} by
48    * default)</li>
49    * </ul>
50    *
51    * @version $Id: 102cfc6786e91c93ea034bf565268a79edb73e2e $
52    * @since 2.0M2
53    */
54    @Component
55    @Singleton
 
56    public class DefaultConverterManager implements ConverterManager
57    {
58    /**
59    * Use to find the proper {@link Converter} component for provided target type.
60    */
61    @Inject
62    @Named("context")
63    private Provider<ComponentManager> componentManagerProvider;
64   
65    /**
66    * Used when no direct {@link Converter} can be found for provided target type and the target type is an
67    * {@link Enum}.
68    */
69    @Inject
70    private Converter<Enum> enumConverter;
71   
72    /**
73    * Used when no direct {@link Converter} can be found for provided target type.
74    */
75    @Inject
76    private Converter defaultConverter;
77   
78    /**
79    * The logger to use for logging.
80    */
81    @Inject
82    private Logger logger;
83   
 
84  237548 toggle @Override
85    public <T> T convert(Type targetType, Object value)
86    {
87    // If the value is already of the right type return it
88  237540 if (targetType instanceof Class && ((Class<?>) targetType).isInstance(value)) {
89  58349 return (T) value;
90    }
91   
92    // Handle wildcards (<? extends OtherType>)
93  179181 if (targetType instanceof WildcardType) {
94  6 Type[] upperBounds = ((WildcardType) targetType).getUpperBounds();
95   
96  6 if (upperBounds.length == 0) {
97    // If the asked type is <?>, don't convert anything
98  0 return (T) value;
99    } else {
100  6 return convert(upperBounds[0], value);
101    }
102    }
103   
104    // Converter type
105  179174 Type converterType = targetType;
106  179175 if (converterType == String.class && value != null) {
107  1682 converterType = value.getClass();
108    }
109   
110    // Convert
111  179173 Converter<T> converter = lookupConverter(converterType);
112   
113  179179 if (converter != null) {
114  179175 return converter.convert(targetType, value);
115    } else {
116  0 throw new ConversionException(
117    "Cannot find Converter to convert value [" + value + "] to type [" + targetType + "] ");
118    }
119    }
120   
121    /**
122    * Find the right {@link Converter} for the provided {@link Class}.
123    *
124    * @param <T> the type in which the provided value has to be converted
125    * @param targetType the type to convert to
126    * @return the {@link Converter} corresponding to the class
127    */
 
128  179174 toggle private <T> Converter<T> lookupConverter(Type targetType)
129    {
130    // Try with complete type
131  179172 Converter<T> converter = getConverter(targetType);
132   
133    // Try with simple class
134  179178 if (converter == null && targetType instanceof ParameterizedType) {
135  16101 Class<?> targetClass = ReflectionUtils.getTypeClass(targetType);
136  16101 converter = getConverter(targetClass);
137    }
138   
139  179176 if (converter == null) {
140  68257 if (targetType instanceof Class && Enum.class.isAssignableFrom((Class<?>) targetType)) {
141    // It's an Enum
142  46404 converter = (Converter<T>) this.enumConverter;
143    } else {
144    // Fallback on default converter
145   
146  21855 this.logger.debug("Using the default Converter for type [{}]", targetType);
147   
148  21855 converter = this.defaultConverter;
149    }
150    }
151   
152  179177 return converter;
153    }
154   
155    /**
156    * @param <T> the type in which the provided value has to be converted
157    * @param targetType the type for which the converter has been registered
158    * @return the converter associated to the provided type
159    */
 
160  195274 toggle private <T> Converter<T> getConverter(Type targetType)
161    {
162  195272 try {
163  195273 ComponentManager componentManager = this.componentManagerProvider.get();
164   
165  195279 ParameterizedType converterType = new DefaultParameterizedType(null, Converter.class, targetType);
166  195279 if (componentManager.hasComponent(converterType)) {
167  110918 return componentManager.getInstance(converterType);
168    }
169   
170    // Old way of registering converters
171  84361 String typeGenericName = getTypeGenericName(targetType);
172  84362 if (componentManager.hasComponent(Converter.class, typeGenericName)) {
173  1 return componentManager.getInstance(Converter.class, typeGenericName);
174    }
175    } catch (ComponentLookupException e) {
176  0 throw new ConversionException("Failed to initialize converter for target type [" + targetType + "]", e);
177    }
178   
179  84361 return null;
180    }
181   
182    /**
183    * Get class name without generics.
184    *
185    * @param type the type
186    * @return type name without generics
187    */
 
188  116551 toggle private String getTypeName(Type type)
189    {
190  116551 String name;
191  116552 if (type instanceof Class) {
192  100443 name = ((Class<?>) type).getName();
193  16105 } else if (type instanceof ParameterizedType) {
194  16103 name = ((Class<?>) ((ParameterizedType) type).getRawType()).getName();
195    } else {
196  2 name = type.toString();
197    }
198   
199  116548 return name;
200    }
201   
202    /**
203    * Get type name.
204    *
205    * @param type the type
206    * @return type name
207    */
 
208  116551 toggle private String getTypeGenericName(Type type)
209    {
210  116549 StringBuilder sb = new StringBuilder(getTypeName(type));
211   
212  116553 if (type instanceof ParameterizedType) {
213  16103 ParameterizedType parameterizedType = (ParameterizedType) type;
214   
215  16103 Type[] generics = parameterizedType.getActualTypeArguments();
216  16103 if (generics.length > 0) {
217  16103 sb.append('<');
218  48294 for (int i = 0; i < generics.length; ++i) {
219  32191 if (i > 0) {
220  16088 sb.append(',');
221    }
222  32191 sb.append(getTypeGenericName(generics[i]));
223    }
224  16103 sb.append('>');
225    }
226    }
227   
228  116551 return sb.toString();
229    }
230    }