Package org.objectweb.speedo.mim.lib

Source Code of org.objectweb.speedo.mim.lib.AbstractHomeImpl

/**
* Copyright (C) 2001-2004 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
*/
package org.objectweb.speedo.mim.lib;

import org.objectweb.jorm.api.PClassMapping;
import org.objectweb.jorm.api.PException;
import org.objectweb.perseus.persistence.api.PersistenceException;
import org.objectweb.perseus.persistence.api.RolledBackPersistenceException;
import org.objectweb.perseus.persistence.api.TransactionalPersistenceManager;
import org.objectweb.speedo.api.Debug;
import org.objectweb.speedo.api.ExceptionHelper;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoFetchGroup;
import org.objectweb.speedo.mim.api.DetachedLifeCycle;
import org.objectweb.speedo.mim.api.HomeItf;
import org.objectweb.speedo.mim.api.StateItf;
import org.objectweb.speedo.mim.api.PersistentObjectItf;
import org.objectweb.speedo.pm.api.POManagerItf;
import org.objectweb.speedo.pm.api.POManagerFactoryItf;
import org.objectweb.speedo.query.api.QueryDefinition;
import org.objectweb.speedo.usercache.api.UserCache;
import org.objectweb.speedo.usercache.lib.CompositeUserCache;
import org.objectweb.speedo.usercache.lib.UserCacheImpl;
import org.objectweb.speedo.workingset.api.TransactionItf;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* @author S.Chassande-Barrioz
*/
public abstract class AbstractHomeImpl implements HomeItf {
    protected TransactionalPersistenceManager tpm = null;
  protected POManagerFactoryItf pmf = null;
  byte cachePolicy = CACHED;
  boolean isShareable = true;
  boolean isFieldLockingLevel = false;
  boolean prefetchOnQuery = true;
  boolean prefetchOnExtent = true;
  boolean prefetchOnGenClass = true;
  protected Map namedQueries = null;
  protected Personality personality;
 
  public AbstractHomeImpl(Personality p) {
    personality = p;
  }
 
  public AbstractHomeImpl(TransactionalPersistenceManager _tpm,
          POManagerFactoryItf _pmf) {
      this.tpm = _tpm;
      this.pmf = _pmf;
  }
 
  /**
   * @return false because it corresponds to most of case
   * Subclass to change the behavior
   */
  protected boolean isAbstract() {
      return false;
  }
 
    /**
     * Create a new instance of a PersistentObjectItf which the clas is given in
     * parameter. The default implementation does a
     * simple 'clazz.newInstance()'.
     */
  protected PersistentObjectItf newSpeedoPOInstance(Class clazz) throws Exception {
        return (PersistentObjectItf) clazz.newInstance();
    }

  // IMPLEMENTATION OF THE HomeItf INTERFACE //
  //-------------------------------------------//
 
  public boolean isCacheable() {
      return (cachePolicy & CACHED) != 0;
  }

    public boolean allLoaded() {
        return (cachePolicy & ALL) != 0;
    }
   
    public boolean hasToFix() {
        return (cachePolicy & FIXED) != 0;
    }
   
  public void setCachePolicy(byte v) {
      cachePolicy = v;
  }

    public boolean isShareable() {
    return isShareable;
  }

  public void setShareable(boolean v) {
    isShareable = v;
  }

  public boolean isFieldLockingLevel() {
        return isFieldLockingLevel;
    }

    public void setFieldLockingLevel(boolean val) {
        isFieldLockingLevel = val;
    }
   
    /**
   * This default implementation does nothing and returns null.
   * Subclass to change the behavior
   */
    public Collection fgGetNestedFetchGroups(String fgName) {
      return null;
  }

  /**
   * This default implementation returns always false.
   * Subclass to change the behavior
   */
  public boolean fgIsDefined(String fgName) {
      return false;
  }

  /**
   * This default implementation does nothing and returns null.
   * Subclass to change the behavior
   */
  public Collection fgGetFieldsToLoad(String fgName) {
      return null;
  }
 
    /**
   * @return the PersistenceManagerFactory which represents the data support
   * inside which the po is persistent.
   */
  public final POManagerFactoryItf getPOManagerFactory() {
    return pmf;
  }

