/*
 * Creado el 17-dic-03
 *
 * Para cambiar la plantilla para este archivo generado vaya a
 * Ventana&gt;Preferencias&gt;Java&gt;Generación de código&gt;Código y comentarios
 */
package es.ejie.frmk.presentacion.sesiondatos;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.beanutils.BasicDynaClass;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaClass;
import org.apache.commons.beanutils.DynaProperty;

import es.ejie.frmk.infraestructura.seguridad.Q70InformacionSeguridadInterface;

/**
 * @version 1.0
 * Fecha: 24-nov-03
 * 
 * Implementacion de la DynaClass para los Q70ContextoJerarquicoEJIE, contiene la estructura
 * y la la forma de acceso a las propiedades del Q70ContextoJerarquicoEJIE.
 * 
 * @see es.ejie.frmk.presentacion.sesiondatos.Q70ContextoJerarquicoEJIE
 * @see org.apache.commons.beanutils.DynaClass
 */
public class Q70ContextoEJIEDynaClass implements DynaClass, Serializable
{
	private static final long serialVersionUID = -8166037739503954380l;

	private DynaClass contextoClass;
	private transient List contextoAntecesoresClass;
	private transient DynaProperty[] propiedadesContexto;

	private transient List listaAtributosInformacionSeguridadInterface;

	//TODO Jgrey ?DynaProperty no tiene sobreescrito el equals(), posibilidad de extension y ademas añadir mas cosas como scope del property y seguridad.

	/**
	 * Construct a new BasicDynaClass with default parameters.
	 */
	public Q70ContextoEJIEDynaClass()
	{
		this(null, null, null);
	}

	/**
	 * Construct a new Q70ContextoEJIEDynaClass with the specified parameters.
	 *
	 * @param name Nombre de esta clase DynaBean
	 * @param dynaBeanClass La implementacion para crear nuevas instancias
	 */
	public Q70ContextoEJIEDynaClass(String name, Class dynaBeanClass)
	{
		this(name, dynaBeanClass, null);
	}

	/**
	 * Construct a new Q70ContextoEJIEDynaClass with the specified parameters.
	 *
	 * @param name Nombre de esta clase DynaBean
	 * @param dynaBeanClass La implementacion para crear nuevas instancias
	 * @param properties Propiedades que va a soportar la clase creada
	 */
	public Q70ContextoEJIEDynaClass(String name, Class dynaBeanClass, DynaProperty properties[])
	{
		this(name, dynaBeanClass, null, null);
	}

	/**
	 * @param name Nombre de esta clase DynaBean
	 * @param dynaBeanClass La implementacion para crear nuevas instancias
	 * @param properties Propiedades que va a soportar la clase creada
	 * @param listaDynaClass Lista de los DynaClass asociados a los contextos anidados del Q70ContextoJerarquicoEJIE
	 */
	public Q70ContextoEJIEDynaClass(String name, Class dynaBeanClass, DynaProperty properties[], List listaDynaClass)
	{
		super();
		if (dynaBeanClass == null)
			dynaBeanClass = Q70ContextoBasico.class;
		contextoClass = new BasicDynaClass(name, dynaBeanClass, properties);
		contextoAntecesoresClass = listaDynaClass;

		for (int i = properties.length - 1; i >= 0; i--)
		{
			doAddToInformacionSeguridad(properties[i], properties[i].getName());
		}
	}

	/**
	 * @see org.apache.commons.beanutils.DynaClass#getName()
	 */
	public String getName()
	{
		return contextoClass.getName();
	}

	/**
	 * @see org.apache.commons.beanutils.DynaClass#getDynaProperty(java.lang.String)
	 */
	public DynaProperty getDynaProperty(String name)
	{
		DynaProperty prop = contextoClass.getDynaProperty(name);
		if (prop != null)
		{
			return prop;
		}

		if (contextoAntecesoresClass != null)
		{
			Iterator it = contextoAntecesoresClass.iterator();
			while (it.hasNext())
			{
				DynaClass element = (DynaClass) it.next();
				try
				{
					prop = element.getDynaProperty(name);
				}
				catch (IllegalArgumentException e)
				{}
				if (prop != null)
					return prop;
			}
		}

		return getInformacionSeguridadInterface(name);
	}

