Package org.jpox.store.mapped.mapping

Source Code of org.jpox.store.mapped.mapping.Mappings

/**********************************************************************
Copyright (c) 2003 Erik Bengtson 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:
2003 Andy Jefferson - coding standards
2005 Andy Jefferson - added handling for left outer join of related fields when in fetch group
2006 Andy Jefferson - added support for primary join table and select of owner object
    ...
**********************************************************************/
package org.jpox.store.mapped.mapping;

import org.jpox.ClassLoaderResolver;
import org.jpox.metadata.AbstractMemberMetaData;
import org.jpox.metadata.Relation;
import org.jpox.store.mapped.DatastoreClass;
import org.jpox.store.mapped.DatastoreContainerObject;
import org.jpox.store.mapped.DatastoreElementContainer;
import org.jpox.store.mapped.DatastoreIdentifier;
import org.jpox.store.mapped.DatastoreObject;
import org.jpox.store.mapped.IdentifierFactory;
import org.jpox.store.mapped.MappedStoreManager;
import org.jpox.store.mapped.StatementExpressionIndex;
import org.jpox.store.mapped.expression.LogicSetExpression;
import org.jpox.store.mapped.expression.QueryExpression;
import org.jpox.store.mapped.expression.ScalarExpression;

/**
* Helper class for doing many tasks with mapping.
*
* @version $Revision: 1.34 $
*/
public class Mappings
{
    /**
     * Add columns to a query. Columns added to the query are obtained from the
     * mappings included in the statementExpressionIndex passed as parameter.
     * After adding columns to the query, statementExpressionIndex is updated
     * with the index/position of the columns in the query.
     * @param qs the Query Statement
     * @param statementExpressionIndex the list of mapping/column indexes to be
     *                                 included in the query
     */
    public static void selectMapping(QueryExpression qs,
                                     StatementExpressionIndex[] statementExpressionIndex)
    {
        selectMapping(qs, null, statementExpressionIndex);
    }

    /**
     * Add columns to a query. Columns added to the query are obtained from the
     * mappings included in the statementExpressionIndex passed as parameter.
     * After adding columns to the query, statementExpressionIndex is updated
     * with the index/position of the columns in the query.
     * @param qs the Query Statement
     * @param tableIdentifier the Identifier for the table which the columns are from (may be null, if TODO)
     * @param statementExpressionIndex the list of mapping/column indexes to be
     *                                 included in the query
     */
    public static void selectMapping(QueryExpression qs,
                                     DatastoreIdentifier tableIdentifier,
                                     StatementExpressionIndex[] statementExpressionIndex)
    {
        if (statementExpressionIndex == null)
        {
            return;
        }
        for (int i = 0; i < statementExpressionIndex.length; ++i)
        {
            if (statementExpressionIndex[i] != null)
            {
                JavaTypeMapping m = statementExpressionIndex[i].getMapping();
                if (m != null)
                {
                    if (m.getNumberOfDatastoreFields() > 0)
                    {
                        int[] columnNumbersByField = (tableIdentifier != null) ? qs.select(tableIdentifier, m, true) : qs.select(m, true);
                        statementExpressionIndex[i].setExpressionIndex(columnNumbersByField);
                    }
                    else
                    {
                        setStatementExpressionForFieldWithNoDatastoreColumns(qs, tableIdentifier, m, statementExpressionIndex[i]);
                    }
                }
            }
        }
    }

