/*******************************************************************************
 * This file is part of GECAMed.
 * 
 * GECAMed is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License (L-GPL) as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * GECAMed 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License (L-GPL)
 * along with GECAMed.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * GECAMed is Copyrighted by the Centre de Recherche Public Henri Tudor (http://www.tudor.lu)
 * (c) CRP Henri Tudor, Luxembourg, 2008
 *******************************************************************************/
package lu.tudor.santec.gecamed.core.utils.querybuilder;

import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;

//***************************************************************************
//* Class Definition and Members                                            *
//***************************************************************************

/**
 * The Group class implements a set of conditions combined by a common
 * operator. A group also accepts other groups inside of it, i.e sub groups, 
 * similar to parantheses in expressions.
 * 
 * @author nico.mack@tudor.lu
 */

public class Group extends TreeNode
	{
	private static final long serialVersionUID = 1L;

	private Operator	m_Operator;
	private Long		m_NumberOfConditions;
	
//***************************************************************************
//* Class Constants                                                         *
//***************************************************************************
	
//***************************************************************************
//* Constructors                                       						*
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * Creates a new empty group.
 */
//---------------------------------------------------------------------------

public Group ()
	{
	m_Operator = new Operator ();
	m_NumberOfConditions = 0L;
	}
	
//---------------------------------------------------------------------------
/**
 * Creates a new empty group using the specified operator to combine conditions
 * and groups added later on.
 * @param p_Operator specifies the combining operator for this group
 */
//---------------------------------------------------------------------------

public Group (Operator p_Operator)
	{
	m_Operator = p_Operator;
	m_NumberOfConditions = 0L;
	}
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Class Primitives                                                        *
//***************************************************************************
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body		                                                        *
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * The getOperator method returns the combining operator defined for this group.
 * @return the combining operator
 */
//---------------------------------------------------------------------------

public Operator getOperator ()
	{
	return m_Operator;
	}

//---------------------------------------------------------------------------
/**
 * The setOperator sets the combining operator for this group to the specified
 * one
 * @param p_Operator specifies the new operator to be used by this group to
 * combine added conditions and groups.
 */
//---------------------------------------------------------------------------

public void setOperator (Operator p_Operator)
	{
	m_Operator = p_Operator;
	}

//---------------------------------------------------------------------------
/**
 * The addCondition method adds the specified condition to this group.
 * @param p_Condition specifies the condition to be added
 */
//---------------------------------------------------------------------------

public void addCondition (Condition p_Condition)
	{
	this.addChild (p_Condition);
	m_NumberOfConditions = 0L;
	}

//---------------------------------------------------------------------------
/**
 * The addCondaddGroupition method adds the specified group as a sub-group to
 * this group.
 * @param p_Group specifies the group to be added
 */
//---------------------------------------------------------------------------

public void addGroup (Group p_Group)
	{
	this.addChild (p_Group);
	m_NumberOfConditions = 0L;
	}

//---------------------------------------------------------------------------
/**
 * The getAllConditions returns all the conditions contained in this group.
 * This includes the conditions that were directly added to this group as well
 * as those that were contained in add sub-groups.
 * @return A collection containing all the conditions found inside this group.
 */
//---------------------------------------------------------------------------

public Collection <Condition> getAllConditions ()
	{
	Collection <TreeNode>	l_Leaves;
	Iterator   <TreeNode>	l_LeafIterator;
	TreeNode				l_Leaf;
	
	Collection <Condition>	l_Conditions;
	
	l_Conditions = new LinkedHashSet <Condition> ();
	m_NumberOfConditions = 0L;
	
	l_Leaves = this.getAllLeaves();
	if (l_Leaves != null)
		{
		l_LeafIterator = l_Leaves.iterator();
		while (l_LeafIterator.hasNext())
			{
			l_Leaf = l_LeafIterator.next();
			if (l_Leaf instanceof Condition) 
				{
				l_Conditions.add ((Condition)l_Leaf);
				m_NumberOfConditions++;
				}
			}
		}
		
	return l_Conditions;
	}

//---------------------------------------------------------------------------
/**
 * The method returns the total number of conditions contained inside this
 * group. Condition count also includes those conditions contained in sub
 * groups.
 * @return the total number of conditions inside this group
 */
//---------------------------------------------------------------------------

public Long getNumberOfConditions ()
	{
	Collection <TreeNode>	l_Leaves;
	Iterator   <TreeNode>	l_LeafIterator;
	TreeNode				l_Leaf;
	
	if (m_NumberOfConditions > 0) return m_NumberOfConditions;
	
	m_NumberOfConditions = 0L;
	
	l_Leaves = this.getAllLeaves();
	if (l_Leaves != null)
		{
		l_LeafIterator = l_Leaves.iterator();
		while (l_LeafIterator.hasNext())
			{
			l_Leaf = l_LeafIterator.next();
			if (l_Leaf instanceof Condition) m_NumberOfConditions++;
			}
		}
		
	return m_NumberOfConditions;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* End Of Class                                                            *
//***************************************************************************
//---------------------------------------------------------------------------

}
