package org.qi4j.api.query.grammar;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Member;
import java.lang.reflect.Proxy;
import org.qi4j.api.association.AssociationStateHolder;
import org.qi4j.api.association.ManyAssociation;
import org.qi4j.api.composite.Composite;
import org.qi4j.api.composite.CompositeInstance;
import org.qi4j.functional.Function;
/**
* Function to get Entity ManyAssociations.
*/
public class ManyAssociationFunction<T>
implements Function<Composite, ManyAssociation<T>>
{
private AssociationFunction<?> traversedAssociation;
private ManyAssociationFunction<?> traversedManyAssociation;
private final AccessibleObject accessor;
public ManyAssociationFunction( AssociationFunction<?> traversedAssociation,
ManyAssociationFunction<?> traversedManyAssociation,
AccessibleObject accessor
)
{
this.traversedAssociation = traversedAssociation;
this.traversedManyAssociation = traversedManyAssociation;
this.accessor = accessor;
}
public AssociationFunction<?> traversedAssociation()
{
return traversedAssociation;
}
public ManyAssociationFunction<?> traversedManyAssociation()
{
return traversedManyAssociation;
}
public AccessibleObject accessor()
{
return accessor;
}
@Override
public ManyAssociation<T> map( Composite entity )
{
try
{
Object target = entity;
if( traversedAssociation != null )
{
target = traversedAssociation.map( entity ).get();
}
if( traversedManyAssociation != null )
{
throw new IllegalArgumentException( "Cannot traverse ManyAssociations" );
}
CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
return ( (AssociationStateHolder) handler.state() ).manyAssociationFor( accessor );
}
catch( IllegalArgumentException e )
{
throw e;
}
catch( Throwable e )
{
throw new IllegalArgumentException( e );
}
}
@Override
public String toString()
{
if( traversedAssociation != null )
{
return traversedAssociation.toString() + "." + ( (Member) accessor ).getName();
}
else
{
return ( (Member) accessor ).getName();
}
}
}