Added: incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/LinkedList.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/LinkedList.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/LinkedList.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/LinkedList.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/sco/SCOHelper.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SCOHelper.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SCOHelper.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SCOHelper.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/sco/SqlDate.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlDate.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlDate.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlDate.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/sco/SqlTime.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlTime.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlTime.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlTime.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/SqlTimestamp.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/sco/TreeMap.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/TreeMap.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/TreeMap.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/TreeMap.java Fri Mar 18 17:02:29 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/ri11/src/java/org/apache/jdo/impl/sco/TreeSet.java URL: http://svn.apache.org/viewcvs/incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/TreeSet.java?view=auto&rev=158176 ============================================================================== --- incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/TreeSet.java (added) +++ incubator/jdo/trunk/ri11/src/java/org/apache/jdo/impl/sco/TreeSet.java Fri Mar 18 17:02:29 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(); + } + } + +}