    /**
     * Convenience method that sets the StatementExpressionIndex for a mapping that has no datastore mappings
     * @param qs The QueryStatement
     * @param tableIdentifier the Identifier for the table which the columns are from (may be null, if TODO)
     * @param m The mapping
     * @param statementExpressionIndex The StatementExpressionIndex to update
     */
    private static void setStatementExpressionForFieldWithNoDatastoreColumns(QueryExpression qs,
                                                                             DatastoreIdentifier tableIdentifier,
                                                                             JavaTypeMapping m,
                                                                             StatementExpressionIndex statementExpressionIndex)
    {
        AbstractMemberMetaData fmd = m.getFieldMetaData();
        ClassLoaderResolver clr = qs.getClassLoaderResolver();
        int relationType = fmd.getRelationType(clr);
        if (relationType == Relation.ONE_TO_ONE_BI)
        {
            if (fmd.getMappedBy() != null)
            {
                // "mapped-by" at this side
                // 1-1 bidirectional single FK relation, with FK in source table.
                // This field is not stored, but instead a foreign is set in the source table which stores a reference to this (target table).
                // A FK is set in the source table refering to the target table.
                // Do a LEFT OUTER JOIN to the related (source) table(s) to pick up the identifier value of this.
                /*
                 * For example :-
                 * TABLE A (TARGET)               TABLE B (SOURCE)
                 * ID                             ID  A_ID (FK)
                 * --                             --  ----
                 * 18                             21  18
                 *
                 * Class A                        Class B
                 * {                              {
                 *    B b;                            A a;
                 * }                              }
                 */

                int[] colNums = null;
                MappedStoreManager storeMgr = qs.getStoreManager();
                JavaTypeMapping[] sourceMappings = null;
                DatastoreClass[] sourceTables = null;
                if (m instanceof ReferenceMapping)
                {
                    // Reference field (with "n" implementations)
                    JavaTypeMapping[] refMappings = ((ReferenceMapping)m).getJavaTypeMapping();
                    sourceTables = new DatastoreClass[refMappings.length];
                    sourceMappings = new JavaTypeMapping[refMappings.length];
                    for (int i=0;i<refMappings.length;i++)
                    {
                        sourceTables[i] = storeMgr.getDatastoreClass(refMappings[i].type, qs.getClassLoaderResolver());
                        sourceMappings[i] = sourceTables[i].getFieldMapping(fmd.getMappedBy());
                    }
                }
                else
                {
                    // PC field
                    sourceTables = new DatastoreClass[1];
                    sourceMappings = new JavaTypeMapping[1];
                    sourceTables[0] = storeMgr.getDatastoreClass(fmd.getTypeName(), qs.getClassLoaderResolver());
                    sourceMappings[0] = sourceTables[0].getFieldMapping(fmd.getMappedBy());
                }

                for (int i=0;i<sourceMappings.length;i++)
                {
                    // Do a LEFT OUTER JOIN for this sourceMapping back to the target id column(s)

                    // TODO Move this hardcoded table name out into the calling class so it controls the names of all table aliases
                    DatastoreIdentifier sourceTableIdentifier =
                        storeMgr.getIdentifierFactory().newIdentifier(IdentifierFactory.TABLE,
                            "SOURCECLASS" + fmd.getAbsoluteFieldNumber() + "_" + i);
                    LogicSetExpression sourceTableExpr = qs.newTableExpression(sourceTables[i], sourceTableIdentifier, true)[0];

                    // Left outer join from target ID to the mapped-by field on the source class
                    ScalarExpression sourceExpr = sourceMappings[i].newScalarExpression(qs, sourceTableExpr);
                    ScalarExpression targetExpr;
                    if (tableIdentifier != null)
                    {
                        LogicSetExpression targetTableExpr;
                        if (qs.getTableExpression(tableIdentifier) == null)
                        {
                            targetTableExpr = qs.newTableExpression(m.getDatastoreContainer(), tableIdentifier);
                        }
                        else
                        {
                            targetTableExpr = qs.getTableExpression(tableIdentifier);
                        }
                        targetExpr = m.getDatastoreContainer().getIDMapping().newScalarExpression(qs, targetTableExpr);
                    }
                    else
                    {
                        targetExpr = m.getDatastoreContainer().getIDMapping().newScalarExpression(qs,
                            qs.getMainTableExpression());
                    }
                    qs.leftOuterJoin(sourceExpr, targetExpr, sourceTableExpr, true, true);

                    // Select the Id column(s) of the source class (via the Left Outer Join)
                    int[] columnNumbersByField = qs.select(sourceTableIdentifier, sourceTables[i].getIDMapping(), true);

                    // Copy these column numbers into our overall column numbers set
                    if (sourceMappings.length == 1)
                    {
                        // We only have one source so just reference these
                        colNums = columnNumbersByField;
                    }
                    else if (colNums != null)
                    {
                        // Append to the end of where we have got to
                        int[] tmpColNums = colNums;
                        colNums = new int[tmpColNums.length + columnNumbersByField.length];
                        for (int j=0;j<tmpColNums.length;j++)
                        {
                            colNums[j] = tmpColNums[j];
                        }
                        for (int j=0;j<columnNumbersByField.length;j++)
                        {
                            colNums[tmpColNums.length+j] = columnNumbersByField[j];
                        }
                        tmpColNums = null;
                    }
                    else
                    {
                        // Add to the start of our column numbers
                        colNums = new int[columnNumbersByField.length];
                        for (int j=0;j<columnNumbersByField.length;j++)
                        {
                            colNums[j] = columnNumbersByField[j];
                        }
                    }
                }

                statementExpressionIndex.setExpressionIndex(colNums);
            }
        }
        else if (relationType == Relation.MANY_TO_ONE_BI)
        {
            AbstractMemberMetaData[] relatedMmds = fmd.getRelatedMemberMetaData(clr);
            // TODO Cater for more than 1 related field
            if (fmd.getJoinMetaData() != null || relatedMmds[0].getJoinMetaData() != null)
            {
                // 1-N bidirectional join table relation.
                // Do a LEFT OUTER JOIN to the join table to pick up the value.
                MappedStoreManager storeMgr = qs.getStoreManager();
                DatastoreContainerObject joinTable = storeMgr.getDatastoreContainerObject(relatedMmds[0]);
                JavaTypeMapping referenceMapping = null;
                JavaTypeMapping selectMapping = null;

                DatastoreElementContainer collTable = (DatastoreElementContainer)joinTable;
                referenceMapping = collTable.getElementMapping();
                selectMapping = collTable.getOwnerMapping();

                DatastoreObject mainTable = qs.getMainTableExpression().getMainTable();
                if (!mainTable.equals(joinTable))
                {
                    // Statement selects the element table and the owner column should be selected
                    // Join across to the join table, and select the owner mapping of the join table

                    // TODO Move this hardcoded table name out into the calling class so it controls the names of all table aliases
                    DatastoreIdentifier joinTableIdentifier =
                        storeMgr.getIdentifierFactory().newIdentifier(IdentifierFactory.TABLE,
                            "JOINTABLE" + fmd.getAbsoluteFieldNumber());
                    LogicSetExpression table_expr_sub = qs.newTableExpression(joinTable, joinTableIdentifier, true)[0];

                    // Left outer join from our Id to the mapped-by field on the other class
                    ScalarExpression subExpr = referenceMapping.newScalarExpression(qs, table_expr_sub);
                    ScalarExpression schExpr = null;
                    if (tableIdentifier != null)
                    {
                        LogicSetExpression targetTableExpr;
                        if (qs.getTableExpression(tableIdentifier) == null)
                        {
                            targetTableExpr = qs.newTableExpression(m.getDatastoreContainer(), tableIdentifier);
                        }
                        else
                        {
                            targetTableExpr = qs.getTableExpression(tableIdentifier);
                        }
                        schExpr = m.getDatastoreContainer().getIDMapping().newScalarExpression(qs, targetTableExpr);
                    }
                    else
                    {
                        schExpr = m.getDatastoreContainer().getIDMapping().newScalarExpression(qs, qs.getMainTableExpression());
                    }
                    qs.leftOuterJoin(subExpr, schExpr, table_expr_sub, true, true);

                    // Select the Id column(s) of the other class (via the Left Outer Join)
                    int[] columnNumbersByField = qs.select(joinTableIdentifier, selectMapping, true);
                    statementExpressionIndex.setExpressionIndex(columnNumbersByField);
                }
                else
                {
                    // The statement selects the join table, and joins to the element, and the owner column should be selected
                    // Select the owner mapping of the join table directly (no join needed)
                    int[] columnNumbersByField = qs.select(selectMapping, true);
                    statementExpressionIndex.setExpressionIndex(columnNumbersByField);
                }
            }
        }
    }

    /**
     * Get the indexes/position for Mapping columns in a given the initial
     * position. Used to set parameters in PreparedStatements
     * @param initialPosition the initialPosition
     * @param mapping the Mapping
     * @return an array containing indexes for parameters
     **/
    public static int[] getParametersIndex(int initialPosition, JavaTypeMapping mapping)
    {
        if (mapping.getNumberOfDatastoreFields() < 1)
        {
            return new int[]{initialPosition};
        }

        int parameter[] = new int[mapping.getNumberOfDatastoreFields()];
        for (int i=0; i<parameter.length; i++)
        {
            parameter[i] = initialPosition+i;
        }
        return parameter;
    }
}
TOP

Related Classes of org.jpox.store.mapped.mapping.Mappings

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.