/**
*
*/
package siena.core;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import siena.ClassInfo;
import siena.PersistenceManager;
import siena.Query;
import siena.Util;
/**
* @author mandubian <pascal.voitot@mandubian.org>
*
*/
public class BaseMany<T> implements Many4PM<T>{
transient private static final long serialVersionUID = -1417704952199421178L;
transient protected PersistenceManager pm;
transient protected Class<T> clazz;
protected Relation relation;
transient protected ProxyList<T> list;
transient protected Query<T> query;
public BaseMany(PersistenceManager pm, Class<T> clazz){
this.pm = pm;
this.clazz = clazz;
list = new ProxyList<T>(this);
this.query = pm.createQuery(clazz);
}
public BaseMany(PersistenceManager pm, Class<T> clazz, RelationMode mode, Object obj, String fieldName) {
this.pm = pm;
this.clazz = clazz;
list = new ProxyList<T>(this);
switch(mode){
case AGGREGATION:
this.relation = new Relation(mode, obj, fieldName);
this.query = pm.createQuery(clazz).aggregated(obj, fieldName);
break;
case RELATION:
this.query = pm.createQuery(clazz).filter(fieldName, obj);
break;
}
query = pm.createQuery(clazz);
}
public SyncList<T> asList() {
return list.sync();
}
public Query<T> asQuery() {
return query;
}
public Many4PM<T> setSync(boolean isSync) {
list.isSync = isSync;
return this;
}
public List<T> asList2Remove() {
return list.elements2Remove;
}
public List<T> asList2Add() {
return list.elements2Add;
}
public Many4PM<T> aggregationMode(Object aggregator, Field field) {
if(relation == null){
this.relation = new Relation(RelationMode.AGGREGATION, aggregator, field);
}
else {
this.relation.mode = RelationMode.AGGREGATION;
this.relation.target = aggregator;
this.relation.discriminator = field;
}
this.query.resetData().aggregated(aggregator, ClassInfo.getSimplestColumnName(field));
return this;
}
public Many4PM<T> relationMode(Object owner, Field field) {
this.query.resetData().filter(ClassInfo.getSimplestColumnName(field), owner);
return this;
}
protected class ProxyList<V> implements SyncList<V>{
transient protected Many<V> many;
transient protected List<V> elements;
transient protected List<V> elements2Remove;
transient protected List<V> elements2Add;
// isSync set to true by default because when you begin you generally want to add new elements
transient protected boolean isSync = true;
public ProxyList(BaseMany<V> many){
this.many = many;
this.elements = new ArrayList<V>();
this.elements2Remove = new ArrayList<V>();
this.elements2Add = new ArrayList<V>();
}
public boolean add(V e) {
if(relation != null && relation.mode == RelationMode.AGGREGATION){
Util.setField(e, ClassInfo.getClassInfo(clazz).aggregator, relation);
}
elements2Add.add(e);
return elements.add(e);
}
public void add(int index, V element) {
if(relation != null && relation.mode == RelationMode.AGGREGATION){
Util.setField(element, ClassInfo.getClassInfo(clazz).aggregator, relation);
}
elements2Add.add(element);
elements.add(index, element);
}
public boolean addAll(Collection<? extends V> c) {
if(relation != null && relation.mode == RelationMode.AGGREGATION){
for(V o:c){
Util.setField(o, ClassInfo.getClassInfo(clazz).aggregator, relation);
}
}
elements2Add.addAll(c);
return elements.addAll(c);
}
public boolean addAll(int index, Collection<? extends V> c) {
if(relation != null && relation.mode == RelationMode.AGGREGATION){
for(V o:c){
Util.setField(o, ClassInfo.getClassInfo(clazz).aggregator, relation);
}
}
elements2Add.addAll(c);
return elements.addAll(index, c);
}
public <F extends V> boolean addAll(F... c) {
if(relation != null && relation.mode == RelationMode.AGGREGATION){
for(V o:c){
Util.setField(o, ClassInfo.getClassInfo(clazz).aggregator, relation);
}
}
List<F> l = Arrays.asList(c);
elements2Add.addAll(l);
return elements.addAll(l);
}
public <F extends V> boolean addAll(int index, F... c) {
if(relation != null && relation.mode == RelationMode.AGGREGATION){
for(V o:c){
Util.setField(o, ClassInfo.getClassInfo(clazz).aggregator, relation);
}
}
List<F> l = Arrays.asList(c);
elements2Add.addAll(l);
return elements.addAll(index, l);
}
public void clear() {
elements2Add.clear();
elements2Remove.addAll(elements);
elements.clear();
}
public boolean contains(Object o) {
return elements.contains(o);
}
public boolean containsAll(Collection<?> c) {
return elements.containsAll(c);
}
public V get(int index) {
return elements.get(index);
}
public int indexOf(Object o) {
return elements.indexOf(o);
}
public boolean isEmpty() {
return elements.isEmpty();
}
public Iterator<V> iterator() {
return elements.iterator();
}
public int lastIndexOf(Object o) {
return elements.lastIndexOf(o);
}
public ListIterator<V> listIterator() {
return elements.listIterator();
}
public ListIterator<V> listIterator(int index) {
return elements.listIterator(index);
}
@SuppressWarnings("unchecked")
public boolean remove(Object o) {
elements2Remove.add((V)o);
return elements.remove(o);
}
public V remove(int index) {
V o = elements.remove(index);
if(relation != null && relation.mode == RelationMode.AGGREGATION){
Util.setField(o, ClassInfo.getClassInfo(clazz).aggregator, null);
}
elements2Remove.add(o);
return o;
}
@SuppressWarnings("unchecked")
public boolean removeAll(Collection<?> c) {
elements2Remove.addAll((Collection<V>)c);
if(relation != null && relation.mode == RelationMode.AGGREGATION){
for(Object o:c){
Util.setField(o, ClassInfo.getClassInfo(clazz).aggregator, null);
}
}
return elements.removeAll(c);
}
public boolean retainAll(Collection<?> c) {
return elements.retainAll(c);
}
public V set(int index, V element) {
Util.setField(element, ClassInfo.getClassInfo(clazz).aggregator, null);
return elements.set(index, element);
}
public int size() {
return elements.size();
}
public List<V> subList(int fromIndex, int toIndex) {
return elements.subList(fromIndex, toIndex);
}
public Object[] toArray() {
return elements.toArray();
}
public <Z> Z[] toArray(Z[] a) {
return elements.toArray(a);
}
public SyncList<V> sync() {
if(!isSync){
return forceSync();
}
return this;
}
public SyncList<V> forceSync() {
elements = many.asQuery().fetch();
elements2Remove.clear();
elements2Add.clear();
isSync = true;
return this;
}
}
}