Package org.objectweb.speedo.pm.jdo.lib

Source Code of org.objectweb.speedo.pm.jdo.lib.JDOPOManager

/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S.Chassande-Barrioz.
*
*/

package org.objectweb.speedo.pm.jdo.lib;

import org.objectweb.fractal.api.control.BindingController;
import org.objectweb.jorm.api.PException;
import org.objectweb.perseus.persistence.api.NoDSIPersistenceException;
import org.objectweb.perseus.persistence.api.PersistenceException;
import org.objectweb.perseus.persistence.api.RolledBackPersistenceException;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.api.SpeedoRuntimeException;
import org.objectweb.speedo.metadata.SpeedoVersion;
import org.objectweb.speedo.mim.api.DetachedLifeCycle;
import org.objectweb.speedo.mim.api.FetchPlanItf;
import org.objectweb.speedo.mim.api.HomeItf;
import org.objectweb.speedo.mim.api.LifeCycle;
import org.objectweb.speedo.mim.api.PersistentObjectItf;
import org.objectweb.speedo.mim.api.StateItf;
import org.objectweb.speedo.mim.jdo.api.JDOPersistentObjectItf;
import org.objectweb.speedo.mim.jdo.lib.JDOFetchPlan;
import org.objectweb.speedo.pm.jdo.api.JDOPOManagerItf;
import org.objectweb.speedo.pm.lib.AbstractPOManager;
import org.objectweb.speedo.query.api.QueryDefinition;
import org.objectweb.speedo.query.jdo.JDOExtent;
import org.objectweb.speedo.query.jdo.JDOQuery;
import org.objectweb.speedo.query.jdo.JDOQueryDefinitionImpl;
import org.objectweb.speedo.workingset.jdo.api.JDOTransactionItf;
import org.objectweb.util.monolog.api.BasicLevel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.jdo.Extent;
import javax.jdo.FetchPlan;
import javax.jdo.JDODataStoreException;
import javax.jdo.JDOException;
import javax.jdo.JDOUnsupportedOptionException;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.jdo.datastore.JDOConnection;
import javax.jdo.datastore.Sequence;
import javax.jdo.listener.DeleteCallback;
import javax.jdo.listener.InstanceLifecycleListener;


