/*******************************************************************************
 * 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.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

/**
 *  The HibernateList class does not immediately extend a generic query object 
 *  but is intended to be used as a value of a HibernateCondition object. It will 
 *  normally be used in conjunction with the IN and NOT IN Operator. The HibernateList 
 *  generates from a given collection of java beans or objects an explicit list. The 
 *  class has three properties, namely Property, BeanClass, and the collection of
 *  bean to generate list from
 *  @author nico.mack@tudor.lu
 */

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

	private String			m_Property;
	private Class<?>		m_BeanClass;
	private Collection <?>	m_Beans;

	private String			m_List;
	
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructors                                       						*
//***************************************************************************
//---------------------------------------------------------------------------

public HibernateList ()
	{
	m_Property  = null;
	m_BeanClass	= null;
	m_Beans 	= null;
	m_List		= null;
	}

//---------------------------------------------------------------------------
/**
 * Creates a new instance of HibernateList.
 * @param p_Property specifies the bean property to be used to generate list.
 * The class automatically generates the getter method from both the specified
 * property and the specified bean class.
 * @param p_BeanClass specifies the class of the java beans in the specified
 * collection.
 * @param p_Beans specifies the collection of beans to generate list from
 */
//---------------------------------------------------------------------------

public HibernateList (String p_Property, Class<?> p_BeanClass, Collection <?> p_Beans)
	{
	m_Property  = p_Property;
	m_BeanClass	= p_BeanClass;
	m_Beans 	= p_Beans;
	m_List		= null;
	}

//---------------------------------------------------------------------------
/**
 * Creates a new instance of HibernateList.
 * @param p_Objects specifies the collection of objects to generate list from
 */
//---------------------------------------------------------------------------

public HibernateList (Collection <?> p_Objects)
	{
	m_Property  = null;
	m_BeanClass	= null;
	m_Beans 	= p_Objects;
	m_List		= null;
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives                                       						*
//***************************************************************************
//---------------------------------------------------------------------------
/**
 * Wraps the specified string in quotes so that it can be used in a hibernate
 * query.
 * @param p_Unquoted specifies the string to be quoted.
 * @return the properly quoted string.
 */
//---------------------------------------------------------------------------

public String quoteString (String p_Unquoted)
	{
	StringBuffer l_Quoted;
	
	l_Quoted = new StringBuffer ();
	l_Quoted.append("'").append(p_Unquoted).append("'");
	
	return l_Quoted.toString();
	}

//---------------------------------------------------------------------------
/**
 * Build the actually list by iterating over the specified collection of
 * beans and calling the getter method for the specified property on every
 * bean. The returned values will be assembled to a string with the of
 * form <b>(</b> value[1]<b>,</b> value[2]<b>,</b> value[3]<b>,</b> .....
 * value[n] <b>)</b>
 * @return the list to be used as a hibernate condition
 */
//---------------------------------------------------------------------------

private String buildList ()
	{
	StringBuffer	l_List;
	Iterator<?>		l_Iterator;
	Object			l_Object;
	Object			l_Value;
	Method			l_Getter = null;
	String			l_Property;
	String			l_Separator = "";
	
	if (m_Beans == null) return "()";
	
	if ((m_BeanClass != null) && (m_Property != null))
		{
		l_Property = m_Property.substring(0,1).toUpperCase() + m_Property.substring(1);
	
		try	{
			l_Getter = m_BeanClass.getMethod("get" + l_Property);
			}
		catch (NoSuchMethodException p_Exception) 
			{
			l_Getter = null;
			}

		if (l_Getter == null)
			{
			try	{
				l_Getter = m_BeanClass.getMethod(m_Property);
				}
			catch (NoSuchMethodException p_Exception) 
				{
				l_Getter = null;
				}
			}
		if (l_Getter == null) return "()";
		}
			
	l_List = new StringBuffer ();
	l_List.append("(");
	
	l_Iterator = m_Beans.iterator();
	while (l_Iterator.hasNext())
		{
		l_Object = l_Iterator.next();
		
		try {
			l_Value = (l_Getter != null)?l_Getter.invoke(l_Object):l_Object;
			}
		catch (IllegalArgumentException p_Exception) 
			{
			l_Value = null;
			} 
		catch (IllegalAccessException p_Exception) 
			{
			l_Value = null;
			} 
		catch (InvocationTargetException p_Exception) 
			{
			l_Value = null;
			}
		
		if (l_Value == null) continue;
		
		if (l_Value instanceof String)
			l_List.append(l_Separator).append(this.quoteString((String)l_Value));
		else l_List.append(l_Separator).append(l_Value.toString());
		l_Separator = ",";
		}
	
	l_List.append(")");
	
	return l_List.toString();
	}

//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body                                       						*
//***************************************************************************
//---------------------------------------------------------------------------

public String getProperty ()
	{
	return m_Property;
	}

//---------------------------------------------------------------------------

public void setProperty (String p_Property)
	{
	m_Property = p_Property;
	m_List	   = null;
	}

//---------------------------------------------------------------------------

public Class<?> getBeanClass ()
	{
	return m_BeanClass;
	}

//---------------------------------------------------------------------------

public void setBeanClass (Class<?> p_BeanClass)
	{
	m_BeanClass = p_BeanClass;
	m_List	   = null;
	}

//---------------------------------------------------------------------------

public Collection<?> getBeans ()
	{
	return m_Beans;
	}

//---------------------------------------------------------------------------

public void setBeans (Collection<?> p_Beans)
	{
	m_Beans = p_Beans;
	m_List	= null;
	}

//---------------------------------------------------------------------------
/**
 * Renders the hibernate specific representation of this list
 * @return Hibernate specific representation of this list
 */
//---------------------------------------------------------------------------

public String toString ()
	{
	if (m_List == null) m_List = this.buildList();
	
	return m_List;
	}

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