  /**
   * It assignes a PersistenceManagerFactory
   * @param _pmf is the PersistenceManagerFactory which represents the data
   * support inside which the po is persistent.
   */
  public final void setPOManagerFactory(POManagerFactoryItf _pmf) {
    this.pmf = _pmf;
  }


  /**
   * @return the TransactionalPersistenceManager which manage the
   * concurrency, loading, ... of the po.
   */
  public final TransactionalPersistenceManager getTransactionalPersistenceManager() {
    return tpm;
  }

  /**
   * It assignes a TransactionalPersistenceManager
   * @param _tpm is the TransactionalPersistenceManager which manage the
   * concurrency, loading, ... of the po.
   */
  public final void setTransactionalPersistenceManager(TransactionalPersistenceManager _tpm) {
    this.tpm = _tpm;
  }

  /**
   * Notifies the transactional persistency manager of a read intention for
   * the given persistent instance.
   * @param sp is the PersistentObjectItf which the read access is requested.
   * @param fields the ids of the fields that may be accessed by the caller
   * of this method. If the i-th bit of 'fields' is set to 1, then the i-th
   * field of the given speedo accessor may be accessed by the caller of this
   * method.
   */
  public final StateItf readIntention(PersistentObjectItf sp, long[] fields) {
    if (!sp.speedoIsActive()) {
      StateItf sa = sp.speedoGetReferenceState();
      if (sa == null) {
        sp.speedoSetReferenceState(sp.speedoCreateState());
      }
      return sa;
    }
    POManagerItf pm = pmf.lookup();
    if (pm == null) {
        throw personality.newUserRuntimeException("When a persistent object is used (read), a PersistenceManager is needed");
    }
    TransactionItf t = pm.getSpeedoTransaction();
    try {
        StateItf sa = (StateItf) tpm.readIntention(t, sp, null);
        sa.loadFields(pm, fields);
        return sa;
        } catch (RolledBackPersistenceException e) {
            throw t.rollBackOnInternalError(e);
    } catch (PersistenceException e) {
      throw personality.newRuntimeException("Impossible to notify a read intention",
              ExceptionHelper.getNested(e));
    }
  }

  public final StateItf writeIntention(PersistentObjectItf sp, long[] fields) {
      return writeIntention(sp, fields, null);
  }
 
  /**
   * Notifies the transactional persistency manager of a write intention for
   * the given persistent instance.
   *
   * @param sp is the PersistentObjectItf which the write access is requested.
   * @param fields the ids of the fields that may be accessed by the caller
   * of this method. If the i-th bit of 'fields' is set to 1, then the i-th
   * field of the given speedo accessor may be accessed by the caller of this
   * method.
   */
  public StateItf writeIntention(PersistentObjectItf sp, long[] fields, Object thinLock) {
    if (!sp.speedoIsActive()) {
      StateItf sa = sp.speedoGetReferenceState();
      if (sa == null) {
        sp.speedoSetReferenceState(sp.speedoCreateState());
      }
      return sa;
    }
    POManagerItf pm = pmf.lookup();
    if (pm == null) {
        throw personality.newUserRuntimeException("When a persistent object is used (read), a PersistenceManager/EntityManager is needed");
    }
    TransactionItf t = pm.getSpeedoTransaction();
    try {
      sendEvent(PRE_DIRTY, sp, null);
        StateItf sa = (StateItf) tpm.writeIntention(t, sp,
                isFieldLockingLevel ? thinLock : null);
        sa.loadFields(pm, fields);
      sendEvent(POST_DIRTY, sp, null);
        return sa;
        } catch (RolledBackPersistenceException e) {
            throw t.rollBackOnInternalError(e);
    } catch (PersistenceException e) {
      throw personality.newRuntimeException("Impossible to notify a write intention",
        ExceptionHelper.getNested(e));
    }
  }

  /**
   * It retrieves the StateItf instance used in the current context.
   * If the po is not active then the reference accessor is returned.
   * If there is an active then the $classNameFields used in the context is
   * returned. Be careul, if the persistent object is not used in the current
   * context, then a null value will be returned, because no StateItf
   * is registered in the working set.
   */
  public final StateItf getState(PersistentObjectItf sp) {
    if (!sp.speedoIsActive()) {
      return sp.speedoGetReferenceState();
    }
    POManagerItf pm = pmf.lookup();
    if (pm == null) {
        throw personality.newUserRuntimeException("When a persistent object is used (read or write), a PersistenceManager is needed");
    }
    return (StateItf) pm.getSpeedoTransaction().lookup(sp.getPName());
  }

