summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.datastore/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'projects/net.wotonomy.datastore/src/main')
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataIndex.java111
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataKey.java142
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataSoup.java257
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataStore.java94
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataView.java111
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultComparator.java145
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataIndex.java239
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataView.java557
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DuplicateList.java49
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/FileSoup.java468
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/SerializedFileSoup.java120
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/UniquelyIdentifiable.java40
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/XMLFileSoup.java130
-rw-r--r--projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/package.html19
14 files changed, 2482 insertions, 0 deletions
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataIndex.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataIndex.java
new file mode 100644
index 0000000..89fa1eb
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataIndex.java
@@ -0,0 +1,111 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+* A DataIndex maintains a list of objects associated with values.
+* The objects can then be retrieved based on the values. This class
+* should not be much more complex than a simple map or list because
+* the DataSoup is responsible for populating it.
+*/
+public interface DataIndex extends Serializable
+{
+ /**
+ * Gets the name of this index. The DataSoup uses this to
+ * uniquely refer to this index.
+ * @return The name of this index.
+ */
+ public String getName();
+
+ /**
+ * The property managed by this index. This is the property
+ * used when the DataSoup builds and rebuilds this index.
+ * @return The property managed by this index.
+ */
+ public String getProperty();
+
+ /**
+ * Adds an object to be associated with the specified value.
+ * @param anObject A data object, usually but not always a DataKey.
+ * @param newValue The property value to be associated with the data object.
+ * @return The data object that was inserted, or null if an error occurred.
+ */
+ public Object addObject( Object anObject, Object newValue );
+
+ /**
+ * Updates an object previously associated with the specified
+ * value to be associated with the specified new value.
+ * @param anObject A data object, usually but not always a DataKey.
+ * @param oldValue The value currently associated with the data object.
+ * @param newValue The value to be associated with the data object.
+ * @return The data object that was updated, or null if an error occurred.
+ */
+ public Object updateObject( Object anObject,
+ Object oldValue, Object newValue );
+
+ /**
+ * Removes an object from the index.
+ * @param anObject A data object, usually but not always a DataKey.
+ * @param oldValue The value currently associated with the data object.
+ * @return The data object that was removed, or null if not found or error.
+ */
+ public Object removeObject( Object anObject, Object oldValue );
+
+ /**
+ * Removes all objects from the index. Usually called before
+ * rebuilding the index.
+ */
+ public void clear();
+
+ /**
+ * Returns all objects in the index whose associated values fall
+ * between the two specified values, inclusive.
+ * @param beginValue The beginning value, or null for all values
+ * up to an including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A List of the matching objects, ordered in increasing
+ * value, or null for invalid query parameters or other error.
+ */
+ public List query( Object beginValue, Object endValue );
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:46:50 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:35 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataKey.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataKey.java
new file mode 100644
index 0000000..6fe574f
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataKey.java
@@ -0,0 +1,142 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.Serializable;
+
+import net.wotonomy.foundation.internal.ValueConverter;
+
+public class DataKey implements Comparable, Serializable, Cloneable
+{
+ static final long serialVersionUID = 8421127539579065705L;
+
+ Long key;
+
+ public DataKey()
+ {
+ key = new Long( 0 );
+ }
+
+ /**
+ * Converts string representation to new object.
+ */
+ public DataKey( String aString )
+ {
+ this();
+ setKeyString( aString );
+ }
+
+ public int hashCode()
+ {
+ return key.intValue();
+ }
+
+ public void increment()
+ {
+ key = new Long( key.longValue() + 1 );
+ }
+
+ public Object clone()
+ {
+ return new DataKey( this.toString() );
+ }
+
+ public String toString()
+ {
+ return key.toString();
+ }
+
+ public String getKeyString()
+ {
+ return key.toString();
+ }
+
+ public void setKeyString( String aString )
+ {
+ Long parsed = ValueConverter.getLong( aString );
+ if ( parsed != null ) key = parsed;
+ }
+
+ public boolean equals( Object anObject )
+ {
+ if ( anObject instanceof String )
+ {
+ if ( toString().equals( anObject ) )
+ {
+ return true;
+ }
+ }
+ if ( ! ( anObject instanceof DataKey ) ) return false;
+ return key.equals( ((DataKey)anObject).key );
+ }
+
+ public int compareTo( Object anObject )
+ {
+ if ( anObject instanceof String )
+ {
+ if ( toString().equals( anObject ) )
+ {
+ return 0;
+ }
+ }
+ if ( ! ( anObject instanceof DataKey ) )
+ {
+ Long converted = (Long) ValueConverter.getLong( anObject );
+ if ( converted != null )
+ {
+ return (int) ( key.longValue() - converted.longValue() );
+ }
+ return 0;
+ };
+ return (int) ( key.longValue() - ((DataKey)anObject).key.longValue() );
+ }
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.4 2003/08/14 19:29:38 chochos
+ * minor cleanup (imports, static method calls, etc)
+ *
+ * Revision 1.3 2001/02/23 23:44:44 mpowers
+ * Fixes for hashcode to ensure proper key comparison.
+ *
+ * Revision 1.2 2001/02/15 21:12:41 mpowers
+ * Added accessors for key throughout the api. This breaks compatibility.
+ * insertObject now returns the permanent key for the newly created object.
+ * The old way returned a copy of the object which was an additional read
+ * that was often ignored. Now you can read it only if you need it.
+ * Furthermore, there was not other way of getting the permanent key.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:04 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataSoup.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataSoup.java
new file mode 100644
index 0000000..3c37d43
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataSoup.java
@@ -0,0 +1,257 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.util.Collection;
+
+public interface DataSoup
+{
+ /**
+ * Adds the specified object to the soup and returns the key
+ * for the new object by which it may be subsequently retrieved.
+ * Null indicates an error, probably due to serialization.
+ * @param anObject Object to be added to soup.
+ * @return The unique identifier used for the new object.
+ */
+ public DataKey addObject( Object anObject );
+
+ /**
+ * Removes the specified object from the soup and returns
+ * the removed object as read from the soup (which is the
+ * original copy of the object). Null indicates object not found.
+ * @param aKey A key for an object to be removed.
+ * @return The object that was removed, or null if not found or error.
+ */
+ public Object removeObject( DataKey aKey );
+
+ /**
+ * Updates the specified object and returns the object
+ * as updated. Null indicates an error writing the object.
+ * @param aKey A key for an object to be updated.
+ * @param aKey The new object for that key.
+ * @return A copy of the updated object, possibly updated,
+ * or null if not found or error.
+ */
+ public Object updateObject( DataKey aKey, Object updatedObject );
+
+ /**
+ * Gets object from data store whose identifier is equal
+ * to the specified object.
+ * @param aKey A key for an object to be retrieved.
+ * @return The corresponding object from the soup.
+ */
+ public Object getObjectByKey( DataKey aKey );
+
+ /**
+ * Registers an object that may or may not be created
+ * later, returning a temporary but uniquely identifiable
+ * key. The key will be replaced with a permanent key when
+ * the object is created with addObject().
+ * @param anObject An object to be registered.
+ * @return A temporary key for this object.
+ */
+ public DataKey registerTemporaryObject( Object anObject );
+
+ // index management
+
+ /**
+ * Adds an index to the soup.
+ * @param aName The string identifier for this index.
+ * @param aProperty The property on which this index will be based.
+ */
+ public void addIndex( String aName, String aProperty );
+
+ /**
+ * Deletes the specified index from the soup.
+ * @param aName The string identifier for the index to be removed.
+ */
+ public void removeIndex( String aName );
+
+ /**
+ * Gets a collection of all indices in this soup.
+ * @return A collection of all indices in this soup.
+ */
+ public Collection getAllIndices();
+
+ // relationship management
+
+ /**
+ * Adds a relation to entries in another soup.
+ * @param aProperty The property on which this relation will be based.
+ * @param aSoup The name of the soup to be related in this store.
+ */
+// public void addRelation( String aProperty, String aSoup );
+
+ /**
+ * Deletes the specified relation to entries in another soup.
+ * @param aProperty The property on which this relation will be based.
+ * @param aSoup The name of the soup to be related in this store.
+ */
+// public void removeRelation( String aProperty, String aSoup );
+
+ /**
+ * Gets a collection of all relations in this soup.
+ * @return A collection of all relation in this soup.
+ */
+// public Collection getAllRelations();
+
+ // queries
+
+ /**
+ * Returns an empty data view, suitable for creating
+ * new entries in the soup.
+ * @return A DataView containing no entries.
+ */
+ public DataView createView();
+
+ /**
+ * Queries by the specified pre-generated index, if it exists.
+ * Will return objects whose values for the indexed property
+ * fall between the two values inclusive.
+ * Otherwise, falls through to queryByProperty.
+ * @param anIndexName The index to be queried.
+ * @param beginValue The beginning value, or null for all values
+ * up to an including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView queryByIndex(
+ String anIndexName, Object beginKey, Object endKey );
+
+ /**
+ * Generates an index based on the specified property
+ * and then executes the query.
+ * Will return objects whose values for the specified property
+ * fall between the two values inclusive.
+ * @param aPropertyName The property to be queried. If null,
+ * will query the objects directly with queryObjects().
+ * @param beginValue The beginning value, or null for all values
+ * up to an including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView queryByProperty(
+ String aPropertyName, Object beginKey, Object endKey );
+
+ /**
+ * Generates an index based on the values of the objects themselves
+ * and then executes the query.
+ * Will return objects whose values fall between the two values inclusive.
+ * @param beginValue The beginning value, or null for all values
+ * up to and including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView queryObjects( Object beginKey, Object endKey );
+
+ /**
+ * Returns a view containing the objects for the specified keys.
+ * @param aKeyList A collection of keys to be placed in the view.
+ * @return A DataView containing the objects for the corresponding
+ * keys, in the order in which the keys are returned from the collection.
+ */
+ public DataView queryByKeys( Collection aKeyList );
+
+ /**
+ * As queryByIndex, but with objects returned in reverse order.
+ * @param anIndexName The index to be queried.
+ * @param beginValue The beginning value, or null for all values
+ * up to and including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView reverseQueryByIndex(
+ String anIndexName, Object beginKey, Object endKey );
+
+ /**
+ * As queryByProperty, but with objects returned in reverse order.
+ * @param aPropertyName The property to be queried. If null,
+ * will query the objects directly with queryObjects().
+ * @param beginValue The beginning value, or null for all values
+ * up to and including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView reverseQueryByProperty(
+ String aPropertyName, Object beginKey, Object endKey );
+
+ /**
+ * As queryObjects, but with objects returned in reverse order.
+ * @param beginValue The beginning value, or null for all values
+ * up to and including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView reverseQueryObjects( Object beginKey, Object endKey );
+
+// public void addIndex( String aName, DataIndex anIndex ) {}
+// public void removeIndex( String aName ) {}
+// public void addTaggedObject( String aKey, Serializable anObject )
+// public Object getTaggedObject( String aKey );
+// public void removeTaggedObject( String aKey );
+// public void setMetaData(
+// String aMetaProperty, Serializable aValue, Serializable anObject );
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.4 2003/08/14 19:29:38 chochos
+ * minor cleanup (imports, static method calls, etc)
+ *
+ * Revision 1.3 2001/03/05 22:12:11 mpowers
+ * Created the control package for a datastore-specific implementation
+ * of EOObjectStore.
+ *
+ * Revision 1.2 2001/02/15 21:12:41 mpowers
+ * Added accessors for key throughout the api. This breaks compatibility.
+ * insertObject now returns the permanent key for the newly created object.
+ * The old way returned a copy of the object which was an additional read
+ * that was often ignored. Now you can read it only if you need it.
+ * Furthermore, there was not other way of getting the permanent key.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:05 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataStore.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataStore.java
new file mode 100644
index 0000000..28fbc90
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataStore.java
@@ -0,0 +1,94 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Iterator;
+
+public class DataStore implements Serializable
+{
+ protected File homeDirectory;
+
+ public DataStore( String aPath )
+ {
+ homeDirectory = new File( aPath );
+
+ // if specified directory does not exist
+ if ( ! homeDirectory.exists() )
+ {
+ homeDirectory.mkdirs();
+ }
+
+ // if existing path is a file, exit with error
+ if ( homeDirectory.isDirectory() )
+ {
+ new RuntimeException( "DataStore: Specified directory is a file." );
+ }
+ }
+
+ public File getHomeDirectory()
+ {
+ return homeDirectory;
+ }
+
+
+ public DataSoup getSoupForName( String aName )
+ {
+ return null;
+ }
+ public void removeSoup( DataSoup aSoup )
+ {
+ // FIXME
+ }
+ public Iterator getAllSoups()
+ {
+ return null;
+ }
+
+ public static void main( String[] argv )
+ {
+ new DataStore( "/Local/Users/michael/Projects/test/data" );
+ }
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.2 2001/03/05 22:12:11 mpowers
+ * Created the control package for a datastore-specific implementation
+ * of EOObjectStore.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:05 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataView.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataView.java
new file mode 100644
index 0000000..fec9cfc
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DataView.java
@@ -0,0 +1,111 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.util.List;
+import java.util.Observer;
+
+public interface DataView extends List
+{
+// public void newQuery( String aProperty, Object beginKey, Object endKey );
+// public void addQuery( String aProperty, Object beginKey, Object endKey );
+// public void removeQuery( String aProperty, Object beginKey, Object endKey );
+// public void retainQuery( String aProperty, Object beginKey, Object endKey );
+
+ /**
+ * This method is called to notify the DataView
+ * that one of its objects has been modified and
+ * should be updated when the view is committed.
+ */
+ public void update(Object o);
+
+ /**
+ * This method is called commit all changes to
+ * the DataView to its data store. The list
+ * elements may be refreshed from the datastore,
+ * although the list itself should remain unchanged.
+ * @return True if the commit was successful,
+ * otherwise false.
+ */
+ public boolean commit();
+
+ /**
+ * Called to add the specified observer to the
+ * list of observers that should receive notifications
+ * when the view if modified. DataViews notify
+ * when objects are added, updated, or deleted,
+ * passing the affected object as the parameter
+ * to the Observer's notify method.
+ * @param o The observer to add.
+ */
+ public void addObserver(Observer o);
+
+ /**
+ * Called to remove the specified observer from the
+ * list of observers that should receive notifications
+ * when the view if modified.
+ * @param o The observer to delete.
+ */
+ public void deleteObserver(Observer o);
+
+ /**
+ * Called to clear the list of observers that should
+ * receive notifications when the view if modified.
+ */
+ public void deleteObservers();
+
+ /**
+ * Returns the key for the specified object.
+ * If the object is not in the view, returns null.
+ */
+ public DataKey getKeyForObject( Object anObject );
+
+ /**
+ * Returns the object for the specified key.
+ * If the key is not in the view, returns null.
+ */
+ public Object getObjectForKey( DataKey aKey );
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.2 2001/02/15 21:12:41 mpowers
+ * Added accessors for key throughout the api. This breaks compatibility.
+ * insertObject now returns the permanent key for the newly created object.
+ * The old way returned a copy of the object which was an additional read
+ * that was often ignored. Now you can read it only if you need it.
+ * Furthermore, there was not other way of getting the permanent key.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:05 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultComparator.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultComparator.java
new file mode 100644
index 0000000..b97b8a1
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultComparator.java
@@ -0,0 +1,145 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import net.wotonomy.foundation.internal.ValueConverter;
+
+/**
+* DefaultComparator exists to compare basic java
+* primitive wrappers, since these classes don't
+* implement Comparable in jdk 1.1.x. Also uses
+* ValueConverter to try to match types for comparison.
+*/
+public class DefaultComparator implements Comparator, Serializable
+{
+ public int compare(Object o1, Object o2)
+ {
+// System.out.println( "compare: " + o1 + " : " + o1.getClass() + " : " + o2 + " : " + o2.getClass() );
+/*
+ if ( ( o1 instanceof Comparable ) && ( o2 instanceof Comparable ) )
+ {
+ return ((Comparable)o1).compareTo( o2 );
+ }
+*/
+ if ( ( o1 instanceof Number ) && ( o2 instanceof Number ) )
+ {
+ // TODO: special case for each type would be faster
+ return (int)
+ ( ((Number)o1).doubleValue() - ((Number)o2).doubleValue() );
+ }
+
+ if ( o1 instanceof StringBuffer )
+ {
+ o1 = o1.toString();
+ }
+ if ( o2 instanceof StringBuffer )
+ {
+ o2 = o2.toString();
+ }
+
+ if ( ( o1 instanceof String ) && ( o2 instanceof String ) )
+ {
+ return ((String)o1).compareTo( ((String)o2) );
+ }
+
+ if ( ( o1 instanceof Character ) && ( o2 instanceof Character ) )
+ {
+ return (int)
+ ((Character)o1).charValue() - ((Character)o2).charValue();
+ }
+
+ if ( ( o1 instanceof Byte ) && ( o2 instanceof Byte ) )
+ {
+ return (int)
+ ((Byte)o1).byteValue() - ((Byte)o2).byteValue();
+ }
+
+ if ( ( o1 instanceof Boolean ) && ( o2 instanceof Boolean ) )
+ {
+ if ( o1.equals( o2 ) ) return 0;
+
+ // presumably TRUE is greater than FALSE
+ if ( o1.equals( Boolean.TRUE ) ) return 1;
+ return -1;
+ }
+
+ // handle all NULL cases: NULL is less than anything else.
+ if ( ( o1 == null ) && ( o2 == null ) ) return 0;
+ if ( ( o1 == null ) && ( o2 != null ) ) return -1;
+ if ( ( o2 == null ) && ( o1 != null ) ) return 1;
+
+ if ( o1.getClass() != o2.getClass() )
+ {
+ Object convertedValue;
+
+ if ( ! ( o2 instanceof String ) )
+ // (string should be lowest common demoninator, if possible)
+ {
+ // convert first to second's type
+ convertedValue =
+ ValueConverter.convertObjectToClass( o1, o2.getClass() );
+ if ( convertedValue != null )
+ {
+ return compare( convertedValue, o2 );
+ }
+ }
+
+ // convert second to first's type
+ convertedValue =
+ ValueConverter.convertObjectToClass( o2, o1.getClass() );
+ if ( convertedValue != null )
+ {
+ return -1 * compare( convertedValue, o1 ); // reverse result
+ }
+ }
+
+ // we tried really hard, but these values are incomparable:
+ // we'll consider them equal.
+ return 0;
+ }
+
+ public boolean equals(Object obj)
+ {
+ return (obj == this);
+ }
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:08 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.3 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataIndex.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataIndex.java
new file mode 100644
index 0000000..a8ede78
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataIndex.java
@@ -0,0 +1,239 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.TreeMap;
+
+/**
+* This implementation of DataIndex wraps a TreeMap and
+* adds the ability to contain objects with duplicate keys.
+*/
+public class DefaultDataIndex implements DataIndex
+{
+ static final long serialVersionUID = -3759982714240822885L;
+
+ protected String name;
+ protected String property;
+ private TreeMap treeMap;
+ private Comparator comparator;
+
+ public DefaultDataIndex()
+ {
+ comparator = new DefaultComparator();
+ setTreeMap( new TreeMap( new DefaultComparator() ) );
+ }
+
+ public DefaultDataIndex( String aName, String aProperty )
+ {
+ this();
+ setName( aName );
+ setProperty( aProperty );
+ }
+
+ // included for xml serialization
+ public Comparator getComparator() { return comparator; }
+ public void setComparator( Comparator aComparator )
+ {
+ comparator = aComparator;
+ // set comparator and copy contents
+ TreeMap map = getTreeMap();
+ setTreeMap( new TreeMap( comparator ) );
+ getTreeMap().putAll( map );
+
+ }
+
+ public String getName() { return name; };
+ public void setName( String aName ) { name = aName; }
+ public String getProperty() { return property; };
+ public void setProperty( String aProperty ) { property = aProperty; }
+ public TreeMap getTreeMap() { return treeMap; }
+ public void setTreeMap( TreeMap aMap ) { treeMap = aMap; }
+
+ public List query( Object beginValue, Object endValue )
+ {
+//System.out.println( "DefaultDataIndex.query: " + beginValue + " : " + endValue );
+ List result = new LinkedList();
+ if ( endValue == null )
+ {
+ if ( beginValue == null )
+ {
+ // begin and end are null, return entire set
+ populateListFromIterator( result, treeMap.values().iterator() );
+ return result;
+ }
+
+ // only end is null, return all starting from beginValue
+ populateListFromIterator( result,
+ treeMap.tailMap( beginValue ).values().iterator() );
+ return result;
+ }
+ else
+ if ( beginValue == null )
+ {
+ // only begin is null, return all ending with endValue
+ populateListFromIterator( result,
+ treeMap.headMap( endValue ).values().iterator() );
+ }
+ else
+ {
+ // begin and end are specified, return all inclusive
+ populateListFromIterator( result,
+ treeMap.subMap( beginValue, endValue ).values().iterator() );
+ }
+
+ // append endValue results, so it's inclusive
+ Object o = treeMap.get( endValue );
+ if ( o != null )
+ {
+ if ( o instanceof DuplicateList )
+ {
+ populateListFromIterator( result,
+ ((DuplicateList)o).iterator() );
+ }
+ else
+ {
+ result.add( o );
+ }
+ }
+
+ // return complete result
+ return result;
+ }
+
+ protected void populateListFromIterator( List aList, Iterator it )
+ {
+ Object o;
+ while ( it.hasNext() )
+ {
+ o = it.next();
+ if ( o instanceof DuplicateList )
+ {
+ populateListFromIterator(
+ aList, ((DuplicateList)o).iterator() );
+ }
+ else
+ {
+ aList.add( o );
+ }
+ }
+ }
+
+ public Object addObject( Object anObject, Object newValue )
+ {
+ Object o = treeMap.get( newValue );
+ if ( o != null )
+ {
+ if ( o instanceof DuplicateList )
+ {
+ ((DuplicateList)o).add( anObject );
+ return anObject;
+ }
+
+ DuplicateList list = new DuplicateList();
+ list.add( o );
+ list.add( anObject );
+ anObject = list;
+
+ }
+if ( anObject == null ) new RuntimeException().printStackTrace();
+
+ treeMap.put( newValue, anObject );
+ return anObject;
+ }
+
+ public Object updateObject( Object anObject,
+ Object oldValue, Object newValue )
+ {
+ removeObject( anObject, oldValue );
+ return addObject( anObject, newValue );
+ }
+
+ public Object removeObject( Object anObject, Object oldValue )
+ {
+ Object o = treeMap.get( oldValue );
+ if ( o != null )
+ {
+ if ( o instanceof DuplicateList )
+ {
+ // remove this item from the list
+ DuplicateList list = (DuplicateList) o;
+ list.remove( anObject );
+
+ // if there are still duplicates, return
+ if ( list.size() > 1 )
+ return anObject;
+
+ // else, list size must be one
+ if ( list.size() == 0 )
+ {
+ System.out.println( "DefaultDataIndex.deleteObject: " + oldValue
+ + " : list size is 1 : this should never happen." );
+ return null;
+ }
+
+ // replace existing list with remaining item from list
+ treeMap.remove( oldValue );
+ treeMap.put( oldValue, list.getFirst() );
+ return anObject;
+ }
+
+ // otherwise, proceed normally
+ treeMap.remove( oldValue );
+ }
+ return anObject;
+ }
+
+ public void clear()
+ {
+ treeMap.clear();
+ }
+
+ public String toString()
+ {
+ return "DefaultDataIndex: " + name + " : " + property + " : " + treeMap.toString();
+ }
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.2 2003/08/14 19:29:38 chochos
+ * minor cleanup (imports, static method calls, etc)
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:11 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.3 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataView.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataView.java
new file mode 100644
index 0000000..ca76252
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DefaultDataView.java
@@ -0,0 +1,557 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Observable;
+
+public class DefaultDataView extends Observable
+ implements DataView
+{
+ protected DataSoup backingSoup;
+ protected List objectList;
+ protected List keyList;
+ protected List addedObjectList;
+ protected List removedObjectList;
+ protected List addedKeyList;
+ protected List removedKeyList;
+ protected Collection updatedObjects;
+ protected boolean fullyLoaded;
+
+ DefaultDataView( DataSoup aSoup, Collection aKeyList )
+ {
+ backingSoup = aSoup;
+ objectList = new ArrayList();
+ keyList = new ArrayList();
+ addedObjectList = new ArrayList();
+ removedObjectList = new ArrayList();
+ addedKeyList = new ArrayList();
+ removedKeyList = new ArrayList();
+ updatedObjects = new LinkedList();
+ fullyLoaded = false;
+
+ setKeyList( aKeyList );
+ }
+
+ void setKeyList( Collection aCollection )
+ {
+ fullyLoaded = false;
+ addedObjectList.clear();
+ removedObjectList.clear();
+ addedKeyList.clear();
+ removedKeyList.clear();
+ updatedObjects.clear();
+ keyList.clear();
+ objectList.clear();
+ if ( ( aCollection == null ) || ( aCollection.size() == 0 ) )
+ {
+ return;
+ }
+ keyList.addAll( aCollection );
+ for ( int i = 0; i < keyList.size(); i++ )
+ {
+ objectList.add( null );
+ }
+ }
+
+ public Object get( int i )
+ {
+ if ( i > keyList.size() ) return null;
+
+ Object o = objectList.get( i );
+ if ( o == null )
+ {
+ Object key = keyList.get( i );
+ if ( key == null ) return null; // FIXME!!
+
+ //NOTE: this is the gateway for getting object from the soup
+ o = backingSoup.getObjectByKey( (DataKey) key );
+
+ objectList.set( i, o );
+ }
+ return o;
+ }
+
+ public int indexOf( Object o )
+ {
+ if ( o == null ) return -1;
+ for ( int i = 0; i < size(); i++ )
+ {
+ if ( o.equals( get( i ) ) )
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private int indexOfIdenticalObject( Object o )
+ {
+ if ( o == null ) return -1;
+ for ( int i = 0; i < size(); i++ )
+ {
+ if ( o == get( i ) )
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public int lastIndexOf( Object o )
+ {
+ if ( o == null ) return -1;
+ int lastIndex = -1;
+ for ( int i = 0; i < size(); i++ )
+ {
+ if ( o.equals( get( i ) ) )
+ {
+ lastIndex = i;
+ }
+ }
+ return lastIndex;
+ }
+
+ protected void loadAllObjects()
+ {
+ if ( fullyLoaded ) return;
+ for ( int i = 0; i < keyList.size(); i++ )
+ {
+ get( i );
+ }
+ fullyLoaded = true;
+ }
+
+ // convenience to return the first object, or null.
+ public Object getObject()
+ {
+ return get( 0 );
+ }
+
+ // marked object as updated
+ public void update( Object anObject )
+ {
+ if ( contains( anObject ) )
+ {
+ if ( ! addedObjectList.contains( anObject ) )
+ {
+ updatedObjects.add( anObject );
+ }
+ }
+
+ // notification
+ setChanged();
+ notifyObservers( anObject );
+ }
+
+ // DefaultDataViews know their parent soup to perform the query
+ // and take the subset
+ public DataView query(
+ String aProperty, Object beginKey, Object endKey ) { return this; }
+
+ public boolean commit()
+ {
+ int index;
+ Object o;
+ DataKey key;
+ for ( int i = 0; i < addedObjectList.size(); i++ )
+ {
+ o = addedObjectList.get(i);
+ key = backingSoup.addObject( o );
+ index = indexOfIdenticalObject( o );
+ keyList.set( index, key );
+ }
+ addedObjectList.clear();
+ addedKeyList.clear();
+ for ( int i = 0; i < removedObjectList.size(); i++ )
+ {
+ backingSoup.removeObject( (DataKey) removedKeyList.get(i) );
+ }
+ removedObjectList.clear();
+ removedKeyList.clear();
+
+ int i;
+ Iterator it = updatedObjects.iterator();
+ while ( it.hasNext() )
+ {
+ i = objectList.indexOf( it.next() );
+ backingSoup.updateObject(
+ (DataKey) keyList.get(i), objectList.get(i) );
+ }
+ updatedObjects.clear();
+
+ // notification
+ setChanged();
+ notifyObservers( this );
+
+ return true;
+ }
+
+ public DataKey getKeyForObject( Object anObject )
+ {
+ int index = indexOfIdenticalObject( anObject );
+ if ( index == -1 ) return null;
+ return (DataKey) keyList.get( index );
+ }
+
+ public Object getObjectForKey( DataKey aKey )
+ {
+ int index = keyList.indexOf( aKey );
+ if ( index == -1 ) return null;
+ return get( index );
+ }
+
+ // interface Collection
+
+ public int size () { return keyList.size(); }
+ public boolean isEmpty () { return keyList.isEmpty(); }
+ public void clear () { setKeyList( null ); };
+ public int hashCode() { return keyList.hashCode(); };
+
+ public boolean equals (Object o)
+ {
+ if ( ! ( o instanceof DefaultDataView ) ) return false;
+ return keyList.equals( ((DefaultDataView)o).keyList );
+ }
+
+ public boolean contains (Object o)
+ {
+ loadAllObjects();
+ return objectList.contains(o);
+ }
+
+ public boolean containsAll (Collection c)
+ {
+ loadAllObjects();
+ return objectList.containsAll( c );
+ }
+
+ public boolean add (Object o)
+ {
+ // if previously removed, restore to list
+ if ( removedObjectList.contains( o ) )
+ {
+ int index = removedObjectList.indexOf( o );
+ removedObjectList.remove( index );
+ Object key = removedKeyList.remove( index );
+ objectList.add( o );
+ keyList.add( key );
+
+ // notification
+ setChanged();
+ notifyObservers( o );
+ return true;
+ }
+
+ // register and add to lists
+ Object key = backingSoup.registerTemporaryObject( o );
+ addedObjectList.add( o );
+ addedKeyList.add( key );
+ objectList.add( o );
+ keyList.add( key );
+
+ // notification
+ setChanged();
+ notifyObservers( o );
+ return true;
+ }
+
+ public Object remove( int index )
+ {
+ Object result = get( index );
+ if ( remove( result ) )
+ {
+ return result;
+ }
+ return null;
+ }
+
+ public boolean remove (Object o)
+ {
+ loadAllObjects();
+
+ int index = objectList.indexOf( o );
+ if ( index == -1 ) return false;
+
+ objectList.remove( index );
+ Object key = keyList.remove( index );
+
+ if ( updatedObjects.contains( o ) )
+ {
+ updatedObjects.remove( o );
+ }
+
+ // if not previously added, track removal
+ if ( ! ( removedObjectList.contains( o ) ) )
+ {
+ removedObjectList.add( o );
+ removedKeyList.add( key );
+ }
+
+ // notification
+ setChanged();
+ notifyObservers( o );
+
+ return true;
+ }
+
+ /**
+ * Set completely replaces the object at the specified
+ * index with the specified object. The new object is not
+ * marked as inserted, and the old object is not marked
+ * as deleted: the new object will be stored in the soup
+ * with the same key. The old object is returned.
+ */
+ public Object set( int index, Object element )
+ {
+ Object result = objectList.set( index, element );
+ update( element );
+ return result;
+ }
+
+ public void add( int index, Object o )
+ {
+ // if previously removed, restore to list
+ if ( removedObjectList.contains( o ) )
+ {
+ int i = removedObjectList.indexOf( o );
+ removedObjectList.remove( i );
+ Object key = removedKeyList.remove( i );
+ objectList.add( index, o );
+ keyList.add( index, key );
+
+ // notification
+ setChanged();
+ notifyObservers( o );
+ return;
+ }
+
+ // register and add to lists
+ Object key = backingSoup.registerTemporaryObject( o );
+ addedObjectList.add( o );
+ addedKeyList.add( key );
+ objectList.add( index, o );
+ keyList.add( index, key );
+
+ // notification
+ setChanged();
+ notifyObservers( o );
+ }
+
+ public boolean addAll (Collection c)
+ {
+ boolean result = true;
+ Iterator it = c.iterator();
+ while ( it.hasNext() )
+ {
+ result = result && add( it.next() );
+ }
+ return result;
+ }
+
+ public boolean addAll (int index, Collection c)
+ {
+ int originalSize = size();
+ boolean result = true;
+ Iterator it = c.iterator();
+ while ( it.hasNext() )
+ {
+ add( index, it.next() );
+ }
+ return ( originalSize + c.size() == size() );
+ }
+
+ public boolean removeAll (Collection c)
+ {
+ boolean result = true;
+ Iterator it = c.iterator();
+ while ( it.hasNext() )
+ {
+ result = result && remove( it.next() );
+ }
+ return result;
+ }
+
+ public boolean retainAll (Collection c)
+ {
+ removeAll( new ArrayList( objectList ) );
+ return addAll( c );
+ }
+
+ public List subList( int fromIndex, int toIndex )
+ {
+ List result = new LinkedList();
+ for ( int i = fromIndex; i < toIndex; i++ )
+ {
+ result.add( get( i ) );
+ }
+ return result;
+ }
+
+ public Iterator iterator()
+ {
+ loadAllObjects();
+ return objectList.iterator();
+
+/* // uncomment to enable on-demand loading
+ return new Iterator()
+ {
+ int index = 0;
+ public boolean hasNext() { return ( index + 1 < keyList.size() ); }
+ public Object next() {
+ return get( index++ ); }
+ public void remove()
+ {
+ Object o = get( index );
+ if ( o != null ) DefaultDataView.this.remove( o );
+ }
+ };
+*/
+ }
+
+ public ListIterator listIterator()
+ {
+ return new DataViewIterator( this );
+ }
+
+ public ListIterator listIterator( int index )
+ {
+ return new DataViewIterator( this, index );
+ }
+
+ public Object[] toArray ()
+ {
+ loadAllObjects();
+ return objectList.toArray();
+ }
+ public java.lang.Object[] toArray (Object[] array)
+ {
+ loadAllObjects();
+ return objectList.toArray( array );
+ }
+
+ protected class DataViewIterator implements ListIterator
+ {
+ DataView theView;
+ int currentIndex;
+
+ //TODO: should track current object in addition to index
+ // to track external changes to the view. (or should be listener)
+ Object currentObject;
+
+ public DataViewIterator( DataView aView )
+ {
+ this( aView, 0 );
+ }
+
+ public DataViewIterator( DataView aView, int index )
+ {
+ theView = aView;
+ if ( theView.size() > index )
+ {
+ currentIndex = index;
+ currentObject = theView.get( currentIndex );
+ }
+ else
+ {
+ index = -1;
+ currentObject = null;
+ }
+ }
+
+ public void add( Object o )
+ {
+ currentIndex++;
+ theView.add( currentIndex, o );
+ }
+
+ public boolean hasNext()
+ {
+ return ( theView.size() > currentIndex + 1 );
+ }
+
+ public boolean hasPrevious()
+ {
+ return ( currentIndex > -1 );
+ }
+
+ public Object next()
+ {
+ return theView.get( ++currentIndex );
+ }
+
+ public int nextIndex()
+ {
+ return currentIndex + 1;
+ }
+
+ public Object previous()
+ {
+ return theView.get( currentIndex-- );
+ }
+
+ public int previousIndex()
+ {
+ return currentIndex;
+ }
+
+ public void remove()
+ {
+ theView.remove( currentIndex-- );
+ }
+
+ public void set( Object o )
+ {
+ theView.set( currentIndex, o );
+ }
+
+ }
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.2 2001/02/15 21:12:41 mpowers
+ * Added accessors for key throughout the api. This breaks compatibility.
+ * insertObject now returns the permanent key for the newly created object.
+ * The old way returned a copy of the object which was an additional read
+ * that was often ignored. Now you can read it only if you need it.
+ * Furthermore, there was not other way of getting the permanent key.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:14 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DuplicateList.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DuplicateList.java
new file mode 100644
index 0000000..ed47b24
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/DuplicateList.java
@@ -0,0 +1,49 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.util.LinkedList;
+
+/**
+* DuplicateList is a marker class used to store values
+* with duplicate keys in the DataIndex TreeMap.
+*/
+public class DuplicateList extends LinkedList
+{
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:14 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/FileSoup.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/FileSoup.java
new file mode 100644
index 0000000..45cc9d8
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/FileSoup.java
@@ -0,0 +1,468 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import net.wotonomy.foundation.internal.Introspector;
+
+abstract public class FileSoup implements DataSoup
+{
+ public static final String INDEX_SUFFIX = ".idx";
+ public static final String MAP_SUFFIX = ".map";
+ private static final String ID_ID = "id";
+ private static final String IDENTITY_PROPERTY = "__SELF__";
+
+ protected DataKey nextUniqueIdentifier;
+ protected File homeDirectory;
+ protected Map indices;
+
+ public FileSoup( String aPath )
+ {
+ homeDirectory = new File( aPath );
+
+ // if specified directory does not exist
+ if ( ! homeDirectory.exists() )
+ {
+ homeDirectory.mkdirs();
+ }
+
+ // if existing path is a file, exit with error
+ if ( homeDirectory.isDirectory() )
+ {
+ new RuntimeException( "DataStore: Specified directory is a file." );
+ }
+
+ // read indices
+ DataIndex index;
+ indices = new HashMap();
+ String[] files = getHomeDirectory().list();
+ for ( int i = 0; i < files.length; i++ )
+ {
+ if ( files[i].endsWith( INDEX_SUFFIX ) )
+ {
+ index = (DataIndex) readFile( files[i] );
+ if ( index != null )
+ {
+ indices.put( index.getName(), index );
+ }
+ }
+ }
+
+ // read unique identifier
+ nextUniqueIdentifier = (DataKey) readFile( ID_ID );
+ if ( nextUniqueIdentifier == null )
+ nextUniqueIdentifier = new DataKey( "1" );
+
+ }
+
+ public File getHomeDirectory()
+ {
+ return homeDirectory;
+ }
+
+ // index management
+
+ public void addIndex( String aName, String aProperty )
+ {
+ DataIndex index = new DefaultDataIndex( aName, aProperty );
+ indices.put( index.getName(), index );
+ buildIndex( index );
+ writeIndices();
+ }
+
+ public void removeIndex( String aName )
+ {
+ indices.remove( aName );
+ writeIndices();
+ }
+
+ public Collection getAllIndices()
+ {
+ return indices.values();
+ }
+
+// public void addIndex( String aName, Index anIndex ) {}
+// public void removeIndex( String aName ) {}
+// public void addTaggedObject( String aKey, Serializable anObject )
+// public Object getTaggedObject( String aKey );
+// public void removeTaggedObject( String aKey );
+// public void setMetaData(
+// String aMetaProperty, Serializable aValue, Serializable anObject );
+
+ protected void buildIndex( DataIndex anIndex )
+ {
+//System.out.print( "FileSoup.buildIndex: " + anIndex.getName() + " : " );
+long millis = System.currentTimeMillis();
+
+ anIndex.clear();
+
+ int count = 0;
+ DataKey key;
+ Object o;
+ Object value;
+ String property = anIndex.getProperty();
+
+ String[] files = getHomeDirectory().list();
+ for ( int i = 0; i < files.length; i++ )
+ {
+ if ( ( ! files[i].equals( ID_ID.toString() )
+ && ( ! files[i].endsWith( INDEX_SUFFIX ) ) ) )
+ {
+ key = new DataKey( files[i] );
+ o = getObjectByKey( key );
+ value = getValueFromObject( o, property );
+ anIndex.addObject( key, value );
+ count++;
+ }
+ }
+
+//System.out.print( count + " objects: " );
+//System.out.println( System.currentTimeMillis() - millis + " milliseconds" );
+ }
+ protected void writeIndices()
+ {
+ DataIndex index;
+ Iterator it = getAllIndices().iterator();
+ while ( it.hasNext() )
+ {
+ index = (DataIndex) it.next();
+ writeFile( index.getName() + INDEX_SUFFIX, index );
+ }
+ }
+
+ // object management
+
+ // this implementation currently uses up a valid key increment
+ public DataKey registerTemporaryObject( Object anObject )
+ {
+ DataKey id = getNextKey();
+
+ if ( anObject instanceof UniquelyIdentifiable )
+ {
+ ((UniquelyIdentifiable)anObject).setUniqueIdentifier( id );
+ }
+
+ return id;
+ }
+
+ /**
+ * Adds the specified object to the soup and returns the key
+ * for the new object by which it may be subsequently retrieved.
+ * Null indicates an error, probably due to serialization.
+ */
+ public DataKey addObject( Object anObject )
+ {
+ DataKey id = getNextKey();
+
+ if ( anObject instanceof UniquelyIdentifiable )
+ { // set id if necessary
+ ((UniquelyIdentifiable)anObject).setUniqueIdentifier( id );
+ }
+
+ writeFile( id.toString(), anObject );
+
+ // update indices
+ DataIndex index;
+ Iterator it = indices.values().iterator();
+ while ( it.hasNext() )
+ {
+ index = (DataIndex)it.next();
+ index.addObject( id,
+ getValueFromObject( anObject, index.getProperty() ) );
+ }
+
+ writeIndices();
+
+ return id;
+ }
+
+ /**
+ * Removes the specified object from the soup and returns
+ * the removed object as read from the soup (which is the
+ * original copy of the object). Null indicates object not found.
+ */
+ public Object removeObject( DataKey aKey )
+ {
+ Object existing = getObjectByKey( aKey );
+ if ( existing != null )
+ {
+ if ( ! deleteFile( aKey.toString() ) )
+ {
+ existing = null; // return error
+ }
+ else
+ {
+ // update indices
+ DataIndex index;
+ Iterator it = indices.values().iterator();
+ while ( it.hasNext() )
+ {
+ index = (DataIndex)it.next();
+ index.removeObject( aKey,
+ getValueFromObject( existing, index.getProperty() ) );
+ }
+
+ writeIndices();
+ }
+ }
+
+ return existing;
+ }
+
+ /**
+ * Updates the specified object and returns the object
+ * as updated. Null indicates an error writing the object.
+ */
+ public Object updateObject( DataKey aKey, Object updatedObject )
+ {
+ Object existing = getObjectByKey( aKey );
+ if ( existing == null )
+ {
+ System.err.println( "FileSoup.updateObject: " +
+ "existing object could not be found with id: " + aKey );
+ return null;
+ }
+
+ Object result = null;
+ if ( updatedObject instanceof UniquelyIdentifiable )
+ {
+ // update key if changed
+ ((UniquelyIdentifiable)updatedObject).setUniqueIdentifier( aKey );
+ }
+
+ if ( writeFile( aKey.toString(), updatedObject ) )
+ {
+ result = updatedObject;
+
+ // update indices
+ DataIndex index;
+ Iterator it = indices.values().iterator();
+ while ( it.hasNext() )
+ {
+ index = (DataIndex)it.next();
+ index.updateObject( aKey,
+ getValueFromObject( existing, index.getProperty() ),
+ getValueFromObject( updatedObject, index.getProperty() ) );
+ }
+
+ writeIndices();
+ }
+
+//System.out.println( "FileSoup.updateObject: " + updatedObject + " -> " + result );
+ return getObjectByKey( aKey );
+ }
+
+ protected DataKey getNextKey()
+ {
+ DataKey id = (DataKey) nextUniqueIdentifier.clone();
+ // while ( id isn't yet in use by the soup ) increment();
+ nextUniqueIdentifier.increment();
+ writeFile( ID_ID.toString(), nextUniqueIdentifier );
+ return id;
+ }
+
+ protected DataKey getNextTempKey()
+ {
+ return getNextKey();
+ }
+
+ /**
+ * Gets object from data store whose identifier is equal
+ * to the specified object.
+ */
+ public Object getObjectByKey( DataKey aKey )
+ {
+ return readFile( aKey.toString() );
+ }
+
+ // queries
+
+ /**
+ * Returns an empty data view, suitable for creating
+ * new entries in the soup.
+ * @return A DataView containing no entries.
+ */
+ public DataView createView()
+ {
+ return new DefaultDataView( this, new LinkedList() );
+ }
+
+ /**
+ * Queries by the specified pre-generated index, if it exists.
+ * Otherwise, falls through to queryByProperty.
+ */
+ public DataView queryByIndex(
+ String anIndexName, Object beginKey, Object endKey )
+ {
+ DataIndex index = (DataIndex) indices.get( anIndexName );
+
+ if ( index == null )
+ {
+ return queryByProperty( anIndexName, beginKey, endKey );
+ }
+
+ return queryByKeys( index.query( beginKey, endKey ) );
+ }
+
+ /**
+ * Generates an index based on the specified property
+ * and then executes the query.
+ */
+ public DataView queryByProperty(
+ String aPropertyName, Object beginKey, Object endKey )
+ {
+ if ( aPropertyName == null ) aPropertyName = IDENTITY_PROPERTY;
+ DataIndex index = new DefaultDataIndex( "temporary", aPropertyName );
+ buildIndex( index );
+ return queryByKeys( index.query( beginKey, endKey ) );
+ }
+
+ /**
+ * Generates an index based on the specified property
+ * and then executes the query.
+ */
+ public DataView queryObjects( Object beginKey, Object endKey )
+ {
+ return queryByProperty( IDENTITY_PROPERTY, beginKey, endKey );
+ }
+
+ /**
+ * Returns a view containing the objects for the specified keys.
+ */
+ public DataView queryByKeys( Collection aKeyList )
+ {
+ return new DefaultDataView( this, aKeyList );
+ }
+
+ /**
+ * As queryByIndex, but with objects returned in reverse order.
+ * @param anIndexName The index to be queried.
+ * @param beginValue The beginning value, or null for all values
+ * up to an including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView reverseQueryByIndex(
+ String anIndexName, Object beginKey, Object endKey )
+ {
+ DataIndex index = (DataIndex) indices.get( anIndexName );
+
+ if ( index == null )
+ {
+ return reverseQueryByProperty( anIndexName, beginKey, endKey );
+ }
+
+ List items = index.query( endKey, beginKey );
+ Collections.reverse( items );
+ return queryByKeys( items );
+ }
+
+ /**
+ * As queryByProperty, but with objects returned in reverse order.
+ * @param aPropertyName The property to be queried. If null,
+ * will query the objects directly with queryObjects().
+ * @param beginValue The beginning value, or null for all values
+ * up to an including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView reverseQueryByProperty(
+ String aPropertyName, Object beginKey, Object endKey )
+ {
+ if ( aPropertyName == null ) aPropertyName = IDENTITY_PROPERTY;
+ DataIndex index = new DefaultDataIndex( "temporary", aPropertyName );
+ buildIndex( index );
+ List items = index.query( endKey, beginKey );
+ Collections.reverse( items );
+ return queryByKeys( items );
+ }
+
+ /**
+ * As queryObjects, but with objects returned in reverse order.
+ * @param beginValue The beginning value, or null for all values
+ * up to an including the end key.
+ * @param endValue The ending value, or null for all values
+ * since and including the begin key.
+ * @return A DataView containing the query results, or null
+ * for invalid query parameters.
+ */
+ public DataView reverseQueryObjects( Object beginKey, Object endKey )
+ {
+ return queryByProperty( IDENTITY_PROPERTY, beginKey, endKey );
+ }
+
+ public Object getValueFromObject( Object anObject, String aProperty )
+ {
+ if ( IDENTITY_PROPERTY.equals( aProperty ) ) return anObject;
+ return Introspector.getValueForObject( anObject, aProperty );
+ }
+
+ // file access methods
+
+ abstract protected boolean writeFile( String name, Object anObject );
+ abstract protected Object readFile( String name );
+ abstract protected boolean deleteFile( String name );
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.4 2003/08/14 19:29:38 chochos
+ * minor cleanup (imports, static method calls, etc)
+ *
+ * Revision 1.3 2001/03/05 22:12:11 mpowers
+ * Created the control package for a datastore-specific implementation
+ * of EOObjectStore.
+ *
+ * Revision 1.2 2001/02/15 21:12:41 mpowers
+ * Added accessors for key throughout the api. This breaks compatibility.
+ * insertObject now returns the permanent key for the newly created object.
+ * The old way returned a copy of the object which was an additional read
+ * that was often ignored. Now you can read it only if you need it.
+ * Furthermore, there was not other way of getting the permanent key.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:20 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.3 2000/12/20 16:25:36 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/SerializedFileSoup.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/SerializedFileSoup.java
new file mode 100644
index 0000000..e466c78
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/SerializedFileSoup.java
@@ -0,0 +1,120 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+public class SerializedFileSoup extends FileSoup
+{
+ public SerializedFileSoup( String aPath )
+ {
+ super( aPath );
+ }
+
+ // file access methods
+
+ protected boolean writeFile( String name, Object anObject )
+ {
+ try
+ {
+ File f = new File( getHomeDirectory(), name );
+ ObjectOutputStream oos = new ObjectOutputStream(
+ new FileOutputStream( f ) );
+ oos.writeObject( anObject );
+ oos.flush();
+ oos.close();
+ return true;
+ }
+ catch ( Exception exc )
+ {
+ System.err.println( "SerializedFileSoup.writeFile: " + exc );
+ }
+
+ return false;
+ }
+
+ protected Object readFile( String name )
+ {
+ Object result = null;
+
+ try
+ {
+ File f = new File( getHomeDirectory(), name );
+ ObjectInputStream ois = new ObjectInputStream(
+ new FileInputStream( f ) );
+ result = ois.readObject();
+ ois.close();
+ }
+ catch ( FileNotFoundException exc )
+ {
+ result = null;
+ }
+ catch ( Exception exc )
+ {
+ System.err.println( "SerializedFileSoup.readFile: " + exc );
+ exc.printStackTrace();
+ }
+ return result;
+ }
+
+ protected boolean deleteFile( String name )
+ {
+ try
+ {
+ File f = new File( getHomeDirectory(), name );
+ if ( f.exists() )
+ {
+ f.delete();
+ return true;
+ }
+ }
+ catch ( Exception exc )
+ {
+ System.err.println( "SerializedFileSoup.deleteFile: " + exc );
+ }
+
+ return false;
+ }
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:20 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:37 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/UniquelyIdentifiable.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/UniquelyIdentifiable.java
new file mode 100644
index 0000000..104932e
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/UniquelyIdentifiable.java
@@ -0,0 +1,40 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+public interface UniquelyIdentifiable
+{
+ Object getUniqueIdentifier();
+ void setUniqueIdentifier( Object id );
+}
+
+/*
+ * $Log$
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:20 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.2 2000/12/20 16:25:37 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/XMLFileSoup.java b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/XMLFileSoup.java
new file mode 100644
index 0000000..94d85fb
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/XMLFileSoup.java
@@ -0,0 +1,130 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.datastore;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.MalformedURLException;
+
+import net.wotonomy.web.xml.XMLRPCDecoder;
+import net.wotonomy.web.xml.XMLRPCEncoder;
+
+public class XMLFileSoup extends FileSoup
+{
+ public XMLFileSoup( String aPath )
+ {
+ super( aPath );
+ }
+
+ // file access methods
+
+ protected boolean writeFile( String name, Object anObject )
+ {
+//System.out.print( "writeFile: " + name + "..." );
+ try
+ {
+ File f = new File( getHomeDirectory(), name );
+ FileOutputStream fos = new FileOutputStream( f );
+ XMLRPCEncoder encoder = new XMLRPCEncoder();
+ encoder.encode( anObject, fos );
+ fos.flush();
+ fos.close();
+ }
+ catch ( Exception exc )
+ {
+ System.err.println( "XMLFileSoup.writeFile: " + exc );
+ return false;
+ }
+//System.out.println( "done." );
+ return true;
+ }
+
+ protected Object readFile( String name )
+ {
+//System.out.print( "readFile: " + name + "..." );
+ Object result = null;
+
+ try
+ {
+ File f = new File( getHomeDirectory(), name );
+ FileInputStream fis = new FileInputStream( f );
+ XMLRPCDecoder decoder = new XMLRPCDecoder();
+ result = decoder.decode( fis, f.getAbsolutePath(), f.toURL() );
+ fis.close();
+ }
+ catch ( MalformedURLException exc )
+ {
+ result = null;
+ }
+ catch ( IOException exc )
+ {
+ result = null;
+ }
+//System.out.println( "done." );
+ return result;
+ }
+
+ protected boolean deleteFile( String name )
+ {
+ try
+ {
+ File f = new File( getHomeDirectory(), name );
+ if ( f.exists() )
+ {
+ f.delete();
+ return true;
+ }
+ }
+ catch ( Exception exc )
+ {
+ System.err.println( "XMLFileSoup.deleteFile: " + exc );
+ }
+
+ return false;
+ }
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/19 16:26:19 cgruber
+ * Move non-unit-test code to tests project
+ * Fix up code to work with proper imports
+ * Fix maven dependencies.
+ *
+ * Revision 1.1 2006/02/16 13:18:56 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.3 2003/08/14 19:29:38 chochos
+ * minor cleanup (imports, static method calls, etc)
+ *
+ * Revision 1.2 2001/02/07 19:26:28 mpowers
+ * XML classes are in new package.
+ *
+ * Revision 1.1.1.1 2000/12/21 15:47:23 mpowers
+ * Contributing wotonomy.
+ *
+ * Revision 1.6 2000/12/20 16:25:37 michael
+ * Added log to all files.
+ *
+ *
+ */
+
diff --git a/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/package.html b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/package.html
new file mode 100644
index 0000000..7ca944c
--- /dev/null
+++ b/projects/net.wotonomy.datastore/src/main/java/net/wotonomy/datastore/package.html
@@ -0,0 +1,19 @@
+<body>
+<p>
+A "low technology" object database, suitable
+for simple application persistence. The design
+goal is to simply store, retrieve, and query
+arbitrary java objects that need no knowledge of
+how they are to be persisted.
+</p>
+<p>
+DataSoup is the primary interface, with
+SerializedFileSoup and XMLFileSoup being the
+primary implementations. Both implementations
+persist arbitrary java objects to the file system,
+with some limitations.
+</p>
+<p>
+This package has dependencies on the util package.
+</p>
+</body>