1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.json.groovy;
18
19 import groovy.lang.Closure;
20 import groovy.lang.GString;
21 import groovy.lang.GroovyObjectSupport;
22 import groovy.lang.MissingMethodException;
23
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Stack;
29
30 import net.sf.json.JSON;
31 import net.sf.json.JSONArray;
32 import net.sf.json.JSONException;
33 import net.sf.json.JSONObject;
34 import net.sf.json.JSONSerializer;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109 public class JsonGroovyBuilder extends GroovyObjectSupport {
110 private static final String JSON = "json";
111 private JSON current;
112 private Map properties;
113 private Stack stack;
114
115 public JsonGroovyBuilder() {
116 stack = new Stack();
117 properties = new HashMap();
118 }
119
120 public Object getProperty( String name ) {
121 if( !stack.isEmpty() ){
122 Object top = stack.peek();
123 if( top instanceof JSONObject ){
124 JSONObject json = (JSONObject) top;
125 if( json.containsKey( name ) ){
126 return json.get( name );
127 }else{
128 return _getProperty( name );
129 }
130 }else{
131 return _getProperty( name );
132 }
133 }else{
134 return _getProperty( name );
135 }
136 }
137
138 public Object invokeMethod( String name, Object arg ) {
139 if( JSON.equals( name ) && stack.isEmpty() ){
140 return createObject( name, arg );
141 }
142
143 Object[] args = (Object[]) arg;
144 if( args.length == 0 ){
145 throw new MissingMethodException( name, getClass(), args );
146 }
147
148 Object value = null;
149 if( args.length > 1 ){
150 JSONArray array = new JSONArray();
151 stack.push( array );
152 for( int i = 0; i < args.length; i++ ){
153 if( args[i] instanceof Closure ){
154 append( name, createObject( (Closure) args[i] ) );
155 }else if( args[i] instanceof Map ){
156 append( name, createObject( (Map) args[i] ) );
157 }else if( args[i] instanceof List ){
158 append( name, createArray( (List) args[i] ) );
159 }else{
160 _append( name, args[i], (JSON) stack.peek() );
161 }
162 }
163 stack.pop();
164 }else{
165 if( args[0] instanceof Closure ){
166 value = createObject( (Closure) args[0] );
167 }else if( args[0] instanceof Map ){
168 value = createObject( (Map) args[0] );
169 }else if( args[0] instanceof List ){
170 value = createArray( (List) args[0] );
171 }
172 }
173
174 if( stack.isEmpty() ){
175 JSONObject object = new JSONObject();
176 object.accumulate( name, current );
177 current = object;
178 }else{
179 JSON top = (JSON) stack.peek();
180 if( top instanceof JSONObject ){
181 append( name, current == null ? value : current );
182 }
183 }
184
185 return current;
186 }
187
188 public void setProperty( String name, Object value ) {
189 if( value instanceof GString ){
190 value = value.toString();
191 try{
192 value = JSONSerializer.toJSON( value );
193 }catch( JSONException jsone ){
194
195 }
196 }else if( value instanceof Closure ){
197 value = createObject( (Closure) value );
198 }else if( value instanceof Map ){
199 value = createObject( (Map) value );
200 }else if( value instanceof List ){
201 value = createArray( (List) value );
202 }
203
204 append( name, value );
205 }
206
207 private Object _getProperty( String name ) {
208 if( properties.containsKey( name ) ){
209 return properties.get( name );
210 }else{
211 return super.getProperty( name );
212 }
213 }
214
215 private void append( String key, Object value ) {
216 Object target = null;
217 if( !stack.isEmpty() ){
218 target = stack.peek();
219 current = (JSON) target;
220 _append( key, value, current );
221 }else{
222 properties.put( key, value );
223 }
224 }
225
226 private void _append( String key, Object value, JSON target ) {
227 if( target instanceof JSONObject ){
228 ((JSONObject) target).accumulate( key, value );
229 }else if( target instanceof JSONArray ){
230 ((JSONArray) target).element( value );
231 }
232 }
233
234 private JSON createArray( List list ) {
235 JSONArray array = new JSONArray();
236 stack.push( array );
237 for( Iterator elements = list.iterator(); elements.hasNext(); ){
238 Object element = elements.next();
239 if( element instanceof Closure ){
240 element = createObject( (Closure) element );
241 }else if( element instanceof Map ){
242 element = createObject( (Map) element );
243 }else if( element instanceof List ){
244 element = createArray( (List) element );
245 }
246 array.element( element );
247 }
248 stack.pop();
249 return array;
250 }
251
252 private JSON createObject( Closure closure ) {
253 JSONObject object = new JSONObject();
254 stack.push( object );
255 closure.setDelegate( this );
256 closure.call();
257 stack.pop();
258 return object;
259 }
260
261 private JSON createObject( Map map ) {
262 JSONObject object = new JSONObject();
263 stack.push( object );
264 for( Iterator properties = map.entrySet()
265 .iterator(); properties.hasNext(); ){
266 Map.Entry property = (Map.Entry) properties.next();
267 String key = String.valueOf( property.getKey() );
268 Object value = property.getValue();
269 if( value instanceof Closure ){
270 value = createObject( (Closure) value );
271 }else if( value instanceof Map ){
272 value = createObject( (Map) value );
273 }else if( value instanceof List ){
274 value = createArray( (List) value );
275 }
276 object.element( key, value );
277 }
278 stack.pop();
279 return object;
280 }
281
282 private JSON createObject( String name, Object arg ) {
283 Object[] args = (Object[]) arg;
284 if( args.length == 0 ){
285 throw new MissingMethodException( name, getClass(), args );
286 }
287
288 if( args.length == 1 ){
289 if( args[0] instanceof Closure ){
290 return createObject( (Closure) args[0] );
291 }else if( args[0] instanceof Map ){
292 return createObject( (Map) args[0] );
293 }else if( args[0] instanceof List ){
294 return createArray( (List) args[0] );
295 }else{
296 throw new JSONException( "Unsupported type" );
297 }
298 }else{
299 JSONArray array = new JSONArray();
300 stack.push( array );
301 for( int i = 0; i < args.length; i++ ){
302 if( args[i] instanceof Closure ){
303 append( name, createObject( (Closure) args[i] ) );
304 }else if( args[i] instanceof Map ){
305 append( name, createObject( (Map) args[i] ) );
306 }else if( args[i] instanceof List ){
307 append( name, createArray( (List) args[i] ) );
308 }else{
309 _append( name, args[i], (JSON) stack.peek() );
310 }
311 }
312 stack.pop();
313 return array;
314 }
315 }
316 }