| name | class, % | method, % | block, % | line, % |
|---|
| | | | | |
| class ClassTypeLibrary$TypeCategory | 100% (1/1) | 83% (5/6) | 93% (129/138) | 86% (13.8/16) |
| valueOf (String): ClassTypeLibrary$TypeCategory | | 0% (0/1) | 0% (0/5) | 0% (0/1) |
| hasDefaultConstructor (Class): boolean | | 100% (1/1) | 73% (11/15) | 58% (2.9/5) |
| <static initializer> | | 100% (1/1) | 100% (104/104) | 100% (11/11) |
| ClassTypeLibrary$TypeCategory (String, int): void | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| ClassTypeLibrary$TypeCategory (String, int, ClassTypeLibrary$1): void | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| values (): ClassTypeLibrary$TypeCategory [] | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary | 100% (1/1) | 100% (6/6) | 96% (91/95) | 95% (20/21) |
| createType (Class): AbstractIndirectType | | 100% (1/1) | 86% (24/28) | 75% (3/4) |
| ClassTypeLibrary (): void | | 100% (1/1) | 100% (23/23) | 100% (6/6) |
| createReader (CachedLexable): Reader | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| createWriter (CachedAppendable): Writer | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| getType (Class): AbstractIndirectType | | 100% (1/1) | 100% (23/23) | 100% (6/6) |
| getTypeFor (Object): IndirectType | | 100% (1/1) | 100% (9/9) | 100% (3/3) |
| | | | | |
| class ClassTypeLibrary$1 | 100% (1/1) | 100% (2/2) | 100% (19/19) | 100% (3/3) |
| ClassTypeLibrary$1 (ClassTypeLibrary, CachedAppendable): void | | 100% (1/1) | 100% (9/9) | 100% (1/1) |
| write (Object): void | | 100% (1/1) | 100% (10/10) | 100% (2/2) |
| | | | | |
| class ClassTypeLibrary$2 | 100% (1/1) | 100% (3/3) | 100% (29/29) | 100% (3/3) |
| ClassTypeLibrary$2 (ClassTypeLibrary, CachedLexable): void | | 100% (1/1) | 100% (9/9) | 100% (1/1) |
| read (): Object | | 100% (1/1) | 100% (10/10) | 100% (1/1) |
| read (Object): Object | | 100% (1/1) | 100% (10/10) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$1 | 100% (1/1) | 100% (3/3) | 100% (21/21) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$1 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (10/10) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$10 | 100% (1/1) | 100% (3/3) | 100% (13/13) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$10 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (2/2) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$2 | 100% (1/1) | 100% (3/3) | 100% (14/14) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$2 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$3 | 100% (1/1) | 100% (3/3) | 100% (14/14) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$3 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$4 | 100% (1/1) | 100% (3/3) | 100% (14/14) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$4 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (3/3) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$5 | 100% (1/1) | 100% (3/3) | 100% (14/14) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$5 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (3/3) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$6 | 100% (1/1) | 100% (3/3) | 100% (14/14) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$6 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (3/3) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$7 | 100% (1/1) | 100% (3/3) | 100% (14/14) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$7 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (4/4) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$8 | 100% (1/1) | 100% (3/3) | 100% (22/22) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$8 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (11/11) | 100% (1/1) |
| | | | | |
| class ClassTypeLibrary$TypeCategory$9 | 100% (1/1) | 100% (3/3) | 100% (22/22) | 100% (3/3) |
| ClassTypeLibrary$TypeCategory$9 (String, int): void | | 100% (1/1) | 100% (6/6) | 100% (1/1) |
| create (Class): AbstractIndirectType | | 100% (1/1) | 100% (5/5) | 100% (1/1) |
| isMember (Class): boolean | | 100% (1/1) | 100% (11/11) | 100% (1/1) |
| 1 | /* |
| 2 | * This file is part of JON. |
| 3 | * |
| 4 | * JON is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU Lesser General Public License as published by |
| 6 | * the Free Software Foundation; either version 3 of the License, or |
| 7 | * (at your option) any later version. |
| 8 | * |
| 9 | * JON is distributed in the hope that it will be useful, |
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 | * GNU Lesser General Public License for more details. |
| 13 | * |
| 14 | * You should have received a copy of the GNU Lesser General Public License |
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | * |
| 17 | * Copyright 2007 Michael Doberenz |
| 18 | */ |
| 19 | package org.fuwjax.jon; |
| 20 | |
| 21 | import java.util.Collection; |
| 22 | import java.util.HashMap; |
| 23 | import java.util.Map; |
| 24 | |
| 25 | import org.fuwjax.jon.accessor.Symbol; |
| 26 | import org.fuwjax.jon.type.AbstractIndirectType; |
| 27 | import org.fuwjax.jon.type.ArrayType; |
| 28 | import org.fuwjax.jon.type.ByteArrayType; |
| 29 | import org.fuwjax.jon.type.CharArrayType; |
| 30 | import org.fuwjax.jon.type.ClassType; |
| 31 | import org.fuwjax.jon.type.EnumType; |
| 32 | import org.fuwjax.jon.type.ListType; |
| 33 | import org.fuwjax.jon.type.MapType; |
| 34 | import org.fuwjax.jon.type.NullType; |
| 35 | import org.fuwjax.jon.type.ObjectType; |
| 36 | import org.fuwjax.jon.type.PrimitiveType; |
| 37 | import org.fuwjax.jon.type.StringType; |
| 38 | import org.fuwjax.jon.type.UnknownType; |
| 39 | |
| 40 | /** |
| 41 | * The default type library based on the current class hierarchy. |
| 42 | * @author michaeldoberenz |
| 43 | */ |
| 44 | public class ClassTypeLibrary implements IndirectTypeLibrary{ |
| 45 | private Map<Class<?>, AbstractIndirectType> types; |
| 46 | |
| 47 | /** |
| 48 | * The possible categories of indirect types. |
| 49 | * @author michaeldoberenz |
| 50 | */ |
| 51 | private enum TypeCategory{ |
| 52 | /** |
| 53 | * An unknown indirect type. |
| 54 | */ |
| 55 | UNKNOWN{ |
| 56 | @Override |
| 57 | public AbstractIndirectType create(final Class<?> cls){ |
| 58 | return new UnknownType(cls); |
| 59 | } |
| 60 | |
| 61 | @Override |
| 62 | public boolean isMember(final Class<?> cls){ |
| 63 | return cls == null || Object.class.equals(cls); |
| 64 | } |
| 65 | }, |
| 66 | /** |
| 67 | * A byte array indirect type. |
| 68 | */ |
| 69 | BYTE_ARRAY{ |
| 70 | @Override |
| 71 | public AbstractIndirectType create(final Class<?> cls){ |
| 72 | return new ByteArrayType(); |
| 73 | } |
| 74 | |
| 75 | @Override |
| 76 | public boolean isMember(final Class<?> cls){ |
| 77 | return byte[].class.equals(cls); |
| 78 | } |
| 79 | }, |
| 80 | /** |
| 81 | * A char array indirect type. |
| 82 | */ |
| 83 | CHAR_ARRAY{ |
| 84 | @Override |
| 85 | public AbstractIndirectType create(final Class<?> cls){ |
| 86 | return new CharArrayType(); |
| 87 | } |
| 88 | |
| 89 | @Override |
| 90 | public boolean isMember(final Class<?> cls){ |
| 91 | return char[].class.equals(cls); |
| 92 | } |
| 93 | }, |
| 94 | /** |
| 95 | * An array indirect type. |
| 96 | */ |
| 97 | ARRAY{ |
| 98 | @Override |
| 99 | public AbstractIndirectType create(final Class<?> cls){ |
| 100 | return new ArrayType(cls); |
| 101 | } |
| 102 | |
| 103 | @Override |
| 104 | public boolean isMember(final Class<?> cls){ |
| 105 | return cls.isArray(); |
| 106 | } |
| 107 | }, |
| 108 | /** |
| 109 | * An enum indirect type. |
| 110 | */ |
| 111 | ENUM{ |
| 112 | @Override |
| 113 | public AbstractIndirectType create(final Class<?> cls){ |
| 114 | return new EnumType(cls); |
| 115 | } |
| 116 | |
| 117 | @Override |
| 118 | public boolean isMember(final Class<?> cls){ |
| 119 | return cls.isEnum(); |
| 120 | } |
| 121 | }, |
| 122 | /** |
| 123 | * A primitive indirect type. |
| 124 | */ |
| 125 | PRIMITIVE{ |
| 126 | @Override |
| 127 | public AbstractIndirectType create(final Class<?> cls){ |
| 128 | return new PrimitiveType(cls); |
| 129 | } |
| 130 | |
| 131 | @Override |
| 132 | public boolean isMember(final Class<?> cls){ |
| 133 | return PrimitiveType.isPrimitive(cls); |
| 134 | } |
| 135 | }, |
| 136 | /** |
| 137 | * An indirect type indirect type. |
| 138 | */ |
| 139 | INDIRECT_TYPE{ |
| 140 | @Override |
| 141 | public AbstractIndirectType create(final Class<?> cls){ |
| 142 | throw new IllegalArgumentException(); |
| 143 | } |
| 144 | |
| 145 | @Override |
| 146 | public boolean isMember(final Class<?> cls){ |
| 147 | return IndirectType.class.isAssignableFrom(cls); |
| 148 | } |
| 149 | }, |
| 150 | /** |
| 151 | * A map indirect type. |
| 152 | */ |
| 153 | MAP{ |
| 154 | @Override |
| 155 | public AbstractIndirectType create(final Class<?> cls){ |
| 156 | return new MapType(cls); |
| 157 | } |
| 158 | |
| 159 | @Override |
| 160 | public boolean isMember(final Class<?> cls){ |
| 161 | return Map.class.isAssignableFrom(cls) && hasDefaultConstructor(cls); |
| 162 | } |
| 163 | }, |
| 164 | /** |
| 165 | * A collection indirect type. |
| 166 | */ |
| 167 | LIST{ |
| 168 | @Override |
| 169 | public AbstractIndirectType create(final Class<?> cls){ |
| 170 | return new ListType(cls); |
| 171 | } |
| 172 | |
| 173 | @Override |
| 174 | public boolean isMember(final Class<?> cls){ |
| 175 | return Collection.class.isAssignableFrom(cls) && hasDefaultConstructor(cls); |
| 176 | } |
| 177 | }, |
| 178 | /** |
| 179 | * Everything-under-the-sun indirect type. |
| 180 | */ |
| 181 | OBJECT{ |
| 182 | @Override |
| 183 | public AbstractIndirectType create(final Class<?> cls){ |
| 184 | return new ObjectType(cls); |
| 185 | } |
| 186 | |
| 187 | @Override |
| 188 | public boolean isMember(final Class<?> cls){ |
| 189 | return true; |
| 190 | } |
| 191 | }; |
| 192 | /** |
| 193 | * Returns true if <code>cls</code> is a member of this category. |
| 194 | * @param cls the possible member of this category |
| 195 | * @return true if <code>cls</code> is a member of this category, false |
| 196 | * otherwise |
| 197 | */ |
| 198 | public abstract boolean isMember(Class<?> cls); |
| 199 | |
| 200 | /** |
| 201 | * Returns an indirect type instance for <code>cls</code>. |
| 202 | * @param cls the class to wrap with an indirect type |
| 203 | * @return the indirect type for <code>cls</code> |
| 204 | */ |
| 205 | public abstract AbstractIndirectType create(Class<?> cls); |
| 206 | |
| 207 | /** |
| 208 | * Returns true if <code>cls</code> has a default constructor. |
| 209 | * @param cls the class |
| 210 | * @return true if <code>cls</code> has a default constructor, false |
| 211 | * otherwise. |
| 212 | */ |
| 213 | static boolean hasDefaultConstructor(final Class<?> cls){ |
| 214 | try{ |
| 215 | return cls.getConstructor() != null; |
| 216 | }catch(RuntimeException e){ |
| 217 | return false; |
| 218 | }catch(NoSuchMethodException e){ |
| 219 | return false; |
| 220 | } |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | /** |
| 225 | * Creates a new instance. |
| 226 | */ |
| 227 | public ClassTypeLibrary(){ |
| 228 | ClassType.DEFAULT.setLibrary(this); |
| 229 | types = new HashMap<Class<?>, AbstractIndirectType>(); |
| 230 | types.put(String.class, StringType.DEFAULT); |
| 231 | types.put(Class.class, ClassType.DEFAULT); |
| 232 | } |
| 233 | |
| 234 | public Writer createWriter(final CachedAppendable writer){ |
| 235 | return new Writer(){ |
| 236 | public void write(final Object object) throws ObjectAccessException, SerialFormatException{ |
| 237 | Symbol.Element.write(writer, object, getType(null)); |
| 238 | } |
| 239 | }; |
| 240 | } |
| 241 | |
| 242 | public Reader createReader(final CachedLexable lexer){ |
| 243 | return new Reader(){ |
| 244 | public Object read() throws ObjectAccessException, SerialFormatException{ |
| 245 | return Symbol.Element.read(lexer, null, getType(null)); |
| 246 | } |
| 247 | |
| 248 | public Object read(final Object object) throws ObjectAccessException, SerialFormatException{ |
| 249 | return Symbol.Element.read(lexer, object, getType(null)); |
| 250 | } |
| 251 | }; |
| 252 | } |
| 253 | |
| 254 | public IndirectType getTypeFor(final Object object){ |
| 255 | if(object == null){ |
| 256 | return NullType.DEFAULT; |
| 257 | } |
| 258 | return getType(object.getClass()); |
| 259 | } |
| 260 | |
| 261 | public AbstractIndirectType getType(final Class<?> cls){ |
| 262 | AbstractIndirectType type = types.get(cls); |
| 263 | if(type == null){ |
| 264 | type = createType(cls); |
| 265 | types.put(cls, type); |
| 266 | type.setLibrary(this); |
| 267 | } |
| 268 | return type; |
| 269 | } |
| 270 | |
| 271 | private AbstractIndirectType createType(final Class<?> cls){ |
| 272 | for(TypeCategory category: TypeCategory.values()){ |
| 273 | if(category.isMember(cls)){ |
| 274 | return category.create(cls); |
| 275 | } |
| 276 | } |
| 277 | throw new IllegalArgumentException(); |
| 278 | } |
| 279 | } |