View Javadoc

1   /*
2    * Copyright 2004 Ronald Blaschke.
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, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.rblasch.convert.type;
17  
18  import org.rblasch.convert.assertion.Assertion;
19  
20  import java.util.ArrayList;
21  import java.util.Arrays;
22  import java.util.Collections;
23  import java.util.HashMap;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Map;
27  
28  /***
29   * @author Ronald Blaschke
30   */
31  public class Types {
32      // cache for already resolved types
33      private static Map/*<Object, Type>*/ types = new HashMap();
34  
35      private static boolean isKnown(final Object key) {
36          return types.containsKey(key);
37      }
38  
39      private static void makeKnown(final Object key, final Type t) {
40          Type knownT = null;
41          if (types.containsValue(t)) {
42              for (final Iterator i = types.values().iterator(); i.hasNext();) {
43                  final Type ti = (Type) i.next();
44                  if (t.equals(ti)) {
45                      knownT = ti;
46                  }
47              }
48          } else {
49              knownT = t;
50          }
51          Assertion.ensure(knownT != null, "Known type must not be null");
52  
53          types.put(key, knownT);
54      }
55  
56      private static Type knownType(final Object key) {
57          if (isKnown(key)) {
58              return (Type) types.get(key);
59          } else {
60              throw new UnknownTypeException(key + " is not a known type");
61          }
62      }
63  
64      public static Type findTypeByName(final String name) throws UnknownTypeException {
65          return findType(name);
66      }
67  
68      public static Type primitiveArrayType() {
69          return ArrayType.getInstance();
70      }
71  
72      public static Type nullType() {
73          return NullType.getInstance();
74      }
75  
76      public static Type findPrimitiveType(final Class c) {
77          return new PrimitiveType(c);
78      }
79  
80      public static Type findTypeByClass(final Class c) {
81          return findType(c);
82      }
83  
84      public static Type findPTypeByName(final String t, final String p1) throws UnknownTypeException {
85          return findPType(t, Collections.singletonList(p1));
86      }
87  
88      public static Type findPTypeByClass(final Class c, final Class p1) throws UnknownTypeException {
89          return findPType(c, Collections.singletonList(p1));
90      }
91  
92      public static Type findPTypeByType(final Type t, final Type p1) throws UnknownTypeException {
93          return findPType(t, Collections.singletonList(p1));
94      }
95  
96      public static ParameterizableType findPTypeByType(final Type t, final List/*<Type>*/ parameters) throws UnknownTypeException {
97          return findPType(t, parameters);
98      }
99  
100     private static ParameterizableType findPType(final Object type, final List/*<Object>*/ parameters) throws UnknownTypeException {
101         final List/* <Object>*/ request = new ArrayList(2);
102         request.add(type);
103         request.addAll(parameters);
104         if (isKnown(request)) {
105             return (ParameterizableType) knownType(request);
106         } else {
107             final ParameterizableType t = findPTypeInternal(type, parameters);
108             makeKnown(request, t);
109             return t;
110         }
111     }
112 
113     private static Type findType(final Object type) throws UnknownTypeException {
114         if (isKnown(type)) {
115             return knownType(type);
116         } else {
117             final Type t = findTypeInternal(type);
118             makeKnown(type, t);
119             return t;
120         }
121     }
122 
123     private static Type findTypeInternal(final Object t) throws UnknownTypeException {
124         if (t instanceof Type) {
125             return (Type) t;
126         } else if (t instanceof String) {
127             return findTypeInternal((String) t);
128         } else if (t instanceof Class) {
129             return findTypeInternal((Class) t);
130         } else {
131             throw new UnknownTypeException("Don't know how to resolve type " + t + " (" + t.getClass() + ")");
132         }
133     }
134 
135     private static Type findTypeInternal(final String name) throws UnknownTypeException {
136         if ("any".equals(name)) {
137             return AnyType.getInstance();
138         } else if ("array".equals(name)) {
139             return ArrayType.getInstance();
140         } else {
141             try {
142                 return PrimitiveType.valueOf(name);
143             } catch (final UnknownTypeException ex) {
144                 try {
145                     return ClassType.valueOf(name);
146                 } catch (final UnknownTypeException ex2) {
147                     try {
148                         return ParameterizableType.valueOf(name);
149                     } catch (final UnknownTypeException ex3) {
150                         throw new UnknownTypeException(name + " is not a known type");
151                     }
152                 }
153             }
154         }
155     }
156 
157     private static Type findTypeInternal(final Class c) throws UnknownTypeException {
158         if (c.isPrimitive()) {
159             return new PrimitiveType(c);
160         } else if (c.isArray()) {
161             return new ParameterizableType(ArrayType.getInstance(),
162                     Arrays.asList(new Type[]{findTypeByClass(c.getComponentType())}));
163         } else {
164             return new ClassType(c);
165         }
166     }
167 
168     private static ParameterizableType findPTypeInternal(final Object t, final List/*<Object>*/ parameters) throws UnknownTypeException {
169         final List/*<Type>*/ l = new ArrayList(parameters.size());
170         for (final Iterator i = parameters.iterator(); i.hasNext();) {
171             l.add(findType(i.next()));
172         }
173         return new ParameterizableType(findType(t), l);
174     }
175 }