/***************************************************************************
 *   Copyright (C) 2011 by Fabrizio Montesi <famontesi@gmail.com>          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Library General Public License as       *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 *                                                                         *
 *   For details about the authors of this software, see the AUTHORS file. *
 ***************************************************************************/

package jolie.runtime.correlation.impl;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import jolie.Interpreter;
import jolie.SessionThread;
import jolie.lang.Constants.ExecutionMode;
import jolie.net.CommChannel;
import jolie.net.CommMessage;
import jolie.net.SessionMessage;
import jolie.runtime.FaultException;
import jolie.runtime.Value;
import jolie.runtime.correlation.CorrelationEngine;
import jolie.runtime.correlation.CorrelationSet;
import jolie.runtime.correlation.CorrelationSet.CorrelationPair;

/**
 * A simple correlation algorithm that performs a sequential check
 * of each running session every time a new message arrives
 * or a session changes one of its correlation values.
 * @author Fabrizio Montesi
 */
public class SimpleCorrelationEngine extends CorrelationEngine
{
	private final Set< SessionThread > sessions = new HashSet< SessionThread >();

	public SimpleCorrelationEngine( Interpreter interpreter )
	{
		super( interpreter );
	}

	public synchronized boolean routeMessage( CommMessage message, CommChannel channel )
	{
		for( SessionThread session : sessions ) {
			if ( correlate( session, message ) ) {
				session.pushMessage( new SessionMessage( message, channel ) );
				return true;
			}
		}
		return false;
	}

	public synchronized void onSessionStart( SessionThread session, Interpreter.SessionStarter starter, CommMessage message )
	{
		sessions.add( session );
		initCorrelationValues( session, starter, message );
	}

	public synchronized void onSingleExecutionSessionStart( SessionThread session )
	{
		sessions.add( session );
	}

	public synchronized void onSessionExecuted( SessionThread session )
	{
		sessions.remove( session );
	}

	public synchronized void onSessionError( SessionThread session, FaultException fault )
	{
		onSessionExecuted( session );
	}

	private boolean correlate( SessionThread session, CommMessage message )
	{
		if ( (interpreter().correlationSets().isEmpty()
			&& interpreter().executionMode() == ExecutionMode.SINGLE)
			||
			session.isInitialisingThread()
		) {
			return true;
		}

		Value sessionValue;
		Value messageValue;
		List< CorrelationPair > pairs;
		CorrelationSet cset = interpreter().getCorrelationSetForOperation( message.operationName() );
		if ( cset == null ) {
			if ( interpreter().executionMode() == ExecutionMode.SINGLE ) {
				return true;
			} else {
				// It must be a session starter.
				return false;
			}
		}
		pairs = cset.getOperationCorrelationPairs( message.operationName() );
		for( CorrelationPair cpair : pairs ) {
			sessionValue = cpair.sessionPath().getValueOrNull( session.state().root() );
			if ( sessionValue == null ) {
				return false;
			} else {
				messageValue = cpair.messagePath().getValueOrNull( message.value() );
				if ( messageValue == null ) {
					return false;
				} else {
					// TODO: Value.equals is type insensitive, fix this with an additional check.
					if ( !sessionValue.isDefined() || !messageValue.isDefined() || !sessionValue.equals( messageValue ) ) {
						return false;
					}
				}
			}
		}

		return true;
	}
}

@@ -3823,20 +3823,22 @@
  ) %7B%0A%09%09%09
-if (
+return
  interpr
@@ -3887,46 +3887,10 @@
 NGLE
+;
  
-) %7B%0A%09%09%09%09return true;%0A%09%09%09%7D else %7B%0A%09%09%09%09
 // I
@@ -3922,31 +3922,8 @@
 er.%0A
-%09%09%09%09return false;%0A%09%09%09%7D%0A
 %09%09%7D%0A

Removed redundant if.