package to.etc.domui.hibernate.types;

import java.util.*;

import org.hibernate.*;
import org.hibernate.collection.*;
import org.hibernate.engine.*;
import org.hibernate.persister.collection.*;
import org.hibernate.usertype.*;

import to.etc.domui.databinding.observables.*;

/**
 * A type for List<T> type properties which makes the property a ObservableList.
 *
 * @author <a href="mailto:jal@etc.to">Frits Jalvingh</a>
 * Created on Jan 11, 2014
 */
public class ObservableListType implements UserCollectionType {
	@Override
	public Object instantiate(int anticipatedSize) {
		return new ObservableList<Object>();
	}

	@Override
	public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister) throws HibernateException {
		return new PersistentObservableList(session);
	}

	@Override
	public PersistentCollection wrap(SessionImplementor session, Object collection) {
		return new PersistentObservableList(session, (List< ? >) collection);
	}

	@Override
	public Iterator getElementsIterator(Object collection) {
		if(null == collection)
			return null;
		ObservableList<Object> ol = (ObservableList<Object>) collection;
		return ol.iterator();
	}

	@Override
	public boolean contains(Object collection, Object entity) {
		if(null == collection)
			return false;
		ObservableList<Object> ol = (ObservableList<Object>) collection;
		return ol.contains(entity);
	}

	@Override
	public Object indexOf(Object collection, Object entity) {
		if(null == collection)
			return null;
		ObservableList<Object> ol = (ObservableList<Object>) collection;
		return Integer.valueOf(ol.indexOf(entity));
	}

	@Override
	public Object replaceElements(Object original, Object target, CollectionPersister persister, Object owner, Map copyCache, SessionImplementor session) throws HibernateException {
		ObservableList<Object> src = (ObservableList<Object>) original;
		ObservableList<Object> dst = (ObservableList<Object>) target;

		//-- Update the lists with as little disturbance as necessary.
		int nch = src.size();
		dst.retainAll(src);								// Remove from b all that is not in a
		nch = nch - dst.size();							// #elements removed
		int di = dst.size() - 1;
		int si = src.size() - 1;
		while(si >= 0) {
			Object sv = src.get(si);
			Object dv = dst.get(di);
			if(sv.equals(dv)) {
				di--;
				si--;
			} else {
				//-- Must be an insert.
				dst.add(di + 1, sv);
				si--;
				nch++;
			}
		}
		if(nch > 0)
			System.out.println("DEBUG OBSERVABLE: changed " + nch + " list entries");
		return dst;
	}
}

@@ -226,56 +226,8 @@
 *;%0A%0A
-import to.etc.domui.databinding.observables.*;%0A%0A
 /**%0A
@@ -537,16 +537,26 @@
 urn new 
+Persistent
 Observab
@@ -1042,32 +1042,42 @@
 %09return null;%0A%09%09
+Persistent
 ObservableList%3CO
@@ -1081,32 +1081,42 @@
 t%3CObject%3E ol = (
+Persistent
 ObservableList%3CO
@@ -1275,24 +1275,34 @@
 rn false;%0A%09%09
+Persistent
 ObservableLi
@@ -1310,32 +1310,42 @@
 t%3CObject%3E ol = (
+Persistent
 ObservableList%3CO
@@ -1507,24 +1507,34 @@
 urn null;%0A%09%09
+Persistent
 ObservableLi
@@ -1546,24 +1546,34 @@
 ject%3E ol = (
+Persistent
 ObservableLi
@@ -1838,16 +1838,26 @@
 ion %7B%0A%09%09
+Persistent
 Observab
@@ -1874,24 +1874,34 @@
 ect%3E src = (
+Persistent
 ObservableLi
@@ -1924,16 +1924,26 @@
 inal;%0A%09%09
+Persistent
 Observab
@@ -1964,16 +1964,26 @@
  dst = (
+Persistent
 Observab

Fix bad mapping in Observable hibernate adapter