Package org.jpox.store.mapped.expression

Source Code of org.jpox.store.mapped.expression.MapExpression

/**********************************************************************
Copyright (c) 2004 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Contributors:
2004 Erik Bengtson - added containsEntry()
2004 Erik Bengtson - added getMethod()
    ...
**********************************************************************/
package org.jpox.store.mapped.expression;

import org.jpox.ClassLoaderResolver;
import org.jpox.exceptions.JPOXUserException;
import org.jpox.store.mapped.DatastoreIdentifier;
import org.jpox.store.mapped.IdentifierFactory;
import org.jpox.store.mapped.mapping.JavaTypeMapping;
import org.jpox.store.mapped.query.StatementText;
import org.jpox.store.mapped.scostore.MapStoreQueryable;
import org.jpox.store.scostore.MapStore;

/**
* An expression that represents some Map field in a query candidate
* class, or a Map field in an object linked from the candidate class
* by navigation.
* <p>
* When navigated through using containsKey(expr) the keys of the Map are
* relationally joined onto the query statement. When navigated through using
* containsValue(expr) the values of the Map are relationally joined onto the
* query statement. These 2 methods are required for JDO 2.0, whilst the
* isEmpty() and contains() are JDO 1.0.1. containsEntry() is a JPOX extension.
* </p>
*
* @version $Revision: 1.33 $
*/
public class MapExpression extends ScalarExpression
{
    private final MapStore mapStore;
    private final String fieldName;

    /**
     * Constructor.
     * @param qs The Query Statement
     * @param mapping The java field mapping
     * @param te The Table Expression
     * @param mapStore the backing store.
     * @param fieldName Name of the field for the map.
     **/
    public MapExpression(QueryExpression qs,
                         JavaTypeMapping mapping,
                         LogicSetExpression te,
                         MapStore mapStore,
                         String fieldName)
    {
        super(qs);

        this.mapping  = mapping;
        this.te = te;
        this.mapStore  = mapStore;
        this.fieldName = fieldName;
    }

    /**
     * Executed when the size() method is found in a query filter.
     * @return  The NumericExpression resulting from the size() method.
     */
    public NumericExpression sizeMethod()
    {
        IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
        String ctIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
        DatastoreIdentifier ctRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, ctIdentifier);

