Package org.jpox.store.mapped.mapping

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

/**********************************************************************
Copyright (c) 2003 Mike Martin 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
2004 Andy Jefferson - implementation of newScalarExpression, newLiteral
2005 Andy Jefferson - basic serialisation support
2005 Andy Jefferson - updated serialisation using SCOUtils methods
    ...
**********************************************************************/
package org.jpox.store.mapped.mapping;

import java.util.Iterator;
import java.util.Set;

import org.jpox.StateManager;
import org.jpox.api.ApiAdapter;
import org.jpox.exceptions.JPOXException;
import org.jpox.exceptions.JPOXUserException;
import org.jpox.sco.Map;
import org.jpox.sco.SCO;
import org.jpox.sco.SCOContainer;
import org.jpox.sco.SCOMap;
import org.jpox.sco.SCOUtils;
import org.jpox.store.exceptions.ReachableObjectNotCascadedException;
import org.jpox.store.mapped.expression.LogicSetExpression;
import org.jpox.store.mapped.expression.MapExpression;
import org.jpox.store.mapped.expression.MapLiteral;
import org.jpox.store.mapped.expression.QueryExpression;
import org.jpox.store.mapped.expression.ScalarExpression;
import org.jpox.store.scostore.MapStore;
import org.jpox.util.JPOXLogger;

/**
* SCO Mapping for Map types.
*
* @version $Revision: 1.52 $
**/
public class MapMapping extends AbstractContainerMapping implements MappingCallbacks
{
    /**
     * Equality operator.
     * @param obj Object to compare against
     * @return Whether they are equal
     */
    public boolean equals(Object obj)
    {
        if (obj == this)
        {
            return true;
        }

        if (!obj.getClass().equals(getClass()))
        {
            return false;
        }

        MapMapping sm = (MapMapping)obj;

        return fmd.equals(sm.fmd) && storeMgr.equals(sm.storeMgr);
    }

    /**
     * Accessor for the Java type represented here.
     * @return The java type
     */
    public Class getJavaType()
    {
        return Map.class;
    }

    // ---------------- Implementation of MappingCallbacks --------------------

    /**
     * Method to be called after the insert of the owner class element.
     * @param sm StateManager of the owner
     */
    public void postInsert(StateManager sm)
    {
        java.util.Map value = (java.util.Map) sm.provideField(fmd.getAbsoluteFieldNumber());
        if (containerIsStoredInSingleColumn())
        {
            // Do nothing when serialised since we are handled in the main request
            if (value != null)
            {
                // Make sure the keys/values are ok for proceeding
                SCOUtils.validateObjectsForWriting(sm.getObjectManager(), value.keySet());
                SCOUtils.validateObjectsForWriting(sm.getObjectManager(), value.values());
            }
            return;
        }

        if (value == null)
        {
            // replace null map with an empty SCO wrapper
            replaceFieldWithWrapper(sm, null, false, false);
            return;
        }

        if (!fmd.isCascadePersist())
        {
            // Field doesnt support cascade-persist so no reachability
            if (JPOXLogger.REACHABILITY.isDebugEnabled())
            {
                JPOXLogger.REACHABILITY.debug(LOCALISER.msg("007006", fmd.getFullFieldName()));
            }

            // Check for any persistable keys/values that arent persistent
            ApiAdapter api = sm.getObjectManager().getApiAdapter();
            Set entries = value.entrySet();
            Iterator iter = entries.iterator();
            while (iter.hasNext())
            {
                Map.Entry entry = (Map.Entry)iter.next();
                if (api.isPersistable(entry.getKey()))
                {
                    if (!api.isPersistent(entry.getKey()) && !api.isDetached(entry.getKey()))
                    {
                        // Key is not persistent so throw exception
                        throw new ReachableObjectNotCascadedException(fmd.getFullFieldName(), entry.getKey());
                    }
                }
                if (api.isPersistable(entry.getValue()))
                {
                    if (!api.isPersistent(entry.getValue()) && !api.isDetached(entry.getValue()))
                    {
                        // Value is not persistent so throw exception
                        throw new ReachableObjectNotCascadedException(fmd.getFullFieldName(), entry.getValue());
                    }
                }
            }
        }
        else
        {
            // Reachability
            if (JPOXLogger.REACHABILITY.isDebugEnabled())
            {
                JPOXLogger.REACHABILITY.debug(LOCALISER.msg("007007", fmd.getFullFieldName()));
            }

            if (value.size() > 0)
            {
                // Add the entries direct to the datastore
                ((MapStore) storeMgr.getBackingStoreForField(sm.getObjectManager().getClassLoaderResolver(), fmd, value.getClass())).putAll(sm, value);

                // Create a SCO wrapper with the entries loaded
                replaceFieldWithWrapper(sm, value, false, false);
            }
            else
            {
                // Create a SCO wrapper
                replaceFieldWithWrapper(sm, null, false, false);
            }
        }
    }

