Package org.datanucleus.store.mapped.scostore

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

/**********************************************************************
Copyright (c) 2002 Kelly Grizzle (TJDO) 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:
2002 Mike Martin (TJDO)
2003 Andy Jefferson - coding standards
2003 Andy Jefferson - changed to use Logger
2004 Andy Jefferson - moved statements from subclasses to this class.
2005 Andy Jefferson - added embedded PC element capability
2005 Andy Jefferson - added dependent-element when removed from collection
    ...
**********************************************************************/
package org.datanucleus.store.mapped.scostore;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.exceptions.NucleusDataStoreException;
import org.datanucleus.metadata.CollectionMetaData;
import org.datanucleus.store.ExecutionContext;
import org.datanucleus.store.ObjectProvider;
import org.datanucleus.store.StoreManager;
import org.datanucleus.store.connection.ManagedConnection;
import org.datanucleus.store.mapped.exceptions.MappedDatastoreException;
import org.datanucleus.store.scostore.SetStore;
import org.datanucleus.util.NucleusLogger;
import org.datanucleus.util.StringUtils;

/**
* Abstract representation of the backing store for a Set/Collection.
*/
public abstract class AbstractSetStore extends AbstractCollectionStore implements SetStore
{
    /**
     * Constructor.
     * @param storeMgr Manager for the store
     * @param clr The ClassLoaderResolver
     * @param specialization the datastore-specific specialization
     */
    protected AbstractSetStore(StoreManager storeMgr, ClassLoaderResolver clr,
            AbstractSetStoreSpecialization specialization)
    {
        super(storeMgr, clr, specialization);
    }

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

    /**
     * Accessor for an iterator for the set.
     * Implemented by the subclass using whatever mechanism the underlying datastore provides.
     * @param ownerSM State Manager for the set.
     * @return Iterator for the set.
     */
    public abstract Iterator iterator(ObjectProvider ownerSM);

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

        boolean modified = false;
        ExecutionContext ec = sm.getExecutionContext();

