Package org.datanucleus.store.mapped.scostore

Source Code of org.datanucleus.store.mapped.scostore.AbstractArrayStore

/**********************************************************************
Copyright (c) 2005 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:
    ...
**********************************************************************/
package org.datanucleus.store.mapped.scostore;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.ManagedConnection;
import org.datanucleus.ObjectManager;
import org.datanucleus.StateManager;
import org.datanucleus.exceptions.NucleusDataStoreException;
import org.datanucleus.store.StoreManager;
import org.datanucleus.store.mapped.DatastoreIdentifier;
import org.datanucleus.store.mapped.exceptions.MappedDatastoreException;
import org.datanucleus.store.mapped.expression.ArrayStoreQueryable;
import org.datanucleus.store.mapped.expression.LogicSetExpression;
import org.datanucleus.store.mapped.expression.QueryExpression;
import org.datanucleus.store.mapped.expression.ScalarExpression;
import org.datanucleus.store.mapped.expression.StringLiteral;
import org.datanucleus.store.mapped.mapping.JavaTypeMapping;
import org.datanucleus.store.scostore.ArrayStore;
import org.datanucleus.util.NucleusLogger;

/**
* Abstract representation of the backing store for an array.
*/
public abstract class AbstractArrayStore extends ElementContainerStore implements ArrayStore, ArrayStoreQueryable
{
    /**
     * Constructor.
     * @param storeMgr Manager for the store
     * @param clr ClassLoader resolver
     */
    protected AbstractArrayStore(StoreManager storeMgr, ClassLoaderResolver clr,
            AbstractArrayStoreSpecialization specialization)
    {
        super(storeMgr, clr, specialization);
    }

    /**
     * Accessor for the array from the datastore.
     * @param ownerSM SM for the owner
     * @return The array (as a List of objects)
     */
    public List getArray(StateManager ownerSM)
    {
        Iterator iter = iterator(ownerSM);
        List elements = new ArrayList();
        while (iter.hasNext())
        {
            Object obj = iter.next();
            elements.add(obj);
        }

        return elements;
    }

    /**
     * Clear the association from owner to all elements. Observes the necessary dependent field settings
     * with respect to whether it should delete the element when doing so.
     * @param ownerSM State Manager for the container.
     */
    public void clear(StateManager ownerSM)
    {
        Collection dependentElements = null;
        if (ownerMemberMetaData.getArray().isDependentElement())
        {
            // Retain the dependent elements that need deleting after clearing
            dependentElements = new HashSet();
            Iterator iter = iterator(ownerSM);
            while (iter.hasNext())
            {
                dependentElements.add(iter.next());
            }
        }
        getSpecialization().clear(ownerSM, this);

        if (dependentElements != null && dependentElements.size() > 0)
        {
            ownerSM.getObjectManager().deleteObjects(dependentElements.toArray());
        }
    }

