package com.jxml.quick.access;
import com.jxml.quick.*;
import com.jxml.quick.tf.*;
import java.beans.*;
import java.lang.reflect.*;

public class QPropertyAccess extends QAccess
{
    public String property;
    protected PropertyDescriptor pd=null;

    protected void setPD(QTargetFactory tf, QContext context)
	throws QPE
    {
	if (pd!=null)
	    return;
	PropertyDescriptor[] pds=tf.getPropertyDescriptors(context);
	if (pds==null)
	    context.throwPE("No PropertyDescriptors Available: "+tf.getClass().getName());
	int s=pds.length;
	int i;
	for (i=0;i<s;++i)
	    {
		if (property.equals(pds[i].getName()) &&
		    !(pds[i] instanceof IndexedPropertyDescriptor) &&
		    validProperty(pds[i]))
		    {
			pd=pds[i];
			return;
		    }
	    }
	context.throwPE("Invalid property: "+property);
    }

    protected boolean validProperty(PropertyDescriptor pd)
    {
	Class propertyType=pd.getPropertyType();
	return propertyType!=null;
    }

    public boolean readable(QTargetFactory parentFactory, QContext context)
	throws QPE
    {
	setPD(parentFactory,context);
	return pd.getReadMethod()!=null;
    }

    public QIterator createIterator()
    {
	return new QSimpleIterator();
    }

    protected Object get(QTargetFactory parentFactory, Object parent, QContext context)
	throws QPE
    {
	Object sargs[] = {};
	try
	{
		return pd.getReadMethod().invoke(parent,sargs);
	}
	catch (Exception e)
	{
		try
		{
			pd=null;
			setPD(parentFactory,context);
			return pd.getReadMethod().invoke(parent,sargs);
		}
		catch (IllegalAccessException ex)
		{
			context.throwPE(ex);
		}
		catch (InvocationTargetException ex)
		{
			context.throwPE(ex);
		}
	}
	return null;
    }

    public void setIteratorParent(QIterator it, 
				  Object parent, 
				  QTargetFactory parentFactory,
				  QContext context)
	throws QPE
    {
	setPD(parentFactory,context);
	((QSimpleIterator)it).setCurrent(get(parentFactory,parent,context));
    }

    public boolean writeable(QTargetFactory parentFactory, QContext context)
	throws QPE
    {
	setPD(parentFactory,context);
	return pd.getWriteMethod()!=null;
    }

    public void add(Object parent, 
		    QTargetFactory parentFactory,
		    Object child, 
		    QContext context)
	throws QPE
    {
	setPD(parentFactory,context);
	Object sargs[] = {child};
	try
	{
		pd.getWriteMethod().invoke(parent,sargs);
	}
	catch (Exception e)
	{
		try
		{
			pd=null;
			setPD(parentFactory,context);
			pd.getWriteMethod().invoke(parent,sargs);
		}
		catch (IllegalAccessException ex)
		{
			context.throwPE(ex);
		}
		catch (InvocationTargetException ex)
		{
			context.throwPE(ex);
		}
	}
    }
}
