/******************************************************************************* * Copyright (c) 2010 EclipseSource and others. All rights reserved. This * program and the accompanying materials are made available under the terms of * the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * EclipseSource - initial API and implementation *******************************************************************************/ package org.eclipse.rwt.internal.protocol; import java.io.PrintWriter; import java.util.Map; public class JsonMessageWriter extends ProtocolMessageWriter { public JsonMessageWriter( final PrintWriter decoratedWriter ) { super( decoratedWriter ); } protected void appendStartMessage() { String message = "{\n \""+ IProtocolConstants.MESSAGE_META + "\" : {\n" + " \"" + IProtocolConstants.META_REQUEST_COUNTER + // TODO: include real next request id // "\" : " + RWTRequestVersionControl.nextRequestId() + "\" : " + 0 + "\n },\n" + " \"" + IProtocolConstants.MESSAGE_WIDGETS + "\" :" + " [\n"; write( message ); } protected void appendEndMessage() { write( "\n ]\n}" ); } protected void appendStartPayload( final String widgetId ) { String payloadStart = null; if( widgetId != null ) { payloadStart = " {\n \"" + IProtocolConstants.WIDGETS_ID + "\" : \"" + widgetId + "\",\n"; } else { payloadStart = " {\n \"" + IProtocolConstants.WIDGETS_ID + "\":null,"; } write( payloadStart ); } protected void appendPayloadSeparator() { write( ",\n" ); } protected void appendEndPayload() { write( "\n }" ); } protected void appendConstructPayload( String widgetId, final String parentId, final String type, final String[] styles, final Object[] arguments ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE ); buffer.append( "\" : \"" + IProtocolConstants.PAYLOAD_CONSTRUCT + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : { " ); if( parentId != null ) { buffer.append( "\"" + IProtocolConstants.KEY_PARENT_ID + "\" : \"" ); buffer.append( parentId + "\", " ); } buffer.append( "\"" + IProtocolConstants.KEY_WIDGET_TYPE + "\" : \"" ); buffer.append( type + "\", " ); buffer.append( "\"" + IProtocolConstants.KEY_WIDGET_STYLE + "\" : " ); buffer.append( getStyleArray( styles ) + ", " ); buffer.append( "\"" + IProtocolConstants.KEY_PARAMETER_LIST + "\" : " ); if( arguments == null ) { buffer.append( "null" ); } else { buffer.append( "[ " ); for( int i = 0; i < arguments.length; i++ ) { addValueSeparatorIfNeeded( buffer, i ); buffer.append( getJsonValueOfObject( arguments[ i ] ) ); } buffer.append( " ]" ); } buffer.append( " }" ); write( buffer.toString() ); } private String getStyleArray( final String[] styles ) { StringBuffer result = new StringBuffer(); if( styles != null && styles.length > 0 ) { result.append( "[ " ); for( int i = 0; i < styles.length; i++ ) { addValueSeparatorIfNeeded( result, i ); result.append( "\"" + styles[ i ] + "\"" ); } result.append( " ]" ); } else { result.append( "null" ); } return result.toString(); } protected void appendDestroyPayload() { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_DESTROY + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD + "\" : " ); buffer.append( " null" ); write( buffer.toString() ); } protected void appendSynchronizePayload( final Map properties ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_SYNCHRONIZE + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : { " ); handleProperties( properties, buffer ); buffer.append( " }" ); write( buffer.toString() ); } protected void appendMultipleSynchronizePayload( final String[] widgetIds, final Map properties ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_MULTI_SYNCHRONIZE + "\"" ); buffer.append( ",\n \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : {" ); handleProperties( properties, buffer ); buffer.append( ", \"" + IProtocolConstants.KEY_WIDGETS + "\" : " ); if( widgetIds.length > 0 ) { buffer.append( "[ " ); for( int i = 0; i < widgetIds.length; i++ ) { addValueSeparatorIfNeeded( buffer, i ); buffer.append( "\"" + widgetIds[ i ] + "\"" ); } buffer.append( " ]" ); } else { throw new IllegalArgumentException( "widgets must not be null" ); } buffer.append( " }" ); write( buffer.toString() ); } protected void appendListenPayload( final Map listeners ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_LISTEN + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : { " ); handleProperties( listeners, buffer ); buffer.append( " }" ); write( buffer.toString() ); } private void handleProperties( final Map properties, final StringBuffer buffer ) { Object[] keys = properties.keySet().toArray(); for( int i = 0; i < keys.length; i++ ) { addValueSeparatorIfNeeded( buffer, i ); String key = ( String )keys[ i ]; buffer.append( "\"" + key + "\" : " ); buffer.append( getJsonValueOfObject( properties.get( key ) ) ); } } protected void appendEventPayload( final String event ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_FIRE_EVENT + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : { " ); buffer.append( "\"" + IProtocolConstants.KEY_EVENT + "\" : " ); buffer.append( "\"" + event + "\" }" ); write( buffer.toString() ); } protected void appendExecutePayload( final String methodName, final Object[] arguments ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_EXECUTE + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD + "\" : { " ); buffer.append( "\"" + IProtocolConstants.KEY_METHODNAME + "\" : \"" ); buffer.append( methodName ); buffer.append( "\", \"" + IProtocolConstants.KEY_PARAMETER_LIST + "\" : " ); if( arguments == null || arguments.length <= 0 ) { buffer.append( "null" ); } else { buffer.append( "[ " ); for( int i = 0; i < arguments.length; i++ ) { addValueSeparatorIfNeeded( buffer, i ); buffer.append( getJsonValueOfObject( arguments[ i ] ) ); } buffer.append( " ]" ); } buffer.append( " }" ); write( buffer.toString() ); } protected void appendExecuteScript( final String scriptType, final String script ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + IProtocolConstants.PAYLOAD_EXECUTE_SCRIPT + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : { " ); buffer.append( "\"" + IProtocolConstants.KEY_SCRIPT_TYPE + "\" : " ); buffer.append( "\"" + scriptType + "\", " ); buffer.append( "\"" + IProtocolConstants.KEY_SCRIPT + "\" : " ); buffer.append( "\"" + script + "\" }" ); write( buffer.toString() ); } private String getJsonValueOfObject( final Object object ) { String result = null; if( object == null ) { result = "null"; } else if( object instanceof String ) { result = "\"" + object.toString() + "\""; } else if( isObjectJsonPrimitive( object ) ){ result = object.toString(); } else { String message = "Parameter object can not be converted to JSON Value"; throw new IllegalArgumentException( message ); } return result; } private boolean isObjectJsonPrimitive( final Object object ) { boolean result = false; if( object instanceof Integer || object instanceof Double || object instanceof Boolean ) { result = true; } return result; } private void addValueSeparatorIfNeeded( final StringBuffer buffer, final int propertyCount ) { if( propertyCount > 0 ) { buffer.append( ", " ); } } protected void appendPayloadType( final String payloadType ) { StringBuffer buffer = new StringBuffer(); buffer.append( " \"" + IProtocolConstants.WIDGETS_TYPE + "\" : " ); buffer.append( "\"" + payloadType + "\",\n" ); buffer.append( " \"" + IProtocolConstants.WIDGETS_PAYLOAD ); buffer.append( "\" : { " ); write( buffer.toString() ); } protected void appendPayloadValue( final Object key, final Object value ) { if( !( key instanceof String ) ) { throw new IllegalArgumentException( "JSON keys must be Strings" ); } StringBuffer buffer = new StringBuffer(); buffer.append( "\"" + key + "\" : " ); if( value instanceof Object[] ) { handleJsonArray( value, buffer ); } else { buffer.append( getJsonValueOfObject( value ) ); } write( buffer.toString() ); } private void handleJsonArray( final Object value, final StringBuffer buffer ) { Object[] values = ( Object[] )value; if( values.length > 0 ) { buffer.append( "[ " ); for( int i = 0; i < values.length; i++ ) { addValueSeparatorIfNeeded( buffer, i ); buffer.append( getJsonValueOfObject( values[ i ] ) ); } buffer.append( " ]" ); } } protected void appendPayloadValueSeparator() { write( ", "); } protected void appendEndPayloadValue() { write( " }" ); } }