Package org.qi4j.api.query.grammar

Source Code of org.qi4j.api.query.grammar.PropertyFunction

package org.qi4j.api.query.grammar;

import org.qi4j.api.association.Association;
import org.qi4j.api.composite.Composite;
import org.qi4j.api.composite.CompositeInstance;
import org.qi4j.api.property.GenericPropertyInfo;
import org.qi4j.api.property.Property;
import org.qi4j.api.query.NotQueryableException;
import org.qi4j.api.query.QueryExpressionException;
import org.qi4j.api.util.Classes;
import org.qi4j.functional.Function;

import java.lang.reflect.*;

/**
* TODO
*/
public class PropertyFunction<T>
        implements Function<Composite, Property<T>>
{
    private PropertyFunction traversedProperty;
    private AssociationFunction traversedAssociation;
    private ManyAssociationFunction<?> traversedManyAssociation;
    private final AccessibleObject accessor;

    public PropertyFunction( PropertyFunction traversedProperty, AssociationFunction traversedAssociation, ManyAssociationFunction<?> traversedManyAssociation, AccessibleObject accessor )
    {
        this.traversedProperty = traversedProperty;
        this.traversedAssociation = traversedAssociation;
        this.traversedManyAssociation = traversedManyAssociation;
        this.accessor = accessor;

        // Verify that the property accessor is not marked as non queryable
        NotQueryableException.throwIfNotQueryable( accessor );
        // Verify that the property type itself (value composites) is not marked as non queryable

        Type returnType = Classes.TYPE_OF.map( accessor );
        if( !Property.class.isAssignableFrom( Classes.RAW_CLASS.map( returnType ) ) )
        {
            throw new QueryExpressionException( "Not a property type:" + returnType );
        }
        Type propertyTypeAsType = GenericPropertyInfo.getPropertyType( returnType );
        if( propertyTypeAsType instanceof ParameterizedType )
        {
            propertyTypeAsType = ( (ParameterizedType) propertyTypeAsType ).getRawType();
        }

        if( !( propertyTypeAsType instanceof Class ) )
        {
            throw new QueryExpressionException( "Unsupported property type:" + propertyTypeAsType );
        }
        Class type = (Class<T>) propertyTypeAsType;
        NotQueryableException.throwIfNotQueryable( type );
    }

    public PropertyFunction getTraversedProperty()
    {
        return traversedProperty;
    }

    public AssociationFunction getTraversedAssociation()
    {
        return traversedAssociation;
    }

    public ManyAssociationFunction getTraversedManyAssociation()
    {
        return traversedManyAssociation;
    }

    public AccessibleObject getAccessor()
    {
        return accessor;
    }

    @Override
    public Property<T> map( Composite entity )
    {
        try
        {
            Object target = entity;
            if (traversedProperty != null)
            {
                Property<?> property = traversedProperty.map( entity );
                if (property == null)
                    return null;
                target = property.get();
            }
            else if (traversedAssociation != null)
            {
                Association<?> association = traversedAssociation.map( entity );
                if (association == null)
                    return null;
                target = association.get();
            }
            else if (traversedManyAssociation != null)
                throw new IllegalArgumentException( "Cannot evaluate a ManyAssociation" );

            if (target == null)
                return null;

            CompositeInstance handler = (CompositeInstance) Proxy.getInvocationHandler( target );
            return handler.state().propertyFor( accessor );
        } catch( IllegalArgumentException e )
        {
            throw e;
        }catch( Throwable e )
        {
            throw new IllegalArgumentException( e );
        }
    }

    @Override
    public String toString()
    {
        if (traversedProperty != null)
            return traversedProperty.toString()+"."+ ((Member)accessor).getName();
        else if (traversedAssociation != null)
            return traversedAssociation.toString()+"."+ ((Member)accessor).getName();
        else
            return ((Member)accessor).getName();
    }
}
TOP

Related Classes of org.qi4j.api.query.grammar.PropertyFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.