/*******************************************************************************
 * Copyright (c) 2004, 2005 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
/*
 *  $RCSfile: ExpressionCommands.java,v $
 *  $Revision: 1.8 $  $Date: 2005/08/24 20:39:08 $ 
 */
package org.eclipse.jem.internal.proxy.common.remote;

import java.io.*;

import org.eclipse.jem.internal.proxy.common.CommandException;

 
/**
 * 
 * @since 1.0.0
 */
public class ExpressionCommands {

	// These are the sub-commands under EXPRESSION_TREE_COMMANDS that can be send.
	public static final byte
		START_EXPRESSION_TREE_PROCESSING = 0,
		PUSH_EXPRESSION = 1,
		END_EXPRESSION_TREE_PROCESSING = 2,
		SYNC_REQUEST = 3,
		PULL_VALUE_REQUEST = 4,
		TRANSFER_EXPRESSION_REQUEST = 5,
		RESUME_EXPRESSION_REQUEST = 6;
		
	// These are the expression specific error codes (it can also send back general ones. See SYNC_REQUEST docs lower down).
	public static final int
		EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION = Commands.MAX_ERROR_CODE+1;	// No expression value occurred.
	
	// These are the flag values sent in proxy resolution when doesn't resolve to proxy.
	public static final int
		EXPRESSIONPROXY_VOIDTYPE = 0,	// Expression proxy resolves to void type.
		EXPRESSIONPROXY_NOTRESOLVED = 1;	// Expression proxy not resolved.
	
	// These are the trace values sent in START_EXPRESSION_TREE_PROCESSING
	public static final byte
		TRACE_DEFAULT = -1,
		TRACE_OFF = 0,
		TRACE_ON = 1;

	public static final String EXPRESSIONTRACE = "proxyvm.expressionTrace";	// The system property for turning on expression tracing. //$NON-NLS-1$
	public static final String EXPRESSIONTRACE_TIMER_THRESHOLD = "proxyvm.expressionTraceTimerThreshold";	// The system property for timer threshold. //$NON-NLS-1$
	
	/*
	 * The format of the commands are:
	 * 		Note: Most of the commands will not being doing a os.flush() at the end. We are just going to
	 * 		be streaming the data over the line. At the end we will flush and then catch up. That way
	 * 		we aren't waiting for the other side as we send the data.
	 * 
	 * START_EXPRESSION_TREE_PROCESSING: 0b, trace
	 * 	Start processing.
	 *  byte(trace): -1 : do default
	 *                0 : no trace
	 *                1 : do trace
	 * 
	 * PUSH_EXPRESSION: 1b, b
	 * 	Push an expression. Where "b" is the expression type from IInternalExpressionConstants. 
	 * 	The actual data that follows is expression type dependent and will be
	 * 	sent in a following call to ExpressionCommands as it builds up the actual command.
	 * 	See REMExpression and each type of push call method within it to see the actual
	 * 	sent data.
	 * 
	 * END_EXPRESSION_TREE_PROCESSING: 2b
	 * 	End the processing and clean up.
	 * 
	 * SYNC_REQUEST: 3b
	 * 	This will return the current status. The reason it is called sync is because the
	 * 	IDE will wait for it to complete and read back the value. It will send back:
	 * 		1: VALUE command with boolean true as the value.
	 * 		2: ERROR command with code of ExpressionClassNotFound, with value of String with message from exception.
	 * 		3: ERROR command with code of EXPRESSION_NOEXPRESSIONVALUE_EXCEPTION, with value of String with message from exception.
	 * 		4: THROWABLE command with the actual exception that occurred.
	 * 
	 *
	 * PULL_VALUE_REQUEST: 4b
	 * 	This will do a sync up and return the value from the expression.
	 * 	IDE will wait for it to compleate and read back the value. It will send back:
	 * 		1: VALUE command with the result as the value.
	 * 		2: ERROR or EXCEPTION if there were errors, see SYNC_REQUEST with the format they are sent back.
	 * 
	 * TRANSFER_EXPRESSION_REQUEST: 5b
	 *  This will do a sync up, and return the ExpressionProcessorController that the request is for. And remove
	 *  the controller from its list of active expression controllers. 
	 *  
	 * RESUME_EXPRESSION_REQUEST: 6b, anExpressionProcessorController
	 *  This will take the given controller and add it to the list of controllers this connection is handling. It returns nothing.  
	 *  
	 * @see org.eclipse.jem.internal.proxy.initParser.tree.IInternalExpressionConstants
	 * @see org.eclipse.jem.internal.proxy.remote.REMExpression
	 * 
	 */
	
