001: /**
002: * Copyright (C) 2001-2004 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.genclass;
018:
019: import org.objectweb.speedo.genclass.api.SpeedoGenClassPO;
020: import org.objectweb.speedo.genclass.api.SpeedoGenClassSerializable;
021: import org.objectweb.speedo.mim.api.HomeItf;
022: import org.objectweb.speedo.mim.api.LifeCycle;
023: import org.objectweb.speedo.mim.api.StateItf;
024: import org.objectweb.speedo.mim.api.PersistentObjectItf;
025: import org.objectweb.speedo.pm.api.POManagerItf;
026: import org.objectweb.speedo.genclass.api.SpeedoGenClassListener;
027: import org.objectweb.speedo.api.Debug;
028: import org.objectweb.speedo.api.SpeedoRuntimeException;
029: import org.objectweb.jorm.util.api.Loggable;
030: import org.objectweb.jorm.api.PBinding;
031: import org.objectweb.jorm.api.PException;
032: import org.objectweb.jorm.api.PClassMapping;
033: import org.objectweb.jorm.api.PAccessor;
034: import org.objectweb.jorm.api.PIndexedElem;
035: import org.objectweb.jorm.api.PBindingCtrl;
036: import org.objectweb.jorm.type.api.PType;
037: import org.objectweb.jorm.naming.api.PName;
038: import org.objectweb.perseus.cache.api.UnFixProtocolException;
039: import org.objectweb.util.monolog.api.Logger;
040: import org.objectweb.util.monolog.api.BasicLevel;
041: import org.objectweb.util.monolog.api.LoggerFactory;
042:
043: import java.util.Collection;
044: import java.util.Collections;
045: import java.util.Iterator;
046: import java.util.List;
047: import java.util.ArrayList;
048:
049: /**
050: * This class is a basic implementation of the SpeedoGenClassPO interface.
051: * It uses a delegate PBinding.
052: *
053: * @author S.Chassande-Barrioz
054: */
055: public abstract class GenClass implements SpeedoGenClassPO,
056: SpeedoGenClassSerializable, Loggable, PBindingCtrl {
057:
058: /**
059: * This fields indicates if the po is active
060: */
061: protected boolean speedoIsActive = false;
062:
063: /**
064: * is the PBinding which permits to store/load the data into/from the support
065: */
066: protected PBindingCtrl pbinding;
067:
068: /**
069: * The logger used to trace this generic class
070: * Defined as transient.
071: */
072: public transient Logger logger;
073:
074: /**
075: * is the name of the mapper inside which the generic class is persistent
076: */
077: protected String mapperName;
078:
079: /**
080: * is the name of the project name inside which the generic class is used.
081: */
082: protected String projectName;
083:
084: /**
085: * is the type of the generic class
086: */
087: protected PType ptype;
088:
089: /**
090: * The linked field associated to this gen class
091: */
092: protected String linkedField = null;
093:
094: /**
095: * Is the PName which
096: */
097: protected Object pnameHints = null;
098:
099: /**
100: * Id of the field that references this gen class instance
101: */
102: protected int gcid;
103:
104: /**
105: * List of SpeedoGenClassListener
106: */
107: protected List listeners;
108:
109: protected long age;
110:
111: protected int fix = 0;
112:
113: protected Object encodedPName;
114:
115: public void init(PType _ptype, String _linkedField,
116: Object _pnameHints, Logger _logger) {
117: this .pnameHints = _pnameHints;
118: this .ptype = _ptype;
119: this .linkedField = _linkedField;
120: this .logger = _logger;
121: }
122:
123: public void speedoSetPNameHints(Object hints) {
124: pnameHints = hints;
125: }
126:
127: public boolean elementIsReference() {
128: return ptype.getNestedPType().getTypeCode() == PType.TYPECODE_REFERENCE;
129: }
130:
131: public void speedoSetGcId(int _gcid) {
132: this .gcid = _gcid;
133: }
134:
135: public void speedoAddGenClassListener(SpeedoGenClassListener l) {
136: if (listeners == null) {
137: listeners = new ArrayList();
138: listeners.add(l);
139: } else {
140: for (int i = 0; i < listeners.size(); i++) {
141: if (listeners.get(i) == l) {
142: return;
143: }
144: }
145: listeners.add(l);
146: }
147: }
148:
149: public void speedoAdd(Object elem, int gcFieldNumber) {
150: throw new SpeedoRuntimeException("Not supported in tuple class");
151: }
152:
153: public boolean speedoAdd(Object elemToAdd, Object hints) {
154: GenClassAccessor gca = (GenClassAccessor) speedoGetHome()
155: .writeIntention(this , null);
156: return gca.speedoAdd(elemToAdd, hints);
157: }
158:
159: public boolean speedoRemove(Object elemToRemove, Object hints) {
160: GenClassAccessor gca = (GenClassAccessor) speedoGetHome()
161: .writeIntention(this , null);
162: return gca.speedoRemove(elemToRemove, hints);
163: }
164:
165: public void fireSpeedoElementAdded(Object elem) {
166: if (Debug.ON && logger != null) {
167: logger.log(BasicLevel.DEBUG,
168: "fireSpeedoElementAdded(): listner: "
169: + (listeners == null ? "no listener" : ""
170: + listeners.size()));
171: }
172: if (listeners == null) {
173: return;
174: }
175: Iterator i = listeners.iterator();
176: while (i.hasNext()) {
177: SpeedoGenClassListener l = (SpeedoGenClassListener) i
178: .next();
179: l.speedoElementAdded(elem, gcid);
180: }
181: }
182:
183: public void fireSpeedoElementRemoved(Object elem) {
184: if (Debug.ON && logger != null) {
185: logger.log(BasicLevel.DEBUG,
186: "fireSpeedoElementRemoved(): listner: "
187: + (listeners == null ? "no listener" : ""
188: + listeners.size()));
189: }
190: if (listeners == null) {
191: return;
192: }
193: Iterator i = listeners.iterator();
194: while (i.hasNext()) {
195: SpeedoGenClassListener l = (SpeedoGenClassListener) i
196: .next();
197: l.speedoElementRemoved(elem, gcid);
198: }
199: }
200:
201: public Object getDataIdentifier(Object o) {
202: if (o instanceof PersistentObjectItf) {
203: if (!((PersistentObjectItf) o).speedoIsActive()) {
204: ((AbstractGenClassHome) speedoGetHome())
205: .makePersistent(null, (PersistentObjectItf) o,
206: this , null);
207: }
208: return ((PersistentObjectItf) o).getCeIdentifier();
209: } else {
210: return o;
211: }
212: }
213:
214: public Collection getDataIdentifiers(Collection os) {
215: if (os == null) {
216: return null;
217: }
218: if (os.size() == 0) {
219: return Collections.EMPTY_LIST;
220: }
221: ArrayList al = new ArrayList();
222: for (Iterator it = os.iterator(); it.hasNext();) {
223: al.add(getDataIdentifier(it.next()));
224: }
225: return al;
226: }
227:
228: // ABSTRACT METHODS //
229: // -----------------//
230:
231: public abstract StateItf speedoCreateState();
232:
233: public abstract StateItf speedoGetReferenceState();
234:
235: public abstract void speedoSetReferenceState(StateItf refAcc);
236:
237: // IMPLEMENTATION OF THE PBindingCtrl INTERFACE //
238: // ---------------------------------------------//
239:
240: public void bind(PName name) throws PException {
241: pbinding.bind(name);
242: }
243:
244: public boolean exist(Object o) throws PException {
245: return pbinding.exist(o);
246: }
247:
248: public PName export(Object o) throws PException {
249: return pbinding.export(o);
250: }
251:
252: public PName export(Object o, Object o1) throws PException {
253: return pbinding.export(o, o1);
254: }
255:
256: public PClassMapping getPClassMapping() {
257: return pbinding.getPClassMapping();
258: }
259:
260: public PName getPName() {
261: return pbinding.getPName();
262: }
263:
264: public byte getStatus() {
265: return pbinding.getStatus();
266: }
267:
268: public void setPName(PName pName) {
269: pbinding.setPName(pName);
270: }
271:
272: public void setStatus(byte b) {
273: pbinding.setStatus(b);
274: }
275:
276: public void init(PClassMapping mapping) throws PException {
277: pbinding.init(mapping);
278: }
279:
280: public void read(Object o, PAccessor accessor) throws PException {
281: pbinding.read(o, accessor);
282: }
283:
284: public void read(Object o, PAccessor pAccessor, Object o1)
285: throws PException {
286: pbinding.read(o, pAccessor, o1);
287: }
288:
289: public void read(Object o, PAccessor pAccessor, Object o1,
290: boolean forUpdate) throws PException {
291: pbinding.read(o, pAccessor, o1, forUpdate);
292: }
293:
294: public void unbind() throws PException {
295: pbinding.unbind();
296: }
297:
298: public void unexport(Object o) throws PException {
299: pbinding.unexport(o);
300: }
301:
302: public void write(Object o, PAccessor accessor) throws PException {
303: if (logger != null)
304: logger.log(BasicLevel.DEBUG, "Writing the gen class: "
305: + linkedField);
306: pbinding.write(o, accessor);
307: boolean retainDeltaForMerge = ((HomeItf) pbinding
308: .getPClassMapping()).isFieldLockingLevel();
309: GenClassAccessor gca = (GenClassAccessor) accessor;
310: if (retainDeltaForMerge && gca.deltaForMerge == null) {
311: gca.deltaForMerge = new ArrayList();
312: }
313: for (Iterator i = gca.elements.iterator(); i.hasNext();) {
314: GenClassElement gce = (GenClassElement) i.next();
315: if (retainDeltaForMerge
316: && gce.getElemStatus() != PIndexedElem.ELEM_MODIFIED) {
317: gce.retainStatusForMerge();
318: gca.deltaForMerge.add(gce);
319: }
320: if (gce.getElemStatus() != PIndexedElem.ELEM_DELETED) {
321: gce.setStatus(PIndexedElem.ELEM_UNMODIFIED);
322: } else {
323: // remove the element
324: i.remove();
325: }
326: }
327: }
328:
329: // IMPLEMENTATION OF THE SpeedoGenClassPO INTERFACE //
330: //-----------------------------------------------------//
331:
332: /**
333: * Assignes the PType of the generic class.
334: * @param _ptype of the generic class
335: */
336: public void speedoSetPType(PType _ptype) {
337: this .ptype = _ptype;
338: }
339:
340: /**
341: * @return the PType of the generic class.
342: */
343: public PType speedoGetPType() {
344: return ptype;
345: }
346:
347: /**
348: * assignes the PBinding to use to load/store the generic class
349: * Call this method with null value means that the generic is no more
350: * persistent.
351: * @param pb is the PBinding.
352: */
353: public void speedoSetPBinding(PBinding pb) {
354: pbinding = (PBindingCtrl) pb;
355: }
356:
357: /**
358: * @return the pbinding associated to the generic class. The value is if the
359: * generic class is not persistent.
360: */
361: public PBinding speedoGetPBinding() {
362: return pbinding;
363: }
364:
365: /**
366: * @return a string which represents the fully path of the persistent field
367: * of the class with wich the generic class is persistent.
368: * If the linked fiekf is the 'f1' provided by the class 'com.foo.Bar'
369: * then the returned string will be 'com.foo.Bar/f1'
370: */
371: public String speedoGetGenClassId() {
372: return linkedField;
373: }
374:
375: /**
376: * Assignes the linked field name for this generic class.
377: * @param lf is tring which represents the fully path of the persistent
378: * field of the class with wich the generic class is persistent.
379: * If the linked fiekf is the 'f1' provided by the class 'com.foo.Bar'
380: * then the expected string is 'com.foo.Bar/f1'
381: */
382: public void speedoSetLinkedField(String lf) {
383: linkedField = lf;
384: }
385:
386: /**
387: * Assignes the new value of the generic class (Collection, Map or Array
388: * or ...).
389: */
390: public void setElements(Object o) {
391: ((GenClassAccessor) speedoGetHome().writeIntention(this , null))
392: .setElements(o);
393: }
394:
395: // IMPLEMENTATION OF THE PersistentObjectItf INTERFACE //
396: //---------------------------------------------//
397:
398: public boolean speedoIsPersistent() {
399: StateItf sa = speedoGetState();
400: return sa == null
401: || LifeCycle.isPersistent(sa.speedoGetStatus());
402: }
403:
404: public void speedoCopyState(StateItf src, StateItf dest) {
405: ((GenClassAccessor) dest).loadFieldsFromAccessor(src);
406: }
407:
408: public Object speedoGetPNameHints() {
409: return pnameHints;
410: }
411:
412: public boolean speedoIsActive() {
413: return speedoIsActive;
414: }
415:
416: public void speedoIsActive(boolean newvalue) {
417: speedoIsActive = newvalue;
418: }
419:
420: public StateItf speedoGetState() {
421: if (!speedoIsActive) {
422: return speedoGetReferenceState();
423: }
424: return speedoGetHome().getState(this );
425: }
426:
427: public Collection getSpeedoAccessors() {
428: return null;
429: }
430:
431: public void removeSpeedoAccessor(StateItf sa) {
432: }
433:
434: public void speedoSetEncodedPName(Object _encodedPName) {
435: this .encodedPName = _encodedPName;
436: }
437:
438: public Object speedoGetEncodedPName() {
439: return encodedPName;
440: }
441:
442: public HomeItf speedoGetHome() {
443: return (HomeItf) getPClassMapping();
444: }
445:
446: public POManagerItf speedoGetPOManager() {
447: return (speedoIsActive ? speedoGetHome().getPOManagerFactory()
448: .lookup() : null);
449: }
450:
451: // IMPLEMENTATION OF THE CacheEntry INTERFACE //
452: //-------------------------------------------//
453:
454: public Object getCeObject() {
455: return this ;
456: }
457:
458: public Object getCeIdentifier() {
459: return getPName();
460: }
461:
462: // IMPLEMENTATION OF THE FixableCacheEntry INTERFACE //
463: //---------------------------------------------------//
464:
465: public void fixCe() {
466: fix++;
467: }
468:
469: public void unfixCe() throws UnFixProtocolException {
470: fix--;
471: }
472:
473: public int getCeFixCount() {
474: return fix;
475: }
476:
477: // IMPLEMENTATION OF THE ReplaceableCacheEntry INTERFACE //
478: //-------------------------------------------------------//
479:
480: public long getCeAge() {
481: return age;
482: }
483:
484: public void setCeAge(long l) {
485: age = l;
486: }
487:
488: // ------------------------------------------------------------------------
489: // IMPLEMENTATION OF THE Loggable INTERFACE
490: // ------------------------------------------------------------------------
491:
492: public void setLogger(Logger _logger) {
493: logger = _logger;
494: }
495:
496: public void setLoggerFactory(LoggerFactory loggerfactory) {
497: logger = loggerfactory.getLogger(this .getClass().getName());
498: }
499:
500: public Logger getLogger() {
501: return logger;
502: }
503:
504: public LoggerFactory getLoggerFactory() {
505: return null;
506: }
507: }
|