KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > cglib > beans > BeanMapEmitter


1 /*
2  * Copyright 2003,2004 The Apache Software Foundation
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 net.sf.cglib.beans;
17
18 import java.beans.*;
19 import java.util.*;
20 import net.sf.cglib.core.*;
21 import org.objectweb.asm.ClassVisitor;
22 import org.objectweb.asm.Label;
23 import org.objectweb.asm.Type;
24
25 class BeanMapEmitter extends ClassEmitter {
26     private static final Type BEAN_MAP =
27       TypeUtils.parseType("net.sf.cglib.beans.BeanMap");
28     private static final Type FIXED_KEY_SET =
29       TypeUtils.parseType("net.sf.cglib.beans.FixedKeySet");
30     private static final Signature CSTRUCT_OBJECT =
31       TypeUtils.parseConstructor("Object");
32     private static final Signature CSTRUCT_STRING_ARRAY =
33       TypeUtils.parseConstructor("String[]");
34     private static final Signature BEAN_MAP_GET =
35       TypeUtils.parseSignature("Object get(Object, Object)");
36     private static final Signature BEAN_MAP_PUT =
37       TypeUtils.parseSignature("Object put(Object, Object, Object)");
38     private static final Signature KEY_SET =
39       TypeUtils.parseSignature("java.util.Set keySet()");
40     private static final Signature NEW_INSTANCE =
41       new Signature("newInstance", BEAN_MAP, new Type[]{ Constants.TYPE_OBJECT });
42     private static final Signature GET_PROPERTY_TYPE =
43       TypeUtils.parseSignature("Class getPropertyType(String)");
44
45     public BeanMapEmitter(ClassVisitor v, String JavaDoc className, Class JavaDoc type, int require) {
46         super(v);
47
48         begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE);
49         EmitUtils.null_constructor(this);
50         EmitUtils.factory_method(this, NEW_INSTANCE);
51         generateConstructor();
52             
53         Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type));
54         Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type));
55         Map allProps = new HashMap();
56         allProps.putAll(getters);
57         allProps.putAll(setters);
58
59         if (require != 0) {
60             for (Iterator it = allProps.keySet().iterator(); it.hasNext();) {
61                 String JavaDoc name = (String JavaDoc)it.next();
62                 if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) ||
63                     (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) {
64                     it.remove();
65                     getters.remove(name);
66                     setters.remove(name);
67                 }
68             }
69         }
70         generateGet(type, getters);
71         generatePut(type, setters);
72
73         String JavaDoc[] allNames = getNames(allProps);
74         generateKeySet(allNames);
75         generateGetPropertyType(allProps, allNames);
76         end_class();
77     }
78
79     private Map makePropertyMap(PropertyDescriptor[] props) {
80         Map names = new HashMap();
81         for (int i = 0; i < props.length; i++) {
82             names.put(((PropertyDescriptor)props[i]).getName(), props[i]);
83         }
84         return names;
85     }
86
87     private String JavaDoc[] getNames(Map propertyMap) {
88         return (String JavaDoc[])propertyMap.keySet().toArray(new String JavaDoc[propertyMap.size()]);
89     }
90
91     private void generateConstructor() {
92         CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
93         e.load_this();
94         e.load_arg(0);
95         e.super_invoke_constructor(CSTRUCT_OBJECT);
96         e.return_value();
97         e.end_method();
98     }
99         
100     private void generateGet(Class JavaDoc type, final Map getters) {
101         final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null);
102         e.load_arg(0);
103         e.checkcast(Type.getType(type));
104         e.load_arg(1);
105         e.checkcast(Constants.TYPE_STRING);
106         EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
107             public void processCase(Object JavaDoc key, Label end) {
108                 PropertyDescriptor pd = (PropertyDescriptor)getters.get(key);
109                 MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod());
110                 e.invoke(method);
111                 e.box(method.getSignature().getReturnType());
112                 e.return_value();
113             }
114             public void processDefault() {
115                 e.aconst_null();
116                 e.return_value();
117             }
118         });
119         e.end_method();
120     }
121
122     private void generatePut(Class JavaDoc type, final Map setters) {
123         final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null);
124         e.load_arg(0);
125         e.checkcast(Type.getType(type));
126         e.load_arg(1);
127         e.checkcast(Constants.TYPE_STRING);
128         EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
129             public void processCase(Object JavaDoc key, Label end) {
130                 PropertyDescriptor pd = (PropertyDescriptor)setters.get(key);
131                 if (pd.getReadMethod() == null) {
132                     e.aconst_null();
133                 } else {
134                     MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod());
135                     e.dup();
136                     e.invoke(read);
137                     e.box(read.getSignature().getReturnType());
138                 }
139                 e.swap(); // move old value behind bean
140
e.load_arg(2); // new value
141
MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod());
142                 e.unbox(write.getSignature().getArgumentTypes()[0]);
143                 e.invoke(write);
144                 e.return_value();
145             }
146             public void processDefault() {
147                 // fall-through
148
}
149         });
150         e.aconst_null();
151         e.return_value();
152         e.end_method();
153     }
154             
155     private void generateKeySet(String JavaDoc[] allNames) {
156         // static initializer
157
declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null);
158
159         CodeEmitter e = begin_static();
160         e.new_instance(FIXED_KEY_SET);
161         e.dup();
162         EmitUtils.push_array(e, allNames);
163         e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY);
164         e.putfield("keys");
165         e.return_value();
166         e.end_method();
167
168         // keySet
169
e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null);
170         e.load_this();
171         e.getfield("keys");
172         e.return_value();
173         e.end_method();
174     }
175
176     private void generateGetPropertyType(final Map allProps, String JavaDoc[] allNames) {
177         final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null);
178         e.load_arg(0);
179         EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
180             public void processCase(Object JavaDoc key, Label end) {
181                 PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key);
182                 EmitUtils.load_class(e, Type.getType(pd.getPropertyType()));
183                 e.return_value();
184             }
185             public void processDefault() {
186                 e.aconst_null();
187                 e.return_value();
188             }
189         });
190         e.end_method();
191     }
192 }
193
Popular Tags