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 }