        return new ContainerSizeExpression(qs, getBackingStoreQueryable().getSizeSubquery(qs, mapping, te, ctRangeVar));
    }

    /**
     * Executed when the containsKey() method is found in a query filter.
     * This is added in JDO 2.0.
     * @param expr The ScalarExpression param for map.containsKey(...).
     * @return The BooleanExpression resulting from map.containsKey().
     **/
    public BooleanExpression containsKeyMethod(ScalarExpression expr)
    {
        // mt... = "map table"
        // vt... = "value table"

        IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
        if (expr instanceof UnboundVariable)
        {
            UnboundVariable var = (UnboundVariable)expr;
            if (var.getVariableType() == null)
            {
                // Set the variable type to be the element type for this collection
                var.setVariableType(qs.getClassLoaderResolver().classForName(mapStore.getKeyType()));
            }
            String vtIdentifier = "UNBOUND" + '.' + var.getVariableName();
            String mtIdentifier = idFactory.newIdentifier(idFactory.newIdentifier(te.getAlias(), fieldName), var.getVariableName()).getIdentifier();

            DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            DatastoreIdentifier vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);

            QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar);
            var.bindTo(getBackingStoreQueryable().joinKeysTo(qexpr,
                                           qs,
                                           mapping,
                                           te,
                                           mtRangeVar,
                                           var.getVariableType(),
                                           expr,
                                           vtRangeVar));
            return new ExistsExpression(qs, qexpr, true);           
        }
        else if (expr instanceof Literal)
        {
            String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
            DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            DatastoreIdentifier vtRangeVar;
            int n = 0;

            do
            {
                String vtIdentifier = mtIdentifier + '.' + (++n);
                vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
            } while (qs.getTableExpression(vtRangeVar) != null);

            ClassLoaderResolver clr = qs.getClassLoaderResolver();
            QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar);
            ScalarExpression joinKeysExpr = getBackingStoreQueryable().joinKeysTo(qexpr,
                                           qs,
                                           mapping,
                                           te,
                                           mtRangeVar,
                                           clr.classForName(expr.getMapping().getType()),
                                           expr,
                                           vtRangeVar);
            qexpr.andCondition(expr.eq(joinKeysExpr));
            return new ExistsExpression(qs, qexpr, true);
        }       
        else
        {
            String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
            DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            DatastoreIdentifier vtRangeVar;

            if (expr.te == null) // literals
            {
                int n = 0;

                do
                {
                    String vtIdentifier = mtIdentifier + '.' + (++n);
                    vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
                } while (qs.getTableExpression(vtRangeVar) != null);
            }
            else
            {
                vtRangeVar = expr.te.getAlias();
            }

            ClassLoaderResolver clr = qs.getClassLoaderResolver();
            ScalarExpression joinKeysExpr =
                getBackingStoreQueryable().joinKeysTo(expr.getQueryExpression(),
                                        qs,
                                        mapping,
                                        te,
                                        mtRangeVar,
                                        clr.classForName(mapStore.getKeyType()),
                                        expr,
                                        vtRangeVar);
            return joinKeysExpr.eq(expr);
        }
    }

    /**
     * Executed when the containsEntry() method is found in a query filter.
     * This is a JPOX extension to JDOQL 1.0.1/2.0.
     * @param keyExpr The ScalarExpression param for map.containsEntry(...).
     * @param valueExpr The ScalarExpression param for map.containsEntry(...).
     * @return The BooleanExpression resulting from map.containsEntry().
     **/
    public BooleanExpression containsEntryMethod(ScalarExpression keyExpr,
                                                 ScalarExpression valueExpr)
    {
        // mt... = "map table"
        // kt... = "key table"
        // vt... = "value table"
        IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
        String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
        DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);

        // obtains a variable name for key
        Class keyType;
        DatastoreIdentifier ktRangeVar;
        UnboundVariable keyVar = null;
        ClassLoaderResolver clr=qs.getClassLoaderResolver();
        int nKey = 0;
        if (keyExpr instanceof UnboundVariable)
        {
            keyVar = (UnboundVariable)keyExpr;
            String ktJavaName = "UNBOUND" + '.' + keyVar.getVariableName();
            keyType = keyVar.getVariableType();
            ktRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, ktJavaName);
        }
        else
        {
            keyType = clr.classForName(mapStore.getKeyType());
            do
            {
                String ktIdentifier = mtIdentifier + '.' + (++nKey);
                ktRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, ktIdentifier);
            } while (qs.getTableExpression(ktRangeVar) != null);
        }

        // obtains a variable name for value
        Class valueType;
        DatastoreIdentifier vtRangeVar;
        UnboundVariable valueVar = null;
        int nValue = 0;
        if (valueExpr instanceof UnboundVariable)
        {
            valueVar = (UnboundVariable)valueExpr;
            String vtJavaName = "UNBOUND" + '.' + valueVar.getVariableName();
            valueType = valueVar.getVariableType();
            vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtJavaName);
        }
        else
        {
            valueType = clr.classForName(mapStore.getValueType());
            do
            {
                String vtIdentifier = mtIdentifier + '.' + (++nValue);
                vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
            } while (qs.getTableExpression(vtRangeVar) != null);
        }

        QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar);
        ScalarExpression[] qclKeyValues =
            getBackingStoreQueryable().joinKeysValuesTo(qexpr,
                                qs,
                                mapping,
                                te,
                                mtRangeVar,
                                keyType,
                                valueType,
                                keyExpr,
                                valueExpr,
                                ktRangeVar,
                                vtRangeVar);

        if (keyExpr instanceof UnboundVariable)
        {
            keyVar.bindTo(qclKeyValues[0]);
        }
        if (valueExpr instanceof UnboundVariable)
        {
            valueVar.bindTo(qclKeyValues[1]);
        }
       
        if (!(keyExpr instanceof UnboundVariable))
        {
            qexpr.andCondition(keyExpr.eq(qclKeyValues[0]));
        }
        if (!(valueExpr instanceof UnboundVariable))
        {
            qexpr.andCondition(valueExpr.eq(qclKeyValues[1]));
        }
        return new ExistsExpression(qs, qexpr, true);
    }
   
    /**
     * Executed when a contains() method is found in a query filter.
     * This simply uses the containsValueMethod() to check against values.
     * @param expr  The ScalarExpression param for map.contains(...).
     * @return  The BooleanExpression resulting from map.contains().
     **/
    public BooleanExpression containsMethod(ScalarExpression expr)
    {
        return containsValueMethod(expr);
    }

    /**
     * Executed when the containsValue() method is found in a query filter.
     * This is added in JDO 2.0.
     * @param expr  The ScalarExpression param for map.containsValue(...).
     * @return  The BooleanExpression resulting from map.containsValue().
     **/
    public BooleanExpression containsValueMethod(ScalarExpression expr)
    {
        // mt... = "map table"
        // vt... = "value table"

        IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
        if (expr instanceof UnboundVariable)
        {
            UnboundVariable var = (UnboundVariable)expr;
            if (var.getVariableType() == null)
            {
                // Set the variable type to be the element type for this collection
                var.setVariableType(qs.getClassLoaderResolver().classForName(mapStore.getValueType()));
            }
            String vtIdentifier = "UNBOUND" + '.' + var.getVariableName();
            String mtIdentifier = idFactory.newIdentifier(idFactory.newIdentifier(te.getAlias(), fieldName), var.getVariableName()).getIdentifier();

            DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            DatastoreIdentifier vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);

            QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar);
            var.bindTo(getBackingStoreQueryable().joinValuesTo(qexpr,
                                           qs,
                                           mapping,
                                           te,
                                           mtRangeVar,
                                           var.getVariableType(),
                                           expr,
                                           vtRangeVar));
            return new ExistsExpression(qs, qexpr, true);           
        }
        else if (expr instanceof Literal)
        {
            String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
            DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            DatastoreIdentifier vtRangeVar;
            int n = 0;

            do
            {
                String vtIdentifier = mtIdentifier + '.' + (++n);
                vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
            } while (qs.getTableExpression(vtRangeVar) != null);

            ClassLoaderResolver clr = qs.getClassLoaderResolver();
            QueryExpression qexpr = getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar);
            ScalarExpression joinValuesExpr = getBackingStoreQueryable().joinValuesTo(qexpr,
                                           qs,
                                           mapping,
                                           te,
                                           mtRangeVar,
                                           clr.classForName(expr.getMapping().getType()),
                                           expr,
                                           vtRangeVar);
            qexpr.andCondition(expr.eq(joinValuesExpr));
            return new ExistsExpression(qs, qexpr, true);
        }       
        else
        {
            String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
            DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            DatastoreIdentifier vtRangeVar;

            if (expr.te == null) // literals
            {
                int n = 0;

                do
                {
                    String vtIdentifier = mtIdentifier + '.' + (++n);
                    vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
                } while (qs.getTableExpression(vtRangeVar) != null);
            }
            else
            {
                vtRangeVar = expr.te.getAlias();
            }
           
            ClassLoaderResolver clr=qs.getClassLoaderResolver();
            ScalarExpression joinValuesExpr =
                getBackingStoreQueryable().joinValuesTo(expr.getQueryExpression(),
                                        qs,
                                        mapping,
                                        te,
                                        mtRangeVar,
                                        clr.classForName(mapStore.getValueType()),
                                        expr,
                                        vtRangeVar);
            return joinValuesExpr.eq(expr);
        }
    }

    /**
     * Return the BooleanExpression for a query filter in the form
     * "map.isEmpty()".
     * @return  The BooleanExpression for a query filter in the form
     *          "map.isEmpty()".
     **/
    public BooleanExpression isEmptyMethod()
    {
        // mt... = "map table"
        IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
        String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();
        DatastoreIdentifier mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);

        return new ExistsExpression(qs, getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar), false);
    }

    /**
     * Method to get a value from the Map for a key
     * @param expr The key argument expression
     * @return The statement
     **/
    public ScalarExpression getMethod(ScalarExpression expr)
    {
        // mt... = "map table"
        // vt... = "value table"
        IdentifierFactory idFactory = qs.getStoreManager().getIdentifierFactory();
        String mtIdentifier = idFactory.newIdentifier(te.getAlias(), fieldName).getIdentifier();

        DatastoreIdentifier mtRangeVar;
        DatastoreIdentifier ktRangeVar;
        DatastoreIdentifier vtRangeVar;
        int n = 0;
        if (expr instanceof UnboundVariable)
        {
            UnboundVariable var = (UnboundVariable)expr;
            if (var.getVariableType() == null)
            {
                // Set the variable type to be the element type for this collection
                var.setVariableType(qs.getClassLoaderResolver().classForName(mapStore.getKeyType()));
            }
            String ktIdentifier = "UNBOUND" + '.' + var.getVariableName();
            String vtIdentifier = "UNBOUNDVALUE" + '.' + var.getVariableName();

            mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);
            ktRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, ktIdentifier);
            vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
        }
        else
        {
            mtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, mtIdentifier);

            do
            {
                String ktJavaName = mtIdentifier + '.' + (++n);
                ktRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, ktJavaName);
            } while (qs.getTableExpression(ktRangeVar) != null);

            n = 0;

            do
            {
                String vtIdentifier = mtIdentifier + '.' + (++n);
                vtRangeVar = idFactory.newIdentifier(IdentifierFactory.TABLE, vtIdentifier);
            } while (qs.getTableExpression(vtRangeVar) != null || vtRangeVar.equals(ktRangeVar));
        }
           
        /* QueryExpression qexpr = */ getBackingStoreQueryable().getExistsSubquery(qs, mapping, te, mtRangeVar);
        ClassLoaderResolver clr=qs.getClassLoaderResolver();
        ScalarExpression[] joinKeysExpr =
            getBackingStoreQueryable().joinKeysToGet(qs,
                qs,
                mapping,
                te,
                mtRangeVar,
                clr.classForName(mapStore.getKeyType()),
                ktRangeVar,
                vtRangeVar);
        if (expr instanceof UnboundVariable)
        {
            UnboundVariable var = (UnboundVariable)expr;
            var.bindTo(joinKeysExpr[0]);
        }
        return new ObjectExpression(qs,joinKeysExpr[1],joinKeysExpr[0].eq(expr), joinKeysExpr[1].te);
    }
   
    /**
     * Method to return the statement text.
     * @param mode (0=PROJECTION;1=FILTER)
     * @return The statement
     * @throws JPOXUserException since this object is inaccessible directly.
     **/
    public StatementText toStatementText(int mode)
    {
        throw new JPOXUserException("Cannot reference Map object directly: field name = " + fieldName);
    }

    private MapStoreQueryable getBackingStoreQueryable()
    {
        return (MapStoreQueryable)mapStore;
    }
}
TOP

Related Classes of org.jpox.store.mapped.expression.MapExpression

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.