/**
* 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;
import org.objectweb.speedo.genclass.api.SpeedoGenClassPO;
import org.objectweb.speedo.genclass.api.SpeedoGenClassSerializable;
import org.objectweb.speedo.mim.api.HomeItf;
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.speedo.genclass.api.SpeedoGenClassListener;
import org.objectweb.speedo.api.Debug;
import org.objectweb.speedo.api.SpeedoRuntimeException;
import org.objectweb.jorm.util.api.Loggable;
import org.objectweb.jorm.api.PBinding;
import org.objectweb.jorm.api.PException;
import org.objectweb.jorm.api.PClassMapping;
import org.objectweb.jorm.api.PAccessor;
import org.objectweb.jorm.api.PIndexedElem;
import org.objectweb.jorm.api.PBindingCtrl;
import org.objectweb.jorm.type.api.PType;
import org.objectweb.jorm.naming.api.PName;
import org.objectweb.perseus.cache.api.UnFixProtocolException;
import org.objectweb.util.monolog.api.Logger;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
/**
* This class is a basic implementation of the SpeedoGenClassPO interface.
* It uses a delegate PBinding.
*
* @author S.Chassande-Barrioz
*/
public abstract class GenClass
implements SpeedoGenClassPO, SpeedoGenClassSerializable, Loggable, PBindingCtrl {
/**
* This fields indicates if the po is active
*/
protected boolean speedoIsActive = false;
/**
* is the PBinding which permits to store/load the data into/from the support
*/
protected PBindingCtrl pbinding;
/**
* The logger used to trace this generic class
* Defined as transient.
*/
public transient Logger logger;
/**
* is the name of the mapper inside which the generic class is persistent
*/
protected String mapperName;
/**
* is the name of the project name inside which the generic class is used.
*/
protected String projectName;
/**
* is the type of the generic class
*/
protected PType ptype;
/**
* The linked field associated to this gen class
*/
protected String linkedField = null;
/**
* Is the PName which
*/
protected Object pnameHints = null;
/**
* Id of the field that references this gen class instance
*/
protected int gcid;
/**
* List of SpeedoGenClassListener
*/
protected List listeners;
protected long age;
protected int fix = 0;
protected Object encodedPName;
public void init(PType _ptype,
String _linkedField,
Object _pnameHints,
Logger _logger) {
this.pnameHints = _pnameHints;
this.ptype = _ptype;
this.linkedField = _linkedField;
this.logger = _logger;
}
public void speedoSetPNameHints(Object hints) {
pnameHints = hints;
}
public boolean elementIsReference() {
return ptype.getNestedPType().getTypeCode() == PType.TYPECODE_REFERENCE;
}
public void speedoSetGcId (int _gcid) {
this.gcid = _gcid;
}
public void speedoAddGenClassListener (SpeedoGenClassListener l) {
if (listeners == null) {
listeners = new ArrayList();
listeners.add(l);
} else {
for(int i=0; i<listeners.size(); i++) {
if (listeners.get(i) == l) {
return;
}
}
listeners.add(l);
}
}
public void speedoAdd(Object elem, int gcFieldNumber) {
throw new SpeedoRuntimeException("Not supported in tuple class");
}
public boolean speedoAdd(Object elemToAdd, Object hints) {
GenClassAccessor gca = (GenClassAccessor) speedoGetHome().writeIntention(this, null);
return gca.speedoAdd(elemToAdd, hints);
}
public boolean speedoRemove(Object elemToRemove, Object hints) {
GenClassAccessor gca = (GenClassAccessor) speedoGetHome().writeIntention(this, null);
return gca.speedoRemove(elemToRemove, hints);
}
public void fireSpeedoElementAdded (Object elem) {
if (Debug.ON && logger != null) {
logger.log(BasicLevel.DEBUG, "fireSpeedoElementAdded(): listner: "
+ (listeners == null ? "no listener" : "" + listeners.size()));
}
if (listeners == null) {
return;
}
Iterator i = listeners.iterator();
while (i.hasNext()) {
SpeedoGenClassListener l = (SpeedoGenClassListener)i.next();
l.speedoElementAdded(elem, gcid);
}
}
public void fireSpeedoElementRemoved (Object elem) {
if (Debug.ON && logger != null) {
logger.log(BasicLevel.DEBUG, "fireSpeedoElementRemoved(): listner: "
+ (listeners == null ? "no listener" : "" + listeners.size()));
}
if (listeners == null) {
return;
}
Iterator i = listeners.iterator();
while (i.hasNext()) {
SpeedoGenClassListener l = (SpeedoGenClassListener)i.next();
l.speedoElementRemoved(elem, gcid);
}
}
public Object getDataIdentifier(Object o) {
if (o instanceof PersistentObjectItf) {
if (!((PersistentObjectItf) o).speedoIsActive()) {
((AbstractGenClassHome) speedoGetHome())
.makePersistent(null, (PersistentObjectItf) o, this, null);
}
return ((PersistentObjectItf) o).getCeIdentifier();
} else {
return o;
}
}
public Collection getDataIdentifiers(Collection os) {
if (os == null) {
return null;
}
if (os.size() == 0) {
return Collections.EMPTY_LIST;
}
ArrayList al = new ArrayList();
for(Iterator it = os.iterator(); it.hasNext();) {
al.add(getDataIdentifier(it.next()));
}
return al;
}
// ABSTRACT METHODS //
// -----------------//
public abstract StateItf speedoCreateState();
public abstract StateItf speedoGetReferenceState();
public abstract void speedoSetReferenceState(StateItf refAcc);
// IMPLEMENTATION OF THE PBindingCtrl INTERFACE //
// ---------------------------------------------//
public void bind(PName name) throws PException {
pbinding.bind(name);
}
public boolean exist(Object o) throws PException {
return pbinding.exist(o);
}
public PName export(Object o) throws PException {
return pbinding.export(o);
}
public PName export(Object o, Object o1) throws PException {
return pbinding.export(o, o1);
}
public PClassMapping getPClassMapping() {
return pbinding.getPClassMapping();
}
public PName getPName() {
return pbinding.getPName();
}
public byte getStatus() {
return pbinding.getStatus();
}
public void setPName(PName pName) {
pbinding.setPName(pName);
}
public void setStatus(byte b) {
pbinding.setStatus(b);
}
public void init(PClassMapping mapping) throws PException {
pbinding.init(mapping);
}
public void read(Object o, PAccessor accessor) throws PException {
pbinding.read(o, accessor);
}
public void read(Object o, PAccessor pAccessor, Object o1) throws PException {
pbinding.read(o, pAccessor, o1);
}
public void read(Object o, PAccessor pAccessor, Object o1, boolean forUpdate) throws PException {
pbinding.read(o, pAccessor, o1, forUpdate);
}
public void unbind() throws PException {
pbinding.unbind();
}
public void unexport(Object o) throws PException {
pbinding.unexport(o);
}
public void write(Object o, PAccessor accessor) throws PException {
if (logger != null)
logger.log(BasicLevel.DEBUG, "Writing the gen class: " + linkedField);
pbinding.write(o, accessor);
boolean retainDeltaForMerge = ((HomeItf) pbinding.getPClassMapping()).isFieldLockingLevel();
GenClassAccessor gca = (GenClassAccessor) accessor;
if (retainDeltaForMerge && gca.deltaForMerge == null) {
gca.deltaForMerge = new ArrayList();
}
for(Iterator i = gca.elements.iterator();i.hasNext();) {
GenClassElement gce = (GenClassElement) i.next();
if (retainDeltaForMerge
&& gce.getElemStatus() != PIndexedElem.ELEM_MODIFIED) {
gce.retainStatusForMerge();
gca.deltaForMerge.add(gce);
}
if (gce.getElemStatus() != PIndexedElem.ELEM_DELETED) {
gce.setStatus(PIndexedElem.ELEM_UNMODIFIED);
} else {
// remove the element
i.remove();
}
}
}
// IMPLEMENTATION OF THE SpeedoGenClassPO INTERFACE //
//-----------------------------------------------------//
/**
* Assignes the PType of the generic class.
* @param _ptype of the generic class
*/
public void speedoSetPType(PType _ptype) {
this.ptype = _ptype;
}
/**
* @return the PType of the generic class.
*/
public PType speedoGetPType() {
return ptype;
}
/**
* assignes the PBinding to use to load/store the generic class
* Call this method with null value means that the generic is no more
* persistent.
* @param pb is the PBinding.
*/
public void speedoSetPBinding(PBinding pb) {
pbinding = (PBindingCtrl) pb;
}
/**
* @return the pbinding associated to the generic class. The value is if the
* generic class is not persistent.
*/
public PBinding speedoGetPBinding() {
return pbinding;
}
/**
* @return a string which represents the fully path of the persistent field
* of the class with wich the generic class is persistent.
* If the linked fiekf is the 'f1' provided by the class 'com.foo.Bar'
* then the returned string will be 'com.foo.Bar/f1'
*/
public String speedoGetGenClassId() {
return linkedField;
}
/**
* Assignes the linked field name for this generic class.
* @param lf is tring which represents the fully path of the persistent
* field of the class with wich the generic class is persistent.
* If the linked fiekf is the 'f1' provided by the class 'com.foo.Bar'
* then the expected string is 'com.foo.Bar/f1'
*/
public void speedoSetLinkedField(String lf) {
linkedField = lf;
}
/**
* Assignes the new value of the generic class (Collection, Map or Array
* or ...).
*/
public void setElements(Object o) {
((GenClassAccessor) speedoGetHome().writeIntention(this, null)).setElements(o);
}
// IMPLEMENTATION OF THE PersistentObjectItf INTERFACE //
//---------------------------------------------//
public boolean speedoIsPersistent() {
StateItf sa = speedoGetState();
return sa == null || LifeCycle.isPersistent(sa.speedoGetStatus());
}
public void speedoCopyState(StateItf src, StateItf dest) {
((GenClassAccessor) dest).loadFieldsFromAccessor(src);
}
public Object speedoGetPNameHints() {
return pnameHints;
}
public boolean speedoIsActive() {
return speedoIsActive;
}
public void speedoIsActive(boolean newvalue) {
speedoIsActive = newvalue;
}
public StateItf speedoGetState() {
if (!speedoIsActive) {
return speedoGetReferenceState();
}
return speedoGetHome().getState(this);
}
public Collection getSpeedoAccessors() {
return null;
}
public void removeSpeedoAccessor(StateItf sa) {
}
public void speedoSetEncodedPName(Object _encodedPName) {
this.encodedPName = _encodedPName;
}
public Object speedoGetEncodedPName() {
return encodedPName;
}
public HomeItf speedoGetHome() {
return (HomeItf) getPClassMapping();
}
public POManagerItf speedoGetPOManager() {
return (speedoIsActive ? speedoGetHome().getPOManagerFactory().lookup() : null);
}
// IMPLEMENTATION OF THE CacheEntry INTERFACE //
//-------------------------------------------//
public Object getCeObject() {
return this;
}
public Object getCeIdentifier() {
return getPName();
}
// IMPLEMENTATION OF THE FixableCacheEntry INTERFACE //
//---------------------------------------------------//
public void fixCe() {
fix++;
}
public void unfixCe() throws UnFixProtocolException {
fix--;
}
public int getCeFixCount() {
return fix;
}
// IMPLEMENTATION OF THE ReplaceableCacheEntry INTERFACE //
//-------------------------------------------------------//
public long getCeAge() {
return age;
}
public void setCeAge(long l) {
age = l;
}
// ------------------------------------------------------------------------
// IMPLEMENTATION OF THE Loggable INTERFACE
// ------------------------------------------------------------------------
public void setLogger(Logger _logger) {
logger = _logger;
}
public void setLoggerFactory(LoggerFactory loggerfactory) {
logger = loggerfactory.getLogger(this.getClass().getName());
}
public Logger getLogger() {
return logger;
}
public LoggerFactory getLoggerFactory() {
return null;
}
}