Coverage Report - org.webslinger.resolver.ObjectWalker
 
Classes in this File Line Coverage Branch Coverage Complexity
ObjectWalker
28%
28/100
37%
10/27
0
 
 1  
 package org.webslinger.resolver;
 2  
 
 3  
 import java.util.HashMap;
 4  
 import java.util.HashSet;
 5  
 import java.util.Iterator;
 6  
 import java.util.ListIterator;
 7  
 import java.util.Map;
 8  
 import java.util.Set;
 9  
 import java.util.WeakHashMap;
 10  
 import java.util.concurrent.ConcurrentHashMap;
 11  
 import javax.imageio.spi.ServiceRegistry;
 12  
 
 13  
 public final class ObjectWalker {
 14  1
     private final ConcurrentHashMap<String, ObjectResolver<?>> registry = new ConcurrentHashMap<String, ObjectResolver<?>>();
 15  
 
 16  1
     public ObjectWalker() {
 17  1
         ClassLoader loader = Thread.currentThread().getContextClassLoader();
 18  1
         if (loader == null) loader = ObjectWalker.class.getClassLoader();
 19  1
         Iterator<ObjectResolverInfo> it = ServiceRegistry.lookupProviders(ObjectResolverInfo.class, loader);
 20  36
         while (it.hasNext()) {
 21  
             try {
 22  35
                 ObjectResolverInfo info = it.next();
 23  35
                 register(info.getType(), info.getResolver());
 24  0
             } catch (RuntimeException e) {
 25  0
             } catch (UnsupportedClassVersionError e) {
 26  35
             }
 27  
         }
 28  1
     }
 29  
 
 30  
     public void register(String name, ObjectResolver<?> resolver) {
 31  35
         registry.put(name, resolver);
 32  35
     }
 33  
 
 34  
     public Object get(Object object, ListIterator<String> it) {
 35  0
         return get(object, it, false);
 36  
     }
 37  
 
 38  
     private Object get(Object object, ListIterator<String> it, boolean leaveEnding) {
 39  0
         while (object != null && it.hasNext()) {
 40  0
             String token = it.next();
 41  0
             if (!it.hasNext() && leaveEnding) {
 42  0
                 it.previous();
 43  0
                 return object;
 44  
             }
 45  
             Object newObject;
 46  0
             if (object instanceof ObjectLookup) {
 47  0
                 ObjectLookup lookup = (ObjectLookup) object;
 48  0
                 newObject = lookup.objectGet(token);
 49  0
             } else {
 50  0
                 newObject = doGet(object.getClass(), object, token);
 51  
             }
 52  0
             if (newObject == null) {
 53  0
                 it.previous();
 54  0
                 return object;
 55  
             }
 56  0
             object = newObject;
 57  0
         }
 58  0
         return object;
 59  
     }
 60  
 
 61  
     private <T> Object doGet(Class<T> type, Object object, String part) {
 62  0
         ObjectResolver<T> resolver = getResolver(type);
 63  0
         if (resolver == null) return null;
 64  0
         return resolver.get(type.cast(object), part);
 65  
     }
 66  
 
 67  
     public String[] list(Object object, ListIterator<String> it) {
 68  0
         object = get(object, it);
 69  0
         if (object == null || it.hasNext()) return null;
 70  0
         if (object instanceof ObjectLookup) {
 71  0
             return ((ObjectLookup) object).objectList();
 72  
         }
 73  0
         return doList(object.getClass(), object);
 74  
     }
 75  
 
 76  
     private <T> String[] doList(Class<T> type, Object object) {
 77  0
         ObjectResolver<T> resolver = getResolver(type);
 78  0
         return resolver.list(type.cast(object));
 79  
     }
 80  
 
 81  
     public boolean hasChildren(Object object, ListIterator<String> it) {
 82  0
         object = get(object, it);
 83  0
         if (object == null || it.hasNext()) return false;
 84  0
         if (object instanceof ObjectLookup) {
 85  0
             return ((ObjectLookup) object).objectHasChildren();
 86  
         }
 87  0
         return doHasChildren(object.getClass(), object);
 88  
     }
 89  
 
 90  
     private <T> boolean doHasChildren(Class<T> type, Object object) {
 91  0
         ObjectResolver<T> resolver = getResolver(type);
 92  0
         return resolver.hasChildren(type.cast(object));
 93  
     }
 94  
 
 95  
     public ObjectResolver<?> getResolver(String name) {
 96  0
         return registry.get(name);
 97  
     }
 98  
 
 99  
     public <T> ObjectResolver<T> getResolver(Class<T> clz) {
 100  897
         return getResolver(clz, null);
 101  
     }
 102  
 
 103  
     public Class getType(Object object, ListIterator<String> it) {
 104  0
         object = get(object, it, true);
 105  0
         if (object == null || !it.hasNext()) return Void.TYPE;
 106  0
         String part = it.next();
 107  0
         if (it.hasNext()) return Void.TYPE;
 108  0
         if (object instanceof ObjectLookup) {
 109  0
             return ((ObjectLookup) object).getType(part);
 110  
         }
 111  0
         return doGetType(object.getClass(), object, part);
 112  
     }
 113  
 
 114  
     private <T> Class doGetType(Class<T> type, Object object, String part) {
 115  0
         ObjectResolver<T> resolver = getResolver(type);
 116  0
         return resolver.getType(type.cast(object), part);
 117  
     }
 118  
 
 119  
     public char[] getChars(Object object, ListIterator<String> it) throws Exception {
 120  0
         object = get(object, it, false);
 121  0
         if (object == null || it.hasNext()) return null;
 122  
         //if (object instanceof ObjectLookup) {
 123  
         //    return ((ObjectLookup) object).getType(part);
 124  
         //}
 125  0
         return getChars(object);
 126  
     }
 127  
 
 128  
     public char[] getChars(Object object) throws Exception {
 129  0
         return doGetChars(object.getClass(), object);
 130  
     }
 131  
 
 132  
     private <T> char[] doGetChars(Class<T> type, Object object) throws Exception {
 133  0
         ObjectResolver<T> resolver = getResolver(type);
 134  0
         if (resolver == null) return null;
 135  0
         return resolver.getChars(type.cast(object));
 136  
     }
 137  
 
 138  
     public void setChars(Object object, ListIterator<String> it, char[] chars) throws Exception {
 139  0
         setChars(object, it, chars, 0, chars.length);
 140  0
     }
 141  
 
 142  
     public void setChars(Object object, ListIterator<String> it, char[] chars, int offset, int length) throws Exception {
 143  0
         object = get(object, it, true);
 144  0
         if (object == null || !it.hasNext()) return;
 145  0
         String part = it.next();
 146  0
         if (it.hasNext()) return;
 147  
         //if (object instanceof ObjectLookup) {
 148  
         //    return ((ObjectLookup) object).getType(part);
 149  
         //}
 150  0
         doSetChars(object.getClass(), object, part, chars, offset, length);
 151  0
     }
 152  
 
 153  
     private <T, P> void doSetChars(Class<T> type, Object object, String part, char[] chars, int offset, int length) throws Exception {
 154  0
         ObjectResolver<T> resolver = getResolver(type);
 155  0
         Class<P> partType = resolver.getType(type.cast(object), part);
 156  0
         ObjectResolver<P> typeResolver = getResolver(partType);
 157  0
         if (typeResolver == null) return;
 158  0
         Object value = typeResolver.newObject(partType, chars, offset, length);
 159  0
         resolver.set(type.cast(object), part, value);
 160  0
     }
 161  
 
 162  
     public Object getObject(String type, char[] chars) throws Exception {
 163  0
         return getObject(type, chars, 0, chars.length);
 164  
     }
 165  
 
 166  
     public Object getObject(String type, char[] chars, int offset, int length) throws Exception {
 167  1
         return getObject(Class.forName(type), chars, offset, length);
 168  
     }
 169  
 
 170  
     public Object getObject(Class<?> type, char[] chars) throws Exception {
 171  0
         return getObject(type, chars, 0, chars.length);
 172  
     }
 173  
 
 174  
     public <T> Object getObject(Class<T> type, char[] chars, int offset, int length) throws Exception {
 175  839
         ObjectResolver<T> typeResolver = getResolver(type);
 176  839
         if (typeResolver == null) return null;
 177  839
         return typeResolver.newObject(type, chars, offset, length);
 178  
     }
 179  
 
 180  
     private <T> ArrayResolver<T> getArrayResolver(Class<T> componentType) {
 181  0
         return new ArrayResolver<T>(componentType);
 182  
     }
 183  
 
 184  
     private <T> ObjectResolver<T> getResolver(Class<T> clz, Set<Class> seen) {
 185  913
         if (clz == null || clz.equals(Object.class)) return null;
 186  910
         if (seen == null) seen = new HashSet<Class>();
 187  910
         ObjectResolver resolver = registry.get(clz.getName());
 188  910
         if (clz.isArray()) {
 189  0
             resolver = getArrayResolver(clz.getComponentType());
 190  
         } else {
 191  910
             if (resolver == null) {
 192  13
                 seen.add(clz);
 193  16
                 for (Class<?> intf: clz.getInterfaces()) {
 194  4
                     resolver = getResolver(intf, seen);
 195  4
                     if (resolver != null) break;
 196  
                 }
 197  13
                 if (resolver == null) resolver = getResolver(clz.getSuperclass(), seen);
 198  
             }
 199  
         }
 200  910
         return resolver;
 201  
     }
 202  
 }