    /**
     * Method to be called after any update of the owner class element.
     * @param sm StateManager of the owner
     */
    public void postUpdate(StateManager sm)
    {
        java.util.Map value = (java.util.Map) sm.provideField(fmd.getAbsoluteFieldNumber());
        if (containerIsStoredInSingleColumn())
        {
            // Do nothing when serialised since we are handled in the main request
            if (value != null)
            {
                // Make sure the keys/values are ok for proceeding
                SCOUtils.validateObjectsForWriting(sm.getObjectManager(), value.keySet());
                SCOUtils.validateObjectsForWriting(sm.getObjectManager(), value.values());
            }
            return;
        }

        if (value == null)
        {
            // replace null map with empty SCO wrapper
            replaceFieldWithWrapper(sm, null, false, false);
            return;
        }

        if (value instanceof SCOContainer)
        {
            SCOContainer sco = (SCOContainer) value;

            if (sm.getObject() == sco.getOwner() && fieldName.equals(sco.getFieldName()))
            {
                // Flush any outstanding updates
                sco.flush();

                return;
            }

            if (sco.getOwner() != null)
            {
                throw new JPOXException("Owned second-class object was somehow assigned to a field other than its owner's").setFatal();
            }
        }

        if (!fmd.isCascadeUpdate())
        {
            // User doesnt want to update by reachability
            if (JPOXLogger.REACHABILITY.isDebugEnabled())
            {
                JPOXLogger.REACHABILITY.debug(LOCALISER.msg("007008", fmd.getFullFieldName()));
            }
            return;
        }
        if (JPOXLogger.REACHABILITY.isDebugEnabled())
        {
            JPOXLogger.REACHABILITY.debug(LOCALISER.msg("007009", fmd.getFullFieldName()));
        }

        // Update the datastore with this value of map (clear old entries and add new ones)
        // TODO Consider making this more efficient picking the ones to remove/add
        MapStore store = ((MapStore) storeMgr.getBackingStoreForField(sm.getObjectManager().getClassLoaderResolver(), fmd, value.getClass()));
        store.clear(sm);
        store.putAll(sm, value);

        // Replace the field with a wrapper containing these entries
        replaceFieldWithWrapper(sm, value, false, false);
    }

    /**
     * Method to be called before any delete of the owner class element.
     * @param sm StateManager of the owner
     **/
    public void preDelete(StateManager sm)
    {
        // Do nothing - dependent deletion is performed by deleteDependent()
        if (containerIsStoredInSingleColumn())
        {
            // Do nothing when serialised since we are handled in the main request
            return;
        }

        // makes sure field is loaded
        sm.getObjectManager().getApiAdapter().isLoaded(sm, fmd.getAbsoluteFieldNumber());
        java.util.Map value = (java.util.Map) sm.provideField(fmd.getAbsoluteFieldNumber());
        if (value == null || value.isEmpty())
        {
            return;
        }

        if (!(value instanceof SCO))
        {
            // Make sure we have a SCO wrapper so we can clear from the datastore
            value = (java.util.Map)sm.wrapSCOField(fmd.getAbsoluteFieldNumber(), value, false, false, true);
        }
        value.clear();
        ((SCOMap)value).flush();
    }

    // -------------------------------- JDOQL Query Methods --------------------------------------

    /**
     * Accessor for a literal representing this type.
     * @param qs The Query
     * @param value the value of this object in the literal
     * @return The literal
     */
    public ScalarExpression newLiteral(QueryExpression qs, Object value)
    {
        if (containerIsStoredInSingleColumn())
        {
            throw new JPOXUserException(LOCALISER.msg("041025", fmd.getFullFieldName())).setFatal();
        }
        return new MapLiteral(qs, this, (java.util.Map)value);
    }

    /**
     * Method to return a scalar expression for the Map.
     * @param qs The QueryStatement
     * @param te The TableExpression
     * @return The ScalarExpression
     **/
    public ScalarExpression newScalarExpression(QueryExpression qs, LogicSetExpression te)
    {
        if (containerIsStoredInSingleColumn())
        {
            throw new JPOXUserException(LOCALISER.msg("041025", fmd.getFullFieldName())).setFatal();
        }
        return new MapExpression(qs, datastoreContainer.getIDMapping(), te, (MapStore) storeMgr.getBackingStoreForField(qs.getClassLoaderResolver(), fmd, null), fieldName);
    }
}
TOP

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

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.