Coverage Report - net.sf.json.groovy.JsonGroovyBuilder
 
Classes in this File Line Coverage Branch Coverage Complexity
JsonGroovyBuilder
0%
0/135
0%
0/84
5.727
 
 1  
 /*
 2  
  * Copyright 2002-2009 the original author or authors.
 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  
 
 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  
  * A Groovy builder for JSON values.
 38  
  *
 39  
  * <pre>
 40  
 def books1 = builder.books {
 41  
    book = [title: "The Definitive Guide to Grails", author: "Graeme Rocher"]
 42  
    book = [title: "The Definitive Guide to Grails", author: "Graeme Rocher"]
 43  
 }
 44  
 
 45  
 def books2 = builder.books {
 46  
    book = new Book(title: "The Definitive Guide to Grails",
 47  
                    author: "Graeme Rocher")
 48  
    book = new Book(title: "The Definitive Guide to Grails",
 49  
                    author: "Graeme Rocher")
 50  
 }
 51  
 
 52  
 def books3 = builder.books {
 53  
    book = {
 54  
       title = "The Definitive Guide to Grails"
 55  
       author= "Graeme Rocher"
 56  
    }
 57  
    book = {
 58  
       title = "The Definitive Guide to Grails"
 59  
       author= "Graeme Rocher"
 60  
    }
 61  
 }
 62  
 
 63  
 def books4 = builder.books {
 64  
    book {
 65  
       title = "The Definitive Guide to Grails"
 66  
       author= "Graeme Rocher"
 67  
    }
 68  
    book {
 69  
       title = "The Definitive Guide to Grails"
 70  
       author= "Graeme Rocher"
 71  
    }
 72  
 }
 73  
 
 74  
 def books5 = builder.books {
 75  
    2.times {
 76  
       book = {
 77  
          title = "The Definitive Guide to Grails"
 78  
          author= "Graeme Rocher"
 79  
       }
 80  
    }
 81  
 }
 82  
 
 83  
 def books6 = builder.books {
 84  
    2.times {
 85  
       book {
 86  
          title = "The Definitive Guide to Grails"
 87  
          author= "Graeme Rocher"
 88  
       }
 89  
    }
 90  
 }
 91  
 
 92  
 
 93  
  all 6 books variables output the same JSON
 94  
 
 95  
 {"books": {
 96  
    "book": [{
 97  
          "title": "The Definitive Guide to Grails",
 98  
          "author": "Graeme Rocher"
 99  
       },{
 100  
          "title": "The Definitive Guide to Grails",
 101  
          "author": "Graeme Rocher"
 102  
       }]
 103  
    }
 104  
 }
 105  
 </pre>
 106  
  *
 107  
  * @author Andres Almiray <aalmiray@users.sourceforge.net>
 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  0
    public JsonGroovyBuilder() {
 116  0
       stack = new Stack();
 117  0
       properties = new HashMap();
 118  0
    }
 119  
 
 120  
    public Object getProperty( String name ) {
 121  0
       if( !stack.isEmpty() ){
 122  0
          Object top = stack.peek();
 123  0
          if( top instanceof JSONObject ){
 124  0
             JSONObject json = (JSONObject) top;
 125  0
             if( json.containsKey( name ) ){
 126  0
                return json.get( name );
 127  
             }else{
 128  0
                return _getProperty( name );
 129  
             }
 130  
          }else{
 131  0
             return _getProperty( name );
 132  
          }
 133  
       }else{
 134  0
          return _getProperty( name );
 135  
       }
 136  
    }
 137  
 
 138  
    public Object invokeMethod( String name, Object arg ) {
 139  0
       if( JSON.equals( name ) && stack.isEmpty() ){
 140  0
          return createObject( name, arg );
 141  
       }
 142  
 
 143  0
       Object[] args = (Object[]) arg;
 144  0
       if( args.length == 0 ){
 145  0
          throw new MissingMethodException( name, getClass(), args );
 146  
       }
 147  
 
 148  0
       Object value = null;
 149  0
       if( args.length > 1 ){
 150  0
          JSONArray array = new JSONArray();
 151  0
          stack.push( array );
 152  0
          for( int i = 0; i < args.length; i++ ){
 153  0
             if( args[i] instanceof Closure ){
 154  0
                append( name, createObject( (Closure) args[i] ) );
 155  0
             }else if( args[i] instanceof Map ){
 156  0
                append( name, createObject( (Map) args[i] ) );
 157  0
             }else if( args[i] instanceof List ){
 158  0
                append( name, createArray( (List) args[i] ) );
 159  
             }else{
 160  0
                _append( name, args[i], (JSON) stack.peek() );
 161  
             }
 162  
          }
 163  0
          stack.pop();
 164  0
       }else{
 165  0
          if( args[0] instanceof Closure ){
 166  0
             value = createObject( (Closure) args[0] );
 167  0
          }else if( args[0] instanceof Map ){
 168  0
             value = createObject( (Map) args[0] );
 169  0
          }else if( args[0] instanceof List ){
 170  0
             value = createArray( (List) args[0] );
 171  
          }
 172  
       }
 173  
 
 174  0
       if( stack.isEmpty() ){
 175  0
          JSONObject object = new JSONObject();
 176  0
          object.accumulate( name, current );
 177  0
          current = object;
 178  0
       }else{
 179  0
          JSON top = (JSON) stack.peek();
 180  0
          if( top instanceof JSONObject ){
 181  0
             append( name, current == null ? value : current );
 182  
          }
 183  
       }
 184  
 
 185  0
       return current;
 186  
    }
 187  
 
 188  
    public void setProperty( String name, Object value ) {
 189  0
       if( value instanceof GString ){
 190  0
          value = value.toString();
 191  
          try{
 192  0
             value = JSONSerializer.toJSON( value );
 193  0
          }catch( JSONException jsone ){
 194  
             // its a String literal
 195  0
          }
 196  0
       }else if( value instanceof Closure ){
 197  0
          value = createObject( (Closure) value );
 198  0
       }else if( value instanceof Map ){
 199  0
          value = createObject( (Map) value );
 200  0
       }else if( value instanceof List ){
 201  0
          value = createArray( (List) value );
 202  
       }
 203  
 
 204  0
       append( name, value );
 205  0
    }
 206  
 
 207  
    private Object _getProperty( String name ) {
 208  0
       if( properties.containsKey( name ) ){
 209  0
          return properties.get( name );
 210  
       }else{
 211  0
          return super.getProperty( name );
 212  
       }
 213  
    }
 214  
 
 215  
    private void append( String key, Object value ) {
 216  0
       Object target = null;
 217  0
       if( !stack.isEmpty() ){
 218  0
          target = stack.peek();
 219  0
          current = (JSON) target;
 220  0
          _append( key, value, current );
 221  
       }else{
 222  0
          properties.put( key, value );
 223  
       }
 224  0
    }
 225  
 
 226  
    private void _append( String key, Object value, JSON target ) {
 227  0
       if( target instanceof JSONObject ){
 228  0
          ((JSONObject) target).accumulate( key, value );
 229  0
       }else if( target instanceof JSONArray ){
 230  0
          ((JSONArray) target).element( value );
 231  
       }
 232  0
    }
 233  
 
 234  
    private JSON createArray( List list ) {
 235  0
       JSONArray array = new JSONArray();
 236  0
       stack.push( array );
 237  0
       for( Iterator elements = list.iterator(); elements.hasNext(); ){
 238  0
          Object element = elements.next();
 239  0
          if( element instanceof Closure ){
 240  0
             element = createObject( (Closure) element );
 241  0
          }else if( element instanceof Map ){
 242  0
             element = createObject( (Map) element );
 243  0
          }else if( element instanceof List ){
 244  0
             element = createArray( (List) element );
 245  
          }
 246  0
          array.element( element );
 247  0
       }
 248  0
       stack.pop();
 249  0
       return array;
 250  
    }
 251  
 
 252  
    private JSON createObject( Closure closure ) {
 253  0
       JSONObject object = new JSONObject();
 254  0
       stack.push( object );
 255  0
       closure.setDelegate( this );
 256  0
       closure.call();
 257  0
       stack.pop();
 258  0
       return object;
 259  
    }
 260  
 
 261  
    private JSON createObject( Map map ) {
 262  0
       JSONObject object = new JSONObject();
 263  0
       stack.push( object );
 264  0
       for( Iterator properties = map.entrySet()
 265  0
             .iterator(); properties.hasNext(); ){
 266  0
          Map.Entry property = (Map.Entry) properties.next();
 267  0
          String key = String.valueOf( property.getKey() );
 268  0
          Object value = property.getValue();
 269  0
          if( value instanceof Closure ){
 270  0
             value = createObject( (Closure) value );
 271  0
          }else if( value instanceof Map ){
 272  0
             value = createObject( (Map) value );
 273  0
          }else if( value instanceof List ){
 274  0
             value = createArray( (List) value );
 275  
          }
 276  0
          object.element( key, value );
 277  0
       }
 278  0
       stack.pop();
 279  0
       return object;
 280  
    }
 281  
 
 282  
    private JSON createObject( String name, Object arg ) {
 283  0
       Object[] args = (Object[]) arg;
 284  0
       if( args.length == 0 ){
 285  0
          throw new MissingMethodException( name, getClass(), args );
 286  
       }
 287  
 
 288  0
       if( args.length == 1 ){
 289  0
          if( args[0] instanceof Closure ){
 290  0
             return createObject( (Closure) args[0] );
 291  0
          }else if( args[0] instanceof Map ){
 292  0
             return createObject( (Map) args[0] );
 293  0
          }else if( args[0] instanceof List ){
 294  0
             return createArray( (List) args[0] );
 295  
          }else{
 296  0
             throw new JSONException( "Unsupported type" );
 297  
          }
 298  
       }else{
 299  0
          JSONArray array = new JSONArray();
 300  0
          stack.push( array );
 301  0
          for( int i = 0; i < args.length; i++ ){
 302  0
             if( args[i] instanceof Closure ){
 303  0
                append( name, createObject( (Closure) args[i] ) );
 304  0
             }else if( args[i] instanceof Map ){
 305  0
                append( name, createObject( (Map) args[i] ) );
 306  0
             }else if( args[i] instanceof List ){
 307  0
                append( name, createArray( (List) args[i] ) );
 308  
             }else{
 309  0
                _append( name, args[i], (JSON) stack.peek() );
 310  
             }
 311  
          }
 312  0
          stack.pop();
 313  0
          return array;
 314  
       }
 315  
    }
 316  
 }