Package org.objectweb.speedo.genclass.map

Source Code of org.objectweb.speedo.genclass.map.MapAccessor

/**
* 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.genclass.map;

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


import org.objectweb.jorm.api.PExceptionIO;
import org.objectweb.jorm.api.PIndexedElem;
import org.objectweb.jorm.naming.api.PName;
import org.objectweb.speedo.api.Debug;
import org.objectweb.speedo.genclass.GenClassAccessor;
import org.objectweb.speedo.genclass.GenClassElement;
import org.objectweb.speedo.genclass.AbstractGenClassHome;
import org.objectweb.speedo.genclass.api.SpeedoGenClassPO;
import org.objectweb.speedo.metadata.SpeedoFetchGroup;
import org.objectweb.speedo.mim.api.DetachedLifeCycle;
import org.objectweb.speedo.mim.api.LifeCycle;
import org.objectweb.speedo.mim.api.StateItf;
import org.objectweb.speedo.mim.api.PersistentObjectItf;
import org.objectweb.speedo.pm.api.POManagerItf;
import org.objectweb.util.monolog.api.BasicLevel;

public class MapAccessor
        extends GenClassAccessor
        implements Map {

    /**
     * A map containing the indexed elements of the genclass. It associates each
     * element to its index. This map does NOT contain the deleted elements.
     */
    protected Map map = null;

    /**
     * Instanciates and initializes a new map with an initial size.
     */
    public MapAccessor(SpeedoGenClassPO apo) {
        super(apo);
        this.elements = new ArrayList();
        this.map = (Map) gcpo.createGenClass();
    }

    public void makePersistent(POManagerItf pm) {
    if (Debug.ON && getLogger() != null) {
      logger.log(BasicLevel.DEBUG, "makePersistent");
    }
        if (elements.size() > 0) {
            ((AbstractGenClassHome) getSpeedoPO().speedoGetHome())
              .makePersistent(pm, values().iterator(), null, null);
        }
    }
  public void deletePersistent(POManagerItf pm) {
    clear();
  }

  public void setElements(Object o) {
    clear();
    if (o != null) {
      putAll(((Map) o));
    }
  }

  public void loadFieldsFromAccessor(StateItf sa) {
    MapAccessor ma = (MapAccessor) sa;
    map.clear();
    map.putAll(ma.map);
    supportDelta = ma.supportDelta;
    elements.clear();
    elements.addAll(ma.elements);
    speedoSetStatus(ma.speedoGetStatus());
  }

  public boolean speedoAdd(Object elemToAdd, Object hints) {
    put(hints, elemToAdd, false);
    return true;
  }

  public boolean speedoRemove(Object elemToRemove, Object hints) {
    return remove(hints, false) != null;
  }

  public void detachCopy(POManagerItf pm, Map detachCtx, StateItf fieldsClone, Collection fgHints){
    ((MapAccessor)fieldsClone).map = new HashMap();
    ((MapAccessor)fieldsClone).loadFieldsFromAccessor(this);
    //copy the elements in the map: collection is no more available when the po is not active
    ((MapAccessor)fieldsClone).map.clear();
    boolean valueToFetch = false;
    Collection fgHintsToSend = new ArrayList();
    synchronized(fgHints){
      Collection copyFgHints = new ArrayList(fgHints);
      Iterator it2 = copyFgHints.iterator();
      while(it2.hasNext() && !valueToFetch){
        String s = (String) it2.next();
        int idxValue = s.indexOf(SpeedoFetchGroup.FG_VALUE);
        if(s.indexOf(SpeedoFetchGroup.FG_KEY) != -1)
          fgHints.remove(s);
        else if(idxValue != -1){
          valueToFetch = true;
          fgHints.remove(s);
          String add = s.substring(idxValue+SpeedoFetchGroup.FG_VALUE.length());
          if(add.length() > 0){
            fgHintsToSend.add(add);
          }
        }
      }
    }
    //get an interator on the PIndexed elements
    Iterator it = ((GenClassAccessor) fieldsClone).elements.iterator();
    while(it.hasNext()){
      //get the PIndexElement
      MapElem iElem = (MapElem) it.next();
      Object elem = iElem.getElement(pm);
      Object clone = null;
      //if the element is a Persistent Object
      if (elem instanceof PersistentObjectItf) {
        //get the speedo po associated
        PersistentObjectItf sp = (PersistentObjectItf) elem;
        if(detachCtx != null)
          clone = detachCtx.get(sp);
        if(clone == null){
          synchronized(fgHints){
            if(valueToFetch){
              //  get the clone of the speedo po
              clone = pm.speedoDetachCopy(sp, detachCtx, fgHintsToSend);
            }
          }
        }
      } else {
        //just copy the java object
        clone = elem;
      }
      Object key = iElem.getIndex();
      //add it in the map of elements reachable when the po is no more active
      ((MapAccessor)fieldsClone).map.put(key, clone);
    }
    ((GenClassAccessor) fieldsClone).speedoSetStatus(LifeCycle.TRANSIENT);
  }
 
  public void attachCopy(POManagerItf pm, Map attachCtx, StateItf fieldsClone) {
    MapAccessor ma = (MapAccessor) fieldsClone;
    //get an iterator on the PIndexed elements of the collection
    Iterator it = ma.map.entrySet().iterator();
    while(it.hasNext()){
      Map.Entry mapEntry = (Map.Entry) it.next();
      Object elem = mapEntry.getValue();
      Object key = mapEntry.getKey();
      boolean put = true;
      if (elem instanceof MapElem) {
        //if the element has not been touched, do not put it in the map again
        put = false;
        elem = ((MapElem) elem).getElement();
      }
      //if the element is a Persistent Object, attach it
      if (elem instanceof PersistentObjectItf) {
        //get the detached speedo po
        PersistentObjectItf spDetached = (PersistentObjectItf) elem;
        PersistentObjectItf sp = (PersistentObjectItf) attachCtx.get(spDetached);
        if(sp == null){
          attachCtx.put(spDetached, sp);
          sp = (PersistentObjectItf) pm.speedoAttachCopy(spDetached, attachCtx);
        }
        //get the pname
        elem = sp.getPName();
      }
      if (put) {
        //put the elem in the element list
        put(key, elem, false);
      }
    }
  }
 
  public void refresh(POManagerItf pm, Map refreshCtx, Collection fgHints){
    commonRefreshRetrieve(pm, refreshCtx, fgHints, true);
  }
 
  public void retrieve(POManagerItf pm, Map retrieveCtx, Collection fgHints){
    commonRefreshRetrieve(pm, retrieveCtx, fgHints, false);
  }
 
  /**
   *
   * @param pm
   * @param ctx
   * @param fgHints
   * @param refresh: if true, call refresh, else call retrieve
   */
  //TODO: what about refreshing a map of String, Double, Integer???
  private void commonRefreshRetrieve(POManagerItf pm, Map ctx, Collection fgHints, boolean refresh){
    boolean valueToFetch = false;
    Collection fgHintsToSend = new ArrayList();
    synchronized(fgHints){
      Collection copyFgHints = new ArrayList(fgHints);
      Iterator it2 = copyFgHints.iterator();
      while(it2.hasNext() && !valueToFetch){
        String s = (String) it2.next();
        int idxValue = s.indexOf(SpeedoFetchGroup.FG_VALUE);
        if(s.indexOf(SpeedoFetchGroup.FG_KEY) != -1)
          fgHints.remove(s);
        else if(idxValue != -1){
          valueToFetch = true;
          fgHints.remove(s);
          String add = s.substring(idxValue+SpeedoFetchGroup.FG_VALUE.length());
          if(add.length() > 0){
            fgHintsToSend.add(add);
          }
        }
      }
    }
    //get an interator on the PIndexed elements
    Iterator it = this.elements.iterator();
    while(it.hasNext()){
      //get the PIndexElement
      MapElem iElem = (MapElem) it.next();
      Object elem = iElem.getElement(pm);
      //if the element is a PO
      if (elem instanceof PersistentObjectItf) {
        //get the speedo po associated
        PersistentObjectItf sp = (PersistentObjectItf) elem;
        if(ctx != null && !ctx.containsKey(sp.getPName())){
          synchronized(fgHints){
            if(valueToFetch){
              if (refresh) {
                //refresh
                              pm.speedoRefresh(sp, ctx, fgHintsToSend);
              } else {
                //retrieve
                pm.speedoRetrieve(sp, ctx, fgHintsToSend);
              }
            }
          }
        }
      }
    }
  }
 
  public Object put(Object key, Object value, boolean withCoherence) {
      MapElem element = null;
      Object res = map.get(key);
      //if detached, just put the value in the map
      if(detachedStatus != DetachedLifeCycle.DETACHED_NONE) {
        map.put(key, value);
      } else {
        if (res == null) {
          // Put a new entry in the map
        element = (MapElem) createPIndexedElem();
        element.setIndex(key);
        elements.add(element);
        map.put(key, element);
        } else {
            // Mark as modify
            element = (MapElem) res;
            element.setStatus(PIndexedElem.ELEM_MODIFIED);
            res = element.getElement(gcpo.speedoGetPOManager());
        }
      element.setElement(value);
 
      if (value instanceof PersistentObjectItf) {
        ((AbstractGenClassHome) getSpeedoPO().speedoGetHome())
          .makePersistent(null, (PersistentObjectItf) value,
                  (SpeedoGenClassPO) getSpeedoPO(), null);
      }
      }
     
    if (withCoherence) {
      Object v = value;
      if (v instanceof PName) {
        v = element.getElement(gcpo.speedoGetPOManager());
      }
      if (v instanceof PersistentObjectItf) {
        gcpo.fireSpeedoElementAdded(v);
      }
    }
    return res;
  }

  public Object remove(Object key, boolean withCoherence) {
    //if detached, just remove the key entry from the map, it returns the value
      if(detachedStatus != DetachedLifeCycle.DETACHED_NONE) {
        return map.remove(key);
      } else {
      GenClassElement gcelem = (GenClassElement) map.get(key);
      if (gcelem == null) {
        return null;
      }
      gcelem.setStatus(PIndexedElem.ELEM_DELETED);
      Object value = get(key);
      map.remove(key);
      if (withCoherence) {
        Object el = gcelem.getElement(gcpo.speedoGetPOManager());
        if (el != null) {
          gcpo.fireSpeedoElementRemoved(el);
        }
      }
      return value;
      }
  }

    // ------------------------------------------------------------------------
    // IMPLEMENTATION OF THE Map INTERFACE
    // ------------------------------------------------------------------------

    public int size() {
        return map.size();
    }

    public boolean isEmpty() {
        return map.isEmpty();
    }

    public boolean containsKey(Object key) {
        return map.containsKey(key);
    }

    public boolean containsValue(Object value) {
        // TODO: support the containsValue method on Map
        return false;
    }

    public Object get(Object key) {
        Object value = map.get(key);
        if (value == null) {
            return null;
        } else {
          //if the state is detached
          if(detachedStatus != DetachedLifeCycle.DETACHED_NONE)
            return value;
          else
            return ((MapElem) value).getElement(gcpo.speedoGetPOManager());
        }
    }

    public Object put(Object key, Object value) {
    return put(key, value, true);
  }

    public Object remove(Object key) {
    return remove(key, true);
    }

    public void putAll(Map t) {
        Iterator i = t.entrySet().iterator();
        while (i.hasNext()) {
            Map.Entry entry = (Map.Entry) i.next();
            put(entry.getKey(), entry.getValue());
        }
    }

    public void clear() {
      if (detachedStatus == DetachedLifeCycle.DETACHED_NONE) {
          Iterator i = elements.iterator();
            POManagerItf pm = null;
          while (i.hasNext()) {
              GenClassElement gcelem = (GenClassElement) i.next();
              gcelem.setStatus(PIndexedElem.ELEM_DELETED);
        if (pm == null) {
          pm = gcpo.speedoGetPOManager();
        }
        Object el = gcelem.getElement(pm);
        if (el != null) {
          gcpo.fireSpeedoElementRemoved(el);
        }
          }
      }
        map.clear();
    supportDelta = false;
    }

    public Set keySet() {
      return Collections.unmodifiableSet(map.keySet());
    }

    public Collection values() {
      ArrayList res = new ArrayList(elements.size());
      //if detached, look into map
      if (detachedStatus != DetachedLifeCycle.DETACHED_NONE) {
        Iterator it = map.values().iterator();
        while(it.hasNext()) {
          res.add(it.next());
        }
      } else {
        //else, look into elements
        for(int i=(elements.size()-1); i>=0; i--) {
            MapElem me = (MapElem) elements.get(i);
            if (me.getElemStatus() != PIndexedElem.ELEM_DELETED) {
              res.add(me.getElement());
            }
        }
      }
      return Collections.unmodifiableCollection(res);
    }

    public Set entrySet() {
      if (detachedStatus != DetachedLifeCycle.DETACHED_NONE) {
        return map.entrySet();
      } else {
        Set res = new HashSet(elements.size());
        for(int i=(elements.size()-1); i>=0; i--) {
          MapElem me = (MapElem) elements.get(i);
          if (me.getElemStatus() != PIndexedElem.ELEM_DELETED) {
            res.add(new MyMapEntry(me));
          }
         }
        return Collections.unmodifiableSet(res);
      }
    }

  private class MyMapEntry implements Map.Entry {
    MapElem me;

    public MyMapEntry(MapElem _me) {
      this.me = _me;
    }

    public Object getKey() {
      return me.getIndex();
    }

    public Object getValue() {
      return me.getElement();
    }

    public Object setValue(Object value) {
      Object res = me.getElement();
      me.setStatus(PIndexedElem.ELEM_MODIFIED);
      me.setElement(value);
      return res;
    }
  }

    // ------------------------------------------------------------------------
    // IMPLEMENTATION OF THE PGenClassAccessor INTERFACE
    // ------------------------------------------------------------------------
    public PIndexedElem createPIndexedElem(GenClassAccessor gca) {
        return new MapElem(gca);
    }

    public void paAdd(PIndexedElem elem, Object conn) throws PExceptionIO {
        GenClassElement gcelem = (GenClassElement) elem;
        // the elem is read from the DS, set it to unmodified.
        gcelem.setStatus(PIndexedElem.ELEM_UNMODIFIED);
        elements.add(gcelem);
        map.put(gcelem.getIndex(), gcelem);
    }

    public int paGetNbElem() {
        return size();
    }

    public Iterator paIterator() {
        return elements.iterator();
    }

    public void paSetNbElem(int nbelem) {
      if (nbelem == -1) {
            elements = new ArrayList();
      } else {
            elements = new ArrayList(nbelem);
      }
        map = (Map) gcpo.createGenClass();
    }

  public void forceDetachedDirty() {
  }

  public void restoreDetachedNone() {
  }

  public void makePersistentOnAttach(POManagerItf pm, Map map) {
    if (Debug.ON && getLogger() != null) {
      logger.log(BasicLevel.DEBUG, "makePersistent");
    }
        if (elements.size() > 0) {
            ((AbstractGenClassHome) getSpeedoPO().speedoGetHome())
              .makePersistent(pm, values().iterator(), null, map);
        }
  }

 
}
TOP

Related Classes of org.objectweb.speedo.genclass.map.MapAccessor

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.