	private DynaProperty getInformacionSeguridadInterface(String name)
	{
		if (listaAtributosInformacionSeguridadInterface != null)
		{
			Iterator it = listaAtributosInformacionSeguridadInterface.iterator();
			while (it.hasNext())
			{
				return new DynaProperty(name, String.class);
			}
		}
		return null;
	}

	/**
	 * @see org.apache.commons.beanutils.DynaClass#getDynaProperties()
	 */
	public DynaProperty[] getDynaProperties()
	{
		if (propiedadesContexto != null)
			return propiedadesContexto;

		int capacity = contextoClass.getDynaProperties().length;
		Iterator it;

		if (contextoAntecesoresClass != null)
		{
			it = contextoAntecesoresClass.iterator();
			while (it.hasNext())
			{
				DynaClass auxDB = (DynaClass) it.next();
				capacity += auxDB.getDynaProperties().length;
			}
		}

		propiedadesContexto = new DynaProperty[capacity];

		int i = 0;
		System.arraycopy(contextoClass.getDynaProperties(), 0, propiedadesContexto, i, contextoClass.getDynaProperties().length);
		i += contextoClass.getDynaProperties().length;

		if (contextoAntecesoresClass != null)
		{
			it = contextoAntecesoresClass.iterator();
			while (it.hasNext())
			{
				DynaProperty[] aux = ((DynaClass) it.next()).getDynaProperties();
				System.arraycopy(aux, 0, propiedadesContexto, i, aux.length);
				i += aux.length;
			}
		}

		return propiedadesContexto;
	}

	/**
	 * @see org.apache.commons.beanutils.DynaClass#newInstance()
	 */
	public DynaBean newInstance() throws IllegalAccessException, InstantiationException
	{
		// TODO ?Debera construir los hijos de esta dynaclass en una lista y pasarsela...
		return contextoClass.newInstance();
	}

	/**
	 * Devuelve la lista de DynaClass anidados asociados a un Q70ContextoJerarquicoEJIE
	 * @return
	 */
	public List getContextoAntecesoresClass()
	{
		return contextoAntecesoresClass;
	}

	/**
	 * Asigna una nueva lista de DynaClass anidados asociados a un Q70ContextoJerarquicoEJIE
	 * @param list Lista de DynaClass anidados
	 */
	public void setContextoAntecesoresClass(List list)
	{
		contextoAntecesoresClass = list;
		propiedadesContexto = null;
	}

	/**
	 * Devuelve la DynaProperty correspondiente al nombre de parametro, pero solo si es una 
	 * de sus propiedades basicas, es decir, no busca en la lista de DynaClass anidados
	 * @return
	 */
	public DynaProperty getPropiedadDePrimerNivel(String nameProperty)
	{
		return contextoClass.getDynaProperty(nameProperty);
	}

	/**
	 * Devuelve la lista de DynaProperty correspondiente a esta DynaClass, pero no devuelve las 
	 * propiedades que esten en la lista de DynaClass anidados
	 * @return
	 */
	public DynaProperty[] getPropiedadesDePrimerNivel()
	{
		return contextoClass.getDynaProperties();
	}

	/**
	 * @param class1
	 */
	public void setContextoClass(DynaClass class1)
	{
		contextoClass = class1;
		propiedadesContexto = null;
	}

	private void doAddToInformacionSeguridad(DynaProperty propiedad, String nombreAtributo)
	{
		Class[] interfaces = propiedad.getType().getInterfaces();
		for (int i = interfaces.length - 1; i >= 0; i--)
		{
			if (interfaces[i].getName().equals(Q70InformacionSeguridadInterface.class.getName()))
			{
				if (listaAtributosInformacionSeguridadInterface == null)
				{
					listaAtributosInformacionSeguridadInterface = new ArrayList(1);
				}
				listaAtributosInformacionSeguridadInterface.add(nombreAtributo);
			}
		}
	}
}
