~play-developers/play/zdb

« back to all changes in this revision

Viewing changes to src/fr/zenexity/json/BeanBinder.java

  • Committer: Leo West
  • Date: 2008-10-15 14:51:02 UTC
  • Revision ID: lwe@lwe-20081015145102-w1kiki42k6tan3ln
added fr.json in source tree

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package fr.zenexity.json;
 
2
 
 
3
import fr.zenexity.json.JSON.FieldWrapper;
 
4
import fr.zenexity.json.JSONTokenizer.Token;
 
5
import java.io.IOException;
 
6
import java.lang.reflect.Field;
 
7
import java.lang.reflect.Modifier;
 
8
import java.lang.reflect.Type;
 
9
import java.util.HashMap;
 
10
import java.util.HashSet;
 
11
import java.util.Map;
 
12
import java.util.Set;
 
13
import java.util.logging.Level;
 
14
import java.util.logging.Logger;
 
15
import static fr.zenexity.json.JSONTokenizer.Token.*;
 
16
 
 
17
class BeanBinder implements JSONBinder {
 
18
 
 
19
    private static final Logger log = Logger.getLogger("fr.zenexity.json");
 
20
    private Class forClass;
 
21
    private Map<String, FieldWrapper> fields = new HashMap<String, FieldWrapper>();
 
22
 
 
23
    public BeanBinder(Class forClass) {
 
24
        super();
 
25
        this.forClass = forClass;
 
26
        initialize();
 
27
    }
 
28
 
 
29
    /**
 
30
     * Introspect the bean class for properties and getters/setters
 
31
     * Field informations are cached in a {@link  FieldWrapper FieldWrapper} structure
 
32
     */
 
33
    private void initialize() {
 
34
        Set<Field> fieldset = new HashSet<Field>();
 
35
        findAllFields(forClass, fieldset);
 
36
        for (Field field : fieldset) {
 
37
            if (isSettable(field)) {
 
38
                FieldWrapper fw = new FieldWrapper(field, forClass);
 
39
                field.setAccessible(true);
 
40
                // todo there is a problem here if a superclass define a private field with same name
 
41
                fields.put(field.getName(), fw);
 
42
            }
 
43
        }
 
44
    }
 
45
 
 
46
    public static void findAllFields(Class clazz, Set<Field> found) {
 
47
        Field[] fields = clazz.getDeclaredFields();
 
48
        for (int i = 0; i < fields.length; i++) {
 
49
            found.add(fields[i]);
 
50
        }
 
51
        Class sClazz = clazz.getSuperclass();
 
52
        if (sClazz != null && sClazz != Object.class) {
 
53
            findAllFields(sClazz, found);
 
54
        }
 
55
    }
 
56
 
 
57
    public Object read(Class<?> clazz, Type type, JSONReader reader) {
 
58
        Token tok = reader.assertIs(START_MAP);
 
59
        try {
 
60
            Object instance = clazz.newInstance();
 
61
            tok = reader.nextToken();
 
62
            if (tok == END_MAP) {
 
63
                return instance;
 
64
            }
 
65
            for (;;) {
 
66
                String key = tok.value;
 
67
                tok = reader.nextToken();
 
68
                reader.assertIs(SEMICOLON);
 
69
                FieldWrapper wrapper = fields.get(key);
 
70
                if (wrapper == null) {
 
71
                    log.fine("no field " + key + " in bean " + clazz.getSimpleName() + " : skipping json data");
 
72
                    reader.skip();
 
73
                } else {
 
74
                    tok = reader.nextToken();
 
75
                    Object value = reader.readInternal(wrapper.field.getName(), wrapper.field.getType(), wrapper.field.getGenericType(), tok);
 
76
                    try {
 
77
                        wrapper.setValue(instance, value);
 
78
                    } catch (Exception e) {
 
79
                        log.log(Level.SEVERE, "unable to set field value for " + wrapper.field, e);
 
80
                    }
 
81
                }
 
82
                //
 
83
                tok = reader.nextToken();
 
84
                if (tok == END_MAP) {
 
85
                    break;
 
86
                }
 
87
                reader.assertIs(COMMA);
 
88
                tok = reader.nextToken();
 
89
            }
 
90
            return instance;
 
91
        } catch (JSONException pex) {
 
92
            throw pex;
 
93
        } catch (Exception ex) {
 
94
            throw JSONException.bindError("beanbinder failure", ex, reader.getParser());
 
95
        }
 
96
    }
 
97
 
 
98
    public boolean isSettable(Field field) {
 
99
        final int unmodifiable = Modifier.STATIC + Modifier.NATIVE + Modifier.FINAL + Modifier.TRANSIENT;
 
100
        return (field.getModifiers() & unmodifiable) == 0;
 
101
    }
 
102
 
 
103
    public void write(Object obj, JSONWriter jsonWriter) {
 
104
        Set<String> keys;
 
105
        try {
 
106
            int i = 0;
 
107
            jsonWriter.writeChar('{');
 
108
            keys = fields.keySet();
 
109
            for (String fieldname : keys) {
 
110
                if (i++ > 0) {
 
111
                    jsonWriter.writeChar(',');
 
112
                }
 
113
                FieldWrapper wrapper = fields.get(fieldname);
 
114
                jsonWriter.writeString(fieldname);
 
115
                jsonWriter.writeChar(':');
 
116
                log.fine("field:"+fieldname+" wrapper:"+wrapper);
 
117
                jsonWriter.write(wrapper.getValue(obj));
 
118
            }
 
119
            jsonWriter.writeChar('}');
 
120
 
 
121
        } catch (IOException ex) {
 
122
            log.log(Level.SEVERE, null, ex);
 
123
        }
 
124
    }
 
125
}