  public final PersistentObjectItf detachCopy(PersistentObjectItf sp,
          POManagerItf pm,
          Map map,
          Object clone,
          Collection fgHints) {
    Logger logger = getLogger();
    if (Debug.ON && logger != null && logger.isLoggable(BasicLevel.DEBUG)) {
      logger.log(BasicLevel.DEBUG, "detachCopy()");
    }
    if (!isAbstract() && clone == null){
      try {
        //instanciate the PersistentObjectItf clone
        clone = newSpeedoPOInstance(sp.getClass());
        PersistentObjectItf spClone = (PersistentObjectItf)clone;
        spClone.speedoSetEncodedPName(pm.getEncodedPName(sp));
        spClone.setCeAge(0);
        spClone.speedoIsActive(false);
        //instanciate the clone of the fields
        StateItf fieldsClone = sp.speedoCreateState();
        spClone.speedoSetReferenceState(fieldsClone);
        fieldsClone.setSpeedoPO(spClone);
        //put the association between the po and its clone into the map
        if(map != null)
          map.put(sp, clone);
        synchronized(fgHints){
          readIntention(sp, null).detachCopy(pm, map, fieldsClone, fgHints);
        }
        //mark the state as detached
        fieldsClone.setDetachedStatus(DetachedLifeCycle.DETACHED_CLEAN);
      } catch(Exception e){
        throw personality.newUserRuntimeException("Detach cannot be performed", new Exception[]{ExceptionHelper.getNested(e)});
      }
    }
    return (PersistentObjectItf)clone;
  }

  public final void attachCopy(PersistentObjectItf sp,
    POManagerItf pm,
    Map map,
    Object clone,
    StateItf sa) {

    if(map != null) {
      if( (PersistentObjectItf) map.get(clone) == sp)
        return;
      map.put(clone, sp);
      //check the validity version
      if (!sa.checkVersion(((PersistentObjectItf)clone).speedoGetReferenceState())) {
        throw personality.newRuntimeException("The detached copy is no more valid.");
      }
      sa.attachCopy(pm, map,
        ((PersistentObjectItf) clone).speedoGetReferenceState());
    }
  }


  public final Collection fgGetFieldsToLoad(String fgName, boolean onlyDirectRef){
    Collection c = fgGetFieldsToLoad(fgName);
    if(onlyDirectRef){
      Iterator it = c.iterator();
      while(it.hasNext()) {
        String s = (String) it.next();
        if(s.indexOf(SpeedoFetchGroup.FG_DOT) != -1
                || s.indexOf(SpeedoFetchGroup.FG_SHARP) != -1
                || s.indexOf(SpeedoFetchGroup.FG_SLASH) != -1
                || s.indexOf(SpeedoFetchGroup.FG_KEY) != -1
                || s.indexOf(SpeedoFetchGroup.FG_VALUE) != -1) {
          it.remove();
        }
      }
    }
    return c;
  }
 
    public void setPrefetchOnExtent(boolean prefetch) {
        this.prefetchOnExtent = prefetch;
    }
   

    public boolean getPrefetchOnExtent() {
        return prefetchOnExtent;
    }
    public void setPrefetchOnGenClass(boolean prefetch) {
        this.prefetchOnGenClass = prefetch;
    }
    public boolean getPrefetchOnGenClass() {
        return prefetchOnGenClass;
    }
    public void setPrefetchOnQuery(boolean prefetch) {
        this.prefetchOnQuery = prefetch;
    }
    public boolean getPrefetchOnQuery() {
        return prefetchOnQuery;
    }
 
  public void initSH() {
  }
 
  public Class getClassForQuery(String className, String queryName) {
      try {
            return getClass().getClassLoader().loadClass(className);
        } catch (ClassNotFoundException e) {
            throw personality.newUserRuntimeException("Class '" + className
                    + "' used in the query '" + queryName
                    + "' defined in by the class '" + getClassName()
                    + "' is not available. See the inner class loading problem: ", e);
        }
  }
 
