gt: 			String var = msgCast.getVar();
context: /*
  FRODO: a FRamework for Open/Distributed Optimization
  Copyright (C) 2008-2013  Thomas Leaute, Brammert Ottens & Radoslaw Szymanek
  
  FRODO is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  FRODO 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 Affero General Public License for more details.
  
  You should have received a copy of the GNU Affero General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  
  
  How to contact the authors: 
  <http://frodo2.sourceforge.net/>
  */
  
  package frodo2.algorithms.bnbadopt;
  
  import java.lang.reflect.Array;
  import java.lang.reflect.Constructor;
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  import org.jdom2.Element;
  
  import frodo2.algorithms.AgentInterface;
  import frodo2.algorithms.StatsReporter;
  import frodo2.algorithms.varOrdering.dfs.DFSgeneration;
  import frodo2.algorithms.varOrdering.dfs.DFSgeneration.DFSview;
  import frodo2.communication.IncomingMsgPolicyInterface;
  import frodo2.communication.Message;
  import frodo2.communication.Queue;
  import frodo2.solutionSpaces.Addable;
  import frodo2.solutionSpaces.DCOPProblemInterface;
  import frodo2.solutionSpaces.UtilitySolutionSpace;
  import frodo2.solutionSpaces.hypercube.Hypercube;
  
  /**
   * @author Brammert Ottens
   * @param <Val> type used for variable values
   * @param <U> type used for utility values
   * 
   * The preprocessing listener computes heuristics for the lower bounds used by bnbadopt. Currently, it implements
   * the following heuristics:
   * 
   * - trivial heuristic: set every lb to 0
   */
  public class Preprocessing <Val extends Addable<Val>, U extends Addable<U> > 
  implements StatsReporter {
  
  	/** The type of the message telling the module to start */
  	public static String START_MSG_TYPE = AgentInterface.START_AGENT;
  
  	/** The type of message containing the heuristics */
  	public final static String HEURISTICS_MSG_TYPE = "Heuristics";
  	
  	/** The type of the heuristics stats message*/
  	public final static String HEURISTICS_STAT_MSG_TYPE = "Heuristics stat";
  
  	/** A list of variables this agent owns */
  	private ArrayList<String> variables = new ArrayList<String> ();
  	
  	/** A list of domains of each of the variables*/
  	private HashMap<String, Val[]> domains;
  	
  	/** The heuristic that is used to generate the lower bounds*/
  	private PreprocessingHeuristic<Val, U> heuristic;
  	
  	/** used to create the null value*/
  	private U zeroObject;
  	
  	/** The agent's queue*/
  	private Queue queue;
  
  	/** The agent's problem */
  	private DCOPProblemInterface<Val, U> problem;
  	
  	/** For each known variable, the name of the agent that owns it */
  	private Map<String, String> owners = new HashMap<String, String> ();
  	
  	/** Whether the algorithm has been started */
  	private boolean started = false;
  	
  	/** Container for the reported heuristics*/
  	public HashMap<String, UtilitySolutionSpace<Val, U>> reportedHeuristics;
  
  	/** Constructor in stats gatherer mode
  	 * @param problem 	not used at this time
  	 * @param e 		not used at this time 
  	 */
  	public Preprocessing (Element e, DCOPProblemInterface<Val, U> problem) {
  		reportedHeuristics = new HashMap<String, UtilitySolutionSpace<Val, U>>();
  		this.heuristic = new SimpleHeuristic<Val, U>(this);
  	}
  	
  	/** Constructor
  	 * @param variables 				the variables
  	 * @param domains 					the domains
  	 * @param heuristicsName 			name of the heuristics class used
  	 * @param zeroObject 				the zero utility
  	 * @throws Exception 	if an error occurs
  	 */
  	public Preprocessing (ArrayList<String> variables, HashMap<String, Val[]> domains, String heuristicsName, U zeroObject) throws Exception {
  		this.variables = variables;
  		this.domains = domains;
  		this.zeroObject = zeroObject;
  		setHeuristics(heuristicsName);
  	}
  	
  	/** Constructor
  	 * @param problem 			the agent's problem
  	 * @param heuristicsName 	name of the heuristic class used
  	 * @throws Exception 	if an error occurs
  	 */
  	public Preprocessing (DCOPProblemInterface<Val, U> problem, String heuristicsName) throws Exception {
  		this.problem = problem;
  		this.zeroObject = problem.getZeroUtility();
  		setHeuristics(heuristicsName);
  	}
  	
  	/** Constructor from XML descriptions
  	 * @param problem 			description of the problem
  	 * @param parameters 		description of the parameters of Preprocessing
  	 * @throws Exception 	if an error occurs
  	 */
  	public Preprocessing (DCOPProblemInterface<Val, U> problem, Element parameters) throws Exception {
  		this.problem = problem;
  		zeroObject = problem.getZeroUtility();
  		
  		// Extract the parameters
  		String heuristicName = parameters.getAttributeValue("heuristic");
  		if (heuristicName == null) 
  			heuristicName = SimpleHeuristic.class.getName();
  		setHeuristics(heuristicName);
  	}
  	
  	/** Parses the problem */
  	private void init () {
  		this.variables = new ArrayList<String> (problem.getMyVars());
  		domains = new HashMap<String, Val[]>();
  		for (String var : variables) 
  			domains.put(var, problem.getDomain(var));
  		
  		owners = problem.getOwners();
  		
  		heuristic.init();
  		
  		this.started = true;
  
  		assert ! problem.maximize() : "bnbadopt only works for minimization problems";
  	}
  	
  	/** @see StatsReporter#reset() */
  	public void reset() {
  		/// @todo Auto-generated method stub
  	}
  
  	/** Helper function to set the heuristics used for preprocessing
  	 * 
  	 * @param heuristicName 	the name of the heuristic class
  	 * @throws ClassNotFoundException 	if the heuristic class name is unknown
  	 * @throws InstantiationException 	if the heuristic class does not have an accessible nullary constructor
  	 * @throws IllegalAccessException 	if the heuristic class does not have an accessible nullary constructor
  	 */
  	@SuppressWarnings("unchecked")
  	private void setHeuristics(String heuristicName) 
  		throws ClassNotFoundException, InstantiationException, IllegalAccessException {
  	
  		try {
  			Class< PreprocessingHeuristic<Val, U> > heuristicClass = (Class<PreprocessingHeuristic<Val, U>>) Class.forName(heuristicName);
  			Class<?> parTypes[] = new Class[1];
  			parTypes[0] = Preprocessing.class;
  			Object[] args = new Object[1];
  			args[0] = this;
  			Constructor<PreprocessingHeuristic<Val, U>> constructor;
  			constructor = heuristicClass.getConstructor(parTypes);
  			this.heuristic = constructor.newInstance(args);
  		} catch (Exception e) {
  			e.printStackTrace();
  		}
  
  	}
  	
  	/**
  	 * Convenience method to used to create a UtilitySpace<Val, U> and fill it with
  	 * the value \c utility
  	 * 
  	 * @author Brammert Ottens, 19 mei 2009
  	 * @param variables		the variable for which the space must be created
  	 * @param utility	the utility to be used
  	 * @return	a UtilitySpace over variable \c var with all utilities set to \c utility
  	 */
  	@SuppressWarnings("unchecked")
  	public UtilitySolutionSpace<Val, U> createUtilitySpace(String[] variables, U utility) {
  		int	domainSize = 1;
  		
  		Val[][] domains = (Val[][])Array.newInstance(Array.newInstance(this.domains.get(this.variables.get(0))[0].getClass(), 0).getClass(), variables.length);
  		for(int i = 0; i < variables.length; i++) {
  			domains[i] = this.problem.getDomain(variables[i]);
  			domainSize *= domains[i].length; 
  		}
  		
  		
  		U[] utilities = (U[]) Array.newInstance(utility.getClass(), domainSize*variables.length);
  		Arrays.fill(utilities, utility);
  		
  		return new Hypercube<Val, U>(variables, domains, utilities, utility.getPlusInfinity());
  	}
  	
  	/** 
  	 * @see frodo2.algorithms.StatsReporter#getStatsFromQueue(frodo2.communication.Queue)
  	 */
  	public void getStatsFromQueue(Queue queue) {
  		queue.addIncomingMessagePolicy(HEURISTICS_STAT_MSG_TYPE, this);
  	}
  
  	/**
  	 * Returns the reported heuristics
  	 * @author Brammert Ottens, 22 jun 2009
  	 * @return	the reported heuristics
  	 */
  	public HashMap<String, UtilitySolutionSpace<Val, U>> getReportedHeuristics() {
  		return this.reportedHeuristics;
  	}
  
  	/** 
  	 * @see frodo2.algorithms.StatsReporter#setSilent(boolean)
  	 */
  	public void setSilent(boolean silent) {
  		// TODO Auto-generated method stub
  		
  	}
  
  	/** @see IncomingMsgPolicyInterface#getMsgTypes() */
  	public Collection<String> getMsgTypes() {
  		ArrayList <String> msgTypes = new ArrayList <String> (4);
  		msgTypes.add(START_MSG_TYPE);
  		msgTypes.add(DFSgeneration.OUTPUT_MSG_TYPE);
  		msgTypes.add(heuristic.getMsgType());
  		msgTypes.add(AgentInterface.AGENT_FINISHED);
  		return msgTypes;
  	}
  
  	/** @see IncomingMsgPolicyInterface#notifyIn(Message) */
  	@SuppressWarnings("unchecked")
  	public void notifyIn( Message msg) {
  		
  		String type = msg.getType();
  		
  		if(type.equals(HEURISTICS_STAT_MSG_TYPE)) { // in stats gatherer mode
  			BoundsMsg<Val, U> msgCast = (BoundsMsg<Val, U>) msg;
  			reportedHeuristics.put(msgCast.getSender(), msgCast.getBounds());
  			return;
  		}
  		
  		else if (type.equals(AgentInterface.AGENT_FINISHED)) {
  			this.reset();
  			return;
  		}
  		
  		// Parse the problem if this hasn't been done yet
  		if (! this.started) 
  			init();
  		
  		if(type.equals(DFSgeneration.OUTPUT_MSG_TYPE)) { // receiving DFS tree information for ONE variable
  			DFSgeneration.MessageDFSoutput<Val, U> msgCast = (DFSgeneration.MessageDFSoutput<Val, U>)msg;
  			
  