/**
* 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.collection;
import org.objectweb.jorm.api.PException;
import org.objectweb.jorm.api.PExceptionIO;
import org.objectweb.jorm.api.PIndexedElem;
import org.objectweb.speedo.api.Debug;
import org.objectweb.speedo.genclass.AbstractGenClassHome;
import org.objectweb.speedo.genclass.GenClassAccessor;
import org.objectweb.speedo.genclass.GenClassElement;
import org.objectweb.speedo.genclass.api.SpeedoGenClassPO;
import org.objectweb.speedo.mim.api.PersistentObjectItf;
import org.objectweb.speedo.mim.api.StateItf;
import org.objectweb.speedo.pm.api.POManagerItf;
import org.objectweb.util.monolog.api.BasicLevel;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
/**
*
* @author S.Chassande-Barrioz
*/
public class ListAccessor extends CollectionAccessor implements List{
/**
* Indicates the number of elements existing on the data support. All
* element added after this index must be marked as CREATED.
*/
protected int loadedSize = -1;
public ListAccessor(SpeedoGenClassPO thepo) {
super(thepo);
}
public void workingSetClosed() {
super.workingSetClosed();
//Update the loaded size after the data support flushing
loadedSize = elements.size();
}
public String toString() {
return "ListAccessor: id=" + gcpo.speedoGetGenClassId();
}
public PIndexedElem createPIndexedElem(GenClassAccessor gca) {
return new ListElem(gca);
}
public void paSetNbElem(int nbelem) {
super.paSetNbElem(nbelem);
loadedSize = 0;
}
public void paAdd(PIndexedElem elem, Object conn) throws PExceptionIO {
super.paAdd(elem, conn);
loadedSize++;
//order the elements list
try {
//get the real index of the last element added
int index = elem.pieGetIntIndexField(CollectionElem.INDEX_FIELD_NAME);
boolean sorted = false;
//bubble sort
for (int i = elements.size()-1; i > 0 && !sorted; i--) {
int currentIndex = ((PIndexedElem) elements.get(i-1)).pieGetIntIndexField(CollectionElem.INDEX_FIELD_NAME);
if (index < currentIndex) {
//swap between i and i-1
elements.set(i, elements.set(i-1, elements.get(i)));
} else {
sorted = true;
}
}
} catch (PException e) {
throw new PExceptionIO(e, "Unable to get the index of PIndexedElem at the ListAccessor level.");
}
}
public boolean add(Object o) {
if(super.add(o)) {
int idx = elements.size() - 1;
ListElem le = (ListElem) elements.get(idx);
le.setIndex(new Integer(idx));
return true;
} else {
return false;
}
}
public boolean addAll(int i, Collection c) {
if (c == null) {
return false;
}
int size = elements.size();
if (size > i) {
Iterator it = c.iterator();
int j = i;
while(it.hasNext()) {
add(j, it.next());
j++;
}
return true;
} else {
throw new IndexOutOfBoundsException("Try to insert at the position "
+ i + " whereas there is only " + size + " elements.");
}
}
public Object get(int i) {
ListElem le = (ListElem) elements.get(i);
if (le.getElemStatus() == PIndexedElem.ELEM_DELETED) {
throw new java.lang.ArrayIndexOutOfBoundsException(i);
}
return le.getElement();
}
public Object set(int i, Object o) {
ListElem le = (ListElem) elements.get(i);
if (le.getElemStatus() == PIndexedElem.ELEM_DELETED) {
throw new java.lang.ArrayIndexOutOfBoundsException(i);
}
Object res = le.getElement();
le.setStatus(PIndexedElem.ELEM_MODIFIED);
le.setElement(o);
return res;
}
public void add(int i, Object o) {
int size = elements.size();
if (size > i) {
Object toAdd = o;
Object tmp = o;
int j = i;
ListElem le;
//insert the new and shift others
while(j < size) {
le =(ListElem) elements.get(j);
tmp = le.element;
le.element = toAdd;
le.setStatus((j < loadedSize
? PIndexedElem.ELEM_MODIFIED
: PIndexedElem.ELEM_CREATED));
toAdd = tmp;
j++;
}
//create a new entry for the shifted element (or the added if i = size)
le = (ListElem) createPIndexedElem();
le.setStatus((j < loadedSize
? PIndexedElem.ELEM_MODIFIED
: PIndexedElem.ELEM_CREATED));
le.setIndex(new Integer(size));
elements.add(le);
} else {
throw new IndexOutOfBoundsException("Try to insert at the position "
+ i + " whereas there is only " + size + " elements.");
}
}
public Object remove(int i) {
return null;
}
public int indexOf(Object o) {
return 0;
}
public int lastIndexOf(Object o) {
return 0;
}
public ListIterator listIterator() {
return null;
}
public ListIterator listIterator(int i) {
return null;
}
public List subList(int i, int i1) {
return null;
}
public void attachCopy(POManagerItf pm, Map map, StateItf fieldsClone) {
CollectionAccessor ca = (CollectionAccessor) fieldsClone;
//get an iterator on the PIndexed elements of the collection
Iterator it = ca.collection.iterator();
int index = 0;
while(it.hasNext()){
Object elem = it.next();
//if it is a persistent object
if (elem instanceof PersistentObjectItf) {
//get the detached speedo po
PersistentObjectItf spDetached = (PersistentObjectItf) elem;
PersistentObjectItf sp = (PersistentObjectItf) map.get(spDetached);
if(sp == null){
map.put(spDetached, sp);
sp = (PersistentObjectItf) pm.speedoAttachCopy(spDetached, map);
}
//put the element of the collection attribute in the elements attribute (the opposite of the jdoDetachCopy method)
speedoAddOnAttach(sp, index++);
} else {
//just add the java object in the collection
speedoAddOnAttach(elem, index++);
}
}
}
protected GenClassElement speedoAddOnAttach(Object o, int index) {
if (o instanceof PersistentObjectItf && !((PersistentObjectItf) o).speedoIsActive()) {
((AbstractGenClassHome) getSpeedoPO().speedoGetHome())
.makePersistent(null, (PersistentObjectItf) o,
(SpeedoGenClassPO) getSpeedoPO(), null);
}
synchronized (this) {
if (contains(o, index)) {
return null;
}
// Put it in the "elements" list
GenClassElement element = (GenClassElement) createPIndexedElem();
element.setElement(o);
return (elements.add(element) ? element : null);
}
}
public boolean contains(Object o, int index) {
tmpelem.setElement(o);
tmpelem.setIndex(new Integer(index));
Iterator it = elements.iterator();
while (it.hasNext()) {
PIndexedElem e = (PIndexedElem) it.next();
if (e.equals(tmpelem) && e.getElemStatus() != PIndexedElem.ELEM_DELETED) {
if (Debug.ON && getLogger() != null) {
logger.log(BasicLevel.DEBUG, "contains(): yes");
}
return true;
}
}
if (Debug.ON && getLogger() != null) {
logger.log(BasicLevel.DEBUG, "contains(): no");
}
return false;
}
}