You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mb...@apache.org on 2005/05/22 20:01:48 UTC
svn commit: r171352 [6/11] - in /incubator/jdo/trunk/runtime20: ./ src/
src/conf/ src/java/ src/java/org/ src/java/org/apache/
src/java/org/apache/jdo/ src/java/org/apache/jdo/ejb/
src/java/org/apache/jdo/impl/ src/java/org/apache/jdo/impl/model/
src/java/org/apache/jdo/impl/model/java/
src/java/org/apache/jdo/impl/model/java/runtime/
src/java/org/apache/jdo/impl/model/jdo/
src/java/org/apache/jdo/impl/model/jdo/xml/
src/java/org/apache/jdo/impl/pm/ src/java/org/apache/jdo/impl/sco/
src/java/org/apache/jdo/impl/state/ src/java/org/apache/jdo/pm/
src/java/org/apache/jdo/query/ src/java/org/apache/jdo/sco/
src/java/org/apache/jdo/state/ src/java/org/apache/jdo/store/
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/LinkedList.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/LinkedList.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/LinkedList.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/LinkedList.java Sun May 22 11:01:45 2005
@@ -0,0 +1,669 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * sco.LinkedList.java
+ */
+
+package org.apache.jdo.impl.sco;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.ListIterator;
+
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUserException;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCOCollection;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * A mutable 2nd class object that represents LinkedList.
+ * @author Marina Vatkina
+ * @version 1.0.1
+ * @see java.util.LinkedList
+ */
+public class LinkedList extends java.util.LinkedList
+ implements SCOCollection {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber = -1;
+
+ private transient Class elementType;
+
+ private transient boolean allowNulls;
+
+ private transient java.util.Vector added = new java.util.Vector();
+
+ private transient java.util.Vector removed = new java.util.Vector();
+
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.sco.Bundle"); // NOI18N
+
+ private final static String _LinkedList = "LinkedList"; // NOI18N
+
+ /**
+ * Constructs an empty <code>LinkedList</code> object.
+ *
+ * @param elementType the element types allowed
+ * @param allowNulls true if nulls are allowed
+ */
+ public LinkedList(Class elementType, boolean allowNulls) {
+ super();
+ this.elementType = elementType;
+ this.allowNulls = allowNulls;
+ }
+
+ /**
+ * Constructs an empty <code>LinkedList</code> object that the specified
+ * initial capacity which is ignored.
+ *
+ * @param elementType the element types allowed
+ * @param allowNulls true if nulls are allowed
+ * @param initialCapacity the initial capacity of the list (ignored).
+ * @exception IllegalArgumentException if the specified initial capacity
+ * is negative
+ */
+ public LinkedList(Class elementType, boolean allowNulls,
+ int initialCapacity) {
+ super();
+ this.elementType = elementType;
+ this.allowNulls = allowNulls;
+ }
+
+ /** ------------------Public Methods----------------*/
+
+ /**
+ * Replaces the element at the specified position in this
+ * LinkedList with the specified element.
+ *
+ * @param index index of element to replace.
+ * @param element element to be stored at the specified position.
+ * @return the element previously at the specified position.
+ * @exception IndexOutOfBoundsException index out of range
+ * (index < 0 || index >= size()).
+ * @exception IllegalArgumentException fromIndex > toIndex.
+ * @see java.util.LinkedList
+ */
+ public Object set(int index, Object element) {
+ SCOHelper.debug(_LinkedList, "set"); // NOI18N
+
+ if (element == null) {
+ SCOHelper.assertNullsAllowed(element, allowNulls);
+ // It is actualy remove
+ return this.remove(index);
+ }
+ SCOHelper.assertElementType(element, elementType);
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Object o = super.set(index, element);
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ if (removed.remove(element) == false) {
+ added.add(element);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ return o;
+ }
+
+
+ /**
+ * Appends the specified element to the end of this LinkedList.
+ *
+ * @param o element to be appended to this LinkedList.
+ * @return true (as per the general contract of Collection.add).
+ * @see java.util.LinkedList
+ */
+ public boolean add(Object o) {
+ SCOHelper.debug(_LinkedList, "add"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ // Mark the field as dirty
+ this.makeDirty();
+
+ if (removed.remove(o) == false) {
+ added.add(o);
+ }
+
+ boolean modified = super.add(o);
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+ /**
+ * Inserts the given element at the beginning of this list.
+ *
+ * @param o the element to be inserted at the beginning of this list.
+ */
+ public void addFirst(Object o) {
+ SCOHelper.debug(_LinkedList, "addFirst"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ // Mark the field as dirty
+ this.makeDirty();
+
+ if (removed.remove(o) == false) {
+ added.add(o);
+ }
+
+ super.addFirst(o);
+
+ // Apply updates
+ this.trackUpdates(true);
+ }
+
+ /**
+ * Appends the given element to the end of this list. (Identical in
+ * function to the <tt>add</tt> method; included only for consistency.)
+ *
+ * @param o the element to be inserted at the end of this list.
+ */
+ public void addLast(Object o) {
+ SCOHelper.debug(_LinkedList, "addLast"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ // Mark the field as dirty
+ this.makeDirty();
+
+ if (removed.remove(o) == false) {
+ added.add(o);
+ }
+
+ super.addLast(o);
+
+ // Apply updates
+ this.trackUpdates(true);
+ }
+
+
+ /**
+ * Removes the first occurrence of the specified element in this LinkedList
+ * If the LinkedList does not contain the element, it is unchanged.
+ *
+ * @param o element to be removed from this LinkedList, if present.
+ * @return true if the LinkedList contained the specified element.
+ * @see java.util.LinkedList
+ */
+ public boolean remove(Object o) {
+ SCOHelper.debug(_LinkedList, "remove"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ if (super.remove(o)) {
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Removes and returns the first element from this list.
+ *
+ * @return the first element from this list.
+ * @throws NoSuchElementException if this list is empty.
+ */
+ public Object removeFirst() {
+ SCOHelper.debug(_LinkedList, "removeFirst"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Object obj = super.removeFirst();
+ if (added.remove(obj) == false) {
+ removed.add(obj);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ return obj;
+ }
+
+ /**
+ * Removes and returns the last element from this list.
+ *
+ * @return the last element from this list.
+ * @throws NoSuchElementException if this list is empty.
+ */
+ public Object removeLast() {
+ SCOHelper.debug(_LinkedList, "removeLast"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Object obj = super.removeLast();
+ if (added.remove(obj) == false) {
+ removed.add(obj);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ return obj;
+ }
+
+ /**
+ * Inserts the specified element at the specified position in this
+ * LinkedList.
+ *
+ * @param index index at which the specified element is to be inserted.
+ * @param element element to be inserted.
+ * @exception IndexOutOfBoundsException index is out of range
+ * (index < 0 || index > size()).
+ * @see java.util.LinkedList
+ */
+ public void add(int index, Object element) {
+ SCOHelper.debug(_LinkedList, "add by index"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(element, allowNulls);
+ SCOHelper.assertElementType(element, elementType);
+ // Mark the field as dirty
+ this.makeDirty();
+
+ super.add(index, element);
+ if (removed.remove(element) == false) {
+ added.add(element);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ }
+
+ /**
+ * Removes the element at the specified position in this LinkedList.
+ * shifts any subsequent elements to the left (subtracts one from their
+ * indices). Returns the element that was removed from the LinkedList.
+ *
+ * @param index the index of the element to removed.
+ * @exception IndexOutOfBoundsException index out of range (index
+ * < 0 || index >= size()).
+ * @see java.util.LinkedList
+ */
+ public Object remove(int index) {
+ SCOHelper.debug(_LinkedList, "remove by index"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Object obj = super.remove(index);
+ if (added.remove(obj) == false) {
+ removed.add(obj);
+ }
+ // Apply updates
+ this.trackUpdates(true);
+
+ return obj;
+ }
+
+ /**
+ * Removes all of the elements from this LinkedList. The LinkedList will
+ * be empty after this call returns (unless it throws an exception).
+ *
+ * @see java.util.LinkedList
+ */
+ public void clear() {
+ SCOHelper.debug(_LinkedList, "clear"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ for (Iterator iter = super.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ }
+ added.clear();
+ super.clear();
+
+ // Apply updates
+ this.trackUpdates(true);
+ }
+
+ /**
+ * Appends all of the elements in the specified Collection to the end of
+ * this LinkedList, in the order that they are returned by the specified
+ * Collection's Iterator.
+ * Delegates to #addAll(int index, Collection c) not to duplicate the
+ * processing.
+ *
+ * @param c elements to be inserted into this LinkedList.
+ * @exception IndexOutOfBoundsException index out of range (index
+ * < 0 || index > size()).
+ * @see java.util.LinkedList
+ */
+ public boolean addAll(Collection c) {
+ SCOHelper.debug(_LinkedList, "addAll"); // NOI18N
+
+ return addAll(this.size(), c);
+ }
+
+ /**
+ * Removes from this LinkedList all of its elements that are contained in the
+ * specified Collection.
+ *
+ * @return true if this LinkedList changed as a result of the call.
+ * @see java.util.LinkedList
+ */
+ public boolean removeAll(Collection c) {
+ SCOHelper.debug(_LinkedList, "removeAll"); // NOI18N
+
+ boolean modified = false;
+ // Mark the field as dirty
+ this.makeDirty();
+
+ Iterator e = c.iterator();
+ while (e.hasNext()) {
+ Object o = e.next();
+ if(super.contains(o)) {
+ removeInternal(o);
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ modified = true;
+ }
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Inserts all of the elements in in the specified Collection into this
+ * LinkedList at the specified position. Shifts the element currently at
+ * that position (if any) and any subsequent elements to the right
+ * (increases their indices). The new elements will appear in the LinkedList
+ * in the order that they are returned by the specified Collection's
+ * iterator.
+ *
+ * @param index index at which to insert first element
+ * from the specified collection.
+ * @param c elements to be inserted into this LinkedList.
+ * @exception IndexOutOfBoundsException index out of range (index
+ * < 0 || index > size()).
+ * @see java.util.LinkedList
+ */
+ public boolean addAll(int index, Collection c) {
+ SCOHelper.debug(_LinkedList, "addAll from index"); // NOI18N
+
+ // iterate the collection and make a list of wrong elements.
+ Throwable[] err = new Throwable[c.size()];
+ int l = 0;
+
+ Iterator i = c.iterator();
+ while (i.hasNext()) {
+ Object o = i.next();
+ try {
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ SCOHelper.validateResult(l, err);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ removed.removeAll(c);
+ added.addAll(c);
+
+ boolean modified = super.addAll(index, c);
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Retains only the elements in this LinkedList that are contained in the
+ * specified Collection.
+ *
+ * @return true if this LinkedList changed as a result of the call.
+ * @see java.util.LinkedList
+ */
+ public boolean retainAll(Collection c) {
+ SCOHelper.debug(_LinkedList, "retainAll"); // NOI18N
+
+ boolean modified = false;
+ java.util.LinkedList v = new java.util.LinkedList();
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ for (Iterator iter = super.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (!c.contains(o)) {
+ v.add(o);
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ modified = true;
+ }
+ }
+
+ // Now remove the rest (stored in "v")
+ for (Iterator iter = v.iterator(); iter.hasNext();) {
+ removeInternal(iter.next());
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_LinkedList, "clone"); // NOI18N
+
+ // Our own implementation as super.clone internally calls clone.add()
+ // for each element before we unset the owner:
+ LinkedList clone = new LinkedList(elementType, allowNulls);
+
+ // Initialize clone with our elements
+ ListIterator it = this.listIterator();
+ while (it.hasNext()) {
+ clone.addInternal(it.next());
+ }
+
+ return clone;
+ }
+
+ /**
+ * @see SCOCollection#reset()
+ */
+ public void reset() {
+ added.clear();
+ removed.clear();
+ }
+
+ /**
+ * @see SCOCollection#addInternal(Object o)
+ */
+ public void addInternal(Object o) {
+ super.add(o);
+ }
+
+
+ /**
+ * @see SCOCollection#addAllInternal(Collection c)
+ */
+ public void addAllInternal(Collection c) {
+ super.addAll(c);
+ }
+
+ /**
+ * @see SCOCollection#getAdded()
+ */
+ public Collection getAdded() {
+ return (Collection)added;
+ }
+
+ /**
+ * @see SCOCollection#getRemoved()
+ */
+ public Collection getRemoved() {
+ return (Collection)removed;
+ }
+
+
+ /**
+ * @see SCOCollection#clearInternal()
+ */
+ public void clearInternal() {
+ super.clear();
+ this.reset();
+ }
+
+ /**
+ * @see SCOCollection#removeInternal(Object o)
+ */
+ public void removeInternal(Object o) {
+ int i = super.indexOf(o);
+ super.remove(i);
+ }
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * Marks object dirty
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber);
+ }
+ }
+
+ /**
+ * Apply changes
+ * @param modified true if content of this list has been changed.
+ */
+ private void trackUpdates(boolean modified) {
+ if (modified && owner != null) {
+ owner.trackUpdates(fieldNumber, this);
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+
+ /**
+ * @see SCO#getOwner ()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * @see SCOCollection#getElementType() {
+ */
+ public Class getElementType() {
+ return elementType;
+ }
+
+ /**
+ * @see SCOCollection#allowNulls() {
+ */
+ public boolean allowNulls() {
+ return allowNulls;
+ }
+
+ /** Get an iterator over the frozen elements of this collection.
+ * This class does not require freezing, so this method returns
+ * a standard iterator.
+ * @since 1.0.1
+ * @return an iterator over the elements.
+ */
+ public Iterator frozenIterator() {
+ return iterator();
+ }
+
+ /** Set the contents of this Collection from the frozen elements.
+ * This class does not support explicit frozen operations, and this method
+ * always throws an exception.
+ * @since 1.0.1
+ * @param elements not used.
+ */
+ public void setFrozen(Object[] elements) {
+ throw new JDOFatalInternalException(
+ msg.msg("EXC_UnsupportedFreezerOperation")); //NOI18N
+ }
+
+ /** Get an iterator regardless of whether the collection is frozen.
+ * This class does not support frozen operations and always returns
+ * a regular iterator.
+ * @since 1.0.1
+ * @return an iterator over the elements of the list.
+ */
+ public Iterator eitherIterator() {
+ return iterator();
+ }
+
+}
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SCOHelper.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SCOHelper.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SCOHelper.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SCOHelper.java Sun May 22 11:01:45 2005
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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 org.apache.jdo.impl.sco;
+
+import javax.jdo.JDOUserException;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.jdo.sco.SCOCollection;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+/**
+ * Helper class used by Tracked SCO implementations. Contains static
+ * methods to allow to simplify implementations of SCO classes in the
+ * same package without extending the same base class, which is
+ * impossible as each Tracked SCO class extends corresponding "regular" SCO.
+ *
+ * @author Marina Vatkina
+ */
+class SCOHelper {
+
+ /**
+ * Message keys for assertions performed.
+ */
+ private final static String EXC_ElementNullsNotAllowed =
+ "EXC_ElementNullsNotAllowed"; // NOI18N
+ private final static String EXC_KeyNullsNotAllowed =
+ "EXC_KeyNullsNotAllowed"; // NOI18N
+ private final static String EXC_ValueNullsNotAllowed =
+ "EXC_ValueNullsNotAllowed"; // NOI18N
+ private final static String EXC_ElementClassCastException =
+ "EXC_ElementClassCastException"; // NOI18N
+ private final static String EXC_KeyClassCastException =
+ "EXC_KeyClassCastException"; // NOI18N
+ private final static String EXC_ValueClassCastException =
+ "EXC_ValueClassCastException"; // NOI18N
+
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.sco.Bundle"); // NOI18N
+
+ /**
+ * Logger for SCO classes.
+ */
+ private static final Log logger = LogFactory.getFactory().getInstance(
+ "org.apache.jdo.impl.sco"); // NOI18N
+
+ /**
+ * Verifies if null values are allowed for elements of an SCOCollection.
+ *
+ * @param o the object to validate
+ * @param allowNulls true if nulls are allowed
+ * @throws JDOUserException if null values are not allowed and the component
+ * to insert is null.
+ */
+ protected static void assertNullsAllowed(Object o, boolean allowNulls) {
+ assertNulls(o, allowNulls, EXC_ElementNullsNotAllowed);
+ }
+
+ /**
+ * Verifies if null values are allowed for keys of an SCOMap.
+ *
+ * @param o the key to validate
+ * @param allowNulls true if nulls are allowed
+ * @throws JDOUserException if null values are not allowed and the key
+ * to set is null.
+ */
+ protected static void assertNullKeysAllowed(Object o, boolean allowNulls) {
+ assertNulls(o, allowNulls, EXC_KeyNullsNotAllowed);
+ }
+
+ /**
+ * Verifies if null values are allowed for values of an SCOMap.
+ *
+ * @param o the value to validate.
+ * @param allowNulls true if nulls are allowed.
+ * @throws JDOUserException if null values are not allowed and the value
+ * to insert is null.
+ */
+ protected static void assertNullValuesAllowed(Object o, boolean allowNulls) {
+ assertNulls(o, allowNulls, EXC_ValueNullsNotAllowed);
+ }
+
+ /**
+ * Verifies that the component to insert is of correct type
+ *
+ * @param o the object to validate.
+ * @param elementType the element types allowed.
+ * @throws JDOUserException if validation fails.
+ */
+ protected static void assertElementType(Object o, Class elementType) {
+ assertType(o, elementType, EXC_ElementClassCastException);
+ }
+
+ /**
+ * Verifies that the key to insert is of correct type.
+ *
+ * @param o the key to validate.
+ * @param keyType the key types allowed.
+ * @throws JDOUserException if validation fails.
+ */
+ protected static void assertKeyType(Object o, Class keyType) {
+ assertType(o, keyType, EXC_KeyClassCastException);
+ }
+
+ /**
+ * Verifies that the value to insert is of correct type.
+ *
+ * @param o the value to validate.
+ * @param valueType the value types allowed.
+ * @throws JDOUserException if validation fails.
+ */
+ protected static void assertValueType(Object o, Class valueType) {
+ assertType(o, valueType, EXC_ValueClassCastException);
+ }
+
+ /**
+ * Helper method to validate errors on processing arrays of objects.
+ * @param l actual size of the array
+ * @param err array of Throwable to validate
+ * @throws JDOUserException if <code>l</code> is greater than 0.
+ */
+ protected static void validateResult(int l, Throwable[] err) {
+ if (l > 0) {
+ Throwable[] t = new Throwable[l];
+ System.arraycopy(err, 0, t, 0, l);
+ throw new JDOUserException(msg.msg(
+ "EXC_FailedToProcessAll"), t); // NOI18N
+ }
+ }
+
+ /**
+ * Verifies if nulls are allowed as instances of this SCO.
+ *
+ * @param o the instance to validate.
+ * @param allowNulls true if nulls are allowed.
+ * @param exc message key for the exception to be thrown.
+ * @throws JDOUserException if validation fails.
+ */
+ protected static void assertNulls(Object o, boolean allowNulls, String exc) {
+ if (allowNulls == false && o == null) {
+ throw new JDOUserException(msg.msg(exc));
+ }
+ }
+
+ /**
+ * Verifies that the value to insert is of correct type.
+ *
+ * @param o the value to validate.
+ * @param type the Class of types allowed.
+ * @param exc message key for the exception to be thrown.
+ * @throws JDOUserException if validation fails.
+ */
+ private static void assertType(Object o, Class type, String exc) {
+ if (type != null && ! type.isAssignableFrom(o.getClass())) {
+ throw new JDOUserException(msg.msg(
+ exc, type.getName()), // NOI18N
+ new Exception[] {new ClassCastException()}, o);
+ }
+ }
+
+ /**
+ * Returns the owner object of the SCO instance
+ *
+ * @return owner object
+ */
+ protected static Object getOwner(StateManagerInternal owner) {
+ return ((owner == null)? null : owner.getObject());
+ }
+
+ /**
+ * Returns the field name
+ *
+ * @return field name as java.lang.String
+ */
+ protected static String getFieldName(StateManagerInternal owner, int fieldNumber) {
+ return ((owner == null)? null : owner.getFieldName(fieldNumber));
+ }
+
+ /**
+ * Tracing method for other SCO implementations.
+ * @param name Class name of an instance calling the method.
+ * @param msg String to display.
+ */
+ protected static void debug(String name, String msg) {
+ logger.debug("In " + name + " " + msg); // NOI18N
+ }
+}
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlDate.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlDate.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlDate.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlDate.java Sun May 22 11:01:45 2005
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * SqlDate.java
+ *
+ */
+
+package org.apache.jdo.impl.sco;
+
+import javax.jdo.JDOHelper;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCODate;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+
+/**
+ * A mutable 2nd class object that represents java.sql.Date.
+ * @author Marina Vatkina
+ * @version 1.0
+ * @see java.sql.Date
+ */
+public class SqlDate extends java.sql.Date
+ implements SCODate {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber;
+
+ private final static String _SqlDate = "SqlDate"; // NOI18N
+
+ /**
+ * Creates a <code>SqlDate</code> object that represents the time at which
+ * it was allocated.
+ */
+ public SqlDate() {
+ super(0);
+ }
+
+ /**
+ * Creates a <code>SqlDate</code> object that represents the given time
+ * in milliseconds.
+ * @param date the number of milliseconds
+ */
+ public SqlDate(long date) {
+ super(date);
+ }
+
+ /**
+ * Sets the <tt>SqlDate</tt> object to represent a point in time that is
+ * <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT.
+ *
+ * @param time the number of milliseconds.
+ * @see java.sql.Date
+ */
+ public void setTime(long time) {
+ SCOHelper.debug(_SqlDate, "setTime"); // NOI18N
+
+ this.makeDirty();
+ super.setTime(time);
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_SqlDate, "clone"); // NOI18N
+
+ Object obj = super.clone();
+ if (obj instanceof SCO)
+ ((SCO)obj).unsetOwner(owner, fieldNumber);
+
+ return obj;
+ }
+
+ /** -----------Depricated Methods------------------*/
+
+ /**
+ * Sets the year of this <tt>SqlDate</tt> object to be the specified
+ * value plus 1900.
+ *
+ * @param year the year value.
+ * @see java.util.Calendar
+ * @see java.sql.Date
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
+ */
+ public void setYear(int year) {
+ SCOHelper.debug(_SqlDate, "setYear"); // NOI18N
+
+ this.makeDirty();
+ super.setYear(year);
+ }
+
+ /**
+ * Sets the month of this date to the specified value.
+ * @param month the month value between 0-11.
+ * @see java.util.Calendar
+ * @see java.sql.Date
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
+ */
+ public void setMonth(int month) {
+ SCOHelper.debug(_SqlDate, "setMonth"); // NOI18N
+
+ this.makeDirty();
+ super.setMonth(month);
+ }
+
+ /**
+ * Sets the day of the month of this <tt>SqlDate</tt> object to the
+ * specified value.
+ *
+ * @param date the day of the month value between 1-31.
+ * @see java.util.Calendar
+ * @see java.sql.Date
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
+ */
+ public void setDate(int date) {
+ SCOHelper.debug(_SqlDate, "setDate"); // NOI18N
+
+ this.makeDirty();
+ super.setDate(date);
+ }
+
+ /** ---------------- internal methods ------------------- */
+
+ /**
+ * Sets the <tt>SqlDate</tt> object without notification of the Owner
+ * field. Used internaly to populate date from DB
+ *
+ * @param time the number of milliseconds.
+ * @see java.sql.Date
+ */
+ public void setTimeInternal(long time) {
+ super.setTime(time);
+ }
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+ /**
+ * @see SCO#getOwner()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * Marks object dirty
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber); //
+ }
+ }
+}
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTime.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTime.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTime.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTime.java Sun May 22 11:01:45 2005
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+/**
+ * SqlTime.java
+ *
+ */
+
+package org.apache.jdo.impl.sco;
+
+import javax.jdo.JDOHelper;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCODate;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+
+/**
+ * A mutable 2nd class object that represents java.sql.Time.
+ * @author Marina Vatkina
+ * @version 1.0
+ * @see java.sql.Time
+ */
+public class SqlTime extends java.sql.Time
+ implements SCODate {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber = -1;
+
+ private final static String _SqlTime = "SqlTime"; // NOI18N
+
+ /**
+ * Creates a <code>SqlTime</code> object that represents the time at which
+ * it was allocated.
+ */
+ public SqlTime() {
+ super(0);
+ }
+
+ /**
+ * Creates a <code>SqlTime</code> object that represents the given time
+ * in milliseconds.
+ * @param date the number of milliseconds
+ */
+ public SqlTime(long date) {
+ super(date);
+ }
+
+ /**
+ * Sets the <tt>SqlTime</tt> object to represent a point in time that is
+ * <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT.
+ *
+ * @param time the number of milliseconds.
+ * @see java.sql.Time
+ */
+ public void setTime(long time) {
+ SCOHelper.debug(_SqlTime, "setTime"); // NOI18N
+
+ this.makeDirty();
+ super.setTime(time);
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_SqlTime, "clone"); // NOI18N
+
+ Object obj = super.clone();
+ if (obj instanceof SCO) {
+ ((SCO)obj).unsetOwner(owner, fieldNumber);
+ }
+
+ return obj;
+ }
+
+ /** -----------Depricated Methods------------------*/
+
+ /**
+ * Sets the hour of this <tt>SqlTime</tt> object to the specified value.
+ *
+ * @param hours the hour value.
+ * @see java.util.Calendar
+ * @see java.sql.Time
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
+ */
+ public void setHours(int hours) {
+ SCOHelper.debug(_SqlTime, "setHours"); // NOI18N
+
+ this.makeDirty();
+ super.setHours(hours);
+ }
+
+ /**
+ * Sets the minutes of this <tt>SqlTime</tt> object to the specified value.
+ *
+ * @param minutes the value of the minutes.
+ * @see java.util.Calendar
+ * @see java.sql.Time
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
+ */
+ public void setMinutes(int minutes) {
+ SCOHelper.debug(_SqlTime, "setMinutes"); // NOI18N
+
+ this.makeDirty();
+ super.setMinutes(minutes);
+ }
+
+ /**
+ * Sets the seconds of this <tt>SqlTime</tt> to the specified value.
+ *
+ * @param seconds the seconds value.
+ * @see java.util.Calendar
+ * @see java.sql.Time
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>.
+ */
+ public void setSeconds(int seconds) {
+ SCOHelper.debug(_SqlTime, "setMinutes"); // NOI18N
+
+ this.makeDirty();
+ super.setSeconds(seconds);
+ }
+
+ /** ---------------- internal methods ------------------- */
+
+ /**
+ * Sets the <tt>SqlTime</tt> object without notification of the Owner
+ * field. Used internaly to populate date from DB
+ *
+ * @param time the number of milliseconds.
+ * @see java.sql.Time
+ */
+ public void setTimeInternal(long time) {
+ super.setTime(time);
+ }
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+
+ /**
+ * @see SCO#getOwner()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * Marks object dirty
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber); //
+ }
+ }
+}
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java Sun May 22 11:01:45 2005
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+/**
+ * SqlTimestamp.java
+ *
+ */
+
+package org.apache.jdo.impl.sco;
+
+import javax.jdo.JDOHelper;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCODate;
+import org.apache.jdo.state.StateManagerInternal;
+
+
+
+/**
+ * A mutable 2nd class object that represents java.sql.Timestamp
+ * @author Marina Vatkina
+ * @version 1.0
+ * @see java.sql.Timestamp
+ */
+public class SqlTimestamp extends java.sql.Timestamp
+ implements SCODate {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber = -1;
+
+ private final static String _SqlTimestamp = "SqlTimestamp"; // NOI18N
+
+ /**
+ * Creates a <code>SqlTimestamp</code> object that represents the time at which
+ * it was allocated.
+ */
+ public SqlTimestamp() {
+ super(0);
+ }
+
+ /**
+ * Creates a <code>SqlTimestamp</code> object that represents the given time
+ * in milliseconds.
+ * @param date the number of milliseconds
+ */
+ public SqlTimestamp(long date) {
+ super(date);
+ }
+
+ /**
+ * Sets the <tt>SqlTimestamp</tt> object to represent a point in time that is
+ * <tt>time</tt> milliseconds after January 1, 1970 00:00:00 GMT.
+ *
+ * @param time the number of milliseconds.
+ * @see java.sql.Timestamp
+ */
+ public void setTime(long time) {
+ SCOHelper.debug(_SqlTimestamp, "setTime"); // NOI18N
+
+ this.makeDirty();
+ super.setTime(time);
+ }
+
+ /**
+ * Sets this <code>Timestamp</code> object's <code>nanos</code> value
+ * to the given value.
+ *
+ * @param n the new fractional seconds component
+ * @exception java.lang.IllegalArgumentException if the given argument
+ * is greater than 999999999 or less than 0
+ * @see java.sql.Timestamp
+ */
+ public void setNanos(int n) {
+ SCOHelper.debug(_SqlTimestamp, "setNanos"); // NOI18N
+
+ this.makeDirty();
+ try {
+ super.setNanos(n);
+ } catch (IllegalArgumentException e) {
+ throw e;
+ }
+ }
+
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_SqlTimestamp, "clone"); // NOI18N
+
+ Object obj = super.clone();
+ if (obj instanceof SCO) {
+ ((SCO)obj).unsetOwner(owner, fieldNumber);
+ }
+
+ return obj;
+ }
+
+ /** -----------Depricated Methods------------------*/
+
+ /**
+ * Sets the year of this <tt>SqlTimestamp</tt> object to be the specified
+ * value plus 1900.
+ *
+ * @param year the year value.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.YEAR, year + 1900)</code>.
+ */
+ public void setYear(int year) {
+ SCOHelper.debug(_SqlTimestamp, "setYear"); // NOI18N
+
+ this.makeDirty();
+ super.setYear(year);
+ }
+
+ /**
+ * Sets the month of this date to the specified value.
+ * @param month the month value between 0-11.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.MONTH, int month)</code>.
+ */
+ public void setMonth(int month) {
+ SCOHelper.debug(_SqlTimestamp, "setMonth"); // NOI18N
+
+ this.makeDirty();
+ super.setMonth(month);
+ }
+
+ /**
+ * Sets the day of the month of this <tt>SqlTimestamp</tt> object to the
+ * specified value.
+ *
+ * @param date the day of the month value between 1-31.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.DAY_OF_MONTH, int date)</code>.
+ */
+ public void setDate(int date) {
+ SCOHelper.debug(_SqlTimestamp, "setDate"); // NOI18N
+
+ this.makeDirty();
+ super.setDate(date);
+ }
+
+
+ /**
+ * Sets the hour of this <tt>SqlTimestamp</tt> object to the specified value.
+ *
+ * @param hours the hour value.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.HOUR_OF_DAY, int hours)</code>.
+ */
+ public void setHours(int hours) {
+ SCOHelper.debug(_SqlTimestamp, "setHours"); // NOI18N
+
+ this.makeDirty();
+ super.setHours(hours);
+ }
+
+ /**
+ * Sets the minutes of this <tt>SqlTimestamp</tt> object to the specified value.
+ *
+ * @param minutes the value of the minutes.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.MINUTE, int minutes)</code>.
+ */
+ public void setMinutes(int minutes) {
+ SCOHelper.debug(_SqlTimestamp, "setMinutes"); // NOI18N
+
+ this.makeDirty();
+ super.setMinutes(minutes);
+ }
+
+ /**
+ * Sets the seconds of this <tt>SqlTimestamp</tt> to the specified value.
+ *
+ * @param seconds the seconds value.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @deprecated As of JDK version 1.1,
+ * replaced by <code>Calendar.set(Calendar.SECOND, int seconds)</code>.
+ */
+ public void setSeconds(int seconds) {
+ SCOHelper.debug(_SqlTimestamp, "setSeconds"); // NOI18N
+
+ this.makeDirty();
+ super.setSeconds(seconds);
+ }
+
+ /** ---------------- internal methods ------------------- */
+
+ /**
+ * Sets the <tt>SqlTimestamp</tt> object without notification of the Owner
+ * field. Used internaly to populate date from DB
+ *
+ * @param time the number of milliseconds.
+ * @see java.sql.Timestamp
+ */
+ public void setTimeInternal(long time) {
+ super.setTime(time);
+ }
+
+ /**
+ * Sets the <tt>SqlTimestamp</tt> object's <code>nanos</code> value without
+ * notification of the Owner field. Used internaly to populate date from DB
+ *
+ * @param n the new fractional seconds component
+ * @exception java.lang.IllegalArgumentException if the given argument
+ * is greater than 999999999 or less than 0
+ * @see java.sql.Timestamp
+ */
+ public void setNanosInternal(int n) {
+ super.setNanos(n);
+ }
+
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+ /**
+ * @see SCO#getOwner()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * Marks object dirty
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber); //
+ }
+ }
+}
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeMap.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeMap.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeMap.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeMap.java Sun May 22 11:01:45 2005
@@ -0,0 +1,603 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * sco.TreeMap.java
+ */
+
+package org.apache.jdo.impl.sco;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.NoSuchElementException;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCOMap;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * A mutable 2nd class object that represents TreeMap.
+ * @author Marina Vatkina
+ * @version 1.0.1
+ * @see java.util.TreeMap
+ */
+public class TreeMap extends java.util.TreeMap implements SCOMap {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber = -1;
+
+ private transient Class keyType;
+
+ private transient Class valueType;
+
+ private transient boolean allowNulls;
+
+ private transient java.util.ArrayList addedKeys = new java.util.ArrayList();
+ private transient java.util.ArrayList addedValues = new java.util.ArrayList();
+
+ private transient java.util.ArrayList removedKeys = new java.util.ArrayList();
+ private transient java.util.ArrayList removedValues = new java.util.ArrayList();
+
+ private transient Map.Entry[] frozenEntries = null;
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.sco.Bundle"); // NOI18N
+
+ private final static String _TreeMap = "TreeMap"; // NOI18N
+
+ /**
+ * Creates a new empty <code>TreeMap</code> object.
+ *
+ * @param keyType the type of the keys allowed.
+ * @param valueType the type of the values allowed.
+ * @param allowNulls true if nulls are allowed.
+ * @see java.util.TreeMap
+ */
+ public TreeMap(Class keyType, Class valueType, boolean allowNulls) {
+ super();
+ this.keyType = keyType;
+ this.valueType = valueType;
+ this.allowNulls = allowNulls;
+ }
+
+ /**
+ * Creates a new empty <code>TreeMap</code> object that has
+ * the specified initial capacity.
+ *
+ * @param keyType the type of the keys allowed.
+ * @param valueType the type of the values allowed.
+ * @param allowNulls true if nulls are allowed
+ * @param c the comparator that will be used to sort this map.
+ * A null value indicates that the elements' natural ordering should
+ * be used.
+ * @see java.util.TreeMap
+ */
+ public TreeMap(Class keyType, Class valueType, boolean allowNulls,
+ Comparator c) {
+
+ super(c);
+ this.keyType = keyType;
+ this.valueType = valueType;
+ this.allowNulls = allowNulls;
+ }
+
+ // -------------------------Public Methods------------------
+
+ /**
+ * Associates the specified value with the specified key in this map.
+ * If the map previously contained a mapping for this key, the old
+ * value is replaced.
+ *
+ * @param key key with which the specified value is to be associated.
+ * @param value value to be associated with the specified key.
+ * @return previous value associated with specified key, or <tt>null</tt>
+ * if there was no mapping for key. A <tt>null</tt> return can
+ * also indicate that the TreeMap previously associated
+ * <tt>null</tt> with the specified key.
+ * @see java.util.TreeMap
+ */
+ public Object put(Object key, Object value) {
+ SCOHelper.debug(_TreeMap, "put"); // NOI18N
+
+ // Check both the key and the value:
+ Throwable[] err = new Throwable[2];
+ int l = 0;
+
+ try {
+ SCOHelper.assertNullKeysAllowed(key, allowNulls);
+ SCOHelper.assertKeyType(key, keyType);
+ } catch (Throwable ex) {
+ err[l++] = ex;
+ }
+ try {
+ SCOHelper.assertNullValuesAllowed(value, allowNulls);
+ SCOHelper.assertValueType(value, valueType);
+ } catch (Throwable ex) {
+ err[l++] = ex;
+ }
+
+ SCOHelper.validateResult(l, err);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ Object o = process(key, value);
+
+ // Apply updates
+ this.trackUpdates(true);
+
+ return o;
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this one.
+ *
+ * These mappings replace any mappings that this map had for any of the
+ * keys currently in the specified Map.
+ *
+ * @param t Mappings to be stored in this map.
+ * @see java.util.TreeMap
+ */
+ public void putAll(Map t) {
+ SCOHelper.debug(_TreeMap, "putAll"); // NOI18N
+
+ // iterate the collection and make a list of wrong elements.
+ Throwable[] err = new Throwable[2*t.size()];
+ int l = 0;
+
+ Iterator i = t.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
+ Object k = e.getKey();
+ Object v = e.getValue();
+
+ // Check both the key and the value:
+ try {
+ SCOHelper.assertNullKeysAllowed(k, allowNulls);
+ SCOHelper.assertKeyType(k, keyType);
+ } catch (Throwable ex) {
+ err[l++] = ex;
+ }
+ try {
+ SCOHelper.assertNullValuesAllowed(v, allowNulls);
+ SCOHelper.assertValueType(v, valueType);
+ } catch (Throwable ex) {
+ err[l++] = ex;
+ }
+ }
+ SCOHelper.validateResult(l, err);
+
+ thaw();
+ boolean modified = false;
+ // Mark the field as dirty
+ this.makeDirty();
+
+ for (i = t.entrySet().iterator(); i.hasNext();) {
+ Map.Entry e = (Map.Entry) i.next();
+ process(e.getKey(), e.getValue());
+ }
+
+ // Apply updates
+ this.trackUpdates(true);
+ }
+
+ /**
+ * Removes the mapping for this key from this map if present.
+ *
+ * @param key key whose mapping is to be removed from the map.
+ * @return previous value associated with specified key, or <tt>null</tt>
+ * if there was no mapping for key. A <tt>null</tt> return can
+ * also indicate that the map previously associated <tt>null</tt>
+ * with the specified key.
+ * @see java.util.TreeMap
+ */
+ public Object remove(Object key) {
+ SCOHelper.debug(_TreeMap, "remove"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ boolean removed = false;
+
+ // Nothing is added to the removed collections if the key has not
+ // been in the map before:
+ if (super.containsKey(key)) {
+ if (addedKeys.remove(key) == false) {
+ removedKeys.add(key);
+ }
+ removed = true;
+ }
+
+ Object o = super.remove(key);
+
+ // Remove old value if there was one:
+ if (removed && addedValues.remove(o) == false) {
+ removedValues.add(o);
+ }
+
+ // Apply updates
+ this.trackUpdates(removed);
+
+ return o;
+ }
+
+ /** These methods need to thaw the map before performing the operation.
+ */
+ public boolean containsKey(Object key) {
+ thaw();
+ return super.containsKey(key);
+ }
+ public boolean containsValue(Object value) {
+ thaw();
+ return super.containsValue(value);
+ }
+ public Set entrySet() {
+ thaw();
+ return super.entrySet();
+ }
+ public boolean equals(Object o) {
+ thaw();
+ return super.equals(o);
+ }
+ public Object get(Object key) {
+ thaw();
+ return super.get(key);
+ }
+ public int hashCode() {
+ thaw();
+ return super.hashCode();
+ }
+ public boolean isEmpty() {
+ thaw();
+ return super.isEmpty();
+ }
+ public Set keySet() {
+ thaw();
+ return super.keySet();
+ }
+ public int size() {
+ thaw();
+ return super.size();
+ }
+ public Collection values() {
+ thaw();
+ return super.values();
+ }
+ public String toString() {
+ thaw();
+ return super.toString();
+ }
+ public SortedMap subMap(Object fromKey, Object toKey) {
+ thaw();
+ return super.subMap(fromKey, toKey);
+ }
+ public SortedMap headMap(Object toKey) {
+ thaw();
+ return super.headMap(toKey);
+ }
+ public SortedMap tailMap(Object fromKey) {
+ thaw();
+ return super.tailMap(fromKey);
+ }
+ public Comparator comparator() {
+ thaw();
+ return super.comparator();
+ }
+ public Object firstKey() throws NoSuchElementException {
+ thaw();
+ return super.firstKey();
+ }
+ public Object lastKey() throws NoSuchElementException {
+ thaw();
+ return super.lastKey();
+ }
+
+ /**
+ * Removes all of the elements from this map.
+ * @see java.util.TreeMap
+ */
+ public void clear() {
+ SCOHelper.debug(_TreeMap, "clear"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ for (Iterator i = super.entrySet().iterator(); i.hasNext();) {
+ Map.Entry e = (Map.Entry) i.next();
+ removedKeys.add(e.getKey());
+ removedValues.add(e.getValue());
+ }
+
+ super.clear();
+ addedKeys.clear();
+ addedValues.clear();
+
+ // Apply updates
+ this.trackUpdates(true);
+
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_TreeMap, "clone"); // NOI18N
+
+ Object obj = super.clone();
+ if (obj instanceof SCO) {
+ ((SCO)obj).unsetOwner(owner, fieldNumber);
+ }
+ return obj;
+ }
+
+ /**
+ * @see SCOMap#reset()
+ */
+ public void reset() {
+ addedKeys.clear();
+ addedValues.clear();
+ removedKeys.clear();
+ removedValues.clear();
+ frozenEntries = null;
+ }
+
+ /**
+ * @see SCOMap#putInternal(Object key, Object value)
+ */
+ public void putInternal(Object key, Object value) {
+ super.put(key, value);
+ }
+
+
+ /**
+ * @see SCOMap#putAllInternal(Map t)
+ */
+ public void putAllInternal(Map t) {
+ for (Iterator i = t.entrySet().iterator(); i.hasNext();) {
+ Map.Entry e = (Map.Entry) i.next();
+ super.put(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * @see SCOMap#getAddedKeys()
+ */
+ public Collection getAddedKeys() {
+ return (Collection)addedKeys;
+ }
+
+ /**
+ * @see SCOMap#getAddedValues()
+ */
+ public Collection getAddedValues() {
+ return (Collection)addedValues;
+ }
+
+ /**
+ * @see SCOMap#getRemovedKeys()
+ */
+ public Collection getRemovedKeys() {
+ return (Collection)removedKeys;
+ }
+
+ /**
+ * @see SCOMap#getRemovedValues()
+ */
+ public Collection getRemovedValues() {
+ return (Collection)removedValues;
+ }
+
+ /**
+ * @see SCOMap#clearInternal()
+ */
+ public void clearInternal() {
+ super.clear();
+ this.reset();
+ }
+
+ /**
+ * @see SCOMap#removeInternal(Object key)
+ */
+ public void removeInternal(Object key) {
+ super.remove(key);
+ }
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+
+ /**
+ * @see SCO#getOwner()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * Notify StateManager to mark field as dirty.
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber); //
+ }
+ }
+ /**
+ * Notify StateManager to process the changes.
+ */
+ private void trackUpdates(boolean modified) {
+ if (modified && owner != null) {
+ owner.trackUpdates(fieldNumber, this);
+ }
+ }
+
+ /**
+ * @see SCOMap#getKeyType() {
+ */
+ public Class getKeyType() {
+ return keyType;
+ }
+
+ /**
+ * @see SCOMap#getValueType() {
+ */
+ public Class getValueType() {
+ return valueType;
+ }
+
+ /**
+ * @see SCOMap#allowNulls() {
+ */
+ public boolean allowNulls() {
+ return allowNulls;
+ }
+
+ /**
+ * Processes single put operation in this map.
+ * @param key key with which the specified value is to be associated.
+ * @param value value to be associated with the specified key.
+ * @return previous value associated with specified key, or <tt>null</tt>
+ * if there was no mapping for key.
+ */
+ private Object process(Object key, Object value) {
+ // Key is added to the addedKeys collection only if it has not
+ // been in the map before:
+ if (!super.containsKey(key)) {
+ if (removedKeys.remove(key) == false) {
+ addedKeys.add(key);
+ }
+ }
+
+ Object o = super.put(key, value);
+
+ // Remove old value:
+ if (addedValues.remove(o) == false) {
+ removedValues.add(o);
+ }
+
+ // Add new value:
+ if (removedValues.remove(value) == false) {
+ addedValues.add(value);
+ }
+
+ return o;
+ }
+
+ /** Returns the frozen state of this Map.
+ * @since 1.0.1
+ * @return the frozen state.
+ */
+ private boolean isFrozen() {
+ return frozenEntries != null;
+ }
+
+ /** Returns the frozen contents of this Map as a Map.Entry[].
+ * @since 1.0.1
+ * @return the frozen entries.
+ */
+ private Map.Entry[] getFrozen() {
+ if (!isFrozen()) {
+ frozenEntries = Freezer.freeze(this, super.size());
+ }
+ return frozenEntries;
+ }
+
+ /** Set the contents of this Map from the frozen elements.
+ * @since 1.0.1
+ * @param entries the frozen entries.
+ */
+ public void setFrozen(Map.Entry[] entries) {
+ frozenEntries = entries;
+ }
+
+ /** Get an iterator regardless of whether the map is frozen.
+ * If frozen, get a frozen iterator.
+ * If thawed, get a regular iterator.
+ * @return the iterator.
+ */
+ public Iterator eitherIterator() {
+ if (isFrozen()) {
+ return frozenIterator();
+ } else {
+ return super.entrySet().iterator();
+ }
+ }
+
+ /** Get an iterator over the frozen elements of this map. This allows
+ * iterator of the elements without thawing them, as is needed for
+ * transcription.
+ * @since 1.0.1
+ * @return the iterator.
+ */
+ public Iterator frozenIterator() {
+ return Freezer.createFrozenIterator(getFrozen());
+ }
+
+ /**
+ * Thaw the frozen elements of this map. If the elements are frozen,
+ * retrieve them from the datastore and internally add them. Then reset
+ * the frozen state since they're not frozen any more.
+ * @since 1.0.1
+ */
+ private void thaw() {
+ if (isFrozen()) {
+ frozenEntries = Freezer.thaw(this, owner, frozenEntries);
+ }
+ }
+
+}
Added: incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeSet.java
URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeSet.java?rev=171352&view=auto
==============================================================================
--- incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeSet.java (added)
+++ incubator/jdo/trunk/runtime20/src/java/org/apache/jdo/impl/sco/TreeSet.java Sun May 22 11:01:45 2005
@@ -0,0 +1,596 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * 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.
+ */
+
+/*
+ * sco.TreeSet.java
+ */
+
+package org.apache.jdo.impl.sco;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.SortedSet;
+import java.util.NoSuchElementException;
+
+import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUserException;
+import javax.jdo.JDOHelper;
+
+import org.apache.jdo.sco.SCO;
+import org.apache.jdo.sco.SCOCollection;
+import org.apache.jdo.state.StateManagerInternal;
+import org.apache.jdo.util.I18NHelper;
+
+
+/**
+ * A mutable 2nd class object that represents TreeSet.
+ * @author Marina Vatkina
+ * @version 1.0.1
+ * @see java.util.TreeSet
+ */
+public class TreeSet extends java.util.TreeSet implements SCOCollection {
+
+ private transient StateManagerInternal owner;
+
+ private transient int fieldNumber = -1;
+
+ private transient Class elementType;
+
+ private transient boolean allowNulls;
+
+ private transient java.util.HashSet added = new java.util.HashSet();
+
+ private transient java.util.HashSet removed = new java.util.HashSet();
+
+ private transient Object[] frozenElements = null;
+
+ /**
+ * I18N message handler
+ */
+ private final static I18NHelper msg = I18NHelper.getInstance(
+ "org.apache.jdo.impl.sco.Bundle"); // NOI18N
+
+ private final static String _TreeSet = "TreeSet"; // NOI18N
+
+ /**
+ * Creates a new empty <code>TreeSet</code> object.
+ *
+ * @param elementType the element types allowed
+ * @param allowNulls true if nulls are allowed
+ * @see java.util.TreeSet
+ */
+ public TreeSet(Class elementType, boolean allowNulls) {
+ super();
+ this.elementType = elementType;
+ this.allowNulls = allowNulls;
+ }
+
+ /**
+ * Creates a new empty <code>TreeSet</code> object that has
+ * the specified comparator.
+ *
+ * @param elementType the element types allowed
+ * @param allowNulls true if nulls are allowed
+ * @param c the comparator that will be used to sort this set.
+ * A null value indicates that the elements' natural ordering should
+ * be used.
+ * @see java.util.TreeSet
+ */
+ public TreeSet(Class elementType, boolean allowNulls, Comparator c) {
+ super(c);
+ this.elementType = elementType;
+ this.allowNulls = allowNulls;
+ }
+
+ // -------------------------Public Methods------------------
+
+ /**
+ * Adds the specified element to this set if it is not already
+ * present.
+ *
+ * @param o element to be added to this set.
+ * @return <tt>true</tt> if the set did not already contain the specified
+ * element.
+ * @see java.util.TreeSet
+ */
+ public boolean add(Object o) {
+ SCOHelper.debug(_TreeSet, "add"); // NOI18N
+
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ boolean modified = super.add(o);
+ if (modified) {
+ if (removed.remove(o) == false) {
+ added.add(o);
+ }
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Adds all of the elements in the specified collection to this collection
+ *
+ * @param c collection whose elements are to be added to this collection.
+ * @return <tt>true</tt> if this collection changed as a result of the
+ * call.
+ * @throws UnsupportedOperationException if the <tt>addAll</tt> method is
+ * not supported by this collection.
+ *
+ * @see java.util.AbstractCollection
+ * @see java.util.TreeSet
+ */
+ public boolean addAll(Collection c) {
+ SCOHelper.debug(_TreeSet, "addAll"); // NOI18N
+
+ // iterate the collection and make a list of wrong elements.
+ Throwable[] err = new Throwable[c.size()];
+ int l = 0;
+
+ Iterator i = c.iterator();
+ while (i.hasNext()) {
+ Object o = i.next();
+ try {
+ SCOHelper.assertNullsAllowed(o, allowNulls);
+ SCOHelper.assertElementType(o, elementType);
+ } catch (Throwable e) {
+ err[l++] = e;
+ }
+ }
+ SCOHelper.validateResult(l, err);
+
+ thaw();
+ boolean modified = false;
+ // Mark the field as dirty
+ this.makeDirty();
+
+ for (Iterator iter = c.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (!super.contains(o)) {
+ if (removed.remove(o) == false) {
+ added.add(o);
+ }
+ super.add(o);
+ modified = true;
+ }
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Removes the given element from this set if it is present.
+ *
+ * @param o object to be removed from this set, if present.
+ * @return <tt>true</tt> if the set contained the specified element.
+ * @see java.util.TreeSet
+ */
+ public boolean remove(Object o) {
+ SCOHelper.debug(_TreeSet, "remove"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ boolean modified = super.remove(o);
+ if (modified) {
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+
+ /**
+ * Removes from this collection all of its elements that are contained in
+ * the specified collection (optional operation). <p>
+ * Processes each element remove internally not to have call backs
+ * into #remove(Object).
+ *
+ * @param c elements to be removed from this collection.
+ * @return <tt>true</tt> if this collection changed as a result of the
+ * call.
+ *
+ * @throws UnsupportedOperationException removeAll is not supported
+ * by this collection.
+ *
+ * @see java.util.TreeSet
+ * @see java.util.AbstractCollection
+ */
+ public boolean removeAll(Collection c) {
+ SCOHelper.debug(_TreeSet, "removeAll"); // NOI18N
+
+ boolean modified = false;
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ for (Iterator iter = c.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (super.contains(o)) {
+ removeInternal(o);
+ modified = true;
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ }
+ }
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Retains only the elements in this collection that are contained in the
+ * specified collection (optional operation).
+ *
+ * @return <tt>true</tt> if this collection changed as a result of the
+ * call.
+ *
+ * @throws UnsupportedOperationException if the <tt>retainAll</tt> method
+ * is not supported by this collection.
+ *
+ * @see java.util.TreeSet
+ * @see java.util.AbstractCollection
+ */
+ public boolean retainAll(Collection c) {
+ SCOHelper.debug(_TreeSet, "retainAll"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ for (Iterator iter = super.iterator(); iter.hasNext();) {
+ Object o = iter.next();
+ if (!c.contains(o)) {
+ if (added.remove(o) == false) {
+ removed.add(o);
+ }
+ }
+ }
+
+ boolean modified = super.retainAll(c);
+
+ // Apply updates
+ this.trackUpdates(modified);
+
+ return modified;
+ }
+
+ /**
+ * Removes all of the elements from this set.
+ * @see java.util.TreeSet
+ */
+ public void clear() {
+ SCOHelper.debug(_TreeSet, "clear"); // NOI18N
+
+ // Mark the field as dirty
+ this.makeDirty();
+
+ thaw();
+ removed.clear();
+ added.clear();
+
+ for (Iterator iter = super.iterator(); iter.hasNext();) {
+ removed.add(iter.next());
+ }
+
+ super.clear();
+
+ // Apply updates
+ this.trackUpdates(true);
+
+ }
+
+ /**
+ * Creates and returns a copy of this object.
+ *
+ * <P>Mutable Second Class Objects are required to provide a public
+ * clone method in order to allow for copying PersistenceCapable
+ * objects. In contrast to Object.clone(), this method must not throw a
+ * CloneNotSupportedException.
+ */
+ public Object clone() {
+ SCOHelper.debug(_TreeSet, "clone"); // NOI18N
+
+ Object obj = super.clone();
+ if (obj instanceof SCO) {
+ ((SCO)obj).unsetOwner(owner, fieldNumber);
+ }
+ return obj;
+ }
+
+ /**
+ * @see SCOCollection#reset()
+ */
+ public void reset() {
+ added.clear();
+ removed.clear();
+ frozenElements = null;
+ }
+
+ /**
+ * @see SCOCollection#addInternal(Object o)
+ */
+ public void addInternal(Object o) {
+ super.add(o);
+ }
+
+
+ /**
+ * @see SCOCollection#addAllInternal(Collection c)
+ */
+ public void addAllInternal(Collection c) {
+ for (Iterator iter = c.iterator(); iter.hasNext();) {
+ super.add(iter.next());
+ }
+ }
+
+ /**
+ * @see SCOCollection#getAdded()
+ */
+ public Collection getAdded() {
+ return (Collection)added;
+ }
+
+ /**
+ * @see SCOCollection#getRemoved()
+ */
+ public Collection getRemoved() {
+ return (Collection)removed;
+ }
+
+
+ /**
+ * @see SCOCollection#clearInternal()
+ */
+ public void clearInternal() {
+ super.clear();
+ this.reset();
+ }
+
+ /**
+ * @see SCOCollection#removeInternal(Object o)
+ */
+ public void removeInternal(Object o) {
+ super.remove(o);
+ }
+
+ /**
+ * @see SCO#unsetOwner(Object owner, int fieldNumber)
+ */
+ public void unsetOwner(Object owner, int fieldNumber) {
+ // Unset only if owner and fieldNumber match.
+ if (this.owner == owner && this.fieldNumber == fieldNumber) {
+ this.owner = null;
+ this.fieldNumber = -1;
+ }
+ }
+
+ /**
+ * @see SCO#setOwner (Object owner, int fieldNumber)
+ */
+ public void setOwner (Object owner, int fieldNumber) {
+ // Set only if it was not set before.
+ if (this.owner == null && owner instanceof StateManagerInternal) {
+ this.owner = (StateManagerInternal)owner;
+ this.fieldNumber = fieldNumber;
+ }
+ }
+
+ /**
+ * @see SCO#getOwner()
+ */
+ public Object getOwner() {
+ return SCOHelper.getOwner(owner);
+ }
+
+ /**
+ * @see SCO#getFieldName()
+ */
+ public String getFieldName() {
+ return SCOHelper.getFieldName(owner, fieldNumber);
+ }
+
+ /**
+ * Notify StateManager to mark field as dirty.
+ */
+ private void makeDirty() {
+ if (owner != null) {
+ owner.makeDirty(fieldNumber); //
+ }
+ }
+ /**
+ * Notify StateManager to process the changes.
+ */
+ private void trackUpdates(boolean modified) {
+ if (modified && owner != null) {
+ owner.trackUpdates(fieldNumber, this);
+ }
+ }
+
+ /**
+ * @see SCOCollection#getElementType() {
+ */
+ public Class getElementType() {
+ return elementType;
+ }
+
+ /**
+ * @see SCOCollection#allowNulls() {
+ */
+ public boolean allowNulls() {
+ return allowNulls;
+ }
+
+ /** These methods need to thaw the map before performing the operation.
+ */
+
+ public boolean contains(Object o) {
+ thaw();
+ return super.contains(o);
+ }
+
+ public boolean containsAll(Collection c) {
+ thaw();
+ return super.containsAll(c);
+ }
+
+ public boolean isEmpty() {
+ thaw();
+ return super.isEmpty();
+ }
+
+ public Iterator iterator() {
+ thaw();
+ return super.iterator();
+ }
+
+ public int size() {
+ thaw();
+ return super.size();
+ }
+
+ public boolean equals(Object o) {
+ thaw();
+ return super.equals(o);
+ }
+
+ public int hashCode() {
+ thaw();
+ return super.hashCode();
+ }
+
+ public String toString() {
+ thaw();
+ return super.toString();
+ }
+
+ public SortedSet subSet(Object fromElement, Object toElement) {
+ thaw();
+ return super.subSet(fromElement, toElement);
+ }
+
+ public SortedSet headSet(Object toElement) {
+ thaw();
+ return super.headSet(toElement);
+ }
+
+ public SortedSet tailSet(Object fromElement) {
+ thaw();
+ return super.tailSet(fromElement);
+ }
+
+ public Comparator comparator() {
+ thaw();
+ return super.comparator();
+ }
+
+ public Object first() throws NoSuchElementException {
+ thaw();
+ return super.first();
+ }
+
+ public Object last() throws NoSuchElementException {
+ thaw();
+ return super.last();
+ }
+
+ /** Returns the frozen state of this set.
+ * @since 1.0.1
+ * @return true if this set is frozen.
+ */
+ private boolean isFrozen() {
+ return frozenElements != null;
+ }
+
+ /** Returns the frozen contents of this Collection, if this Collection
+ * is implicitly user-orderable. If the collection is not frozen already,
+ * freeze it first.
+ * @since 1.0.1
+ * @return the frozen elements of this collection.
+ */
+ private Object[] getFrozen() {
+ if (!isFrozen()) {
+ frozenElements = Freezer.freeze(this, super.size());
+ }
+ return frozenElements;
+ }
+
+ /** Set the contents of this Collection from the frozen elements, if this Collection
+ * is implicitly user-orderable.
+ * @since 1.0.1
+ * @param elements the frozen elements of this set.
+ */
+ public void setFrozen(Object[] elements) {
+ frozenElements = elements;
+ }
+
+ /**
+ * Thaw the frozen elements of this collection. If the elements are frozen,
+ * retrieve them from the datastore and internally add them. Then reset
+ * the frozen state since they're not frozen any more.
+ * @since 1.0.1
+ */
+ private void thaw() {
+ if (isFrozen()) {
+ frozenElements = Freezer.thaw(this, owner, frozenElements);
+ }
+ }
+
+ /** Create a new iterator over the frozen elements without thawing.
+ * @since 1.0.1
+ * @return the frozen iterator.
+ */
+ public Iterator frozenIterator() {
+ return Freezer.createFrozenIterator(getFrozen());
+ }
+
+ /** Create an iterator regardless whether the collection is frozen.
+ * If frozen, don't thaw the collection, but get a frozen iterator.
+ * If thawed, get a regular iterator.
+ * @since 1.0.1
+ * @return the iterator.
+ */
+ public Iterator eitherIterator() {
+ if (isFrozen()) {
+ return frozenIterator();
+ } else {
+ return super.iterator();
+ }
+ }
+
+}