/**
* Is a fractal component exporting the POManagerItf interface. This
* implementation delegates most of the JDO methods (javax.jdo.PersistenceManager)
* to the underlying TransactionPersistenceManager, the perseus component
* managing the concurrency, the caching and the loading aspect.
* In order to represents a working set (transtional or not) this PM is linked
* forever to an org.objectweb.speedo.workingset.jdo.api.JDOTransactionItf instance. The
* status of this JDOTransactionItf instance changes when this PM is allocated
* or closed, or when transaction demarcations are done through the
* javax.jdo.Transaction interface.
* This implementation uses a QueryManager for allocating CompiledQuery
* instance. Concerning the javax.jdo.Query implementation,  this PM uses
* org.objectweb.speedo.query.lib.SpeedoQuery which are created each time
* (No pooling mechanism).
* The last dependencies is the JormFactory and a P
*
*
* @see javax.jdo.PersistenceManager
* @see org.objectweb.perseus.persistence.api.TransactionalPersistenceManager
* @see org.objectweb.speedo.mapper.api.JormFactory
* @see org.objectweb.speedo.pm.api.POManagerFactoryItf
* @see org.objectweb.speedo.query.api.QueryManager
* @see org.objectweb.speedo.query.api.CompiledQuery
* @see org.objectweb.speedo.workingset.jdo.api.JDOTransactionItf
*
* @author S.Chassande-Barrioz
*/
public class JDOPOManager
    extends AbstractPOManager
        implements JDOPOManagerItf,
    BindingController{


    /**
     * The user object
     */
    private Object userObject = null;

    /**
   * indicates if the cache must be ignore on queries
   */
  boolean ignoreCache = true;

  private HashMap userObjects = new HashMap();
 
    public JDOPOManager() {
      super();
    }

  public Query createQuery(Object o) {
    JDOQuery sq = new JDOQuery();
    sq.withPrefetch(prefetchOnQuery);
    sq.setPOManager(this);
    //initialize the fetch plan of the speedo query
    sq.setFetchPlan(getFetchPlan());
    sq.setQueryManager(queryManager);
    sq.setIgnoreCache(ignoreCache);
    sq.setLogger(loggerFactory.getLogger(logger.getName() + ".query"));
    if (o!= null && o instanceof JDOQueryDefinitionImpl) {
      sq.defineWith((JDOQueryDefinitionImpl) o);
    }
    return sq;
  }



    // IMPLEMENTATION OF THE JDOConnection INTERFACE //
    //-----------------------------------------------//

    public Object getNativeConnection() {
        try {
            if (((JDOTransactionItf) tx).getOptimistic()) {
                return new DSConnectionFilter(
                        tx.getConnectionHolder().getCHConnectionForRead(),
                        true);
            } else {
                return new DSConnectionFilter(
                        tx.getConnectionHolder().getCHConnectionForWrite(),
                        false);
            }
        } catch(PersistenceException e) {
            throw new JDODataStoreException("Impossible to allocate a native connection:", e);
        }
    }

    // IMPLEMENTATION OF THE PersistentManager INTERFACE //
    //---------------------------------------------------//
    public boolean isClosed() {
        return isPOMClosed();
    }
   
    public void addInstanceLifecycleListener(InstanceLifecycleListener l, Class[] classes) {
        // TODO: support lifeCycle listener (add)
    }
    public void removeInstanceLifecycleListener(InstanceLifecycleListener classes) {
        // TODO: support lifeCycle listener (remove)
    }
    public void flush() {
        try {
          speedoFlush();
        } catch (PersistenceException e) {
            throw new JDODataStoreException("Impossible to flush the working set");
        }
    }

    public JDOConnection getDataStoreConnection() {
        return this;
    }

    public FetchPlanItf speedoGetFetchPlan() {
    if(fetchPlan == null){
        fetchPlan = new JDOFetchPlan();
    }
    return fetchPlan;
     
    }
    public FetchPlan getFetchPlan() {
      return (FetchPlan) speedoGetFetchPlan();
    }

    /**
   * Fetches the Null PName associated to the PBinder of the persistent class
   */
  public java.lang.Class getObjectIdClass(Class cls) {
        bindPMThread();
        if (cls == null) {
          return null;
        }
        try {
            return jf.getPBinder(cls).getNull().getClass();
        } catch (PException e) {
            Exception ie = ExceptionHelper.getNested(e);
            logger.log(BasicLevel.ERROR,
                    "Error during the fetching of the manager of the class "
                    + cls.getName(), ie);
            throw new JDOException("", ie);
        }
    }

    /**
     * This method closes the PersistenceManager.
     * @exception javax.jdo.JDOUserException if the transaction associated to
     * the persistence manager is active.
     * @exception javax.jdo.JDOFatalDataStoreException if there is a problem while
     * releasing the persistence manager.
     */
    public void close() {
      closePOManager();
    }

    /**
     * Return the JDOTransactionItf instance associated with a PersistenceManager.
     * @return the JDOTransactionItf associated with this
     * PersistenceManager.
     */
    public javax.jdo.Transaction currentTransaction() {
        bindPMThread();
        return ((JDOTransactionItf) tx);
    }

    /**
     * Mark an instance as no longer needed in the cache.
     * @param o the instance to evict from the cache.
     */
    public void evict(Object o) {
      if (o == null)
        return;
        assertIsOpen();
        bindPMThread();
        JDOPersistentObjectItf sp = (JDOPersistentObjectItf) o;
        if (tx.isActive() && sp.jdoIsDirty())
            throw new JDOUserException("Impossible to evict a dirty " +
                    "instance attached to an active transaction");
        try {
      tpm.evict(tx, sp.getCeIdentifier(), false);
        } catch (PersistenceException e) {
            throw new JDOUserException(
                "Impossible to evict the persistent object from the cache", e);
        }
    }

    /** Mark an array of instances as no longer needed in the cache.
     * @see #evict(java.lang.Object pc)
     * @param pcs the array of instances to evict from the cache.
     * @exception javax.jdo.JDOUserException if some instances cannot be removed.
     */
    public void evictAll(Object[] pcs) {
        Throwable[] th = new Throwable[pcs.length];
        int lg = 0;
        for (int i = 0; i < pcs.length; i++) {
            try {
                if (pcs[i] != null) {
                  evict(pcs[i]);
                }
            } catch (Throwable e) {
                th[lg] = e;
                lg++;
            }
        }
        if (lg > 0) {
            Throwable[] tfin = new Throwable[lg];
            System.arraycopy(th, 0, tfin, 0, lg);
            throw new JDOUserException("Impossible to evict", tfin);
        }
    }

    /** Mark a Set of instances as no longer needed in the cache.
     * @see #evict(java.lang.Object pc)
     * @param pcs the Set of instance to evict from the cache.
     */
    public void evictAll(Collection pcs) {
        evictAll(pcs.toArray());
    }

    /** Mark all persistent-nontransactional instances as no longer needed
     * in the cache. It transitions all persistent-nontransactional instances to
     * hollow. Transactional instances are subject to eviction based on the
     * RetainValues setting.
     * @see #evict(java.lang.Object pc)
     */
    public void evictAll() {
      assertIsOpen();
    try {
      tpm.evictAll(tx, false);
    } catch (PersistenceException e) {
      throw new JDOException("Error during the eviction of all cache entries: ",
              ExceptionHelper.getNested(e));
    }
  }

    /** Refresh the state of the instance from the data store.
     * <P>In an optimistic transaction, the state of instances in the cache
     * might not match the state in the data store.  This method is used to
     * reload the state of the instance from the data store so that a subsequent
     * commit is more likely to succeed.
     * <P>Outside a transaction, this method will refresh nontransactional
     * state.
     * @param o the instance to refresh.
     */
    public void refresh(Object o) {
      if (o == null)
        return;
      PersistentObjectItf sp = (PersistentObjectItf) o;
      assertIsOpen();
      bindPMThread();
      assertIsPO(sp, "refresh");
        assertPOManager(sp);
        if (!sp.speedoIsActive())
            throw new JDOUserException("Refresh on a transient instance.");
      speedoRefresh(sp, new HashMap(), new ArrayList());
    }

    public void speedoRefresh(PersistentObjectItf sp, Map map, Collection fgHints){
        try {
          if (map != null && !map.containsKey(sp.getPName())) {
            map.put(sp.getPName(), sp);
            tpm.refresh(tx, sp);
            StateItf sa = (StateItf) tpm.readIntention(tx, sp, null);
            sa.refresh(this, map, fgHints);
          }
        } catch (PersistenceException e) {
        throw new JDOException("Impossible to refresh a persistent instance", e);
      }
    }
   
    /** Refresh the state of an array of instances from the data store.
     * @see #refresh(java.lang.Object pc)
     * @param pcs the array of instances to refresh.
     * object.
     */
    public void refreshAll(Object[] pcs) {
        Throwable[] th = new Throwable[pcs.length];
        int lg = 0;
        for (int i = 0; i < pcs.length; i++) {
            try {
              if (pcs[i] != null) {
                refresh(pcs[i]);
              }
            } catch (Throwable e) {
                th[lg] = e;
                lg++;
            }
        }
        if (lg > 0) {
            Throwable[] tfin = new Throwable[lg];
            System.arraycopy(th, 0, tfin, 0, lg);
            throw new JDOUserException("Impossible to refresh", tfin);
        }
    }

    /** Refresh the state of a Set of instances from the data store.
     * @see #refresh(java.lang.Object pc)
     * @param pcs the Set of instances to refresh.
     */
    public void refreshAll(Collection pcs) {
        refreshAll(pcs.toArray());
    }

    /** Refresh the state of all applicable instances from the data store.
     * <P>If called with an active transaction, all transactional instances
     * will be refreshed.  If called outside an active transaction, all
     * nontransactional instances will be refreshed.
     * @see #refresh(java.lang.Object pc)
     */
    public void refreshAll() {
      assertIsOpen();
      if (!tx.isActive()) {
        return;
      }
      Set entries = tx.entries();
      int size = entries.size();
      if (size == 0) {
        return;
      }
      Object[] sps = new Object[size];
      Iterator it = entries.iterator();
      int i=0;
      while(it.hasNext() && i<sps.length) {
            org.objectweb.perseus.persistence.api.State s = (org.objectweb.perseus.persistence.api.State) it.next();
        sps[i] = s.getCacheEntry();
        i++;
      }
        refreshAll(sps);
    }

    public void refreshAll(JDOException arg0) {
        //TODO: review the refreshAll(JDOException) behavior
        refreshAll();
    }


    /**
     * Create a new Query with no elements.
     * @return the new Query.
     */
    public Query newQuery() {
        assertIsOpen();
        bindPMThread();
    return createQuery(null);
    }

    public Query newQuery(String query) {
        assertIsOpen();
        bindPMThread();
        //TODO: Implements newQuery(String)
    return createQuery(null);
    }
   
    public Query newNamedQuery(Class klass, String name) {
      try {
      QueryDefinition qd = ((HomeItf) jf.getPClassMapping(klass)).getNamedQuery(name);
      return createQuery(qd);
    } catch (PException e) {
            Exception ie = ExceptionHelper.getNested(e);
            logger.log(BasicLevel.ERROR,
                    "Error during the fetching of the manager of the class "
                    + klass.getName(), ie);
            throw new JDOException("Error during the fetching of the manager of the class ", ie);
    }
    }

    /**
     * Create a new Query using elements from another Query.
     * The other Query must have been created by the same JDO implementation.
     * It might be active in a different PersistenceManager or might have been
     * serialized and restored.
     * <P>All of the settings of the other Query are copied to this Query,
     * except for the candidate Set or Extent.
     * @return the new Query
     * @param compiled another Query from the same JDO implementation
     */
    public Query newQuery(Object compiled) {
        assertIsOpen();
        bindPMThread();
    return createQuery(compiled);
    }

    /**
     * Create a new Query using the specified language.
     * @param language the language of the query parameter
     * @param query the query, which is of a form determined by the language
     * @return the new Query
     */
    public Query newQuery(String language, Object query) {
        assertIsOpen();
        bindPMThread();
        if (language.compareTo("java.jdo.query.toVerify") == 0) {
      return createQuery(query);
        } else
            throw new JDOUnsupportedOptionException("Language \"" + language
                    + "\"" + " is not supported by this jdo implementation");
    }

    /**
     * Create a new Query specifying the Class of the candidate instances.
     * @param cls the Class of the candidate instances
     * @return the new Query
     */
    public Query newQuery(Class cls) {
        assertIsOpen();
        bindPMThread();
        Query q = createQuery(null);
        q.setClass(cls);
        if (getObjectIdClass(cls) == null)
            throw new JDOUnsupportedOptionException(
                    "There is a problem with the specified class");
        return q;
    }

    public Query newQuery(Extent extent) {
        assertIsOpen();
        bindPMThread();
    JDOQuery q = (JDOQuery) createQuery(null);
        Class c = extent.getCandidateClass();
        q.setIncludeSubClasses(extent.hasSubclasses());
        q.setClass(c);
        if (getObjectIdClass(c) == null)
            throw new JDOUnsupportedOptionException(
                    "There is a problem with the specified class");
        return q;
    }

    public Query newQuery(Extent extent, String filter) {
        assertIsOpen();
        bindPMThread();
        Query q = newQuery(extent);
        q.setFilter(filter);
        return q;
    }

    /**
     * Create a new Query with the Class of the candidate instances and
     * candidate Set.
     * @param cls the Class of results
     * @param cln the Set of candidate instances
     * @return the new Query
     */
    public Query newQuery(Class cls, Collection cln) {
        assertIsOpen();
        bindPMThread();
    Query q = createQuery(null);
        q.setClass(cls);
        q.setCandidates(cln);
        return q;
    }

    /**
     * Create a new Query with the Class of the candidate instances and filter.
     * @param cls the Class of results
     * @param filter the filter for candidate instances
     * @return the new Query
     */
    public Query newQuery(Class cls, String filter) {
        assertIsOpen();
        bindPMThread();
    Query q = createQuery(null);
        q.setClass(cls);
        q.setFilter(filter);
        return q;
    }

    /**
     * Create a new Query with the Class of the candidate instances,
     * candidate Set, and filter.
     * @param cls the Class of candidate instances
     * @param cln the Set of candidate instances
     * @param filter the filter for candidate instances
     * @return the new Query
     */
    public Query newQuery(Class cls, Collection cln, String filter) {
        assertIsOpen();
        bindPMThread();
    Query q = createQuery(null);
        q.setClass(cls);
        q.setCandidates(cln);
        q.setFilter(filter);
        return q;
    }

    /** Not implemented. The PersistenceManager manages a collection of
     * instances in the data store based on the class of the instances. This
     * method returns a Extent of instances in the data store that might be
     * iterated or given to a Query. The Extent itself might not reference any
     * instances, but only hold the class name and an
     * indicator whether subclasses are included in the Extent.
     * @param persistenceCapableClass Class of instances
     * @param subclasses whether to include instances of subclasses
     * @return an Extent of the specified Class
     */
    public Extent getExtent(Class persistenceCapableClass,
                            boolean subclasses) {
        assertIsOpen();
        bindPMThread();
        return new JDOExtent(
      persistenceCapableClass, subclasses, this, jf, prefetchOnExtent, logger);
    }

    public Extent getExtent(Class arg0) {
        return getExtent(arg0, true);
    }


    /** This method locates a persistent instance in the cache of instances
     * managed by this PersistenceManager.  The getObjectById method attempts
     * to find an instance in the cache with the specified JDO identity.
     * The oid parameter object might have been returned by an earlier call
     * to getObjectId or getTransactionalObjectId, or might have been
     * constructed by the application.
     * @see #getObjectId(java.lang.Object pc)
     * @see #getTransactionalObjectId(java.lang.Object pc)
     * @return the PersistenceCapable instance with the specified
     * ObjectId
     * @param oid an ObjectId
     * @param validate if the existence of the instance is to be validated. The
     * flag is ignored in this implementation.
     */
    public Object getObjectById(Object oid, boolean validate) {
        assertIsOpen();
        bindPMThread();
        return speedoGetObjectById(oid, validate);
    }

    public Object getObjectById(Class arg0, Object oid) {
        assertIsOpen();
        bindPMThread();
        return speedoGetObjectById(newObjectIdInstance(arg0, oid), false);
    }
   
    public Object getObjectById(Object oid) {
        assertIsOpen();
        bindPMThread();
        return speedoGetObjectById(oid, false);
    }
   
    public Collection getObjectsById(Collection arg0, boolean validate) {
        if (arg0 == null) {
            return Collections.EMPTY_LIST;
        }
        assertIsOpen();
        bindPMThread();
        ArrayList al = new ArrayList(arg0.size());
        for(Iterator it = arg0.iterator(); it.hasNext();) {
            Object oid = it.next();
            if (oid == null) {
                al.add(null);
                continue;
            }
            try {
                al.add(speedoGetObjectById(oid, validate));
            } catch (Exception e) {
                al.add(null);
            }
        }
        return al;
    }
   
    public Collection getObjectsById(Collection arg0) {
        return getObjectsById(arg0, true);
    }
   
    public Object[] getObjectsById(Object[] arg0, boolean arg1) {
        if (arg0 == null) {
            return new Object[0];
        }
        assertIsOpen();
        bindPMThread();
        Object[] objs = new Object[arg0.length];
        for(int i=0; i<arg0.length; i++) {
            Object oid = arg0[i];
            if (oid == null) {
                objs[i] = null;
                continue;
            }
            try {
                objs[i] = speedoGetObjectById(oid, arg1);
            } catch (Exception e) {
                objs[i] = null;
            }
        }
        return objs;
    }
   
    public Object[] getObjectsById(Object[] arg0) {
        return getObjectsById(arg0, true);
    }

    public Object speedoGetObjectById(Object oid, boolean validate) {
        if (oid == null)
            return null;
        try {
          try {
                return super.speedoGetObject(oid, null, validate);
            } catch (SpeedoRuntimeException e) {
                throw (Exception) e.getCause();
            }
    } catch (NoDSIPersistenceException e) {
      throw new JDOUserException(
          "No data store instance matching to the specified identifier: "
              + oid, ExceptionHelper.getNested(e));
        } catch (RolledBackPersistenceException e) {
      throw ((JDOTransactionItf) tx).rollBackOnInternalError(e);
        } catch (Exception e) {
      Exception ie = ExceptionHelper.getNested(e);
      logger.log(BasicLevel.ERROR,
          "Impossible to fetch a persistent object with the identifier: " + oid, ie);
            throw new JDOException("", ie);
        }
    }

    /** The ObjectId returned by this method represents the JDO identity of
     * the instance.  The ObjectId is a copy (clone) of the internal state
     * of the instance, and changing it does not affect the JDO identity of
     * the instance.
     * @see #getTransactionalObjectId(java.lang.Object pc)
     * @see #getObjectById(java.lang.Object oid, boolean validate)
     * @param pc the PersistenceCapable instance
     * @return the ObjectId of the instance
     */
    public Object getObjectId(Object pc) {
        assertIsOpen();
        bindPMThread();
        //the object must be persistence capable. otherwise, it doesn't have an
        //objectid
        try {
            assertIsPO(pc, "");
        } catch (Exception e) {
            return null;
        }
        PersistentObjectItf sp = (PersistentObjectItf) pc;
        if (!sp.speedoIsActive())
            throw new JDOUserException("Object non persistent.");
        assertPOManager(sp);
        try {
            return pnc.encodeAbstract(sp.getPName());
        } catch (PException e) {
            throw new JDOException(
                    "Problem while encoding persistent name.",
                    new Exception[]{ExceptionHelper.getNested(e)});
        }
    }

    public Object getEncodedPName(PersistentObjectItf po) {
      return getObjectId(po);
    }
   
    /** Not implemented. The ObjectId returned by this method represents the JDO
     * identity of the instance.  The ObjectId is a copy (clone) of the internal
     * state of the instance, and changing it does not affect the JDO identity
     * of the instance.
     * <P>If the object identity is being changed in the transaction, by the
     * application modifying one or more of the application key fields,
     * then this method returns the current identity in the transaction.
     * <P>If there is no transaction in progress, or if none of the key fields
     * is being modified, then this method will return the same value as
     * getObjectId.
     * @see #getObjectId(java.lang.Object pc)
     * @see #getObjectById(java.lang.Object oid, boolean validate)
     * @param o a PersistenceCapable instance
     * @return the ObjectId of the instance
     */
    public Object getTransactionalObjectId(Object o) {
        assertIsOpen();
        bindPMThread();
        throw new JDOUnsupportedOptionException("Not implemented.");
    }

    /** Make the transient instance persistent in this PersistenceManager.
     * This method must be called in an active transaction.
     * The PersistenceManager assigns an ObjectId to the instance and
     * transitions it to persistent-new.
     * The instance will be managed in the Extent associated with its Class.
     * The instance will be put into the data store at commit.
     * The closure of instances of PersistenceCapable classes
     * reachable from persistent
     * fields will be made persistent at commit.  [This is known as
     * persistence by reachability.]
     * @param o a transient instance of a Class that implements
     * PersistenceCapable
     */
    public Object makePersistent(Object o) {
        assertIsOpen();
        bindPMThread();
    assertIsPO(o, "");
    if (o == null)
      return null;
    JDOPersistentObjectItf jdopo = (JDOPersistentObjectItf) o;
    if (jdopo.speedoGetReferenceState().getDetachedStatus() == DetachedLifeCycle.DETACHED_NONE) {
      return speedoMakePersistent((PersistentObjectItf) o, null);
    } else {
      return speedoAttachCopy(o, new HashMap());
    }
    }
   
    public Object speedoMakePersistent(PersistentObjectItf po, Map map) {
        JDOPersistentObjectItf jdopo = (JDOPersistentObjectItf) po;
        if (jdopo.jdoIsPersistent())
            return po;
        if (!jdopo.speedoIsActive()) {
          if (jdopo.speedoGetReferenceState().getDetachedStatus() != DetachedLifeCycle.DETACHED_NONE) {
             return null;
          }
        }
        synchronized(jdopo) {
            if (jdopo.jdoIsPersistent())
                return po;
            try {
              return speedoPersist(po, map);
            } catch (Exception e) {
                try {
                    jdopo.init(null);
                } catch (PException e1) {
                    logger.log(BasicLevel.WARN, "Error during unbinding:", e1);
                }
                if (e instanceof RolledBackPersistenceException) {
                    throw ((JDOTransactionItf) tx).rollBackOnInternalError(e);
                } else {
                    throw new JDODataStoreException(
                        "Problem while making persistent.",
                        new Exception[]{ExceptionHelper.getNested(e)});
                }
            }
        }
    }

    /** Make an array of instances persistent.
     * @param pcs an array of transient instances
     * @exception javax.jdo.JDOUserException if an object cannot be made persistent.
     * @see #makePersistent(java.lang.Object pc)
     */
    public Object[] makePersistentAll(Object[] pcs) {
        if (pcs == null || pcs.length == 0)
            return null;
        assertIsOpen();
        bindPMThread();
        Exception[] th = new Exception[pcs.length];
        //the list of returned persistent objects
        Object[] pos = new Object[pcs.length];
        int lg = 0;
        //HashMap in case of detach
        HashMap map = new HashMap(1);
        for (int i = 0; i < pcs.length; i++) {
            try {
        assertIsPO(pcs[i], "");
        if (true) {
          pos[i] = speedoMakePersistent((PersistentObjectItf) pcs[i], null);
        } else {
          pos[i] = speedoAttachCopy(pcs[i], map);
        }
            } catch (Exception e) {
                th[lg] = e;
                lg++;
            }
        }
        if (lg > 0) {
            Exception[] tfin = new Exception[lg];
            System.arraycopy(th, 0, tfin, 0, lg);
            throw new JDOUserException("Impossible to make persistent : ", tfin);
        } else {
          return pos;
        }
    }

    /** Make a Set of instances persistent.
     * @param pcs a Set of transient instances
     * @see #makePersistent(java.lang.Object pc)
     */
    public Collection makePersistentAll(Collection pcs) {
        if (pcs == null || pcs.size() == 0)
            return null;
        Object[] pos = makePersistentAll(pcs.toArray());
        return Arrays.asList(pos);
    }

    /** Delete the persistent instance from the data store.
     * This method must be called in an active transaction.
     * The data store object will be removed at commit.
     * Unlike makePersistent, which makes the closure of the instance
     * persistent, the closure of the instance is not deleted from the data
     * store.
     * This method has no effect if the instance is already deleted in the
     * current transaction.
     * @param o a persistent instance
     * @exception javax.jdo.JDOUserException if the instance is transient or managed by
     * another PersistenceManager.
     */
    public void deletePersistent(Object o) {
        assertIsOpen();
        bindPMThread();
        speedoDeletePersistent(o);
    }
  
    public void speedoDeletePersistent(Object o) {
        JDOPersistentObjectItf sp = (JDOPersistentObjectItf) o;
      // Verify the instance is managed by this persistence manager
      assertPOManager(sp);
      // Verify the transaction is active
      if (!tx.isActive()) {
        throw new JDOUserException("DeletePersistent " +
            "must be called in an active transaction");
      }
      StateItf sa = null;
      try {
        if (!sp.jdoIsPersistent()) {
          throw new JDOUserException(
              "DeletePersistent on an instance non persistent.");
        }
        if (sp.jdoIsDeleted()) {
          return;
        }
             sp.speedoGetHome().sendEvent(HomeItf.PRE_REMOVE, sp, null);
        sa = (StateItf) tpm.unexport(tx, sp);
             sp.speedoGetHome().sendEvent(HomeItf.POST_REMOVE, sp, null);
      } catch (RolledBackPersistenceException e) {
        throw ((JDOTransactionItf) tx).rollBackOnInternalError(e);
      } catch (PersistenceException e) {
        throw new JDOException("", ExceptionHelper.getNested(e));
      }
      //remove the multivalued fields and cascade delete
      sa.deletePersistent(this);
        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG,
                    "Delete a persistent instance, identifier=" + sp.getPName());
        }
    }
    public void speedoDeletePersistent(Object oid, Class pc) {
        // Verify the transaction is active
        if (!tx.isActive()) {
            throw new JDOUserException("DeletePersistent " +
                "must be called in an active transaction");
        }
        boolean mustLoad = DeleteCallback.class.isAssignableFrom(pc);
        if (!mustLoad) {
            HomeItf home;
            try {
                home = (HomeItf) jf.getPClassMapping(pc);
            } catch (PException e) {
                throw new JDOException("", e);
            }
            mustLoad = home.hasInstanceLifeCycleListeners();
            if (!mustLoad) {
                //TODO: manage cascade delete
            }
        }
        if (mustLoad) {
            PersistentObjectItf po = (PersistentObjectItf) speedoGetObjectById(oid, false);
            speedoDeletePersistent(po);
            return;
        }
        //no listener or callback
//TODO       
       
    }

   
   
    public void deleteByQuery(QueryDefinition qd) {
  }

  /** Delete an array of instances from the data store.
     * @param pcs a Set of persistent instances
     * @see #deletePersistent(java.lang.Object pc)
     */
    public void deletePersistentAll(Object[] pcs) {
        if (pcs == null)
            return;
        assertIsOpen();
        bindPMThread();
        Throwable[] th = new Throwable[pcs.length];
        int lg = 0;
        for (int i = 0; i < pcs.length; i++) {
            try {
                speedoDeletePersistent(pcs[i]);
            } catch (Throwable e) {
                th[lg] = e;
                lg++;
            }
        }
        if (lg > 0) {
            Throwable[] tfin = new Throwable[lg];
            System.arraycopy(th, 0, tfin, 0, lg);
            throw new JDOUserException
                    ("Impossible to delete persistent : ", tfin);
        }
    }

    /** Delete a Set of instances from the data store.
     * @param pcs a Set of persistent instances
     * @see #deletePersistent(java.lang.Object pc)
     */
    public void deletePersistentAll(Collection pcs) {
        if (pcs == null)
            return;
        deletePersistentAll(pcs.toArray());
    }

    /** Make an instance transient, removing it from management by this
     * PersistenceManager.
     * <P>The instance loses its JDO identity and it is no longer associated
     * with any PersistenceManager.  The state of fields is preserved unchanged.
     * @param o the instance to make transient.
     * @exception javax.jdo.JDOUserException if the instance is dirty.
     */
    public void makeTransient(Object o) {
    assertIsOpen();
    bindPMThread();
    if (o == null || !(o instanceof JDOPersistentObjectItf)
      || !((JDOPersistentObjectItf) o).jdoIsPersistent()) {
      return;
    }
        JDOPersistentObjectItf sp = (JDOPersistentObjectItf) o;
        synchronized(sp) {
      if (sp.jdoIsDirty()) {
        throw new JDOUserException("Try to make transient a dirty instance.");
            }
      try {
        tpm.unbind(tx, sp);
      } catch (PersistenceException e) {
        throw new JDOUserException("Impossible to make transient the persistent instance: ",
            ExceptionHelper.getNested(e));
      }
    }
    }

    /** Make an array of instances transient, removing them from management by
     * this PersistenceManager.
     * @see #makeTransient(java.lang.Object pc)
     * @param pcs the instances to make transient.
     */
    public void makeTransientAll(Object[] pcs) {
        if (pcs == null)
            return;
        Throwable[] th = new Throwable[pcs.length];
        int lg = 0;
        for (int i = 0; i < pcs.length; i++) {
            try {
                makeTransient(pcs[i]);
            } catch (Throwable e) {
                th[lg] = e;
                lg++;
            }
        }
        if (lg > 0) {
            Throwable[] tfin = new Throwable[lg];
            System.arraycopy(th, 0, tfin, 0, lg);
            throw new JDOUserException("Impossible to make transient: ", tfin);
        }
    }

    /** Make a Set of instances transient, removing them from management
     * by this PersistenceManager.
     * <P>The instances lose their JDO identity and they are no longer
     * associated with any PersistenceManager.  The state of fields is preserved
     * unchanged.
     * @param pcs the instances to make transient.
     */
    public void makeTransientAll(Collection pcs) {
        if (pcs == null)
            return;
        makeTransientAll(pcs.toArray());
    }

    /** Make an instance subject to transactional boundaries.
     * @see javax.jdo.PersistenceManager#makeTransactional
     * @param o the instance to make transactional.
     */
    public void makeTransactional(Object o) {
//TODO: support the makeTransactional method
        throw new JDOUnsupportedOptionException("not yet implemented");
    }

    /** Make an array of instances subject to transactional boundaries.
     * @param pcs the array of instances to make transactional.
     * @see #makeTransactional(java.lang.Object pc)
     */
    public void makeTransactionalAll(Object[] pcs) {
        if (pcs == null || pcs.length == 0)
            return;
        Throwable[] th = new Throwable[pcs.length];
        int lg = 0;
        for (int i = 0; i < pcs.length; i++) {
            try {
                makeTransactional(pcs[i]);
            } catch (Throwable e) {
                th[lg] = e;
                lg++;
            }
        }
        if (lg > 0) {
            Throwable[] tfin = new Throwable[lg];
            System.arraycopy(th, 0, tfin, 0, lg);
            throw new JDOUserException
                    ("Impossible to make transactional : ", tfin);
        }
    }

    /** Make a Set of instances subject to transactional boundaries.
     * @param pcs the Set of instances to make transactional.
     * @see #makeTransactional(java.lang.Object pc)
     */
    public void makeTransactionalAll(Collection pcs) {
        if (pcs == null || pcs.size() == 0)
            return;
        makeTransactionalAll(pcs.toArray());
    }

    public void makeNontransactional(Object o) {
        JDOPersistentObjectItf sp = (JDOPersistentObjectItf) o;
        //preconditions
        assertIsOpen();
        bindPMThread();
        assertIsPO(sp, "");
        assertPOManager(sp);
        if (sp.jdoIsDirty())
            throw new JDOUserException("Try to make non-transactional a dirty instance.");
    sp.speedoGetState().speedoChangeStatus(LifeCycle.ACTION_MAKENONTRANSACTIONAL);
    }

    public void makeNontransactionalAll(Object[] pcs) {
        if (pcs == null || pcs.length == 0)
            return;
        ArrayList th = new ArrayList(pcs.length);
        for (int i = 0; i < pcs.length; i++) {
            try {
                makeNontransactional(pcs[i]);
            } catch (Throwable e) {
                th.add(e);
            }
        }
        if (th.size() > 0) {
            throw new JDOUserException("Impossible to make non transactional : ",
                    (Throwable[]) th.toArray(new Throwable[0]));
        }
    }

    public void makeNontransactionalAll(Collection pcs) {
        if (pcs == null || pcs.size() == 0)
            return;
        makeNontransactionalAll(pcs.toArray());
    }

    public void setUserObject(Object o) {
        bindPMThread();
        userObject = o;
    }

    /** The application can manage the PersistenceManager instances
     * more easily by having an application object associated with each
     * PersistenceManager instance.
     * @return the user object associated with this PersistenceManager
     * @see #setUserObject
     */
    public Object getUserObject() {
        bindPMThread();
        return userObject;
    }

    public PersistenceManagerFactory getPersistenceManagerFactory() {
        return (PersistenceManagerFactory) pmf;
    }


    /** Set the Multithreaded flag for this PersistenceManager.  Applications
     * that use multiple threads to invoke methods or access fields from
     * instances managed by this PersistenceManager must set this flag to true.
     * Instances managed by this PersistenceManager include persistent or
     * transactional instances of PersistenceCapable classes, as well as
     * helper instances such as Query, JDOTransactionItf, or Extent.
     * @param flag the Multithreaded setting.
     */
    public void setMultithreaded(boolean flag) {
    semaphore.init(flag);
    }

    /** Get the current Multithreaded flag for this PersistenceManager.
     * This option is ignored by the implementation.
     * @see #setMultithreaded
     * @return the Multithreaded setting.
     */
    public boolean getMultithreaded() {
        return semaphore.on;
    }

    /** Set the ignoreCache parameter for queries.
     * @param flag the ignoreCache setting.
     */
    public void setIgnoreCache(boolean flag) {
        ignoreCache = flag;
    }

    /** Get the ignoreCache setting for queries.
     * @return the ignoreCache setting.
     * @see #setIgnoreCache
     */
    public boolean getIgnoreCache() {
        return ignoreCache;
    }

    public Object newObjectIdInstance(Class aClass, Object s) {
        assertIsOpen();
        bindPMThread();
        try {
            return pnc.decodeAbstract(s, aClass);
        } catch (PException e) {
            throw new JDOUserException("Invalid persistent object identifier "
                    + s + " for the class " + aClass, new Exception[]{e});
        }
    }

    public void retrieve(Object o) {
        assertIsOpen();
        bindPMThread();
        assertIsPO(o, "retrieve(Object)");
    speedoRetrieve((PersistentObjectItf) o, new HashMap(), new ArrayList());
    }

   
    public void speedoRetrieve(PersistentObjectItf sp, Map map, Collection fgHints){
        try {
          if (map != null && !map.containsKey(sp.getPName())) {
            map.put(sp.getPName(), sp);
            tpm.refresh(tx, sp);
            StateItf sa = (StateItf) tpm.readIntention(tx, sp, null);
            sa.retrieve(this, map, fgHints);
          }
        } catch (PersistenceException e) {
        throw new JDOException("Impossible to retrieve a persistent instance", e);
      }
    }
   
    public void retrieveAll(Collection pcs) {
    assertIsOpen();
    bindPMThread();
    if (pcs == null) {
      return;
    }
    for(Iterator it = pcs.iterator(); it.hasNext();) {
      Object o = it.next();
      assertIsPO(o, "retrieve(Collection)");
      speedoRetrieve((PersistentObjectItf) o, new HashMap(), new ArrayList());
    }
    }

    public void retrieveAll(Object[] pcs) {
    assertIsOpen();
    bindPMThread();
    if (pcs == null) {
      return;
    }
    for(int i = 0; i<pcs.length; i++) {
      assertIsPO(pcs[i], "retrieve(Collection)");
      if(((PersistentObjectItf) pcs[i]).speedoGetReferenceState() != null)
           speedoRetrieve((PersistentObjectItf) pcs[i], new HashMap(), new ArrayList());
    }
    }

  public void retrieveAll(Collection collection, boolean b) {
    retrieveAll(collection);
  }

  public void retrieveAll(Object[] objects, boolean b) {
    retrieveAll(objects);
  }

  /**
   * Make a detached copy of the persitent object o and return it.
   * Only the fields belonging to the fetch group are reachable.
   * @param o
   * @return the detached copy of the persistent object
   */
  public Object detachCopy(Object o){
    assertIsOpen();
    assertIsPO(o, "detachCopy");
    return speedoDetachCopy((PersistentObjectItf)o, new HashMap(), new ArrayList());
  }
 
  public Object speedoDetachCopy(PersistentObjectItf po, Map map, Collection fgHints){
        JDOPersistentObjectItf jdopo = (JDOPersistentObjectItf) po;
    //check the meta info about the detachability of the class
    if(jdopo.jdoIsPersistent()){
      if(jdopo.jdoIsDeleted()){
        //persistent_deleted
        if(!jdopo.jdoIsNew())
          throw new JDOUserException("This object cannot be detached: it has been deleted from the datastore.");
      }
    }
    else{
      //makePersistent
      speedoMakePersistent(jdopo, null);
   
    if(!jdopo.speedoGetHome().isDetachable()){
      throw new JDOUserException("This class cannot be detached: it has not been defined as detachable in the jdo file.");
    }
      jdopo.speedoGetHome().sendEvent(HomeItf.PRE_DETACH, jdopo, null);
    //persistent_new or persistent_dirty: updated with object id and version
    if(jdopo.jdoIsTransactional() && jdopo.jdoIsDirty()){
      try{
        StateItf sa = (StateItf) tpm.writeIntention(tx, jdopo, null);
        if(!sa.hasBeenFlush()){
          //flush
          tpm.flush(tx, sa);
        }
      } catch (Exception e) {
        throw new JDODataStoreException(
        "Problem while flushing a persistent object in order to detach a copy.",
        new Exception[]{ExceptionHelper.getNested(e)});
      }
    }
    //the core processing
    //avoid cycles using a map
    try{
      synchronized(fgHints){
        PersistentObjectItf copy = jdopo.speedoGetHome().detachCopy(jdopo, this, map, null, fgHints);
        if (jdopo.speedoGetHome().getVersioningStrategy() == SpeedoVersion.VERSION_NUMBER) {
          copy.speedoGetReferenceState().speedoChangeVersion();
        }
        return copy;
      }
    }
    catch(Exception e){
      throw new JDOUserException("Detach cannot be performed", new Exception[]{ExceptionHelper.getNested(e)});
    } finally {
        jdopo.speedoGetHome().sendEvent(HomeItf.POST_DETACH, jdopo, null);
    }
  }
 
  /**
   * Create a detached copy for each element of collection (assuming each element is persistent).
   * If there are duplicates in collection, the corresponding detached copy is used for each such duplicate.
   * @param collection
   * @return the collection of the detached copies in the same order than the parameter
   */
  public Collection detachCopyAll(Collection collection){
    assertIsOpen();
    if (collection == null)
      return null;
    makePersistentAll(collection);
    ArrayList copies = new ArrayList();
    for (Iterator it = collection.iterator(); it.hasNext();){
      copies.add(detachCopy(it.next()));
    }
    return copies;
  }
 
  public Object[] detachCopyAll(Object[] objects){
    assertIsOpen();
    if(objects == null)
      return null;
    makePersistentAll(objects);
    Object[] copies = new Object[objects.length];
    for (int i = 0; i < objects.length; i++){
      copies[i] = detachCopy(objects[i]);
    }
    return copies;
  }
 
 
 
  /**
   * Apply the changes contained in the detached object to the corresponding persistent instance in the cache.
   * @param detached
   * @param map is the attachement context
   * @return the peristent object containg attached values
   */
  public Object speedoAttachCopy(Object detached, Map map){
    // if the detached object is null
    // then do nothing
    if (detached == null)
      return null;
   
    Object o = map.get(detached);
    // if the object is being or has been processed
    // then return the attached copy
    if (o != null)
      return o;
   
    Object oid = ((PersistentObjectItf)detached).speedoGetEncodedPName();
    PersistentObjectItf sp = null;
    try {
      if (oid == null) {
        //make the object persistent
        speedoMakePersistent((PersistentObjectItf) detached, map);
        //return detached;
        sp = (PersistentObjectItf) detached;
      } else {
        sp = (PersistentObjectItf) speedoGetObjectById(oid, false);
      }
        sp.speedoGetHome().sendEvent(HomeItf.PRE_ATTACH, sp, null);
      StateItf sar = sp.speedoGetHome().readIntention(sp, null);
      //if made persistent in this method
      // force the state to detached_dirty
      if (oid == null) {
        sar.forceDetachedDirty();
      }
      //call the attach method on the po
      sp.speedoGetHome().attachCopy(sp, this, map, detached, sar);
      // if made persistent in this method
      // restore the state to detached_none
      if (oid == null) {
        sar.restoreDetachedNone();
      }
      //change the version on attach
      sar.speedoChangeVersion();
        sp.speedoGetHome().sendEvent(HomeItf.POST_ATTACH, sp, null);
      return sp;
    } catch (Exception e) {
      Exception ie = ExceptionHelper.getNested(e);
      String msg = "Impossible to attach a copy of the persistent object with the identifier: " + oid;
      logger.log(BasicLevel.INFO, msg, ie);
      throw (e instanceof JDOException
          ? (JDOException) e
                     : new JDOException(msg, ie));
    }
  }

  public Object getUserObject(Object arg0) {
        return userObjects.get(arg0);
    }
    public Object putUserObject(Object arg0, Object arg1) {
        return userObjects.put(arg0, arg1);
    }
    public Object removeUserObject(Object arg0) {
        return userObjects.remove(arg0);
    }
 
 
    public void checkConsistency() {
        flush();
        // TODO: verify consistency of state in the WS
    }
   
    public Sequence getSequence(String name) {
        Sequence s = (Sequence) pmf.getSequenceManager().getSequence(name);
        if (s == null) {
          throw new JDOUserException("The sequence " + name + " has not been found."
              + "Be sure that one class of the package the sequence belongs to has been loaded.");
        }
        return s;
    }
   
    public Object newInstance(Class arg0) {
        if (arg0 == null) {
            return null;
        }
        if (arg0.isInterface()) {
            throw new JDOUserException(
                "Speedo does not support persistent interface currently: "
                    + arg0.getName());
        } else {
            try {
                return arg0.newInstance();
            } catch (Exception e) {
                throw new JDOUserException(
                  "Speedo does not support persistent abstract class currently: "
                        + arg0.getName());
            }
        }
    }
   
    public void closePOManager() {
      super.closePOManager();
      if (nbUse == 0) {
        userObject = null;
      }
    }
    protected void resetPMOnOpen(Object connectionspec) {
        ((JDOTransactionItf) tx).setOptimistic(((PersistenceManagerFactory) pmf).getOptimistic());
        setIgnoreCache(((PersistenceManagerFactory) pmf).getIgnoreCache());
        boolean multithreaded = ((PersistenceManagerFactory) pmf).getMultithreaded();
    if (multithreaded != semaphore.on)
          semaphore.init(multithreaded);
    }


  public void makeTransient(Object o, boolean useFetchPlan) {
    if (!useFetchPlan) {
      makeTransient(o);
    } else {
      //TODO: implement
    }
  }

  public void makeTransientAll(Object[] os, boolean useFetchPlan) {
    if (!useFetchPlan) {
      makeTransientAll(os);
    } else {
      //TODO: implement
    }
  }

  public void makeTransientAll(Collection os, boolean useFetchPlan) {
    if (!useFetchPlan) {
      makeTransientAll(os);
    } else {
      //TODO: implement
    }
  }

  public void retrieve(Object o, boolean FGOnly) {
    if (!FGOnly) {
      retrieve(o);   
    } else {
      //TODO: implement
    }
  }

  /* (non-Javadoc)
   * @see javax.jdo.PersistenceManager#getDetachAllOnCommit()
   */
  public boolean getDetachAllOnCommit() {
    // TODO Auto-generated method stub
    return false;
  }

  /* (non-Javadoc)
   * @see javax.jdo.PersistenceManager#setDetachAllOnCommit(boolean)
   */
  public void setDetachAllOnCommit(boolean arg0) {
    // TODO Auto-generated method stub
  }

}
TOP

Related Classes of org.objectweb.speedo.pm.jdo.lib.JDOPOManager

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.