001: /*
002: * Copyright (c) 1998 - 2005 Versant Corporation
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: * Versant Corporation - initial API and implementation
010: */
011: package com.versant.core.jdo.sco.detached;
012:
013: import com.versant.core.jdo.VersantStateManager;
014: import com.versant.core.common.VersantFieldMetaData;
015: import com.versant.core.jdo.sco.VersantSimpleSCO;
016:
017: import javax.jdo.spi.PersistenceCapable;
018: import java.io.Serializable;
019: import java.util.Collection;
020: import java.util.Iterator;
021: import java.util.LinkedList;
022: import java.util.ListIterator;
023:
024: import com.versant.core.common.BindingSupportImpl;
025:
026: /**
027: * Detached LinkedList SCO implementation.
028: */
029: public final class DetachSCOLinkedList extends LinkedList implements
030: Serializable, VersantSimpleSCO {
031:
032: private PersistenceCapable owner;
033: private int fieldNo;
034: private VersantStateManager stateManager;
035:
036: public DetachSCOLinkedList(PersistenceCapable owner,
037: VersantStateManager stateManager, VersantFieldMetaData fmd,
038: Object[] originalData) {
039: this .owner = owner;
040: this .fieldNo = fmd.getManagedFieldNo();
041: this .stateManager = stateManager;
042: int n = originalData == null ? 0 : originalData.length;
043: for (int i = 0; i < n; i++) {
044: Object o = originalData[i];
045: if (o == null)
046: throw createNPE();
047: super .add(o);
048: }
049: }
050:
051: public Object removeFirst() {
052: Object result = super .removeFirst();
053: makeDirty();
054: return result;
055: }
056:
057: public Object removeLast() {
058: Object result = super .removeLast();
059: makeDirty();
060: return result;
061: }
062:
063: private RuntimeException createNPE() {
064: return BindingSupportImpl.getInstance().nullElement(
065: "Null element not allowed.");
066: }
067:
068: public void addFirst(Object o) {
069: if (o == null)
070: throw createNPE();
071: super .addFirst(o);
072: makeDirty();
073: }
074:
075: public void addLast(Object o) {
076: if (o == null)
077: throw createNPE();
078: super .addLast(o);
079: makeDirty();
080: }
081:
082: public boolean addAll(int index, Collection c) {
083: if (super .addAll(index, c)) {
084: makeDirty();
085: return true;
086: }
087: return false;
088: }
089:
090: protected void removeRange(int fromIndex, int toIndex) {
091: super .removeRange(fromIndex, toIndex);
092: makeDirty();
093: }
094:
095: public boolean removeAll(Collection c) {
096: boolean modified = false;
097: // get unwrapped iterator from super so we can do remove
098: Iterator e = super .listIterator(0);
099: while (e.hasNext()) {
100: Object o = e.next();
101: if (c.contains(o)) {
102: e.remove();
103: modified = true;
104: }
105: }
106: if (modified)
107: makeDirty();
108: return modified;
109:
110: }
111:
112: public boolean retainAll(Collection c) {
113: boolean modified = false;
114: // get an unwrapped Iterator so we can call remove
115: Iterator e = super .listIterator(0);
116: while (e.hasNext()) {
117: Object o = e.next();
118: if (!c.contains(o)) {
119: e.remove();
120: modified = true;
121: }
122: }
123: if (modified)
124: makeDirty();
125: return modified;
126: }
127:
128: public Object set(int index, Object element) {
129: if (element == null)
130: throw createNPE();
131: Object result = super .set(index, element);
132: makeDirty();
133: return result;
134: }
135:
136: public ListIterator listIterator(int index) {
137: return new ListIteratorImp(super .listIterator(index));
138: }
139:
140: /**
141: * The set call in our superclass ListIterator is the only modification
142: * operation that does not delegate to the list. This is disallowed for
143: * managed relationships as there is no way for us to get at the current
144: * element.
145: */
146: private class ListIteratorImp implements ListIterator {
147:
148: private ListIterator i;
149:
150: public void set(Object o) {
151: i.set(o);
152: DetachSCOLinkedList.this .makeDirty();
153: }
154:
155: public void remove() {
156: i.remove();
157: DetachSCOLinkedList.this .makeDirty();
158: }
159:
160: public void add(Object o) {
161: i.add(o);
162: DetachSCOLinkedList.this .makeDirty();
163: }
164:
165: public ListIteratorImp(ListIterator i) {
166: this .i = i;
167: }
168:
169: public boolean hasNext() {
170: return i.hasNext();
171: }
172:
173: public Object next() {
174: return i.next();
175: }
176:
177: public boolean hasPrevious() {
178: return i.hasPrevious();
179: }
180:
181: public Object previous() {
182: return i.previous();
183: }
184:
185: public int nextIndex() {
186: return i.nextIndex();
187: }
188:
189: public int previousIndex() {
190: return i.previousIndex();
191: }
192: }
193:
194: public boolean add(Object o) {
195: if (o == null)
196: throw createNPE();
197: super .add(o);
198: makeDirty();
199: return true;
200: }
201:
202: public void add(int index, Object element) {
203: if (element == null)
204: throw createNPE();
205: super .add(index, element);
206: makeDirty();
207: }
208:
209: public Object remove(int index) {
210: Object result = super .remove(index);
211: if (result != null) {
212: makeDirty();
213: }
214: return result;
215: }
216:
217: public boolean remove(Object o) {
218: if (super .remove(o)) {
219: makeDirty();
220: return true;
221: }
222: return false;
223: }
224:
225: public void clear() {
226: super .clear();
227: makeDirty();
228: }
229:
230: private void makeDirty() {
231: if (stateManager != null && owner != null) {
232: stateManager.makeDirty(owner, fieldNo);
233: }
234: }
235:
236: public void makeTransient() {
237: owner = null;
238: stateManager = null;
239: }
240: }
|