	/**
	 * Send the start expression processing command.
	 * @param expressionID
	 * @param trace 
	 * @param os
	 * 
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendStartExpressionProcessingCommand(int expressionID, byte trace, DataOutputStream os) throws IOException {
		os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
		os.writeInt(expressionID);
		os.writeByte(START_EXPRESSION_TREE_PROCESSING);
		os.writeByte(trace);
	}
	
	/**
	 * Send the end expression processing command.
	 * @param expressionID 
	 * @param os
	 * 
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendEndExpressionProcessingCommand(int expressionID, DataOutputStream os) throws IOException {
		os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
		os.writeInt(expressionID);
		os.writeByte(END_EXPRESSION_TREE_PROCESSING);
		os.flush();	// Flushing because we are done and want to make sure everything goes out.
	}
	
	/**
	 * Send an expression subcommand.
	 * @param expressionID 
	 * @param os
	 * @param subcommand
	 * 
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendExpressionCommand(int expressionID, DataOutputStream os, byte subcommand) throws IOException {
		os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
		os.writeInt(expressionID);
		os.writeByte(PUSH_EXPRESSION);
		os.writeByte(subcommand);
	}
	
	/**
	 * Send just a byte.
	 * 
	 * @param os
	 * @param aByte
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendByte(DataOutputStream os, byte aByte) throws IOException {
		os.writeByte(aByte);
	}
	
	/**
	 * Send just an int.
	 * 
	 * @param os
	 * @param anInt
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendInt(DataOutputStream os, int anInt) throws IOException {
		os.writeInt(anInt);
	}
	
	/**
	 * Send just a string.
	 * 
	 * @param os
	 * @param aString
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendString(DataOutputStream os, String aString) throws IOException {
		Commands.sendStringData(os, aString);
	}
	
	/**
	 * Send just a boolean.
	 * 
	 * @param os
	 * @param aBool
	 * @throws IOException
	 * 
	 * @since 1.0.0
	 */
	public static void sendBoolean(DataOutputStream os, boolean aBool) throws IOException {
		os.writeBoolean(aBool);
	}
	
	/**
	 * Send the pull value command. After processing the proxies, caller should call getFinalValue() to get the value.
	 * @param expressionID 
	 * @param os
	 * @param is
	 * @param proxyids if not <code>null</code>, then this is the list of expression proxy ids that need to be returned as rendered.
	 * @param sender sender used to process the resolved proxy ids, or <code>null</code> if no proxy ids.
	 * @throws CommandException
	 * 
	 * @since 1.0.0
	 */
	public static void sendPullValueCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException {
		try {
			os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
			os.writeInt(expressionID);
			os.writeByte(PULL_VALUE_REQUEST);
			sendProxyIDs(os, proxyids);
			os.flush();
			if (proxyids != null) {
				Commands.readBackValue(is, proxyids, Commands.ARRAY_IDS);	// Read the array header.
				sender.initialize(proxyids);
				Commands.readArray(is, proxyids.anInt, sender, proxyids, true);	// Read the array.
			}
		} catch (CommandException e) {
			// rethrow this exception since we want these to go on out.
			throw e;
		} catch (IOException e) {
			// Wrapper this one.
			throw new UnexpectedExceptionCommandException(false, e);
		}		
	}
	
