/* * Copyright (c) 2008-2013, 2015 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Martin Taal - initial api * Eike Stepper - maintenance */ package org.eclipse.emf.cdo.server.internal.hibernate.tuplizer; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDExternal; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.server.internal.hibernate.HibernateUtil; import org.eclipse.net4j.util.collection.MoveableList; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** * Wraps a moveable list so that hibernate always sees an object view while cdo always sees a cdoid view. The same for * EEnum: cdo wants to see an int (the ordinal), hibernate the real eenum value. This to support querying with EENum * parameters. * * @author Martin Taal */ public class HibernateMoveableListWrapper implements MoveableList<Object> { private List<Object> delegate; private EStructuralFeature eFeature; private boolean resolveCDOID; public HibernateMoveableListWrapper() { } public Object move(int targetIndex, int sourceIndex) { int size = size(); if (sourceIndex >= size) { throw new IndexOutOfBoundsException("sourceIndex=" + sourceIndex + ", size=" + size); //$NON-NLS-1$ //$NON-NLS-2$ } if (targetIndex >= size) { throw new IndexOutOfBoundsException("targetIndex=" + targetIndex + ", size=" + size); //$NON-NLS-1$ //$NON-NLS-2$ } Object object = get(sourceIndex); if (targetIndex == sourceIndex) { return object; } if (targetIndex < sourceIndex) { moveUp1(targetIndex, sourceIndex - targetIndex); } else { moveDown1(targetIndex, targetIndex - sourceIndex); } set(targetIndex, object); return object; } private void moveUp1(int index, int count) { for (int i = count; i > 0; i--) { set(index + i, get(index + i - 1)); } } private void moveDown1(int index, int count) { for (int i = count; i > 0; i--) { set(index - i, get(index - i + 1)); } } /** * @return the delegate */ public List<Object> getDelegate() { return delegate; } /** * @param delegate * the delegate to set */ public void setDelegate(List<Object> delegate) { this.delegate = delegate; } protected Object getObject(Object o) { if (o == null) { return null; } if (o instanceof CDOID && CDOIDUtil.isNull((CDOID)o)) { return null; } else if (o instanceof CDOIDExternal) { return o; } else if (resolveCDOID && o instanceof CDOID) { return HibernateUtil.getInstance().getCDORevision((CDOID)o); } return o; } protected List<Object> getObjects(List<?> ids) { List<Object> result = new ArrayList<Object>(); for (Object o : ids) { result.add(getObject(o)); } return result; } protected Object getValue(Object o) { if (o instanceof CDOIDExternal) { return o; } // can happen for primitive typed lists if (!(o instanceof CDORevision)) { return o; } return HibernateUtil.getInstance().getCDOID(o); } protected List<Object> getValues(Collection<?> c) { List<Object> newC = new ArrayList<Object>(); for (Object o : c) { newC.add(getValue(o)); } return newC; } public void add(int index, Object element) { getDelegate().add(index, getValue(element)); } public boolean add(Object o) { return getDelegate().add(getValue(o)); } public boolean addAll(Collection<? extends Object> c) { return getDelegate().addAll(getValues(c)); } public boolean addAll(int index, Collection<? extends Object> c) { return getDelegate().addAll(index, getValues(c)); } public void clear() { getDelegate().clear(); } public boolean contains(Object o) { return getDelegate().contains(getValue(o)); } public boolean containsAll(Collection<?> c) { return getDelegate().containsAll(getValues(c)); } public Object get(int index) { return getObject(getDelegate().get(index)); } public int indexOf(Object o) { return getDelegate().indexOf(getValue(o)); } public boolean isEmpty() { return getDelegate().isEmpty(); } public Iterator<Object> iterator() { return new CDOHibernateIterator(getDelegate().iterator(), resolveCDOID); } public int lastIndexOf(Object o) { return getDelegate().lastIndexOf(getValue(o)); } public ListIterator<Object> listIterator() { return new CDOHibernateListIterator(getDelegate().listIterator(), resolveCDOID); } public ListIterator<Object> listIterator(int index) { return new CDOHibernateListIterator(getDelegate().listIterator(index), resolveCDOID); } public Object remove(int index) { return getDelegate().remove(index); } public boolean remove(Object o) { return getDelegate().remove(getValue(o)); } public boolean removeAll(Collection<?> c) { return getDelegate().removeAll(getValues(c)); } public boolean retainAll(Collection<?> c) { return getDelegate().retainAll(getValues(c)); } public Object set(int index, Object element) { return getDelegate().set(index, getValue(element)); } public int size() { return getDelegate().size(); } public List<Object> subList(int fromIndex, int toIndex) { return getObjects(getDelegate().subList(fromIndex, toIndex)); } public Object[] toArray() { Object[] result = new Object[size()]; int i = 0; for (Object o : this) { result[i++] = o; } return result; } @SuppressWarnings("unchecked") public <T> T[] toArray(T[] a) { int i = 0; for (Object o : this) { a[i++] = (T)o; } return a; } EStructuralFeature getEFeature() { return eFeature; } void setEFeature(EStructuralFeature eFeature) { this.eFeature = eFeature; resolveCDOID = !HibernateUtil.getInstance().isCDOResourceContents(eFeature) && eFeature instanceof EReference; } private static final class CDOHibernateIterator implements Iterator<Object> { private final Iterator<?> delegate; private final boolean resolveCDOID; public CDOHibernateIterator(Iterator<?> delegate, boolean resolveCDOID) { this.delegate = delegate; this.resolveCDOID = resolveCDOID; } public boolean hasNext() { return delegate.hasNext(); } public Object next() { Object o = delegate.next(); if (o instanceof CDOIDExternal) { return o; } else if (resolveCDOID && o instanceof CDOID) { return HibernateUtil.getInstance().getCDORevision((CDOID)o); } return o; } public void remove() { delegate.remove(); } } private static final class CDOHibernateListIterator implements ListIterator<Object> { private final ListIterator<Object> delegate; private final boolean resolveCDOID; public CDOHibernateListIterator(ListIterator<Object> delegate, boolean resolveCDOID) { this.delegate = delegate; this.resolveCDOID = resolveCDOID; } public void add(Object o) { delegate.add(HibernateUtil.getInstance().getCDOID(o)); } public boolean hasNext() { return delegate.hasNext(); } public boolean hasPrevious() { return delegate.hasPrevious(); } public Object next() { Object o = delegate.next(); if (resolveCDOID && o instanceof CDOID) { return HibernateUtil.getInstance().getCDORevision((CDOID)delegate.next()); } return o; } public int nextIndex() { return delegate.nextIndex(); } public Object previous() { Object o = delegate.previous(); if (o instanceof CDOID) { return HibernateUtil.getInstance().getCDORevision((CDOID)delegate.next()); } return o; } public int previousIndex() { return delegate.previousIndex(); } public void remove() { delegate.remove(); } public void set(Object o) { delegate.set(HibernateUtil.getInstance().getCDOID(o)); } } }