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 &lt; 0 || index &gt;= size()).
+     * @exception IllegalArgumentException fromIndex &gt; 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 &lt; 0 || index &gt; 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
+     *            &lt; 0 || index &gt;= 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
+     *            &lt; 0 || index &gt; 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
+     *            &lt; 0 || index &gt; 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();
+        }
+    }
+    
+}