	/**
	 * Send a sync command. This does a synchronize with the remote expression processor. It makes sure that the
	 * stream is caught and doesn't return until everything on the stream has been processed. Should then call
	 * getFinalValue() to verify the expression is valid.
	 * @param expressionID 
	 * @param os
	 * @param is
	 * @param proxyids if not <code>null</code>, then this is the list of expression proxy ids that need to be returned as rendered.
	 * @param sender the sender used for reading back the proxyid resolutions, or <code>null</code> if no proxy ids.
	 * 
	 * @throws CommandException
	 * 
	 * @since 1.0.0
	 */
	public static void sendSyncCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject proxyids, Commands.ValueSender sender) throws CommandException {
		try {
			os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
			os.writeInt(expressionID);
			os.writeByte(SYNC_REQUEST);
			sendProxyIDs(os, proxyids);
			os.flush();
			if (proxyids != null) {
				Commands.readBackValue(is, proxyids, Commands.ARRAY_IDS);	// Read the array header.
				sender.initialize(proxyids);
				Commands.readArray(is, proxyids.anInt, sender, proxyids, true);	// Read the array.
			}
		} catch (CommandException e) {
			// rethrow this exception since we want these to go on out.
			throw e;
		} catch (Exception e) {
			// Wrapper this one.
			throw new UnexpectedExceptionCommandException(false, e);
		}		
	}	
	
	/**
	 * Send the proxyids (if not null) as part of a command. Used by sync and pullValue.
	 * @param os
	 * @param proxyids <code>null</code> if not requesting proxy ids.
	 * @throws IOException
	 * @throws CommandException
	 * 
	 * @since 1.1.0
	 */
	private static void sendProxyIDs(DataOutputStream os, Commands.ValueObject proxyids) throws IOException, CommandException {
		if (proxyids != null) {
			os.writeBoolean(true);	// Indicates proxy ids being sent.
			Commands.writeValue(os, proxyids, false, false);
		} else
			os.writeBoolean(false);	// No proxyids being sent.
	}
	
	/**
	 * Send the transfer expression command and receive back the expression processor controller.
	 * 
	 * @param expressionID
	 * @param os
	 * @param is
	 * @param expressionProcesserController
	 * @throws CommandException
	 * 
	 * @since 1.1.0
	 */
	public static void sendTransferExpressionCommand(int expressionID, DataOutputStream os, DataInputStream is, Commands.ValueObject expressionProcesserController) throws CommandException {
		try {
			os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
			os.writeInt(expressionID);
			os.writeByte(TRANSFER_EXPRESSION_REQUEST);
			os.flush();
			Commands.readBackValue(is, expressionProcesserController, Commands.NO_TYPE_CHECK); // Read the expression processor controller
		} catch (CommandException e) {
			throw e;
		} catch (Exception e) {
			// Wrapper this one.
			throw new UnexpectedExceptionCommandException(false, e);
		}
	}

	/**
	 * Send the resume expression command with given expression processor controller.
	 * 
	 * @param expressionID
	 * @param os
	 * @param expressionProcessorController
	 * @throws CommandException
	 * 
	 * @since 1.1.0
	 */
	public static void sendResumeExpressionCommand(int expressionID, DataOutputStream os, Commands.ValueObject expressionProcessorController) throws CommandException {
		try {
			os.writeByte(Commands.EXPRESSION_TREE_COMMAND);
			os.writeInt(expressionID);
			os.writeByte(RESUME_EXPRESSION_REQUEST);
			Commands.writeValue(os, expressionProcessorController, false, false);
		} catch (CommandException e) {
			throw e;
		} catch (Exception e) {
			// Wrapper this one.
			throw new UnexpectedExceptionCommandException(false, e);
		}			
	}
	
	private ExpressionCommands() {
		// Never intended to be instantiated.
	}
	
}
