/* * #! * Ontopia Engine * #- * Copyright (C) 2001 - 2013 The Ontopia Project * #- * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * !# */ package net.ontopia.persistence.proxy; import java.util.Collection; import java.util.Iterator; import java.util.NoSuchElementException; /** * INTERNAL: A set implementation that wraps an identity collection * and presents the underlying collection as if it had PersistentIF * instances inside. All identity lookup is done lazily, and no state * is stored by this instance except for the current TransactionIF and * the wrapped identities collection. */ public class IdentityCollectionWrapper<E> implements Collection<E> { protected final TransactionIF txn; protected final Collection<?> other; public IdentityCollectionWrapper(TransactionIF txn, Collection<?> identities) { this.txn = txn; this.other = identities; } // -- immutable collection public void clear() { throw new UnsupportedOperationException(); } public boolean add(E o) { throw new UnsupportedOperationException(); } public boolean addAll(Collection<? extends E> c) { throw new UnsupportedOperationException(); } public boolean remove(Object o) { throw new UnsupportedOperationException(); } public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); } public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); } // -- other public int size() { return other.size(); } public boolean isEmpty() { return other.isEmpty(); } public boolean contains(Object o) { return other.contains((o instanceof PersistentIF ? ((PersistentIF)o)._p_getIdentity() : o)); } public boolean containsAll(Collection<?> c) { Iterator<?> e = c.iterator(); while (e.hasNext()) { if(!contains(e.next())) return false; } return true; } public Object[] toArray() { Object[] result = new Object[size()]; Iterator it = iterator(); int i = 0; for (; it.hasNext(); i++) { result[i] = it.next(); } if (i+1 < result.length) { Object[] r = new Object[i+1]; System.arraycopy(result, 0, r, 0, i+1); return r; } else { return result; } } public <T> T[] toArray(T[] a) { int size = size(); if (a.length < size) a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size); int i = 0; Iterator<E> it = iterator(); for (; it.hasNext(); i++) { a[i] = (T) it.next(); } if (a.length > i+1) a[i+1] = null; return a; } // -- object public String toString() { StringBuilder buf = new StringBuilder(); buf.append("["); Iterator<E> i = iterator(); boolean hasNext = i.hasNext(); while (hasNext) { E o = i.next(); buf.append(o == this ? "(this Collection)" : String.valueOf(o)); hasNext = i.hasNext(); if (hasNext) buf.append(", "); } buf.append("]"); return buf.toString(); } // -- iterator public Iterator<E> iterator() { return new IdentityCollectionIterator<E>(other.iterator()); } class IdentityCollectionIterator<F> implements Iterator<F> { private Iterator<?> iter; private int has_next = -1; private F next; private IdentityCollectionIterator(Iterator<?> iter) { this.iter = iter; } public boolean hasNext() { while (has_next == -1) _next(); // updates has_next return has_next == 1; } public F next() { if (has_next == 0) { throw new NoSuchElementException(); } else if (has_next == 1) { has_next = -1; return next; } else { _next(); return next(); } } public void _next() { // get object from iterator Object o; try { o = iter.next(); } catch (NoSuchElementException e) { has_next = 0; return; } // resolve object if (o == null) { has_next = 1; next = null; } else if (o instanceof IdentityIF) { try { o = txn.getObject((IdentityIF)o, true); if (o == null) { _next(); } else { has_next = 1; next = (F) o; } } catch (Throwable t) { has_next = -1; next = null; } } else { has_next = 1; next = (F) o; } } public void remove() { throw new UnsupportedOperationException(); } } }