    /**
     * Method to set the array for the specified owner to the passed value.
     * @param ownerSM State Manager for the owner
     * @param array the array
     * @return Whether the array was updated successfully
     */
    public boolean set(StateManager ownerSM, Object array)
    {
        if (array == null || Array.getLength(array) == 0)
        {
            return true;
        }

        // Validate all elements for writing
        int length = Array.getLength(array);
        for (int i = 0; i < length; i++)
        {
            Object obj = Array.get(array, i);
            validateElementForWriting(ownerSM, obj, null);
        }

        boolean modified = false;
        List exceptions = new ArrayList();
        boolean batched = allowsBatching() && length > 1;

        try
        {
            ObjectManager om = ownerSM.getObjectManager();
            ManagedConnection mconn = storeMgr.getConnection(om);
            try
            {
                getSpecialization().processBatchedWrites(mconn);

                // Loop through all elements to be added
                Object element = null;
                for (int i = 0; i < length; i++)
                {
                    element = Array.get(array, i);

                    try
                    {
                        // Add the row to the join table
                        int[] rc = getSpecialization().internalAdd(ownerSM, this, element, mconn, batched, i,
                            (i == length - 1));
                        if (rc != null)
                        {
                            for (int j = 0; j < rc.length; j++)
                            {
                                if (rc[j] > 0)
                                {
                                    // At least one record was inserted
                                    modified = true;
                                }
                            }
                        }
                    }
                    catch (MappedDatastoreException mde)
                    {
                        mde.printStackTrace();
                        exceptions.add(mde);
                        NucleusLogger.DATASTORE.error(mde);
                    }
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (MappedDatastoreException e)
        {
            e.printStackTrace();
            exceptions.add(e);
            NucleusLogger.DATASTORE.error(e);
        }

        if (!exceptions.isEmpty())
        {
            // Throw all exceptions received as the cause of a JPOXDataStoreException so the user can see which
            // record(s) didn't persist
            String msg = LOCALISER.msg("056009", ((Exception) exceptions.get(0)).getMessage());
            NucleusLogger.DATASTORE.error(msg);
            throw new NucleusDataStoreException(msg, (Throwable[]) exceptions.toArray(new Throwable[exceptions.size()]), ownerSM
                    .getObject());
        }

        return modified;
    }

    /**
     * Adds one element to the association owner vs elements
     * @param sm State Manager for the container
     * @param element The element to add
     * @param position The position to add this element at
     * @return Whether it was successful
     */
    public boolean add(StateManager sm, Object element, int position)
    {
        validateElementForWriting(sm, element, null);

        boolean modified = false;

        try
        {
            ObjectManager om = sm.getObjectManager();
            ManagedConnection mconn = storeMgr.getConnection(om);

            try
            {
                // Add a row to the join table
                int[] returnCode = getSpecialization().internalAdd(sm, this, element, mconn, false, position,
                    true);
                if (returnCode[0] > 0)
                {
                    modified = true;
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (MappedDatastoreException e)
        {
            throw new NucleusDataStoreException(LOCALISER.msg("056009", e.getMessage()), e.getCause());
        }

        return modified;
    }

    /**
     * Accessor for an iterator through the array elements.
     * @param ownerSM State Manager for the container.
     * @return The Iterator
     */
    public abstract Iterator iterator(StateManager ownerSM);

    private AbstractArrayStoreSpecialization getSpecialization()
    {
        return (AbstractArrayStoreSpecialization) specialization;
    }

    // ----------------------------- TODO Remove these when we replace JDOQL -----------------------------------

    /**
     * Query utility to generate an exists() statement for an element.
     * The generated query will be of the form
     * <PRE>
     * SELECT 1 FROM JOINTABLE THIS_JOIN WHERE THIS_JOIN.OWNER_ID_OID = THIS.OWNER_ID
     * </PRE>
     * @param qs The JDOQL query statement
     * @param mapping mapping of the field
     * @param ownerTe Expression for the table
     * @param arrayTableAlias alias for the array
     * @return The JDOQL query statement
     */
    public QueryExpression getExistsSubquery(QueryExpression qs, JavaTypeMapping mapping, LogicSetExpression ownerTe,
            DatastoreIdentifier arrayTableAlias)
    {
        QueryExpression stmt = dba.newQueryStatement(containerTable, arrayTableAlias, qs.getClassLoaderResolver());
        stmt.setParent(qs);

        // Join for the owner
        ScalarExpression ownerExpr = mapping.newScalarExpression(stmt, ownerTe);
        ScalarExpression ownerInCollectionExpr = ownerMapping.newScalarExpression(stmt, stmt.getTableExpression(arrayTableAlias));
        stmt.andCondition(ownerExpr.eq(ownerInCollectionExpr));

        stmt.select(arrayTableAlias, elementMapping);

        return stmt;
    }

    /**
     * Query utility to generate a subquery for the size() of the collection.
     * The generated query will be of the form
     * <PRE>
     * SELECT COUNT(*) FROM JOINTABLE THIS_JOIN WHERE THIS_JOIN.OWNER_ID_OID = THIS.OWNER_ID
     * </PRE>
     * @param qs The query statement
     * @param mapping mapping of the field
     * @param ownerTe Expression for the table
     * @param arrayTableAlias alias for the array
     * @return The query statement
     */
    public QueryExpression getSizeSubquery(QueryExpression qs, JavaTypeMapping mapping,
            LogicSetExpression ownerTe, DatastoreIdentifier arrayTableAlias)
    {
        QueryExpression stmt = dba.newQueryStatement(containerTable, arrayTableAlias, qs.getClassLoaderResolver());
        stmt.setParent(qs);

        // Join for the owner
        ScalarExpression ownerExpr = mapping.newScalarExpression(stmt, ownerTe);
        ScalarExpression ownerInCollectionExpr = ownerMapping.newScalarExpression(stmt, stmt.getTableExpression(arrayTableAlias));
        stmt.andCondition(ownerExpr.eq(ownerInCollectionExpr));

        // Select COUNT(*)
        JavaTypeMapping m = storeMgr.getMappingManager().getMapping(String.class);
        StringLiteral lit = (StringLiteral)m.newLiteral(stmt, "COUNT(*)");
        lit.generateStatementWithoutQuotes();
        stmt.selectScalarExpression(lit);

        return stmt;
    }
}
TOP

Related Classes of org.datanucleus.store.mapped.scostore.AbstractArrayStore

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.