001    /*
002     * Copyright (c) 2005, 2007 IBM Corporation and others.
003     * All rights reserved.   This program and the accompanying materials
004     * are made available under the terms of the Eclipse Public License v1.0
005     * which accompanies this distribution, and is available at
006     * http://www.eclipse.org/legal/epl-v10.html
007     *
008     * Contributors:
009     *   IBM - initial API and implementation
010     *
011     * $Id: DerivedSubsetEObjectEList.java,v 1.10 2007/05/24 02:46:26 khussey Exp $
012     */
013    package org.eclipse.uml2.common.util;
014    
015    import java.util.ConcurrentModificationException;
016    import java.util.List;
017    import java.util.ListIterator;
018    
019    import org.eclipse.emf.ecore.EStructuralFeature;
020    import org.eclipse.emf.ecore.InternalEObject;
021    import org.eclipse.emf.ecore.util.FeatureMapUtil;
022    import org.eclipse.emf.ecore.util.InternalEList;
023    
024    /**
025     * A modifiable derived list whose values are obtained from a single multivalued
026     * source feature. This list is ideal for implementing derived subset features.
027     * 
028     * @since 1.2
029     */
030    public class DerivedSubsetEObjectEList<E>
031                    extends DerivedEObjectEList<E> {
032    
033            protected class DerivedSubsetListIterator
034                            extends DerivedListIterator {
035    
036                    protected int expectedModCount = modCount;
037    
038                    @Override
039                    public void remove() {
040                            checkModCount();
041    
042                            if (valuesIterator == null) {
043                                    throw new IllegalStateException();
044                            }
045    
046                            switch (prepared) {
047                                    case 3 :
048                                    case 1 :
049                                            preparePrevious();
050                                            break;
051                                    case -1 :
052                                    case -3 :
053                                            prepareNext();
054                                            break;
055                            }
056    
057                            prepared = 0;
058    
059                            valuesIterator.remove();
060    
061                            modCount++;
062                            expectedModCount++;
063                    }
064    
065                    @Override
066                    public void set(Object element) {
067                            checkModCount();
068    
069                            if (valuesIterator == null) {
070                                    throw new IllegalStateException();
071                            }
072    
073                            switch (prepared) {
074                                    case 3 :
075                                    case 1 :
076                                            preparePrevious();
077                                            break;
078                                    case -1 :
079                                    case -3 :
080                                            prepareNext();
081                                            break;
082                            }
083    
084                            prepared = 0;
085    
086                            valuesIterator.set(element);
087    
088                            modCount++;
089                            expectedModCount++;
090                    }
091    
092                    @Override
093                    public void add(Object element) {
094                            checkModCount();
095    
096                            if (valuesIterator == null) {
097                                    @SuppressWarnings("unchecked")
098                                    List<Object> valuesList = resolve()
099                                            ? (List<Object>) owner.eGet(sourceFeatureIDs[featureIndex],
100                                                    resolve(), true)
101                                            : ((InternalEList<Object>) owner.eGet(
102                                                    sourceFeatureIDs[featureIndex], resolve(), true))
103                                                    .basicList();
104    
105                                    valuesList.listIterator(valuesList.size()).add(element);
106                            } else {
107    
108                                    switch (prepared) {
109                                            case 3 :
110                                                    preparePrevious();
111                                                    break;
112                                            case -3 :
113                                                    prepareNext();
114                                                    break;
115                                    }
116    
117                                    valuesIterator.add(element);
118                            }
119    
120                            prepared = 0;
121    
122                            modCount++;
123                            expectedModCount++;
124    
125                            index++;
126                    }
127    
128                    protected void checkModCount() {
129    
130                            if (modCount != expectedModCount) {
131                                    throw new ConcurrentModificationException();
132                            }
133                    }
134            }
135    
136            protected class ResolvingDerivedSubsetListIterator
137                            extends DerivedSubsetListIterator {
138    
139                    @Override
140                    protected boolean resolve() {
141                            return true;
142                    }
143    
144            }
145    
146            protected class EmptyDerivedSubsetListIterator
147                            extends EmptyDerivedListIterator {
148    
149                    @Override
150                    public void remove() {
151                            throw new IllegalStateException();
152                    }
153    
154                    @Override
155                    public void set(Object element) {
156                            throw new IllegalStateException();
157                    }
158    
159                    @Override
160                    public void add(Object element) {
161                            throw new IllegalStateException();
162                    }
163    
164            }
165    
166            public DerivedSubsetEObjectEList(Class<?> dataClass, InternalEObject owner,
167                            int featureID, int[] sourceFeatureIDs) {
168                    super(dataClass, owner, featureID, sourceFeatureIDs);
169    
170                    EStructuralFeature feature = sourceFeatureIDs.length == 1
171                            ? getEStructuralFeature(sourceFeatureIDs[0])
172                            : null;
173    
174                    if (feature == null || !feature.isMany()
175                            || FeatureMapUtil.isFeatureMap(feature)) {
176    
177                            throw new IllegalArgumentException(String.valueOf(sourceFeatureIDs));
178                    }
179            }
180    
181            public DerivedSubsetEObjectEList(Class<?> dataClass, InternalEObject owner,
182                            int featureID, int sourceFeatureID) {
183                    this(dataClass, owner, featureID, new int[]{sourceFeatureID});
184            }
185    
186            @Override
187            public List<E> basicList() {
188    
189                    return new DerivedSubsetEObjectEList<E>(dataClass, owner, featureID,
190                            sourceFeatureIDs) {
191    
192                            @Override
193                            public ListIterator<E> listIterator(int index) {
194                                    return basicListIterator(index);
195                            }
196                    };
197            }
198    
199            @Override
200            protected ListIterator<E> newListIterator() {
201                    return new DerivedSubsetListIterator();
202            }
203    
204            @Override
205            protected ListIterator<E> newResolvingListIterator() {
206                    return new ResolvingDerivedSubsetListIterator();
207            }
208    
209            @Override
210            protected ListIterator<E> newEmptyListIterator() {
211                    return new EmptyDerivedSubsetListIterator();
212            }
213    
214            @Override
215            protected boolean isNotificationRequired() {
216                    return owner.eNotificationRequired();
217            }
218    
219    }