        try
        {
            ManagedConnection mconn = storeMgr.getConnection(ec);
            try
            {
                int[] num = getSpecialization().internalAdd(sm, mconn, false, element, true, this);
                if (num[0] > 0)
                {
                    modified = true;
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (MappedDatastoreException e)
        {
            NucleusLogger.DATASTORE.error(e);
            String msg = LOCALISER.msg("056009", e.getMessage());
            NucleusLogger.DATASTORE.error(msg);
            throw new NucleusDataStoreException(msg, e);
        }

        return modified;
    }
   
    /**
     * Adds all elements from a collection to the association owner vs elements
     * @param sm State Manager for the container
     * @param elements The elements to add
     * @param size Current size of set (if known). Not used by sets
     * @return Whether it was successful
     */
    public boolean addAll(ObjectProvider sm, Collection elements, int size)
    {
        if (elements == null || elements.size() == 0)
        {
            return false;
        }

        boolean modified = false;
        List exceptions = new ArrayList();
        boolean batched = (elements.size() > 1);

        // Validate all elements for writing
        Iterator iter = elements.iterator();
        while (iter.hasNext())
        {
            validateElementForWriting(sm, iter.next(), null);
        }

        ExecutionContext ec = sm.getExecutionContext();
        ManagedConnection mconn = storeMgr.getConnection(ec);
        try
        {
            // Loop through all elements to be added
            iter = elements.iterator();
            Object element = null;
            int[] returnCode = null;
            while (iter.hasNext())
            {
                element = iter.next();

                try
                {
                    returnCode = getSpecialization().internalAdd(sm, mconn, batched, element, !batched || (batched && !iter.hasNext()), this);
                }
                catch (MappedDatastoreException mde)
                {
                    exceptions.add(mde);
                    NucleusLogger.DATASTORE.error(mde);
                }
            }

            if (exceptions.size() == 0)
            {
                if (returnCode == null)
                {
                    modified = false;
                }
                else
                {
                    for (int i=0;i<returnCode.length;i++)
                    {
                        if (returnCode[i] > 0)
                        {
                            modified = true;
                        }
                    }
                }
            }
        }
        finally
        {
            mconn.release();
        }

        if (!exceptions.isEmpty())
        {
            // Throw all exceptions received as the cause of a NucleusDataStoreException 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()]), sm.getObject());
        }

        return modified;
    }

    /**
     * Removes the association to one element
     * @param sm State Manager for the container
     * @param element Element to remove
     * @param size Current size
     * @param allowDependentField Whether to allow any cascade deletes caused by this removal
     * @return Whether it was successful
     */
    public boolean remove(ObjectProvider sm, Object element, int size, boolean allowDependentField)
    {
        if (!validateElementForReading(sm, element))
        {
            NucleusLogger.DATASTORE.debug("Attempt to remove element=" + StringUtils.toJVMIDString(element) + " but doesn't exist in this Set.");
            return false;
        }

        Object elementToRemove = element;
        ExecutionContext ec = sm.getExecutionContext();
        if (ec.getApiAdapter().isDetached(element))
        {
            // Element passed in is detached so find attached version (DON'T attach this object)
            elementToRemove = ec.findObject(ec.getApiAdapter().getIdForObject(element), true, false,
                element.getClass().getName());
        }

        boolean modified = getSpecialization().remove(sm, elementToRemove, size, this);
        CollectionMetaData collmd = ownerMemberMetaData.getCollection();
        boolean dependent = collmd.isDependentElement();
        if (ownerMemberMetaData.isCascadeRemoveOrphans())
        {
            dependent = true;
        }
        if (allowDependentField && dependent && !collmd.isEmbeddedElement())
        {
            // TODO Could this element be stored as a duplicate in this set ?
            // Delete the element if it is dependent
            sm.getExecutionContext().deleteObjectInternal(elementToRemove);
        }

        return modified;
    }

    /**
     * Remove all elements from a collection from the association owner vs
     * elements. This implementation iterates around the remove() method doing
     * each element 1 at a time. Please refer to the JoinSetStore and
     * FKSetStore for the variations used there. This is used for Map key and value
     * stores.
     * @param sm State Manager for the container
     * @param elements Collection of elements to remove
     * @return Whether the database was updated
     */
    public boolean removeAll(ObjectProvider sm, Collection elements, int size)
    {
        if (elements == null || elements.size() == 0)
        {
            return false;
        }

        boolean modified = false;
        List exceptions = new ArrayList();
        boolean batched = (elements.size() > 1);

        // Validate all elements exist
        Iterator iter = elements.iterator();
        while (iter.hasNext())
        {
            Object element = iter.next();
            if (!validateElementForReading(sm, element))
            {
                NucleusLogger.DATASTORE.debug("AbstractSetStore::removeAll element=" + element + " doesn't exist in this Set.");
                return false;
            }
        }

        try
        {
            ExecutionContext ec = sm.getExecutionContext();
            ManagedConnection mconn = storeMgr.getConnection(ec);
            try
            {
                Object element = null;
                iter = elements.iterator();
                getSpecialization().preInternalRemove(mconn);

                while (iter.hasNext())
                {
                    element = iter.next();
                    try
                    {
                        // Process the remove
                        int[] rc = getSpecialization().internalRemove(
                            sm, mconn, batched, element, !batched || (batched && !iter.hasNext()), this);
                        if (rc != null)
                        {
                            for (int i=0;i<rc.length;i++)
                            {
                                if (rc[i] > 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 NucleusDataStoreException so the user can see which record(s) didn't remove
            String msg = LOCALISER.msg("056012", ((Exception) exceptions.get(0)).getMessage());
            NucleusLogger.DATASTORE.error(msg);
            throw new NucleusDataStoreException(msg, (Throwable[])exceptions.toArray(new Throwable[exceptions.size()]), sm.getObject());
        }

        return modified;
    }
}
TOP

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

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.