| /* |
| * 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)); |
| } |
| } |
| |
| } |