/*******************************************************************************
* Copyright (c) 2010, 2015 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.rap.rwt.internal.protocol;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.rap.json.JsonObject;
import org.eclipse.rap.json.JsonValue;
import org.eclipse.rap.rwt.internal.protocol.Operation.CallOperation;
import org.eclipse.rap.rwt.internal.protocol.Operation.CreateOperation;
import org.eclipse.rap.rwt.internal.protocol.Operation.DestroyOperation;
import org.eclipse.rap.rwt.internal.protocol.Operation.ListenOperation;
import org.eclipse.rap.rwt.internal.protocol.Operation.SetOperation;
public class ProtocolMessageWriter {
private final JsonObject head;
private final List<Operation> operations;
private Operation pendingOperation;
private boolean alreadyCreated;
public ProtocolMessageWriter() {
head = new JsonObject();
operations = new ArrayList<>();
}
public void appendHead( String property, int value ) {
appendHead( property, JsonValue.valueOf( value ) );
}
public void appendHead( String property, String value ) {
appendHead( property, JsonValue.valueOf( value ) );
}
public void appendHead( String property, JsonValue value ) {
ensureMessagePending();
head.add( property, value );
}
public void appendCreate( String target, String type ) {
prepareOperation( new CreateOperation( target, type ) );
}
public void appendSet( String target, String property, int value ) {
appendSet( target, property, JsonValue.valueOf( value ) );
}
public void appendSet( String target, String property, double value ) {
appendSet( target, property, JsonValue.valueOf( value ) );
}
public void appendSet( String target, String property, boolean value ) {
appendSet( target, property, JsonValue.valueOf( value ) );
}
public void appendSet( String target, String property, String value ) {
appendSet( target, property, JsonValue.valueOf( value ) );
}
public void appendSet( String target, String property, JsonValue value ) {
CreateOperation createOperation = findPendingOperation( target, CreateOperation.class );
if( createOperation != null ) {
createOperation.putProperty( property, value );
} else {
SetOperation setOperation = findPendingOperation( target, SetOperation.class );
if( setOperation == null ) {
setOperation = new Operation.SetOperation( target );
prepareOperation( setOperation );
}
setOperation.putProperty( property, value );
}
}
public void appendListen( String target, String eventType, boolean listen ) {
ListenOperation operation = findPendingOperation( target, ListenOperation.class );
if( operation == null ) {
operation = new ListenOperation( target );
prepareOperation( operation );
}
operation.putListener( eventType, listen );
}
public void appendCall( String target, String methodName, JsonObject parameters ) {
prepareOperation( new CallOperation( target, methodName, parameters ) );
}
public void appendDestroy( String target ) {
prepareOperation( new DestroyOperation( target ) );
}
private void prepareOperation( Operation operation ) {
ensureMessagePending();
appendPendingOperation();
pendingOperation = operation;
}
public ResponseMessage createMessage() {
ensureMessagePending();
alreadyCreated = true;
return createMessageObject();
}
private void ensureMessagePending() {
if( alreadyCreated ) {
throw new IllegalStateException( "Message already created" );
}
}
private ResponseMessage createMessageObject() {
appendPendingOperation();
return new ResponseMessage( head, operations );
}
@SuppressWarnings( "unchecked" )
private <T extends Operation> T findPendingOperation( String target, Class<T> type ) {
boolean matches = pendingOperation != null
&& pendingOperation.getClass().equals( type )
&& pendingOperation.getTarget().equals( target );
return matches ? (T) pendingOperation : null;
}
private void appendPendingOperation() {
if( pendingOperation != null ) {
operations.add( pendingOperation );
}
}
}