  public final QueryDefinition addNamedQuery(String name, QueryDefinition query) {
    return (QueryDefinition) namedQueries.put(name, query);
  }
  public final QueryDefinition removeNamedQuery(String name) {
    return (QueryDefinition) namedQueries.remove(name);
  }
  public final QueryDefinition getNamedQuery(String name) {
    return (QueryDefinition) namedQueries.get(name);
  }
 
  public String getPath() {
      return getClassName();
  }
 
  //IMPLEMENTATION OF THE UserCacheHelper INTERFACE //
  //------------------------------------------------//
 
  protected UserCache[] userCaches = new UserCache[0];

  protected synchronized UserCache addUserCache(String userCacheName, String[] fields, int id) {
      UserCacheImpl uc = new UserCacheImpl();
      uc.setName(userCacheName);
      uc.setIndexFieldNames(fields);
      uc.setId(id);
      uc.setActive(true);
      if (id >= userCaches.length) {
          UserCache[] newUserCaches = new UserCache[id+1];
          System.arraycopy(userCaches, 0, newUserCaches, 0, userCaches.length);
        userCaches = newUserCaches;
      }
      userCaches[id] = uc;
      return uc;
  }

  /**
   * This method is implemented by the generated XXXHome class
   */
  public boolean activeUserCache(String cacheName) {
      return false;
  }
  public UserCache getUserCache(int cacheId) {
      if (cacheId < 0
              || cacheId >= userCaches.length
              || userCaches[cacheId] == null) {
          return null;
      }
      return userCaches[cacheId];
  }
 
  public UserCache getUserCache(Collection fieldNames) {
      PClassMapping[] pcms = null;
      try {
            pcms = getSubPCMs();
        } catch (PException e) {
            throw personality.newRuntimeException("Impossible to fetch home of sub class of "
                    + getClassName(), e);
        }
      if (pcms == null || pcms.length == 0) {
          return getUserCacheOfTheClass(fieldNames);
      }
      ArrayList ucs = null;
      //get the user cache of this class
      UserCache uc = getUserCacheOfTheClass(fieldNames);
      //if it not null, add it to the list
      if(uc != null) {
         if (ucs == null) {
                ucs = new ArrayList();
            }
            ucs.add(uc);
      }
      //then do the same for each subclass
      for (int i = 0; i < pcms.length; i++) {
          uc = ((AbstractHomeImpl) pcms[i])
            .getUserCacheOfTheClass(fieldNames);
          if (uc != null) {
              if (ucs == null) {
                  ucs = new ArrayList();
              }
              ucs.add(uc);
          }
        }
      if (ucs != null) {
          return new CompositeUserCache((UserCache[])
                  ucs.toArray(new UserCache[ucs.size()]));
      }
      return null;
  }
 
  private UserCache getUserCacheOfTheClass(Collection fieldNames) {
      for(int i=0; i<userCaches.length; i++) {
          if (userCaches[i] != null && userCaches[i].isActive()) {
            String[] fns = userCaches[i].getIndexFieldNames();
            List l = Arrays.asList(fns);
            if (fns.length == fieldNames.size()
                    && fieldNames.containsAll(l)
                    && l.containsAll(fieldNames)
                    ) {
                return userCaches[i];
            }
          }
      }
      return null;
  }
     
    public Collection getActiveUserCache() {
        if (userCaches == null || userCaches.length == 0) {
            return Collections.EMPTY_LIST;
        }
        ArrayList al = new ArrayList();
      for(int i=0; i<userCaches.length; i++) {
          if (userCaches[i] != null && userCaches[i].isActive()) {
            al.add(userCaches[i]);
          }
      }
        return al;
    }
    public void userCacheEntryUnbound(Object oid) {
        if (userCaches == null || userCaches.length == 0) {
            return;
        }
      for(int i=0; i<userCaches.length; i++) {
          if (userCaches[i] != null && userCaches[i].isActive()) {
            userCaches[i].unbindFromOID(oid);
          }
      }
    }
}
TOP

Related Classes of org.objectweb.speedo.mim.lib.AbstractHomeImpl

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.