All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.datanucleus.store.fieldmanager.DeleteFieldManager Maven / Gradle / Ivy

Go to download

DataNucleus Core provides the primary components of a heterogenous Java persistence solution. It supports persistence API's being layered on top of the core functionality.

There is a newer version: 6.0.7
Show newest version
/**********************************************************************
Copyright (c) 2006 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:
2011 Andy Jefferson - add null if bidir and not dependent functionality
    ...
**********************************************************************/
package org.datanucleus.store.fieldmanager;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.datanucleus.ExecutionContext;
import org.datanucleus.api.ApiAdapter;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.RelationType;
import org.datanucleus.state.ObjectProvider;

/**
 * Field manager that deletes all "dependent" PC objects referenced from the source object.
 * Effectively provides "delete-dependent".
 */
public class DeleteFieldManager extends AbstractFieldManager
{
    /** ObjectProvider for the owning object. */
    private final ObjectProvider op;

    private boolean manageRelationships = false;

    /**
     * Constructor.
     * @param op The ObjectProvider for the object.
     */
    public DeleteFieldManager(ObjectProvider op)
    {
        this(op, false);
    }

    /**
     * Constructor.
     * @param op The ObjectProvider for the object.
     * @param manageRelationships Whether to make an attempt to manage relationships when bidir fields are affected by this deletion (RDBMS typically doesnt need this)
     */
    public DeleteFieldManager(ObjectProvider op, boolean manageRelationships)
    {
        this.op = op;
        this.manageRelationships = manageRelationships;
    }

    /**
     * Utility method to process the passed persistable object.
     * @param pc The PC object
     */
    protected void processPersistable(Object pc)
    {
        ObjectProvider pcOP = op.getExecutionContext().findObjectProvider(pc);
        if (pcOP != null)
        {
            if (pcOP.isDeleting() || pcOP.becomingDeleted())
            {
                // Already becoming deleted so jump out
                return;
            }
        }

        // Delete it
        op.getExecutionContext().deleteObjectInternal(pc);
    }

    /**
     * Method to store an object field.
     * @param fieldNumber Number of the field (absolute)
     * @param value Value of the field
     */
    public void storeObjectField(int fieldNumber, Object value)
    {
        if (value != null)
        {
            AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
            ExecutionContext ec = op.getExecutionContext();
            RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
            if (RelationType.isRelationSingleValued(relationType))
            {
                // Process PC fields
                if (mmd.isDependent())
                {
                    processPersistable(value);
                }
                else if (manageRelationships && RelationType.isBidirectional(relationType) && !mmd.isEmbedded())
                {
                    ObjectProvider valueOP = ec.findObjectProvider(value);
                    if (valueOP != null && !valueOP.getLifecycleState().isDeleted() && !valueOP.isDeleting())
                    {
                        AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver())[0];
                        if (relationType == RelationType.ONE_TO_ONE_BI)
                        {
                            valueOP.replaceFieldMakeDirty(relMmd.getAbsoluteFieldNumber(), null);
                            valueOP.flush();
                        }
                        else if (relationType == RelationType.MANY_TO_ONE_BI)
                        {
                            // Make sure field at other side is loaded, and remove from any Collection
                            valueOP.loadField(relMmd.getAbsoluteFieldNumber());
                            Object relValue = valueOP.provideField(relMmd.getAbsoluteFieldNumber());
                            if (relValue != null)
                            {
                                if (relValue instanceof Collection)
                                {
                                    ((Collection)relValue).remove(op.getObject());
                                }
                            }
                        }
                    }
                }
            }
            else if (RelationType.isRelationMultiValued(relationType))
            {
                ApiAdapter api = ec.getApiAdapter();
                if (value instanceof Collection)
                {
                    // Process all elements of the Collection that are PC
                    boolean dependent = mmd.getCollection().isDependentElement();
                    if (mmd.isCascadeRemoveOrphans())
                    {
                        dependent = true;
                    }
                    if (dependent)
                    {
                        // Process any elements that are persistable
                        Collection coll = (Collection)value;
                        Iterator iter = coll.iterator();
                        while (iter.hasNext())
                        {
                            Object element = iter.next();
                            if (api.isPersistable(element))
                            {
                                processPersistable(element);
                            }
                        }
                    }
                    else if (manageRelationships && RelationType.isBidirectional(relationType) && !mmd.isEmbedded() && !mmd.getCollection().isEmbeddedElement())
                    {
                        if (relationType == RelationType.ONE_TO_MANY_BI)
                        {
                            Collection coll = (Collection)value;
                            Iterator iter = coll.iterator();
                            while (iter.hasNext())
                            {
                                Object element = iter.next();
                                if (api.isPersistable(element))
                                {
                                    ObjectProvider elementOP = ec.findObjectProvider(element);
                                    if (elementOP != null && !elementOP.getLifecycleState().isDeleted() && !elementOP.isDeleting())
                                    {
                                        AbstractMemberMetaData relMmd = mmd.getRelatedMemberMetaData(ec.getClassLoaderResolver())[0];
                                        elementOP.replaceFieldMakeDirty(relMmd.getAbsoluteFieldNumber(), null);
                                        elementOP.flush();
                                    }
                                }
                            }
                        }
                    }
                }
                else if (value instanceof Map)
                {
                    // Process all keys, values of the Map that are PC
                    Map map = (Map)value;
                    if (mmd.hasMap() && mmd.getMap().isDependentKey())
                    {
                        // Process any keys that are persistable
                        Set keys = map.keySet();
                        Iterator iter = keys.iterator();
                        while (iter.hasNext())
                        {
                            Object mapKey = iter.next();
                            if (api.isPersistable(mapKey))
                            {
                                processPersistable(mapKey);
                            }
                        }
                    }
                    if (mmd.hasMap() && mmd.getMap().isDependentValue())
                    {
                        // Process any values that are persistable
                        Collection values = map.values();
                        Iterator iter = values.iterator();
                        while (iter.hasNext())
                        {
                            Object mapValue = iter.next();
                            if (api.isPersistable(mapValue))
                            {
                                processPersistable(mapValue);
                            }
                        }
                    }
                    // TODO Handle nulling of bidirs
                }
                else if (value instanceof Object[])
                {
                    // Process all array elements that are PC
                    if (mmd.hasArray() && mmd.getArray().isDependentElement())
                    {
                        // Process any array elements that are persistable
                        for (int i=0;i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy