/******************************************************************************* * Copyright (c) 2009, 2010 Fraunhofer IWU 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: * Fraunhofer IWU - initial API and implementation *******************************************************************************/ package net.enilink.komma.em.internal.behaviours; import java.util.AbstractList; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.ListIterator; import java.util.RandomAccess; import java.util.Spliterator; import net.enilink.commons.iterator.IExtendedIterator; import net.enilink.commons.iterator.WrappedIterator; import net.enilink.commons.util.IPartialOrderProvider; import net.enilink.commons.util.LinearExtension; import net.enilink.composition.properties.komma.KommaPropertySet; import net.enilink.composition.properties.traits.Refreshable; import net.enilink.komma.core.IReference; import net.enilink.komma.em.concepts.IResource; import net.enilink.vocab.komma.KOMMA; public class OrderedPropertySet<E> extends KommaPropertySet<E> implements List<E>, RandomAccess, Cloneable, Refreshable { private List<E> internalList = new AbstractList<E>() { @Override public void add(int index, E element) { ensureCache().add(index, element); E succElement = null; if (index < getCache().size() - 1) { succElement = getCache().get(index + 1); } E predElement = null; if (index > 0) { predElement = getCache().get(index - 1); } if (succElement != null) { getPrecedes(element).add(succElement); } if (predElement != null) { if (succElement != null) { getPrecedes(predElement).remove(succElement); } getPrecedes(predElement).add(element); } OrderedPropertySet.super.add(element); } @Override public E get(int index) { return ensureCache().get(index); } @Override public int indexOf(Object o) { return ensureCache().indexOf(o); } @Override public int lastIndexOf(Object o) { return ensureCache().lastIndexOf(o); } @Override public E remove(int index) { E removed = ensureCache().remove(index); if (removed != null) { E succElement = null; if (index < getCache().size()) { succElement = getCache().get(index); } E predElement = null; if (index > 0) { predElement = getCache().get(index - 1); } if (succElement != null) { getPrecedes(removed).remove(succElement); } if (predElement != null) { if (succElement != null) { getPrecedes(predElement).add(succElement); } getPrecedes(predElement).remove(removed); } OrderedPropertySet.super.remove(removed); } return removed; } @Override public E set(int index, E element) { E oldElement = ensureCache().set(index, element); if (index < getCache().size() - 1) { E succElement = getCache().get(index + 1); if (succElement != null) { if (oldElement != null) { getPrecedes(oldElement).remove(succElement); } getPrecedes(element).add(succElement); } } if (index > 0) { E predElement = getCache().get(index - 1); if (predElement != null) { if (oldElement != null) { getPrecedes(predElement).remove(oldElement); } getPrecedes(predElement).add(element); } } OrderedPropertySet.super.add(element); return oldElement; } @Override public int size() { return OrderedPropertySet.super.size(); } }; public OrderedPropertySet(IReference bean, IReference property) { super(bean, property); } @Override public boolean add(E o) { add(ensureCache().size(), o); return true; } @Override public void add(int index, E element) { internalList.add(index, element); } @Override public boolean addAll(int index, Collection<? extends E> c) { return internalList.addAll(index, c); } protected IExtendedIterator<E> createElementsIterator() { class ElementsIterator extends WrappedIterator<E> { E current; int index = -1; List<E> list; protected ElementsIterator(List<E> list) { super(list.iterator()); } public E next() { index++; return current = base.next(); } public void remove() { base.remove(); if (current != null && index < list.size()) { Object succElement = list.get(index); if (succElement != null) { getPrecedes(current).remove(succElement); } } current = null; } } return new ElementsIterator(ensureCache()); } private final List<E> ensureCache() { List<E> list = getCache(); if (list == null) { final List<E> values = super.createElementsIterator().toList(); list = new LinearExtension<E>(new IPartialOrderProvider<E>() { @Override public Collection<E> getElements() { return values; } @Override public Collection<E> getSuccessors(E element) { return getPrecedes(element); } }).createLinearExtension(new ArrayList<E>()); setCache(list); } return list; } @Override public E get(int index) { return internalList.get(index); } @Override protected int getCacheLimit() { return Integer.MAX_VALUE; } @SuppressWarnings("unchecked") private Collection<E> getPrecedes(E element) { return (Collection<E>) ((IResource) element) .get(KOMMA.PROPERTY_PRECEDES); } @Override public int indexOf(Object o) { return internalList.indexOf(o); } @Override public int lastIndexOf(Object o) { return internalList.lastIndexOf(o); } @Override public ListIterator<E> listIterator() { return internalList.listIterator(); } @Override public ListIterator<E> listIterator(int index) { return internalList.listIterator(index); } public E remove(int index) { return internalList.remove(index); } @Override public boolean remove(Object o) { int index = ensureCache().indexOf(o); if (index >= 0) { remove(index); return true; } return false; } @Override public E set(int index, E element) { return internalList.set(index, element); } @Override public List<E> subList(int fromIndex, int toIndex) { return internalList.subList(fromIndex, toIndex); } @Override public Spliterator<E> spliterator() { return internalList.spliterator(); } }