summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-27 11:38:33 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-27 11:38:33 -0400
commit7c279747beb43c7e88633a6228a155a30e6834f7 (patch)
tree511176048944fa7332dc1a163a6148c46e7c61b3
Initial import
-rw-r--r--.gitignore7
-rw-r--r--israfil-foundation-cache/pom.xml29
-rw-r--r--israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java54
-rw-r--r--israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java46
-rw-r--r--israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java48
-rw-r--r--israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java96
-rw-r--r--israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java124
-rw-r--r--israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java46
-rw-r--r--israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java124
-rw-r--r--israfil-foundation-collections/pom.xml29
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java105
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java113
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java132
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java72
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java94
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java202
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java49
-rw-r--r--israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java66
-rw-r--r--israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java125
-rw-r--r--israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java107
-rw-r--r--israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java97
-rw-r--r--israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java104
-rw-r--r--israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java70
-rw-r--r--israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java55
-rw-r--r--israfil-foundation-concurrent/pom.xml28
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java64
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java77
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java82
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java212
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java109
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java70
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java62
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java101
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java53
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java71
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java50
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java90
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java49
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java97
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java64
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java74
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java85
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java104
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java61
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java79
-rw-r--r--israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java68
-rw-r--r--israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java121
-rw-r--r--israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java93
-rw-r--r--israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java218
-rw-r--r--israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java53
-rw-r--r--israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java81
-rw-r--r--israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java74
-rw-r--r--israfil-foundation-container/pom.xml21
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java98
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java55
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java64
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java69
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java80
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java63
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java216
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java57
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java62
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java64
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java48
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java58
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java48
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java48
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java62
-rw-r--r--israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java55
-rwxr-xr-xisrafil-foundation-container/src/site/apt/index.apt45
-rw-r--r--israfil-foundation-container/src/site/apt/lifecycle.apt111
-rw-r--r--israfil-foundation-container/src/site/apt/usage.apt106
-rw-r--r--israfil-foundation-container/src/site/site.xml20
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java150
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java263
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java52
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java154
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java104
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java79
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java54
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java71
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java54
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java54
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java94
-rw-r--r--israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java83
-rw-r--r--israfil-foundation-core/pom.xml21
-rwxr-xr-xisrafil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java59
-rw-r--r--israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java52
-rw-r--r--israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java54
-rw-r--r--israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java58
-rw-r--r--israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java195
-rw-r--r--israfil-foundation-core/src/test/conf/testng.xml24
-rw-r--r--israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java61
-rw-r--r--israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java90
-rw-r--r--israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java91
-rw-r--r--israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java49
-rw-r--r--israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java131
-rw-r--r--israfil-foundation-dynamic/pom.xml33
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java62
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java69
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java297
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java50
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java144
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java54
-rw-r--r--israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java197
-rw-r--r--israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java120
-rw-r--r--israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java160
-rw-r--r--israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java174
-rw-r--r--israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java210
-rw-r--r--israfil-foundation-lifecycle/pom.xml21
-rw-r--r--israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java51
-rw-r--r--israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java49
-rw-r--r--israfil-foundation-notification/pom.xml28
-rw-r--r--israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java59
-rw-r--r--israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java200
-rw-r--r--israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java180
-rw-r--r--israfil-foundation-nspace/pom.xml21
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java56
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java36
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java38
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java39
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java98
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java225
-rwxr-xr-xisrafil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java165
-rwxr-xr-xisrafil-foundation-nspace/src/site/apt/Specification.apt63
-rwxr-xr-xisrafil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd58
-rwxr-xr-xisrafil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java211
-rwxr-xr-xisrafil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java87
-rw-r--r--israfil-foundation-testing/pom.xml21
-rw-r--r--israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java1350
-rw-r--r--israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java342
-rw-r--r--israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java98
-rw-r--r--israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java113
-rw-r--r--israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java263
-rw-r--r--israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java86
-rw-r--r--israfil-foundation-valuemodel/pom.xml30
-rw-r--r--israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java23
-rw-r--r--israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java37
-rw-r--r--israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java22
-rw-r--r--israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java108
-rw-r--r--israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java44
-rw-r--r--israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java143
-rw-r--r--pom.xml151
-rwxr-xr-xtools/scripts/mvn-deploy-files185
-rwxr-xr-xtools/scripts/mvn-deploy-wlp92-jars158
145 files changed, 14360 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7f5a48b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.DS_Store
+.settings
+.svn
+.project
+target/
+.classpath
+.wtpmodules
diff --git a/israfil-foundation-cache/pom.xml b/israfil-foundation-cache/pom.xml
new file mode 100644
index 0000000..4167e2e
--- /dev/null
+++ b/israfil-foundation-cache/pom.xml
@@ -0,0 +1,29 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-cache</artifactId>
+ <name>Israfil Foundation Lightweight Caching</name>
+ <version>1.0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-core</artifactId>
+ <version>[1.0.0,1.1)</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java
new file mode 100644
index 0000000..2ad96cf
--- /dev/null
+++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Cache.java 499 2007-05-15 19:16:17Z christianedwardgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * A cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface Cache<K,T> {
+
+ public String getId();
+
+ public ObjectFactory<T> getFactory();
+
+ public void setFactory(ObjectFactory<T> factory);
+
+ public T get(K ... path) ;
+
+ public void purge(K ... path);
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java
new file mode 100644
index 0000000..06b9a29
--- /dev/null
+++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Fetcher.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * The main application class for the Quote Refresh Service.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface Fetcher {
+
+ public void fetch();
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java
new file mode 100644
index 0000000..0bdccc1
--- /dev/null
+++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Cache.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * A cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface FetcherCache {
+
+ public Object get(Fetcher fetcher, String cacheName, String itemKey, String ... path) ;
+
+ void set(String cacheName, String itemKey, Object value, String ... path);
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java
new file mode 100644
index 0000000..37530a0
--- /dev/null
+++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: GenericCache.java 499 2007-05-15 19:16:17Z christianedwardgruber $
+ */
+package net.israfil.foundation.caching;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+
+/**
+ * A non-thread-safe cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class GenericCache<K,T> implements Cache <K,T>{
+
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ private String id;
+
+ private ObjectFactory<T> factory;
+
+ private Map<K[],T> _caches = new HashMap<K[],T>();
+
+ public GenericCache(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Retrieves an object from a path in the cache
+ * @param An array of path items identifying the path through the map keys.
+ */
+ public T get(K ... path) {
+
+ // Get the item from the map
+
+ return null;
+ }
+
+ public ObjectFactory<T> getFactory() {
+ return factory;
+ }
+
+ public void purge(K... path) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setFactory(ObjectFactory<T> factory) {
+ try {
+ lock.writeLock().lock();
+ this.factory = factory;
+
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java
new file mode 100644
index 0000000..ce42bc2
--- /dev/null
+++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: GenericCache.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * A non-thread-safe cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class GenericFetcherCache implements FetcherCache {
+
+ private Map<String,Object> _caches = new HashMap<String,Object>();
+
+ /**
+ * Retrieves an object from a path in the cache
+ * @param cacheName A string identifying from which cache the object will be retrieved
+ * @param An array of path items identifying the path through the map keys.
+ */
+ public Object get(Fetcher fetcher, String cacheName, String itemKey, String ... path) {
+
+ // Fetch the map containing the item.
+ Map<String,Object> cache = _getLocationInMap(_caches,new ArrayList<String>(_prepPathList(cacheName,path)));
+
+ // Get the item from the map
+ Object o = cache.get((itemKey==null) ? "__NULL__" : itemKey);
+ if (o == null) {
+ // Item doesn't exist, so try to fetch, then retrieve again.
+ fetcher.fetch();
+ o = cache.get((itemKey==null) ? "__NULL__" : itemKey);
+ }
+ return o;
+ }
+
+
+ /**
+ * A method to set values within the cache, to be used by Fetcher implementations
+ * in setting up the cache when they fetch.
+ */
+ public void set(String cacheName, String itemKey, Object value, String ... path) {
+ List<String> pathList = _prepPathList(cacheName,path);
+ Map<String,Object> cache = _getLocationInMap(_caches,new ArrayList<String>(pathList));
+ cache.put(itemKey,value);
+ }
+
+ /**
+ * Creates a List that contains the pathelements, starting from the
+ * cache name down to the bottom, but excluding the actual final path
+ * item.
+ */
+ static List<String> _prepPathList(String cacheName,String[] pathElements) {
+ List<String> pathList;
+ if (pathElements == null || pathElements.length < 1) {
+ pathList = new ArrayList<String>();
+ } else {
+ // Need to make this explicitly an arrayList, so that
+ // add(index,value) will work.
+ pathList = new ArrayList<String>(Arrays.asList(pathElements));
+ }
+ pathList.add(0,cacheName);
+ return pathList;
+ }
+
+ /**
+ * Recursively traverses the cache map, creating maps at path locations
+ * where they do not already exist.
+ */
+ @SuppressWarnings("unchecked")
+ static Map<String, Object> _getLocationInMap(
+ Map<String, Object> currentMap, List<String> cachePath) {
+ if (cachePath == null || cachePath.size() < 1) return currentMap;
+ String cacheName = (String)cachePath.remove(0); // pull the first one
+
+ Object cacheObject = (Map<String,Object>)currentMap.get(cacheName);
+ if (cacheObject == null) {
+ cacheObject = new HashMap<String,Object>();
+ currentMap.put(cacheName,cacheObject);
+ }
+ if (! (cacheObject instanceof Map))
+ throw new IllegalArgumentException("Attempted to find a map at location ("+cachePath+") in cache ("+cacheName+"), but found a " + cacheObject.getClass().getName() + ".");
+ Map<String,Object> cache = (Map<String,Object>)cacheObject;
+
+ return _getLocationInMap(cache,cachePath);
+ }
+
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java
new file mode 100644
index 0000000..b16ee1c
--- /dev/null
+++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Fetcher.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * The main application class for the Quote Refresh Service.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface ObjectFactory <T> {
+
+ public T produce(Object ... parameters);
+
+}
diff --git a/israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java b/israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java
new file mode 100644
index 0000000..2ea505c
--- /dev/null
+++ b/israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: GenericCacheTest.java 499 2007-05-15 19:16:17Z christianedwardgruber $
+ */
+package net.israfil.foundation.caching;
+
+import net.israfil.foundation.core.Counter;
+import net.israfil.foundation.core.SimpleCounter;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: christianedwardgruber $
+ * @version $Revision: 499 $
+ */
+@Test
+public class GenericCacheTest {
+
+ Object o;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ o = "AnObject";
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ o = null;
+ }
+
+ public void testGenericCache() {
+ final Counter fetchCount = new SimpleCounter();
+ final FetcherCache c = new GenericFetcherCache();
+ Assert.assertEquals(0,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o);
+ fetchCount.increment();
+ }
+ },"testCache","testItem"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o);
+ fetchCount.increment();
+ }
+ },"testCache","testItem"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ }
+
+ public void testGenericCacheWithSubcache() {
+ final Counter fetchCount = new SimpleCounter();
+ final FetcherCache c = new GenericFetcherCache();
+ Assert.assertEquals(0,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ }
+
+ public void testGenericCacheWithDeepSubcache() {
+ final Counter fetchCount = new SimpleCounter();
+ final FetcherCache c = new GenericFetcherCache();
+ Assert.assertEquals(0,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache","subSubCache","subSubSubCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache","subSubCache","subSubSubCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache","subSubCache","subSubSubCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache","subSubCache","subSubSubCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ }
+}
diff --git a/israfil-foundation-collections/pom.xml b/israfil-foundation-collections/pom.xml
new file mode 100644
index 0000000..72014ea
--- /dev/null
+++ b/israfil-foundation-collections/pom.xml
@@ -0,0 +1,29 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-collections</artifactId>
+ <name>Israfil Foundation Collections Extras</name>
+ <version>1.0.3-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-testing</artifactId>
+ <version>1.0.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java
new file mode 100644
index 0000000..3447adc
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArraySet.java 76 2006-08-03 15:37:05Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * An ArrayList backed Set implementation, whose primary purpose is
+ * to provide a Set that maintains the order of elements based on
+ * indexes and/or the order in which items are added. Most
+ * particularly it's to guarrantee deterministic results of an
+ * iterator, where the iterator provides each element in the order
+ * of the underlying list.
+ *
+ * Unlike a LinkedHashSet, this implementation leaves a duplicate
+ * element in its original position. It's performance characteristics
+ * on input are similar, since a comparison still has to happen
+ * for de-dupliation, but obtaining the item by index is constant time.
+ *
+ * TODO: Consider making this a SortedSet, using the list order as the guarrantee. Not sure if it's a legit use of the API.
+ * @See java.util.LinkedHashSet
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class ArraySet<E> extends AbstractSet<E> {
+
+ private transient ArrayList<E> internalList;
+
+ public ArraySet() {
+ internalList = new ArrayList<E>();
+ }
+
+ public ArraySet(int initialCapacity) {
+ internalList = new ArrayList<E>(initialCapacity);
+ }
+
+ public ArraySet(Collection<E> col) {
+ internalList = new ArrayList<E>(col);
+ Iterator<E> i = col.iterator();
+ while (i.hasNext()) {
+ internalList.add(i.next());
+ }
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public int size() {
+ return internalList.size();
+ }
+
+ @Override
+ public boolean add(E o) {
+ if (internalList.contains(o)) return false;
+ else {
+ internalList.add(o);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return internalList.remove(o);
+ }
+
+ public E get(Integer index) {
+ return internalList.get(index);
+ }
+}
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java
new file mode 100644
index 0000000..880de92
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArrayUtils.java 48 2006-02-23 06:11:53Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An array utility class. This class is generic, so its usage is similar
+ * to the following:
+ * Foo[] foo1 = new Foo[]{ aFoo, bFoo, cFoo };
+ * Foo[] foo2 = new Foo[]{ dFoo, eFoo, fFoo };
+ * Foo[] fooResult = ArrayUtils.add(new Foo[],foo1,foo2);
+ *
+ * fooResult would be equivalent: new Foo[]{ aFoo, bFoo, cFoo, dFoo, eFoo, fFoo }
+ *
+ * This util is mostly helpful for putting together large batches of like
+ * arrays into a long single array, such as large groups of parameter lists
+ * or whatever.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class ArrayUtils {
+ private static final Logger logger = Logger.getLogger(ArrayUtils.class.getName());
+
+ /**
+ * Adds arrays of like type creating a new array containing
+ * all elements of the added arrays. Note that you have to
+ * pass in a typed array, because you can't create an array
+ * from a generic type in the code.
+ *
+ * i.e. you can't do this with Generics.
+ * <pre>
+ * public class Foo<T> {
+ * public T[] getArray() {
+ * T[] array = new T[a];
+ * }
+ * }
+ * </pre>
+ *
+ * However, as described in the tests, you can simply pass
+ * it an empty array of that type.
+ *
+ * @param resultBucket An array of the type you are attempting to aggregate. Can be empty. If it has sufficient space, it will be used for the aggregated result.
+ * @param arrays The arrays to be aggregated.
+ * @return An array of the provided type, containing the aggregated contents of the provided arrays.
+ */
+ public static <E> E[] aggregate(E[] resultBucket, E[] ... arrays)
+ {
+ logger.log(Level.FINER,Array.newInstance(arrays.getClass().getComponentType(),0).getClass().getCanonicalName());
+ List<E> resultList = new ArrayList<E>();
+ for (E[] t : arrays) {
+ for (E element : t) {
+ resultList.add(element);
+ }
+ }
+ logger.log(Level.FINER,resultList.toString());
+ return (E[])resultList.toArray(resultBucket);
+ }
+
+ /**
+ * A method that tests the eqivalence (content equality) of
+ * two arrays.
+ * @param a1
+ * @param a2
+ * @return
+ */
+ public static boolean equivalent(Object[] o1, Object[] o2) {
+ if (o1 == null && (o2 == null || o2.length == 0)) return true;
+ if (o2 == null && o1.length == 0) return true;
+ if (o1.length != o2.length) return false;
+ for (int i = 0; i < o1.length; i++) {
+ if (o1[i] != o2[i]) return false;
+ }
+ return true;
+ }
+
+}
+
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java
new file mode 100644
index 0000000..9258c6f
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: IterableResultSet.java 26 2006-02-13 16:35:44Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.lang.ref.WeakReference;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A simple wrapper that provides an Iterable implementation back-ended
+ * by a result-set. Allows a ResultSet to be used in a JDK 5.0 extended
+ * for-loop syntax.
+ *
+ * No result set can have more than one Iterable wrapper around it at a time.
+ * However, it is impossible for this object to know implicitly when it is
+ * no longer required (to free the reference). Therefore, when this
+ * wrapper is concluded, it should be disposed of via the dispose() method.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class IterableResultSet implements Iterable<Map<String,Object>> {
+
+ protected static final Map<ResultSet,IterableResultSet> iterables = new WeakHashMap<ResultSet,IterableResultSet>();
+ protected final WeakReference<ResultSet> resultRef;
+
+ public IterableResultSet(ResultSet result) {
+ if (iterables.containsKey(result)) throw new RuntimeException("Cannot have two IterableResultSet wrappers around the same resultset.");
+ this.resultRef = new WeakReference<ResultSet>(result);
+ }
+
+ public Iterator<Map<String,Object>> iterator() {
+ if (resultRef.get() == null) throw new RuntimeException("ResultSet object not available to iterate.");
+ return new ResultSetIterator(resultRef.get());
+ }
+
+ public void dispose() {
+ ResultSet rs = resultRef.get();
+ if (rs == null) return;
+ if (iterables.containsKey(rs)) {
+ iterables.get(rs).dispose();
+ }
+ resultRef.clear();
+ }
+
+ public static class ResultSetIterator implements Iterator<Map<String,Object>> {
+ private static final Logger logger = Logger.getLogger(ResultSetIterator.class.getName());
+ protected ResultSet result;
+
+ boolean hasNext = true;
+
+
+ public ResultSetIterator(ResultSet result) {
+ this.result = result;
+ try {
+ hasNext = result.first();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean hasNext() {
+ return hasNext;
+ }
+
+ public Map<String,Object> next() {
+ try {
+ Map<String,Object> row = new HashMap<String,Object>();
+ for(int i = 1; i <= result.getMetaData().getColumnCount(); i++) {
+ row.put(result.getMetaData().getColumnName(i),result.getObject(i));
+ }
+ hasNext = result.next();
+ return row;
+ } catch (SQLException e) {
+ logger.log(Level.FINER,"SQLException thrown while iterating across result set.",e);
+ return null;
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("Removal of records from underlying result set not supported.");
+ }
+
+ public void dispose() {
+ if (iterables.containsKey(result)) iterables.remove(result);
+ result = null;
+ }
+
+ public void finalize() throws Throwable {
+ dispose();
+ super.finalize();
+ }
+ }
+}
+
+
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java
new file mode 100644
index 0000000..3b5656d
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: IterableResultSet.java 26 2006-02-13 16:35:44Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.security.SecureRandom;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Random;
+
+/**
+ * A simple wrapper that provides an Iterable implementation that wraps
+ * a collection and returns a RandomOrderIterator when asked for an iterator.
+ *
+ * No result set can have more than one Iterable wrapper around it at a time.
+ * However, it is impossible for this object to know implicitly when it is
+ * no longer required (to free the reference). Therefore, when this
+ * wrapper is concluded, it should be disposed of via the dispose() method.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class RandomOrderIterable<E> implements Iterable<E> {
+
+ private Collection<E> _collection;
+ private Random _random = null;
+
+ public RandomOrderIterable(Collection<E> collection) {
+ _collection = collection;
+ }
+
+ public RandomOrderIterable(Collection<E> collection, Random random) {
+ this(collection);
+ _random = random;
+ }
+
+ public Iterator<E> iterator() {
+ return new RandomOrderIterator<E>(_collection,(_random == null) ? new SecureRandom() : _random);
+ }
+
+}
+
+
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java
new file mode 100644
index 0000000..8b97e4a
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArraySet.java 76 2006-08-03 15:37:05Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * An iterator that is constructed from a collection and returns the
+ * contents of the collection in random order. Note that this is
+ * an iterator over a copy of the collection, not the collection
+ * itself, so remove() is not supported, and underlying changes
+ * to the original collection will not be reflected in this iterator.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class RandomOrderIterator<E> implements Iterator<E> {
+
+ private transient List<E> _collection;
+
+ private transient Random _random = new SecureRandom();
+
+ private transient List<Integer> _indexes;
+
+
+ public RandomOrderIterator(Collection<E> collection) {
+ _collection = new ArrayList<E>(collection);
+ _indexes = new LinkedList<Integer>();
+ for (int i = 0; i < _collection.size();i++) {
+ _indexes.add(i); // populate index source.
+ }
+ }
+
+ public RandomOrderIterator(Collection<E> collection, Random random) {
+ this(collection);
+ this._random = random;
+ }
+
+ public boolean hasNext() {
+ return _indexes.size() > 0;
+ }
+
+ public E next() {
+ Integer index = _indexes.remove(_random.nextInt(_indexes.size()));
+ return _collection.get(index);
+ }
+
+ /**
+ * Because of the means required to track the current node,
+ * removing anything from the underlying collection is not supported.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+}
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java
new file mode 100644
index 0000000..0ac0164
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2003, Christian Edward Gruber
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ReciprocalHashMap.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A two-way map, backed by java.util.HashMaps, where each key matches one
+ * value and is unique, and where each value maps to a key, and is unique
+ * among all values.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ *
+ */
+public class ReciprocalHashMap<K,V> extends java.util.AbstractMap<K,V>
+ implements ReciprocalMap<K,V> {
+
+ Set<Map.Entry<K,V>> entrySetByKey = new HashSet<Map.Entry<K,V>>();
+ Set<Map.Entry<V,K>> entrySetByValue = new HashSet<Map.Entry<V,K>>();
+
+ @Override
+ public Set<Map.Entry<K,V>> entrySet() {
+ return entrySetByKey;
+ }
+
+ public Set<Map.Entry<V,K>> entrySetByValue() {
+ return entrySetByValue;
+ }
+
+ public boolean contains(K key, V value) {
+ V value1 = get(key);
+ if (value == value1) return true;
+ else if (value == null) return false; // assume null == null handled.
+ else return value.equals(value1);
+ }
+
+ public Entry<V,K> getEntryByValue(V value) {
+ Iterator<Entry<V,K>> i = entrySetByValue().iterator();
+ if (value==null) {
+ while (i.hasNext()) {
+ Entry<V,K> e = i.next();
+ if (e.getKey()==null) return e;
+ }
+ } else {
+ while (i.hasNext()) {
+ Entry<V,K> e = i.next();
+ if (value.equals(e.getKey())) return e;
+ }
+ }
+ return null;
+ }
+ public Entry<K,V> getEntryByKey(K value) {
+ Iterator<Entry<K,V>> i = entrySet().iterator();
+ if (value==null) {
+ while (i.hasNext()) {
+ Entry<K,V> e = i.next();
+ if (e.getKey()==null) return e;
+ }
+ } else {
+ while (i.hasNext()) {
+ Entry<K,V> e = i.next();
+ if (value.equals(e.getKey())) return e;
+ }
+ }
+ return null;
+ }
+
+ public K getKey(V value) {
+ Entry<V,K> e = getEntryByValue(value);
+ return (e == null) ? null : e.getValue();
+ }
+
+ public V getValue(K key) {
+ Entry<K,V> e = getEntryByKey(key);
+ return (e == null) ? null : e.getValue();
+ }
+
+ public K removeByValue(V value) {
+ Entry<V,K> valEntry = getEntryByValue(value);
+ Entry<K,V> keyEntry = getEntryByKey(valEntry.getValue());
+ if (keyEntry != null) entrySetByKey.remove(keyEntry);
+ if (valEntry != null) entrySetByValue.remove(valEntry);
+ return keyEntry.getKey();
+ }
+
+ public V removeByKey(K key) {
+ Entry<K,V> keyEntry = getEntryByKey(key);
+ Entry<V,K> valEntry = getEntryByValue(keyEntry.getValue());
+ if (keyEntry != null) entrySetByKey.remove(keyEntry);
+ if (valEntry != null) entrySetByValue.remove(valEntry);
+ return valEntry.getKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override public V remove(Object key) {
+ return this.removeByKey((K)key);
+ }
+
+
+ @Override public V put(K key, V value) {
+ Entry<K,V> keyEntry = getEntryByKey(key);
+ Entry<V,K> valueEntry = getEntryByValue(value);
+
+ V oldValue = null;
+
+ if (keyEntry != null) {
+ Entry<V,K> inverseKeyEntry = getEntryByValue(keyEntry.getValue());
+ keyEntry.getKey();
+ entrySetByKey.remove(keyEntry);
+ entrySetByValue.remove(inverseKeyEntry);
+ }
+ if (valueEntry != null) {
+ Entry<K,V> inverseValueEntry = getEntryByKey(valueEntry.getValue());
+ oldValue = valueEntry.getKey();
+ entrySetByValue.remove(valueEntry);
+ entrySetByKey.remove(inverseValueEntry);
+ }
+ entrySetByKey.add(new ReciprocalEntry<K,V>(key,value));
+ entrySetByValue.add(new ReciprocalEntry<V,K>(value,key));
+
+ return oldValue;
+ }
+
+ static class ReciprocalEntry<K, V> implements Entry<K, V> {
+ private K key;
+ private V value;
+
+ public ReciprocalEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() { return key; }
+
+ public V getValue() { return value; }
+
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ public int hashCode() {
+ return ((key == null) ? 0 : key.hashCode()) ^
+ ((value == null) ? 0 : value.hashCode());
+ }
+
+ @Override public String toString() {
+ return "ReciprocalEntry[" + key + "=" + value + "]";
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry)) return false;
+ try {
+ Map.Entry<K,V> e = (Map.Entry<K,V>)o;
+ return safeEquals(key, e.getKey()) && safeEquals(value, e.getValue());
+ } catch (ClassCastException cce) {
+ return false;
+ }
+ }
+
+ private static boolean safeEquals(Object o1, Object o2) {
+ return (o1 == null ? o2 == null : o1.equals(o2));
+ }
+ }
+
+} \ No newline at end of file
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java
new file mode 100644
index 0000000..687d3ed
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003, Christian Edward Gruber
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ReciprocalMap.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.Map;
+
+/**
+ * Interface for a two-way map, where each key matches one value and is unique,
+ * and where each value maps to a key, and is unique among all values.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface ReciprocalMap<K,V> extends Map<K,V> {
+ public boolean contains( K key, V value );
+ public K getKey( V value );
+ public K removeByValue( V value );
+ public V getValue( K key );
+ public V removeByKey( K key );
+}
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java
new file mode 100644
index 0000000..83a9f66
--- /dev/null
+++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArraySet.java 19 2006-01-30 21:52:52Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.AbstractCollection;
+import java.util.Iterator;
+
+/**
+ * A simple unmodifyable implementation of Collection that takes a single (possibly
+ * null) constructor parameter. The collection then "contains" this single object.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+//@Copyright(years={"2006"},owner="Israfil Consulting Services Corporation",license="BSD")
+
+public class SoloCollection<E> extends AbstractCollection<E> {
+ protected final E o;
+ public SoloCollection(E o) {
+ super();
+ this.o = o;
+ }
+
+ public Iterator<E> iterator() {
+ return new Iterator<E>() {
+ boolean beforeFirst = true;
+ public boolean hasNext() { return beforeFirst; }
+ public E next() { beforeFirst = false; return o; }
+ public void remove() {
+ throw new UnsupportedOperationException("Cannot remove from a singleton colelction");
+ }
+ };
+ }
+
+ public int size() { return 1; }
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java
new file mode 100644
index 0000000..5e804e4
--- /dev/null
+++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 76 $
+ */
+@Test
+public class ArraySetTest {
+
+ ArraySet<String> stringSet;
+ String string1 = "String1";
+ String string2 = "String2";
+ String string3 = "String3";
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ stringSet = new ArraySet<String>();
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ stringSet = null;
+ }
+
+ public void testBasicArrayAndListBehaviour() {
+ Assert.assertEquals(0,stringSet.size());
+ stringSet.add(string1);
+ stringSet.add(string2);
+ stringSet.add(string3);
+ Assert.assertEquals(3,stringSet.size());
+ stringSet.add(string2);
+ Assert.assertEquals(3,stringSet.size());
+ Iterator<String> iter = stringSet.iterator();
+ Assert.assertEquals(string1,iter.next());
+ Assert.assertEquals(string2,iter.next());
+ Assert.assertEquals(string3,iter.next());
+ }
+
+ public void testAddAllFromArrayList() {
+ List<String> list = new ArrayList<String>();
+ list.add(string1);
+ list.add(string2);
+ list.add(string3);
+ list.add(string2);
+ Assert.assertEquals(4,list.size());
+ stringSet.addAll(list);
+ Assert.assertEquals(3,stringSet.size());
+ Iterator<String> iter = stringSet.iterator();
+ Assert.assertEquals(string1,iter.next());
+ Assert.assertEquals(string2,iter.next());
+ Assert.assertEquals(string3,iter.next());
+ }
+
+ public void testRemove() {
+ Assert.assertEquals(0,stringSet.size());
+ stringSet.add(string1);
+ stringSet.add(string2);
+ stringSet.add(string3);
+ Assert.assertEquals(3,stringSet.size());
+ stringSet.remove(string2);
+ Assert.assertEquals(2,stringSet.size());
+ Iterator<String> iter = stringSet.iterator();
+ Assert.assertEquals(string1,iter.next());
+ Assert.assertEquals(string3,iter.next());
+ }
+
+ public void testCreateWithCapacity() {
+ stringSet = new ArraySet<String>(3);
+ stringSet.add(string1);
+ Assert.assertEquals(string1,stringSet.iterator().next());
+ }
+
+ public void testCreateWithCollection() {
+ ArrayList<String> list = new ArrayList<String>();
+ list.add(string1);
+ list.add(string2);
+ list.add(string1);
+ stringSet = new ArraySet<String>(list);
+ Assert.assertEquals(string1,stringSet.iterator().next());
+ }
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java
new file mode 100644
index 0000000..3d7edec
--- /dev/null
+++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 48 $
+ */
+@Test
+public class ArrayUtilsTest {
+
+ final String s1 = "s1",s2 = "s1",s3 = "s1",s4 = "s1",
+ s5 = "s1",s6 = "s1",s7 = "s1";
+
+ public void testArrayUtilOrder1() {
+ String[] sArray1 = new String[] { s1,s2,s3 };
+ String[] sArray2 = new String[] { s4,s5 };
+ String[] sArray3 = new String[] { s6,s7 };
+ String[] saResult = ArrayUtils.aggregate(new String[] {},sArray1,sArray2,sArray3);
+ String[] expected = new String[]{s1,s2,s3,s4,s5,s6,s7};
+ for (int i = 0; i < saResult.length ; i++ ) {
+ Assert.assertEquals(expected[i],saResult[i]);
+ }
+ Assert.assertEquals(String[].class,saResult.getClass());
+ }
+
+ public void testArrayUtilOrder2() {
+ String[] sArray2 = new String[] { s1,s2,s3 };
+ String[] sArray1 = new String[] { s4,s5 };
+ String[] sArray3 = new String[] { s6,s7 };
+ String[] saResult = ArrayUtils.aggregate(new String[] {},sArray1,sArray2,sArray3);
+ String[] expected = new String[]{s4,s5,s1,s2,s3,s6,s7};
+ for (int i = 0; i < saResult.length ; i++ ) {
+ Assert.assertEquals(expected[i],saResult[i]);
+ }
+ Assert.assertEquals(String[].class,saResult.getClass());
+ }
+
+ public void testVaryingTypeAddition() {
+ TestA tA1 = new TestA("tA1");
+ TestA[] tAa1 = new TestA[] { tA1 };
+ TestB tB1 = new TestB("tB1");
+ TestB[] tBa1 = new TestB[] { tB1 };
+ TestA[] result = ArrayUtils.aggregate(new TestA[]{},tAa1,tBa1);
+ Assert.assertEquals(2,result.length);
+ Assert.assertEquals(TestA[].class,result.getClass());
+ }
+
+ public void testStringArrayAggregation() {
+ String[] sa1 = { "s1", "s2" };
+ String[] sa2 = { "s3", "s4" };
+ String[] sa3 = ArrayUtils.aggregate(new String[]{},sa1,sa2);
+ Assert.assertEquals(sa1[0],sa3[0]);
+ Assert.assertEquals(sa1[1],sa3[1]);
+ Assert.assertEquals(sa2[0],sa3[2]);
+ Assert.assertEquals(sa2[1],sa3[3]);
+ }
+
+
+ public class TestA {
+ public final String text;
+ public TestA(String text) {
+ this.text = text;
+ }
+ }
+ public class TestB extends TestA {
+ public TestB(String ext) {
+ super(ext);
+ }
+ }
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java
new file mode 100644
index 0000000..ae04d14
--- /dev/null
+++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.sql.ResultSet;
+import java.util.Map;
+
+import net.israfil.foundation.mock.sql.MockResultSet;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 26 $
+ */
+@Test
+public class IterableResultSetTest {
+
+ String colA = "columnA", colB = "columnB" , colC = "columnC";
+ String[] columns = { colA, colB, colC };
+ Object[][] rows = { { new Integer(0), "cBr0", new Float(2.56f) },
+ { new Integer(1), "cBr1", new Float(4.45f) },
+ { new Integer(2), "cBr2", new Float(9.15f) },
+ { new Integer(3), "cBr3", new Float(-25.45f) } };
+
+ IterableResultSet irs;
+ ResultSet rs;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ rs = new MockResultSet(columns,rows);
+ irs = new IterableResultSet( rs );
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ rs = null;
+ irs = null;
+ }
+
+ @Test(expectedExceptions={UnsupportedOperationException.class})
+ public void testRemove() {
+ irs.iterator().remove();
+ }
+
+ public void testIterableRSInAction() throws Throwable {
+ rs.last();
+ IterableResultSet irs = new IterableResultSet(rs);
+ int rowCount = 0;
+ for (Map<String,Object> row : irs) {
+ rowCount++;
+ for(int colNum = 0; colNum < columns.length; colNum++) {
+ Assert.assertEquals(rows[rowCount-1][colNum],row.get(columns[colNum]));
+ }
+ }
+ Assert.assertEquals(4,rowCount);
+ irs.dispose();
+ }
+
+
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java
new file mode 100644
index 0000000..3b7de37
--- /dev/null
+++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Random;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 76 $
+ */
+@Test
+public class RandomOrderIteratorTest {
+
+ Collection<String> c;
+ final String string1 = "String1";
+ final String string2 = "String2";
+ final String string3 = "String3";
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ c = new ArrayList<String>();
+ c.add(string1);
+ c.add(string2);
+ c.add(string3);
+ }
+
+ @AfterMethod
+ public void tearDown() throws Exception {
+ c = null;
+ }
+
+ public void testRandomIteratorWithSeed0() {
+ Iterator<String> i = new RandomOrderIterator<String>(c,new Random(0l));
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string1,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string3,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string2,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+ public void testRandomIteratorWithSeed5() {
+ Iterator<String> i = new RandomOrderIterator<String>(c,new Random(5l));
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string3,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string1,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string2,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+ public void testRandomIteratorWithSeed92283842() {
+ Iterator<String> i = new RandomOrderIterator<String>(c,new Random(92283842l));
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string2,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string3,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string1,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java
new file mode 100644
index 0000000..b49dfe8
--- /dev/null
+++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class ReciprocalHashMapTest {
+
+ public void testSimpleCase() throws Throwable {
+ ReciprocalHashMap<String,Integer> map = new ReciprocalHashMap<String,Integer>();
+ Assert.assertNotNull(map);
+ map.put("Five",5);
+ Assert.assertEquals(1,map.size());
+ Assert.assertTrue(map.contains("Five",5));
+ Assert.assertEquals("Five",map.getKey(5));
+ Assert.assertEquals((Integer)5,map.getValue("Five"));
+ Assert.assertEquals((Integer)5,map.get("Five"));
+
+ map.put("Three",5);
+ Assert.assertEquals("Three",map.getKey(5));
+ Assert.assertEquals((Integer)5,map.getValue("Three"));
+ Assert.assertEquals(null,map.getValue("Five"));
+ Assert.assertEquals(1,map.size());
+
+ map.put("Five",4);
+ Assert.assertEquals("Five",map.getKey(4));
+ Assert.assertEquals((Integer)4,map.getValue("Five"));
+ Assert.assertEquals(2,map.size());
+ }
+
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java
new file mode 100644
index 0000000..0c91598
--- /dev/null
+++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class SoloCollectionTest {
+
+ public void testSingleCollection() {
+ Object o = new Object();
+ SoloCollection<Object> sc = new SoloCollection<Object>(o);
+ Assert.assertNotNull(sc.iterator());
+ Assert.assertTrue(sc.contains(o));
+ Assert.assertEquals(o,sc.iterator().next());
+ }
+}
diff --git a/israfil-foundation-concurrent/pom.xml b/israfil-foundation-concurrent/pom.xml
new file mode 100644
index 0000000..98b100a
--- /dev/null
+++ b/israfil-foundation-concurrent/pom.xml
@@ -0,0 +1,28 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-concurrent</artifactId>
+ <name>Israfil Foundation Concurrency Classes</name>
+ <version>1.0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-lifecycle</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java
new file mode 100644
index 0000000..2389c95
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractGated implements Gated {
+
+ private GateState state = GateState.Close;
+
+ public AbstractGated() {}
+
+ public void close() {
+ this.state = GateState.Close;
+ }
+
+ public GateState getState() {
+ return state;
+ }
+
+ public void open() {
+ this.state = GateState.Open;
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java
new file mode 100644
index 0000000..4c5226a
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractPipe<I,O> extends AbstractGated implements Pipe<I,O> {
+
+ protected BlockingQueue<I> queue;
+
+ public AbstractPipe() {}
+
+ public BlockingQueue<I> getQueue() { return queue; }
+ public void setQueue(BlockingQueue<I> queue) { this.queue = queue; }
+
+ public void consume(I item) {
+ try {
+ this.consume(item,0,null);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public O produce() {
+ try {
+ return this.produce(0,null);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected static void validateTimeout(long timeout, TimeUnit unit) {
+ if (timeout > 0 && unit == null)
+ throw new IllegalArgumentException("Cannot set a timeout with a null TimeUnit");
+ }
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java
new file mode 100644
index 0000000..df1d757
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public abstract class AbstractPump<T> extends RepeatingWorker {
+
+ protected Long timeout = 0L;
+ protected TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;
+
+ public AbstractPump() {}
+
+ public AbstractPump(String name, long timeout, TimeUnit timeoutUnit) {
+ super(name);
+ this.timeout = timeout;
+ this.timeoutUnit = timeoutUnit;
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (this.timeout == null)
+ throw new IllegalStateException("Timeoutunit cannot be null.");
+ if (this.timeoutUnit == null)
+ throw new IllegalStateException("Timeoutunit cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public long getTimeout() { return timeout; }
+
+ public void setTimeout(long timeout) { this.timeout = timeout; }
+
+ public TimeUnit getTimeoutUnit() { return timeoutUnit; }
+
+ public void setTimeoutUnit(TimeUnit timeoutUnit) {
+ this.timeoutUnit = timeoutUnit;
+ }
+
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java
new file mode 100644
index 0000000..14e51a0
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Worker.java 401 2007-01-26 02:05:20Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An object that wraps a Thread and performs units of work within that
+ * thread.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractWorker implements Runnable, Worker {
+ private static Logger logger = Logger.getLogger(AbstractWorker.class.getName());
+
+ private Thread _thread = null;
+ private String _name = this.getClass().getName();
+ private Throwable _error = null;
+
+ private WorkerState state = WorkerState.Stopped;
+
+ public AbstractWorker() { }
+
+ public AbstractWorker(String name) {
+ this._name = name;
+ }
+
+ /**
+ * Runnable.run() implementation.
+ *
+ */
+ public void run() {
+ try {
+ //execute lifecycle
+ state = WorkerState.Starting;
+ _thread = Thread.currentThread();
+ _thread.setName(_name);
+ _error = null;
+ if (init()) {
+ state = WorkerState.Running;
+ executeLifecycle();
+ }
+ state = WorkerState.Stopping;
+ deinit();
+ state = WorkerState.Stopped;
+ } catch (InterruptedException e){
+ state = WorkerState.Stopped;
+ logger.log(Level.FINE,this.getName() + " interrupted, setting stopped state.",e);
+ _error = e;
+ } catch (RuntimeInterruptedException e){
+ state = WorkerState.Stopped;
+ logger.log(Level.FINE,this.getName() + " interrupted, setting stopped state.",e);
+ _error=e;
+ } catch (Throwable e){
+ state = WorkerState.Stopped;
+ logger.log(Level.SEVERE,e.getClass().getName() + " thrown within run() method of " +
+ this.getName() + ", setting stopped state.",e);
+ _error = e;
+ }
+ }
+
+ abstract void executeLifecycle() throws InterruptedException;
+
+ // Lifecycle phases
+
+ protected boolean init() throws InterruptedException {
+ validate();
+ return _thread != null && _thread.isAlive();
+ }
+
+ protected void preProcess() throws InterruptedException { }
+
+ protected abstract void process() throws InterruptedException;
+
+ protected void postProcess() throws InterruptedException { }
+
+ protected void deinit() throws InterruptedException { }
+
+ protected void validate() {
+ if (getName() == null || getName().equals(""))
+ throw new IllegalStateException(getClass().getName() + " cannot start without a name.");
+ }
+
+ //
+ // SIGNALING
+ //
+ // TODO: Validate signaling.
+ // TODO: Implement cleaner signaling.
+ //
+
+ public boolean isRunning() {
+ return _thread != null && _thread.isAlive() && state == WorkerState.Running;
+ }
+ public boolean isStopping(){
+ return state == WorkerState.Stopping;
+ }
+ public boolean isStarting(){
+ return state == WorkerState.Starting;
+ }
+ public boolean isStopped(){
+ return state == WorkerState.Stopped;
+ }
+
+ // Accessors
+
+ public Thread getThread() { return _thread; }
+
+ public String getName() { return _name; }
+
+ public void setName(String name) { this._name = name; }
+
+ /**
+ * If the worker has stopped due to a thrown error, it should be captured
+ * and available via this method. This method will throw an IllegalStateException
+ * if called when the worker is not in a Stopped state.
+ *
+ */
+ public Throwable getError() {
+ if (!isStopped()) throw new IllegalStateException("No error available when worker not stopped.");
+ else return this._error;
+ }
+ /**
+ * Start the worker
+ * @return boolean Did the Worker startup properly.
+ */
+ public boolean start() {
+ try {
+ if (!isStopped())
+ throw new IllegalStateException("Attempted to start a worker that wasn't stopped");
+ Thread t = new Thread(this);
+ t.start();
+ Thread.yield();
+ return true;
+ } catch (Exception e) {
+ logger.log(Level.INFO,this.getName() + "Thread failed to start",e);
+ return false;
+ }
+ }
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after 20ms if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop() throws InterruptedException{
+ stop(20);
+ }
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds) throws InterruptedException{
+ if (state == WorkerState.Stopped) return; // succeed fast.
+ state = WorkerState.Stopping;
+ if (getThread() != null) getThread().join(timeout_miliseconds);
+ hardStop();
+ }
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds,int timeout_nanoseconds) throws InterruptedException{
+ if (state == WorkerState.Stopped) return; // succeed fast.
+ state = WorkerState.Stopping;
+ if (getThread() != null) getThread().join(timeout_miliseconds,timeout_nanoseconds);
+ hardStop();
+ }
+
+ protected void hardStop() {
+ if (isStopped() || getThread() == null) return;
+ getThread().interrupt();
+ this._thread = null;
+ this.state = WorkerState.Stopped;
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java
new file mode 100644
index 0000000..3ed37af
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class CollectingPump<T> extends AbstractPump<T> {
+
+ protected Collection<ConcurrentProducer<T>> producers = null;
+ protected ConcurrentConsumer<T> consumer = null;
+ private List<ConcurrentProducer<T>> producersArray = null;
+ private int currentItem;
+
+ public CollectingPump() {}
+
+ public CollectingPump(String name, Collection<ConcurrentProducer<T>> producers, ConcurrentConsumer<T> consumer,
+ long timeout, TimeUnit timeoutUnit) {
+ super(name,timeout,timeoutUnit);
+ setProducers(producers);
+ setConsumer(consumer);
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (getConsumer() == null)
+ throw new IllegalStateException("consumer cannot be null.");
+ if (getProducers() == null || getProducers().size() == 0)
+ throw new IllegalStateException("producers cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public Collection<ConcurrentProducer<T>> getProducers() { return producers; }
+
+ public void setProducers(Collection<ConcurrentProducer<T>> producers) {
+ if (this.isRunning())
+ throw new IllegalStateException("Cannot set producers while this pump is not stopped.");
+ this.producers = producers;
+ }
+
+ public ConcurrentConsumer<T> getConsumer() { return consumer; }
+
+ public void setConsumer(ConcurrentConsumer<T> consumer) {
+ if (!this.isStopped())
+ throw new IllegalStateException("Cannot set consumer while this pump is not stopped.");
+ this.consumer = consumer;
+ }
+
+ @Override
+ protected boolean init() throws InterruptedException {
+ boolean init = super.init() && this.getConsumer() != null &&
+ this.getProducers() != null && this.getProducers().size() > 0;
+ if (!init) return init; // fail fast.
+ producersArray = new ArrayList<ConcurrentProducer<T>>(producers); // get consistent list.
+ return init;
+ }
+
+ @Override
+ protected void process() throws InterruptedException {
+ ConcurrentProducer<T> producer = producersArray.get(currentItem++);
+ if (currentItem >= producersArray.size()) currentItem = 0;
+ consumer.consume(producer.produce());
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java
new file mode 100644
index 0000000..c3bf409
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Sink.java 356 2007-01-21 04:17:47Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.lifecycle.Consumer;
+
+/**
+ * A Consumer that overloads consume() with timeout values.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface ConcurrentConsumer<T> extends Consumer<T> {
+
+ /**
+ * Consumes an item of type T. This version will block until
+ * interrupted. To keep conformity with Consumer<T>, if
+ * interrupted, a RuntimeInterruptedException should be thrown.
+ * This is an unchecked exception.
+ *
+ * @param item The item to be consumed.
+ */
+ public void consume(T item);
+
+
+ /**
+ * Consumes an item of type T. If the consumer is not ready, then it will
+ * block the call until the timeout has been reached or the method is
+ * interrupted.If the object is closed, then this method will return
+ * null. This method will never return null except when it is closed.
+ *
+ * @param item The item to be consumed.
+ * @param timeout The length of time consume should attempt to operate.
+ * @param timeoutUnit The unit by which timeout should be interpreted.
+ */
+ public void consume(T item, long timeout, TimeUnit timeoutUnit) throws InterruptedException;
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java
new file mode 100644
index 0000000..2298b87
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 355 2007-01-21 02:41:03Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.lifecycle.Producer;
+
+/**
+ * An object that is a source (producer) of objects
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface ConcurrentProducer<T> extends Producer<T> {
+
+ /**
+ * Produces an item of type T. If the producer is not ready, then it will
+ * block the call until the timeout is interrupted. To keep conformity with
+ * Producer<T>, if interrupted, a RuntimeInterruptedException should be thrown.
+ * This is an unchecked exception.
+ */
+ public T produce();
+
+ /**
+ * Produces an item of type T. If the producer is not ready, then it will
+ * block the call until the timeout is reached or the method is
+ * interrupted.
+ */
+ public T produce(long timeout, TimeUnit unit) throws InterruptedException;
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java
new file mode 100644
index 0000000..ecce5db
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class DistributingPump<T> extends AbstractPump<T> {
+
+ protected ConcurrentProducer<T> producer;
+ protected Collection<ConcurrentConsumer<T>> consumers;
+ private List<ConcurrentConsumer<T>> consumersArray = null;
+ private int currentItem;
+
+ public DistributingPump() {}
+
+ public DistributingPump(String name, ConcurrentProducer<T> producer, Collection<ConcurrentConsumer<T>> consumers,
+ long timeout, TimeUnit timeoutUnit) {
+ super(name,timeout,timeoutUnit);
+ setProducer(producer);
+ setConsumers(consumers);
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (getProducer() == null)
+ throw new IllegalStateException("consumer cannot be null.");
+ if (getConsumers() == null || getConsumers().size() == 0)
+ throw new IllegalStateException("producers cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public ConcurrentProducer<T> getProducer() { return producer; }
+
+ public void setProducer(ConcurrentProducer<T> producer) { this.producer = producer; }
+
+ public Collection<ConcurrentConsumer<T>> getConsumers() { return consumers; }
+
+ public void setConsumers(Collection<ConcurrentConsumer<T>> consumers) { this.consumers = consumers; }
+
+ @Override
+ protected boolean init() throws InterruptedException {
+ boolean init = super.init() && this.getProducer() != null &&
+ this.getConsumers() != null && this.getConsumers().size() > 0;
+ if (!init) return init; // fail fast.
+ consumersArray = new ArrayList<ConcurrentConsumer<T>>(consumers); // get consistent list.
+ return init;
+ }
+
+ @Override
+ protected void process() throws InterruptedException {
+ ConcurrentConsumer<T> consumer = consumersArray.get(currentItem++);
+ if (currentItem >= consumersArray.size()) currentItem = 0;
+ consumer.consume(producer.produce());
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java
new file mode 100644
index 0000000..18a2acf
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * A Gated object is one which can be in an open or closed state, and which
+ * provides operations to set the state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Gated {
+
+ public void open();
+
+ public void close();
+
+ public GateState getState();
+
+ public static enum GateState { Open, Close }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java
new file mode 100644
index 0000000..3c6f196
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: OneShotWorker.java 365 2007-01-22 04:36:55Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.logging.Logger;
+
+/**
+ * A Worker sub-class that implements a one-shot lifecycle, performing any
+ * initialization, pre-actions, the desired work, any post-work actions, and
+ * any de-initialization.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class OneShotWorker extends AbstractWorker {
+
+ private static Logger logger = Logger.getLogger(OneShotWorker.class.getName());
+
+ public OneShotWorker() { }
+
+ public OneShotWorker(String name) {
+ super(name);
+ }
+
+ public void executeLifecycle() throws InterruptedException {
+ logger.finer(getName() + " about to pre-process.");
+ preProcess();
+ logger.finer(getName() + " completed pre-processing.");
+ logger.finer(getName() + " about to process.");
+ process();
+ logger.finer(getName() + " completed processing.");
+ logger.finer(getName() + " about to post-process.");
+ postProcess();
+ logger.finer(getName() + " completed post-processing.");
+ }
+
+ public void preProcess() { }
+
+ public void postProcess() { }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java
new file mode 100644
index 0000000..9789f25
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Pipe<I,O> extends ConcurrentProducer<O>, ConcurrentConsumer<I>, Gated {
+
+
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java
new file mode 100644
index 0000000..2e23c2a
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class ProcessingPipe<I,O> extends AbstractPipe<I,O> {
+
+ protected Processor<I,O> processor;
+ protected Integer timeout;
+ protected TimeUnit timeoutUnit;
+
+ public ProcessingPipe() {}
+
+ public Processor<I,O> getProcessor() { return processor; }
+ public void setProcessor(Processor<I,O> processor) {
+ this.processor = processor;
+ }
+ public Integer getTimeout() { return timeout; }
+ public void setTimeout(Integer timeout) { this.timeout = timeout; }
+ public TimeUnit getTimeoutUnit() { return timeoutUnit; }
+ public void setTimeoutUnit(TimeUnit timeoutUnit) {
+ this.timeoutUnit = timeoutUnit;
+ }
+
+ public void consume(I item, long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ try {
+ if (timeout > 0) getQueue().offer(item,timeout,unit);
+ else getQueue().put(item);
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ }
+
+ public O produce(long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ O processedItem = null;
+ try {
+ if (timeout > 0)
+ processedItem = this.processor.process(getQueue().poll(timeout,unit),getTimeout(),getTimeoutUnit());
+ else
+ processedItem = this.processor.process(getQueue().poll(),getTimeout(),getTimeoutUnit());
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ return processedItem;
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java
new file mode 100644
index 0000000..90a5cc7
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that proceses an item and returns a result.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Processor<I,O> {
+
+ public O process(I item) throws InterruptedException;
+
+ public O process(I item, long timeout, TimeUnit timeoutUnit) throws InterruptedException;
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java
new file mode 100644
index 0000000..a6588fc
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: RepeatingWorker.java 367 2007-01-22 23:02:28Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A Worker sub-class that implements a slightly different lifecycle. In
+ * particular, it iterates based on a continuProcessing() signalling method.
+ * It also implements pre and post processing logic in case any per-iteration
+ * setup and tear-down is required.
+ *
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class RepeatingWorker extends AbstractWorker {
+
+ private static Logger logger = Logger.getLogger(RepeatingWorker.class.getName());
+
+ public RepeatingWorker() { }
+
+ public RepeatingWorker(String name) { super(name); }
+
+ public void executeLifecycle() throws InterruptedException {
+ do {
+ logger.finer(getName() + " about to pre-process.");
+ preProcess();
+ logger.finer(getName() + " completed pre-processing.");
+ logger.finer(getName() + " about to process.");
+ process();
+ logger.finer(getName() + " completed processing.");
+ logger.finer(getName() + " about to post-process.");
+ postProcess();
+ logger.finer(getName() + " completed post-processing.");
+ Thread.yield();
+ } while (continueProcessing() && delay());
+ }
+
+ public abstract boolean continueProcessing() throws InterruptedException;
+
+ /**
+ * @return long Number of milliseconds to delay between iterations
+ */
+ public abstract long iterationDelay();
+
+ /**
+ * Returns boolean only so it can be used in a while statement. delay()
+ * simply sleeps as long as iterationDelay() indicates, then returns true,
+ * unless interrupted in which case it returns false.
+ */
+ private boolean delay() {
+ try {
+ Thread.sleep(iterationDelay());
+ return true;
+ } catch (InterruptedException e) {
+ logger.log(Level.WARNING, getName() + " interrupted.",e);
+ return false;
+ }
+ }
+
+ public void preProcess() { }
+
+ public void postProcess() { }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java
new file mode 100644
index 0000000..ee05a44
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: OneShotWorker.java 365 2007-01-22 04:36:55Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * A runtime (unchecked) equivalent to InterruptedException
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class RuntimeInterruptedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -667612054120346668L;
+
+ public RuntimeInterruptedException() {
+ super();
+ }
+
+ public RuntimeInterruptedException(String s) {
+ super(s);
+ }
+
+ public RuntimeInterruptedException(String s, Throwable cause) {
+ super(s,cause);
+ }
+
+ public RuntimeInterruptedException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java
new file mode 100644
index 0000000..d1383fb
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that consumes an object and queues it, then produces the object
+ * upon request. If the processor has an unfilled queue, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class SimplePipe<I> extends AbstractPipe<I,I> {
+
+ public SimplePipe() {}
+
+ public void consume(I item, long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ try {
+ if (timeout > 0) getQueue().offer(item,timeout,unit);
+ else getQueue().put(item);
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ }
+
+ public I produce(long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ try {
+ if (timeout > 0)
+ return getQueue().poll(timeout,unit);
+ else
+ return getQueue().poll();
+ } catch (InterruptedException e) {
+ throw e;
+ }
+
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java
new file mode 100644
index 0000000..4b9b11a
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SimplePump.java 367 2007-01-22 23:02:28Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class SimplePump<T> extends AbstractPump<T> {
+
+ protected ConcurrentProducer<T> producer;
+ protected ConcurrentConsumer<T> consumer;
+
+ public SimplePump() {}
+
+ public SimplePump(String name, ConcurrentProducer<T> producer, ConcurrentConsumer<T> consumer,
+ long timeout, TimeUnit timeoutUnit) {
+ super(name,timeout,timeoutUnit);
+ setProducer(producer);
+ setConsumer(consumer);
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (getConsumer() == null)
+ throw new IllegalStateException("consumer cannot be null.");
+ if (getProducer() == null )
+ throw new IllegalStateException("producer cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public ConcurrentProducer<T> getProducer() { return producer; }
+
+ public void setProducer(ConcurrentProducer<T> producer) { this.producer = producer; }
+
+ public ConcurrentConsumer<T> getConsumer() { return consumer; }
+
+ public void setConsumer(ConcurrentConsumer<T> consumer) { this.consumer = consumer; }
+
+ @Override
+ protected void process() throws InterruptedException {
+ consumer.consume(producer.produce());
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java
new file mode 100644
index 0000000..697d466
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2003 - 2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Worker.java 401 2007-01-26 02:05:20Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * An object that wraps a Thread and performs units of work within that
+ * thread. Very handy for concurrent development.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Worker {
+
+
+
+ //
+ // SIGNALING
+ //
+ // TODO: Validate signaling.
+ // TODO: Implement cleaner signaling.
+ //
+
+ public boolean isRunning();
+
+ public boolean isStopping();
+
+ public boolean isStarting();
+
+ public boolean isStopped();
+
+ // Accessors
+
+ public String getName();
+
+ /**
+ * If the worker has stopped due to a thrown error, it should be captured
+ * and available via this method. This method will throw an IllegalStateException
+ * if called when the worker is not in a Stopped state.
+ *
+ */
+ public Throwable getError();
+
+ /**
+ * Start the worker
+ * @return boolean Did the Worker startup properly.
+ */
+ public boolean start();
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after 20ms if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop() throws InterruptedException;
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds) throws InterruptedException;
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds,int timeout_nanoseconds) throws InterruptedException;
+
+ public static enum WorkerState {
+ Stopped,Starting,Running,Stopping
+ }
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java
new file mode 100644
index 0000000..7fd2121
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Dynamic.java 14 2006-01-27 23:50:37Z cgruber $
+ */
+package net.israfil.foundation.concurrent.consumers;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.concurrent.ConcurrentConsumer;
+
+/**
+ * A consumer that consumes strings and sends them to a provided logger at a
+ * provided level.
+ *
+ * @author <a href="cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class LoggingStringConsumer implements ConcurrentConsumer<String> {
+ private Logger logger;
+ private Level level;
+ public LoggingStringConsumer(Logger logger,Level level) {
+ this.logger = logger;
+ this.level = level;
+ }
+ public void consume(String item) {
+ logger.log(level,item);
+ }
+ public void consume(String item, long timeout, TimeUnit unit) throws InterruptedException {
+ throw new UnsupportedOperationException("Timeouts not supported. Use consume(String)");
+ }
+} \ No newline at end of file
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java
new file mode 100644
index 0000000..f232b00
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Dynamic.java 14 2006-01-27 23:50:37Z cgruber $
+ */
+package net.israfil.foundation.concurrent.producers;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.CharBuffer;
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.concurrent.ConcurrentProducer;
+
+/**
+ * A provider that reads an input stream and creates strings out of lines
+ * of text.
+ *
+ * @author <a href="cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class ReaderStringProducer implements ConcurrentProducer<String> {
+ Reader reader = null;
+ public ReaderStringProducer(Reader reader) {
+ this.reader = reader;
+ }
+ public String produce() {
+ CharBuffer cb = CharBuffer.allocate(1024);
+ int count = 0;
+ try {
+ int val = reader.read();
+ while (val != -1) {
+ cb.append( (char)val );
+ count++;
+ if ((char)val == '\n') break;
+ val = reader.read();
+ }
+ if (count == 0 && val == -1) return null;
+ } catch (IOException e) { return null; }
+ char[] finalarray = new char[count];
+ cb.position(0);
+ cb.get(finalarray);
+ return new String(finalarray);
+ }
+ public String produce(long timeout, TimeUnit unit) throws InterruptedException {
+ throw new UnsupportedOperationException("Timeouts not supported. Use produce()");
+ }
+
+
+
+ }
+ \ No newline at end of file
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java
new file mode 100644
index 0000000..0abe15b
--- /dev/null
+++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent.timing;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * An object that represents a timeout value;
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class Timeout {
+
+ private final long startTime;
+ private final long timeout;
+
+ public Timeout(long timeout) {
+ this.timeout = timeout;
+ startTime = System.currentTimeMillis();
+ }
+ public void assertWithinTimeout() throws TimeoutException {
+ long now = System.currentTimeMillis();
+ if (now - startTime > timeout) {
+ throw new TimeoutException("Timeout of " + timeout + "ms exceeded: " + (now - startTime) + "ms.");
+ }
+ }
+ public long getStartTime() {
+ return startTime;
+ }
+ public long getTimeout() {
+ return timeout;
+ }
+ public void sleep(long interval) throws InterruptedException {
+ Thread.sleep(interval);
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java
new file mode 100644
index 0000000..dce834e
--- /dev/null
+++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: WorkerTest.java 368 2007-01-22 23:23:03Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import net.israfil.foundation.concurrent.timing.Timeout;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * A Test Class
+ *
+ * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 368 $
+ */
+@Test
+public class AbstractWorkerTest {
+
+ public void testWorker() throws InterruptedException {
+ FakeWorker w = new FakeWorker("MockWorker");
+ Assert.assertNull(w.getThread());
+ //Assert.assertEquals("MockWorker",w.getId());
+ Assert.assertFalse(w.didInit);
+ Assert.assertFalse(w.didWork);
+ Assert.assertFalse(w.didDeInit);
+
+ // startup thread and give it some processor time.
+ w.start();
+ Timeout timeout = new Timeout(10000);
+ while (!w.isRunning()) {
+ timeout.sleep(10);
+ }
+
+ Assert.assertTrue(w.isRunning());
+ Assert.assertNotNull(w.getThread());
+ Assert.assertTrue(w.getThread().isAlive());
+
+ // Assert.assert pre-work state.
+ Assert.assertTrue(w.didInit);
+ Assert.assertFalse(w.doWork);
+ Assert.assertFalse(w.didWork);
+ Assert.assertFalse(w.didDeInit);
+
+ // Signal worker to start work and check state.
+ w.doWork = true;
+ timeout = new Timeout(10000);
+ while (!w.didWork) {
+ timeout.sleep(10);
+ }
+
+ w.stop(5000);
+ Assert.assertTrue(w.didDeInit);
+
+ }
+
+
+ public static class FakeWorker extends AbstractWorker {
+
+ public boolean didWork = false, didInit = false, didDeInit = false;
+ public volatile boolean doWork = false;
+
+ public FakeWorker(String id) {
+ super(id);
+ }
+
+ public boolean init() {
+ didInit = true;
+ return true;
+ }
+
+ public void deinit() {
+ didDeInit = true;
+ }
+
+ protected void executeLifecycle() throws InterruptedException {
+ while (!isStopping() && !doWork) Thread.sleep(10);
+ preProcess();
+ process();
+ postProcess();
+ }
+
+ public void process() throws InterruptedException {
+ didWork=true;
+ while(!isStopping()) Thread.sleep(10);
+ }
+
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java
new file mode 100644
index 0000000..304f219
--- /dev/null
+++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2006 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ * A Test Class
+ *
+ * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class OneShotWorkerTest {
+
+ public void testOneShotWorker() throws InterruptedException {
+ throw new SkipException("Unimplemented tests");
+ }
+
+ public static class TestOneShotWorker extends OneShotWorker {
+
+ boolean preProcessed = false;
+ boolean processed = false;
+ boolean postProcessed = false;
+ boolean initialized = false;
+ boolean deinitialized = false;
+
+ @Override
+ public void postProcess() {
+ super.postProcess();
+ this.postProcessed = true;
+ }
+
+ @Override
+ public void preProcess() {
+ super.preProcess();
+ this.preProcessed = true;
+ }
+
+ @Override
+ protected void deinit() throws InterruptedException {
+ // TODO Auto-generated method stub
+ super.deinit();
+ }
+
+ @Override
+ protected boolean init() throws InterruptedException {
+ // TODO Auto-generated method stub
+ return super.init();
+ }
+
+ @Override
+ protected void process() throws InterruptedException {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java
new file mode 100644
index 0000000..5d714f8
--- /dev/null
+++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.concurrent.timing.Timeout;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * A Test Class
+ *
+ * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class PumpTest {
+
+
+ public void testSimplePump() throws InterruptedException {
+ SimplePump<String> pump = new SimplePump<String>();
+ pump.setTimeout(10000L);
+ MockProducer<String> p = new MockProducer<String>();
+ final MockConsumer<String> c = new MockConsumer<String>();
+ pump.setConsumer(c);
+ pump.setProducer(p);
+ Assert.assertNotNull(pump.getConsumer());
+ Assert.assertNotNull(pump.getProducer());
+ Assert.assertTrue(pump.isStopped());
+ pump.start();
+ Timeout timeout = new Timeout(20000);
+ while(!pump.isRunning()) timeout.sleep(5);
+ Assert.assertNull(p.item);
+ Assert.assertNull(c.item);
+ String itemA = "a";
+ p.item = itemA;
+ timeout = new Timeout(20000);
+ while( c.item == null) {
+ timeout.sleep(5);
+ }
+ Assert.assertEquals(itemA,c.item);
+ pump.stop();
+ Assert.assertTrue(pump.isStopped());
+ }
+
+ public void testCollectingPump() throws InterruptedException {
+ CollectingPump<String> pump = new CollectingPump<String>();
+ MockProducer<String> p1 = new MockProducer<String>();
+ MockProducer<String> p2 = new MockProducer<String>();
+ MockProducer<String> p3 = new MockProducer<String>();
+ final MockConsumer<String> c = new MockConsumer<String>();
+ pump.setConsumer(c);
+ List<ConcurrentProducer<String>> producers = new ArrayList<ConcurrentProducer<String>>();
+ producers.add(p1);
+ producers.add(p2);
+ producers.add(p3);
+ pump.setProducers(producers);
+ Assert.assertNotNull(pump.getConsumer());
+ Assert.assertNotNull(pump.getProducers());
+ Assert.assertTrue(pump.isStopped());
+ pump.start();
+ Timeout timeout = new Timeout(20000);
+ while(!pump.isRunning()) timeout.sleep(5);
+ Assert.assertNull(p1.item);
+ Assert.assertNull(c.item);
+ String itemA = "a", itemB = "b", itemC = "c";
+ p1.item = itemA;
+ p2.item = itemB;
+ p3.item = itemC;
+ Assert.assertNotNull(p1.item);
+ Assert.assertNotNull(p2.item);
+ Assert.assertNotNull(p3.item);
+ timeout = new Timeout(20000);
+ while(c.item == null) timeout.sleep(5);
+ Assert.assertEquals(itemA, c.item);
+ Assert.assertNull(p1.item);
+ c.item = null;
+ timeout = new Timeout(20000);
+ while(c.item == null) timeout.sleep(5);
+ Assert.assertEquals(itemB, c.item);
+ Assert.assertNull(p2.item);
+ c.item = null;
+ timeout = new Timeout(20000);
+ while(c.item == null) timeout.sleep(5);
+ Assert.assertEquals(itemC, c.item);
+ Assert.assertNull(p3.item);
+ c.item = null;
+ pump.stop();
+ Assert.assertTrue(pump.isStopped());
+ }
+
+ public void testDistributingPump() throws InterruptedException {
+ if (true) return;
+ DistributingPump<String> pump = new DistributingPump<String>();
+ MockProducer<String> p = new MockProducer<String>();
+ MockConsumer<String> c1 = new MockConsumer<String>();
+ MockConsumer<String> c2 = new MockConsumer<String>();
+ MockConsumer<String> c3 = new MockConsumer<String>();
+ List<ConcurrentConsumer<String>> consumers = new ArrayList<ConcurrentConsumer<String>>();
+ consumers.add(c1);
+ consumers.add(c2);
+ consumers.add(c3);
+ pump.setConsumers(consumers);
+ pump.setProducer(p);
+ Assert.assertNotNull(pump.getConsumers());
+ Assert.assertNotNull(pump.getProducer());
+ Assert.assertTrue(pump.isStopped());
+ Timeout timeout = new Timeout(500);
+ while(!pump.isRunning()) timeout.sleep(5);
+ Assert.assertNull(p.item);
+ Assert.assertNull(c1.item);
+ Assert.assertNull(c2.item);
+ Assert.assertNull(c3.item);
+ String itemA = "a", itemB = "b", itemC = "c";
+ p.item = itemA;
+ timeout = new Timeout(20000);
+ while(c1.item == null) timeout.sleep(5);
+ Assert.assertEquals(itemA,c1.item);
+ Assert.assertNull(p.item);
+ p.item = itemB;
+ timeout = new Timeout(20000);
+ while(c1.item == null) timeout.sleep(5);
+ Assert.assertEquals(itemB,c1.item);
+ Assert.assertNull(p.item);
+ p.item = itemC;
+ timeout = new Timeout(20000);
+ while(c1.item == null) timeout.sleep(5);
+ Assert.assertEquals(itemC,c1.item);
+ Assert.assertNull(p.item);
+ pump.stop();
+ Assert.assertTrue(pump.isStopped());
+ }
+
+ public static class MockProducer<T> extends MockStringPipeComponent<T> implements ConcurrentProducer<T> {
+ public T produce() {
+ try {
+ return produce(0,null);
+ } catch (InterruptedException e) {
+ throw new RuntimeInterruptedException(e);
+ }
+ }
+ public T produce(long timeoutMillis, TimeUnit unit) throws InterruptedException {
+ Thread.sleep(delay);
+ Timeout timeout = new Timeout(timeoutMillis);
+ while (this.item == null && (timeoutMillis < 1 || unit == null))
+ timeout.sleep(5);
+ Long start = System.currentTimeMillis();
+ if (this.item == null) return null; // in case of timeouts.
+ synchronized (this.item) {
+ T oldItem = this.item;
+ this.item = null;
+ return oldItem;
+ }
+ }
+ }
+
+ public static class MockConsumer<T> extends MockStringPipeComponent<T> implements ConcurrentConsumer<T> {
+ public void consume(T item) {
+ try {
+ consume(item,0,null);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ public void consume(T item, long timeoutMillis, TimeUnit unit) throws InterruptedException {
+ Thread.sleep(delay);
+ Timeout timeout = new Timeout(timeoutMillis);
+ while (this.item != null && (timeoutMillis < 1 || unit == null))
+ timeout.sleep(5);
+ this.item = item;
+ }
+ }
+
+ public static class MockStringPipeComponent<T> {
+ public T item = null;
+ public long delay = 0;
+ public static boolean timeout(Long start, Long timeout) {
+ return (System.currentTimeMillis() - start) < timeout;
+ }
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java
new file mode 100644
index 0000000..f7b2303
--- /dev/null
+++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ * A Test Class
+ *
+ * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class RepeatingWorkerTest {
+
+ public void testRepeatingWorker() throws InterruptedException {
+ throw new SkipException("Unimplemented tests");
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java
new file mode 100644
index 0000000..a0980ff
--- /dev/null
+++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.concurrent.consumers;
+
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.concurrent.ConcurrentConsumer;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * A Test Class
+ *
+ * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class LoggingStringConsumerTest{
+
+
+ public void testLoggingStringConsumer() throws InterruptedException {
+ String message1 = "message 1";
+ String message2 = "message 2";
+ String message3 = "message 3";
+ MockLogger log = new MockLogger("MockLogger",null);
+ ConcurrentConsumer<String> c = new LoggingStringConsumer(log,Level.INFO);
+ c.consume(message1);
+ Assert.assertEquals(message1,log.rawMessage);
+ c.consume(message2);
+ Assert.assertEquals(message2,log.rawMessage);
+ c.consume(message3);
+ Assert.assertEquals(message3,log.rawMessage);
+ }
+
+ public class MockLogger extends Logger {
+ String rawMessage = null;
+ public MockLogger(String name, String resourceBundleName) {
+ super(name, resourceBundleName);
+ }
+
+ public void log(LogRecord record) {
+ rawMessage = record.getMessage();
+ }
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java
new file mode 100644
index 0000000..43344e4
--- /dev/null
+++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.concurrent.producers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * A Test Class
+ *
+ * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class ReaderStringProducerTest {
+
+
+ public void testInputStreamStringProducer() throws Exception {
+ String s1 = "This is a test;\n";
+ String s2 = "This is a second test.";
+ String string = s1+s2;
+ ReaderStringProducer producer = new ReaderStringProducer(
+ new StringReader(string)
+ );
+ Assert.assertEquals(s1,producer.produce());
+ Assert.assertEquals(s2,producer.produce());
+ Assert.assertEquals(null,producer.produce());
+ }
+
+
+ public static class ReaderInputStream extends InputStream {
+ private Reader source;
+ public ReaderInputStream(Reader source) { this.source = source; }
+ @Override
+ public int read() throws IOException { return source.read(); }
+ }
+}
diff --git a/israfil-foundation-container/pom.xml b/israfil-foundation-container/pom.xml
new file mode 100644
index 0000000..742064d
--- /dev/null
+++ b/israfil-foundation-container/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-container</artifactId>
+ <name>Israfil Foundation Trivial IoC Container</name>
+ <version>1.0.0-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2008</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java
new file mode 100644
index 0000000..fe6a978
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError;
+
+/**
+ * A convenience abstract class that implements basic component storage and
+ * lookup, as well as basic component instance assignment.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ *
+ */
+public abstract class AbstractContainer implements Container {
+
+ private final Map components = new HashMap();
+
+ private final Container parent;
+
+ private boolean running = false;
+
+ public AbstractContainer() {
+ parent = null;
+ }
+
+ public AbstractContainer(Container parent) {
+ this.parent = parent;
+ }
+
+ protected boolean isStored(Object key) {
+ return components.containsKey(key);
+ }
+
+ public boolean hasComponent(Object key) {
+ return components.containsKey(key) || (parent != null && parent.hasComponent(key));
+ }
+
+ public boolean isRunning() {
+ return this.running;
+ }
+
+ public void start() {
+ this.running = true;
+ }
+
+ protected Container getParent() { return parent; }
+
+ protected Object getStoredComponent(Object key) {
+ Object result = components.get(key);
+ if (result == null && parent != null)
+ result = parent.getComponent(key);
+ return result;
+ }
+
+ protected void store(Object key, Object component) {
+ if (hasComponent(key)) {
+ if (getComponent(key) == component) return;
+ throw new ComponentAlreadyRegisteredError("Object already registered for key: " + key);
+ }
+ components.put(key, component);
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java
new file mode 100644
index 0000000..c4047f1
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+/**
+ * A convenience implementation of Startable
+ */
+public abstract class AbstractStartable implements Startable {
+
+ private boolean started = false;
+
+ /**
+ * @see Startable.start();
+ */
+ public void start() {
+ this.started = true;
+ }
+
+ /**
+ * @see Startable.isRunning();
+ */
+ public boolean isRunning() { return started; }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java
new file mode 100644
index 0000000..623851b
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+/**
+ * A Container that uses an AutoWiringAdapter to ensure that
+ * components can be created appropriately with their dependencies
+ * satisfied automatically.
+ *
+ */
+public interface AutoWiringAdaptableContainer extends Container {
+
+ public void start();
+
+ /**
+ * Register a component. The component's class must satisfy the
+ * test <code>Injectable.class.isAssignableFrom(type);</code>
+ * to ensure that the provided component implements the lifecycle
+ * mechanisms necessary to auto-wire.
+ *
+ */
+ public void registerType(Object key, AutoWiringAdapter componentAdapter);
+
+ /**
+ * Register an independent component. This is a convenience registry
+ * method for those components without dependencies, and which
+ * have a default constructor. Only classes which fit these
+ * criteria should be used in this method.
+ *
+ */
+ public void registerType(Object key, Class<?> implementation);
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java
new file mode 100644
index 0000000..56436a5
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+/**
+ * An adapter interface that's used in the "AutoWiringContainer"
+ * to allow the user to specify a component's dependencies upon registration.
+ * This is not ideal, in that it's not auto-discovered constructor-based
+ * dependency injection, but since dynamic reflection is not available in the
+ * J2ME CLDC 1.1 spec, an alternate and generic injection mechanism
+ * is necessary. Implementors of this interface should be CLDC safe.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface AutoWiringAdapter {
+
+ /**
+ * This method should return a list of keys defining the dependencies
+ * this object requires to operate, in the order expected by the
+ * create(Object[]) method.
+ */
+ public Object[] dependencies();
+
+ /**
+ * Returns the type that this adapter will create. This should be the
+ * most concrete (narrowest) common type this adapter will create, if
+ * there is more than one possibility.
+ */
+ public Class getType();
+
+ /**
+ * A method that implementors use to create a component given a set of
+ * parameters. Callers must return the parameters in the order provided
+ * by the dependencies() method.
+ */
+ public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException;
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java
new file mode 100644
index 0000000..0bc0982
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+/**
+ * A container for components that will satisfy requests if the
+ * component is available. How these component requests are satisfied
+ * are implementation dependent, as well as how inter-component
+ * dependencies are resolved.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ *
+ */
+public interface Container {
+
+ /**
+ * Returns true if the Component is available and prepared.
+ * It throws a ContainerNotStarted runtime exception if the this method
+ * is used before the container is started.
+ *
+ * This method must be implemented by implementors of Container in a
+ * thread-safe and reentrant way.
+ */
+ public boolean hasComponent(Object key);
+
+ /**
+ * Returns the component named by the key if it is available, or null if no
+ * such component is available. It throws a ContainerNotStarted runtime
+ * exception if this method is used before the container is started.
+ *
+ * This method must be implemented by implementors of Container in a
+ * thread-safe and reentrant way.
+ */
+ public Object getComponent(Object key);
+
+ /**
+ * Begin the lifecycle of the container, after which components should be
+ * accessible. Implementors should stop any component registration as of
+ * the start() call. Subsequent start() calls should be ignored.
+ */
+ public void start();
+
+ /**
+ * Returns true if the container has been started, and false if it has
+ * not been started.
+ */
+ public boolean isRunning();
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java
new file mode 100644
index 0000000..89d3b11
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2008-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2008-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+
+
+/**
+ * A deprecated class that was the old name for DefaultContainer.
+ * Maintained to reduce API breakage.
+ * @Deprecated Class renamed to DefaultContainer.
+ */
+public class DefaultAutoWiringAdaptableContainer extends DefaultContainer {
+
+ public DefaultAutoWiringAdaptableContainer() {
+ super();
+ }
+
+ public DefaultAutoWiringAdaptableContainer(boolean failEarly) {
+ super(failEarly);
+ }
+
+ public DefaultAutoWiringAdaptableContainer(Container parent,
+ boolean failEarly) {
+ super(parent, failEarly);
+ }
+
+ public DefaultAutoWiringAdaptableContainer(Container parent) {
+ super(parent);
+ }
+
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java
new file mode 100644
index 0000000..f11dc47
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter;
+import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError;
+import net.israfil.foundation.container.error.CouldNotCreateComponentError;
+import net.israfil.foundation.container.error.UnsatisfiedDependencyError;
+import net.israfil.foundation.container.util.CyclicalReferenceDetectionUtil;
+import net.israfil.foundation.container.util.NonDuplicateStack;
+
+
+/**
+ * A default implementation of AutoWiringAdaptableContainer, a Container
+ * that uses an AutoWiringAdapter to ensure that components can be
+ * created appropriately with their dependencies satisfied automatically.
+ *
+ * This adapter is intended for constructor injection, but relies on the
+ * adapter to perform such. No reflection is used by this class itself.
+ *
+ */
+public class DefaultContainer extends AbstractContainer implements AutoWiringAdaptableContainer {
+
+ private Map<Object,Object> registry = new HashMap<Object,Object>();
+
+ private final boolean failEarly;
+
+ private boolean starting = false;
+
+ private final Object CREATION_MUTEX = new Object();
+
+ /**
+ * A default constructor that will throw errors regarding circular
+ * dependencies at registration time, throw missing dependency errors
+ * at wire-up (getComponent()) time, and has no parent.
+ *
+ * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time.
+ */
+ public DefaultContainer() {
+ super();
+ this.failEarly = false;
+ }
+
+ /**
+ * Construct this container such that it detects missing dependencies
+ * upon invocation of start(). Otherwise, it will fail at wire time,
+ * rather than at registration time. Circular references will give errors
+ * at registration time.
+ *
+ * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time.
+ */
+ public DefaultContainer(boolean failEarly) {
+ super();
+ this.failEarly = failEarly;
+ }
+
+ /**
+ * This method constructs a DefaultAutoWiringAdaptableContainer that
+ * has a parent container for backup resolution. The parent container
+ * can be of any type of Container.
+ *
+ * @param parent The parent container (optional)
+ */
+ public DefaultContainer(Container parent) {
+ super(parent);
+ this.failEarly = false;
+ }
+
+ /**
+ * Construct this container such that it detects missing dependencies
+ * upon invocation of start(). Otherwise, it will fail at wire time,
+ * rather than at registration time. Circular references will give errors
+ * at registration time. This method also provides for a parent container.
+ * The parent container can be of any type of Container.
+ *
+ * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time.
+ * @param parent The parent Container (optional)
+ */
+ public DefaultContainer(Container parent, boolean failEarly) {
+ super(parent);
+ this.failEarly = failEarly;
+ }
+
+ public synchronized void start() {
+ if (isRunning() ||
+ starting) return;
+ if (getParent() != null && !getParent().isRunning()) throw new RuntimeException("Parent container is not started.");
+ this.starting = true;
+ if (failEarly) {
+ for (Object key : registry.keySet()) {
+ // force get each component, forcing all wiring.
+ Object ignore = getComponent(key);
+ if (false) ignore.hashCode(); // cover warning - compiler should remove
+ }
+ }
+ super.start();
+ starting = false;
+ }
+
+ public void registerType(Object key, Class<?> componentType) {
+ registerType(key,componentType, 0);
+ }
+
+ protected void registerType(Object key, Class<?> componentType, long timeout) {
+ registerType(key,new IndependentAutoWiringAdapter(componentType), timeout);
+ }
+
+ public void registerType(Object key, AutoWiringAdapter componentAdapter) {
+ registerType(key,componentAdapter,0);
+ }
+
+ /**
+ * Registers a component for later instantiation and (optionally) startup.
+ *
+ * @param key the key by which this component will be identified in the system
+ * @param componentAdapter an AutoWiringAdapter for creating this component and listing its dependencies
+ * @param timeout an (optional) timeout applied to any startup lifecycle
+ */
+ protected void registerType(Object key, AutoWiringAdapter componentAdapter, long timeout) {
+ if (this.isRunning()) throw new RuntimeException("Cannot register when container is started.");
+ // FIXME: Figure out whether to support parent registry checking. Probably can't do it.
+
+ if (registry.containsKey(key)) throw new ComponentAlreadyRegisteredError("Component already registered for " + key);
+ detectCircularDependencies(key,componentAdapter);
+ registry.put(key, componentAdapter);
+ }
+
+ private void detectCircularDependencies(Object key,AutoWiringAdapter componentAdapter) {
+ NonDuplicateStack nds = new NonDuplicateStack();
+ nds.push(key);
+ CyclicalReferenceDetectionUtil.detectCircularDependencies(this.registry, nds, componentAdapter);
+ }
+
+ /**
+ * This method wires the object up with its dependencies, providing said
+ * dependencies to the object's adapter. It also starts the object if its
+ * startable
+ * @param originalKey
+ * @param adapter
+ * @return
+ */
+ private Object wireObject(Object originalKey, AutoWiringAdapter adapter) {
+ Object[] dependencies = adapter.dependencies();
+ Object[] parameters = new Object[dependencies.length];
+ for (int depn = 0; depn < dependencies.length; depn++ ) {
+ Object key = adapter.dependencies()[depn];
+ parameters[depn] = getComponent(key);
+ if (parameters[depn] == null) throw new UnsatisfiedDependencyError("Could not materialize dependency for key " + key);
+ }
+ try {
+ Object o = adapter.create(parameters);
+ if (o == null) throw new InstantiationException("Could not create a non-null object. Adapter " + adapter.getClass().getName() + " returned null.");
+ else {
+ try {
+ Startable s = ((Startable)o);
+ if (!s.isRunning()) s.start();
+ } catch (ClassCastException e) {}
+ return o;
+ }
+ } catch (IllegalAccessException e) {
+ throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e);
+ } catch (InstantiationException e) {
+ throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e);
+ } catch (Throwable e) {
+ throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e);
+ }
+ }
+
+ public Object getComponent(Object key) {
+ Object component = super.getStoredComponent(key);
+ if (component == null && registry.containsKey(key)) {
+ synchronized (CREATION_MUTEX) {
+ if (component == null) { // in case following thread gets in just after storage.
+ component = wireObject(key,(AutoWiringAdapter)registry.get(key));
+ store(key, component);
+ }
+ }
+ }
+ return component;
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java
new file mode 100644
index 0000000..34b0399
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+/**
+ * A simple interface that, if implemented, allows a component
+ * to participate in a startup phase of lifecycle.
+ */
+public interface Startable {
+
+ /**
+ * Begin the lifecycle of the component, after which it should be
+ * usable. This component should only act on its own startup
+ * lifecycle, and should assume that any components that are
+ * provided through dependency injection are already started
+ * before this command is executed.
+ */
+ public void start();
+
+ /**
+ * Returns true if the container has been started, and false if it has
+ * not been started.
+ */
+ public boolean isRunning();
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java
new file mode 100644
index 0000000..6500275
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.adapters;
+
+import net.israfil.foundation.container.AutoWiringAdapter;
+
+/**
+ * A convenience implementation of AutoWiringAdapter which can be used
+ * for those clases that have no dependencies and have a default constructor.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractAutoWiringAdapter implements AutoWiringAdapter{
+
+ private final Object[] dependencies;
+
+ private final Class type;
+
+ public AbstractAutoWiringAdapter(Class type, Object[] dependencies) {
+ if (type == null)
+ throw new IllegalArgumentException("An independent component must have a type.");
+ this.type = type;
+ this.dependencies = dependencies;
+ }
+
+ public Object[] dependencies() { return dependencies; }
+
+ public Class getType() { return type; }
+
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java
new file mode 100644
index 0000000..ff945a8
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.adapters;
+
+import java.util.Map;
+
+/**
+ * A convenience implementation of AutoWiringAdapter which can be used
+ * for those clases that have no dependencies and have a default constructor.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class IndependentAutoWiringAdapter extends AbstractAutoWiringAdapter{
+
+ private static final Object[] NO_DEPENDENCIES = {};
+
+ public IndependentAutoWiringAdapter(Class type) {
+ super(type, NO_DEPENDENCIES);
+ }
+
+ /**
+ * This method implements AutoWiringAdapter.create() but throws
+ * a runtime exception if any parameters are passed, and uses
+ * the default (no parameter) constructor via Class.newInstance();
+ * to generate the new instance.
+ */
+ public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException {
+ if (parameters != null && parameters.length > 0)
+ throw new IllegalArgumentException("Cannot pass any parameters to the creation of an independent component.");
+ return getType().newInstance();
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java
new file mode 100644
index 0000000..a065d81
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+public class ComponentAlreadyRegisteredError extends RuntimeException {
+
+ private static final long serialVersionUID = 7557424125890830358L;
+
+ public ComponentAlreadyRegisteredError() {
+ super();
+ }
+
+ public ComponentAlreadyRegisteredError(String message) {
+ super(message);
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java
new file mode 100644
index 0000000..f8f9563
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+
+public class CouldNotCreateComponentError
+ extends RuntimeException {
+
+ private static final long serialVersionUID = 398473685547742652L;
+
+ public CouldNotCreateComponentError() {
+ super();
+ }
+
+ public CouldNotCreateComponentError(Throwable t) {
+ super(t);
+ }
+
+ public CouldNotCreateComponentError(String message) {
+ super(message);
+ }
+
+ public CouldNotCreateComponentError(String message, Throwable t) {
+ super(message,t);
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java
new file mode 100644
index 0000000..067e364
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+public class CyclicalDependencyError extends RuntimeException {
+
+ private static final long serialVersionUID = 2260997982445143566L;
+
+ public CyclicalDependencyError() {
+ super();
+ }
+
+ public CyclicalDependencyError(String message) {
+ super(message);
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java
new file mode 100644
index 0000000..3110fb9
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+public class UnsatisfiedDependencyError extends RuntimeException {
+
+ private static final long serialVersionUID = 502309807798988770L;
+
+ public UnsatisfiedDependencyError() {
+ super();
+ }
+
+ public UnsatisfiedDependencyError(String message) {
+ super(message);
+ }
+
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java
new file mode 100644
index 0000000..eb9f25c
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.util;
+
+import java.util.Map;
+
+import net.israfil.foundation.container.AutoWiringAdapter;
+import net.israfil.foundation.container.error.CyclicalDependencyError;
+
+/**
+ * A utility class that provides convenience methods for circular
+ * reference detection.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class CyclicalReferenceDetectionUtil {
+ public static void detectCircularDependencies(Map registry, NonDuplicateStack nds, AutoWiringAdapter componentAdapter) {
+ Object[] deps = componentAdapter.dependencies();
+ for (int i = 0; i < deps.length; i++) {
+ if (registry.containsKey(deps[i])) {
+ try {
+ nds.push(deps[i]);
+ } catch (IllegalArgumentException e) {
+ throw new CyclicalDependencyError("Item " + deps[i] + " is involved in a cyclic dependency. The full path is: " + nds);
+ }
+ detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(deps[i]));
+ nds.pop();
+ }
+ }
+ }
+}
diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java
new file mode 100644
index 0000000..d253024
--- /dev/null
+++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.util;
+
+import java.util.Stack;
+
+/**
+ * A simple stack object which throws an IllegalArgumentException if an
+ * attempt is made to push an object already contained within the stack.
+ *
+ * Primarily used for circular reference detection.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class NonDuplicateStack<T> extends Stack<T> {
+
+ private static final long serialVersionUID = -5777711467165769847L;
+
+ public T push(T item) {
+ if (contains(item)) throw new IllegalArgumentException("Duplicate item.");
+ return super.push(item);
+ }
+
+}
diff --git a/israfil-foundation-container/src/site/apt/index.apt b/israfil-foundation-container/src/site/apt/index.apt
new file mode 100755
index 0000000..10a0281
--- /dev/null
+++ b/israfil-foundation-container/src/site/apt/index.apt
@@ -0,0 +1,45 @@
+ ------
+ Israfil Micro-Container
+ ------
+ Christian Edward Gruber
+ ------
+ May 2, 2007
+
+Overview
+
+ The micro-container is an extremely lightweight IoC container supporting
+ dependency injection. It is built with the principles in mind that
+ spawned {{{http://www.picocontainer.org/} pico-container}} but with the
+ explicit constraints to which J2ME applications centered around the
+ CLDC 1.1 are bound. This includes a complete absence of any constructor
+ or method lookup (reflection) or dynamic proxy support.
+
+ Like pico-container, Israfil's micro-container only handles the
+ registration and vending of components, not additional services such as
+ persistence, and the like.
+
+Isn't Micro bigger than Pico?
+
+ Yes, but micro-container wasn't as taken, and israfil-micro is a placeholder
+ for any further frameworks that might be developed in the J2ME footprint.
+ I briefly considered femto-container, but it was too obscure even for me.
+
+Can I use this in commercial or other software?
+
+ Yes. The micro-container, as with all Israfil Micro and Foundation libraries
+ are licensed under the terms of the BSD license, which provides you with a
+ license to distribute with or without modification, and to prepare derivative
+ works, with the sole exception that you retain the notice (specific terms
+ are available in the license page linked from the menu.) The short answer
+ is yes, go for it, it won't cost you a penny, and you won't be obliged to
+ show anyone your code.
+
+How do I use it?
+
+ I recommend looking at pico-container's site for really good theoretical
+ presentations of this kind of software. Tapestry5 also contains an ioc
+ framework par-excellence, and it has some ok docs. Some specific usage
+ documentation for this framework (around staging the container and getting
+ things set up in a practical application) are available in the usage page
+ linked from the menu.
+ \ No newline at end of file
diff --git a/israfil-foundation-container/src/site/apt/lifecycle.apt b/israfil-foundation-container/src/site/apt/lifecycle.apt
new file mode 100644
index 0000000..3a62be5
--- /dev/null
+++ b/israfil-foundation-container/src/site/apt/lifecycle.apt
@@ -0,0 +1,111 @@
+ ------
+ Israfil Micro-Container : Component Lifecycle
+ ------
+ Christian Edward Gruber
+ ------
+ May 2, 2007
+
+
+ Since one bad pattern in java is to engage in all sorts of side behaviours
+ during construction, components can separate construction from initialization
+ by implementing the Startable interface. Startable components are started
+ before they are provided to any caller.
+
+%{toc}
+
+The Startable interface
+
+ The Startable interface is quite simple:
+
+-------------------
+
+package net.israfil.micro.container;
+
+public interface Startable {
+
+ public void start();
+
+ public boolean isRunning();
+
+}
+
+-------------------
+
+ Implementors should start whatever they need to in order to be ready to
+ accept calls, including marshalling any resources necessary, etc.
+
+ Care should be taken to time-out appropriately, as the container offers
+ its thread to the component during this initialization, and faulty
+ initialization can lock the container.
+
+Registering components with dependencies
+
+ Registration of components with dependencies is a bit more complicated, as it
+ requires an adapter:
+
+-------------------
+
+public void registerType(Object key, AutoWiringAdapter componentAdapter);
+
+-------------------
+
+ AutoWiringAdapters can be created on the fly, for instance by using an anonymous
+ inner class that implements AutoWiringAdapter or extending AbstractAutoWiringAdapter:
+
+-------------------
+
+container.registerType(ComponentThree.class,new AbstractAutoWiringAdapter(
+ ComponentThree.class, new Object[] {ComponentOne.class}
+ ) {
+ public Object create(Object[] params) throws IllegalAccessException, InstantiationException {
+ return new ComponentThreeImpl((ComponentOne)params[0]);
+ }
+});
+
+-------------------
+
+ Another option is to create a constant adapter on the component itself
+
+-------------------
+
+public class ComponentThreeImpl implements ComponentThree {
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ ComponentThree.class, new Object[] {ComponentOne.class}
+ ) {
+ public Object create(Object[] params) throws IllegalAccessException, InstantiationException {
+ return new ComponentThreeImpl((ComponentOne)params[0]);
+ }
+ });
+
+ private final ComponentOne one;
+
+ public ComponentThreeImpl(ComponentOne one) {
+ this.one = one;
+ }
+
+ public void doStuff() { one.whatever(); }
+}
+
+-------------------
+
+ Having created this adapter constant, you can then more easily register the
+ component in the following way:
+
+-------------------
+
+container.registerType(ComponentThree.class,ComponentThreeImpl.adapter);
+
+-------------------
+
+Retrieving components
+
+ Retrieving components is quite simple, using the getComponent method.
+
+-------------------
+
+ComponentThree three = (ComponentThree)container.getComponent(ComponentThree.class);
+three.doStuff();
+
+-------------------
+
+
diff --git a/israfil-foundation-container/src/site/apt/usage.apt b/israfil-foundation-container/src/site/apt/usage.apt
new file mode 100644
index 0000000..54ce418
--- /dev/null
+++ b/israfil-foundation-container/src/site/apt/usage.apt
@@ -0,0 +1,106 @@
+ ------
+ Israfil Micro-Container : Usage
+ ------
+ Christian Edward Gruber
+ ------
+ May 2, 2007
+
+
+ The default container is an auto-wiring container which allows for registration
+ of components quite simply, if they have no dependencies. Components with
+ dependencies require the use of an adapter which explicitly declares the
+ dependencies, and provides a builder method which receives the dependencies and
+ explicitly constructs the component, avoiding any use of reflection, which is
+ not supported in the CLDC 1.1 profile.
+
+%{toc}
+
+Setting up the auto-wiring container.
+
+ Setting up the container should be done early in your entry-point code.
+ The default container auto-wires components on first use of the component,
+ unless configured to pre-initialize them. This allows for early creation
+ of the container and registration of components without incurring the
+ up-front performance cost.
+
+ Registration for independent components works quite simply:
+
+-------------------
+
+AutoWiringAdaptableContainer container = new DefaultAutoWiringAdaptablecContainer();
+container.registerType(ComponentOne.class,ComponentOneImpl.class);
+container.registerType(ComponentTwo.class,ComponentTwoImpl.class);
+
+-------------------
+
+Registering components with dependencies
+
+ Registration of components with dependencies is a bit more complicated, as it
+ requires an adapter:
+
+-------------------
+
+public void registerType(Object key, AutoWiringAdapter componentAdapter);
+
+-------------------
+
+ AutoWiringAdapters can be created on the fly, for instance by using an anonymous
+ inner class that implements AutoWiringAdapter or extending AbstractAutoWiringAdapter:
+
+-------------------
+
+container.registerType(ComponentThree.class,new AbstractAutoWiringAdapter(
+ ComponentThree.class, new Object[] {ComponentOne.class}
+ ) {
+ public Object create(Object[] params) throws IllegalAccessException, InstantiationException {
+ return new ComponentThreeImpl((ComponentOne)params[0]);
+ }
+});
+
+-------------------
+
+ Another option is to create a constant adapter on the component itself
+
+-------------------
+
+public class ComponentThreeImpl implements ComponentThree {
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ ComponentThree.class, new Object[] {ComponentOne.class}
+ ) {
+ public Object create(Object[] params) throws IllegalAccessException, InstantiationException {
+ return new ComponentThreeImpl((ComponentOne)params[0]);
+ }
+ });
+
+ private final ComponentOne one;
+
+ public ComponentThreeImpl(ComponentOne one) {
+ this.one = one;
+ }
+
+ public void doStuff() { one.whatever(); }
+}
+
+-------------------
+
+ Having created this adapter constant, you can then more easily register the
+ component in the following way:
+
+-------------------
+
+container.registerType(ComponentThree.class,ComponentThreeImpl.adapter);
+
+-------------------
+
+Retrieving components
+
+ Retrieving components is quite simple, using the getComponent method.
+
+-------------------
+
+ComponentThree three = (ComponentThree)container.getComponent(ComponentThree.class);
+three.doStuff();
+
+-------------------
+
+
diff --git a/israfil-foundation-container/src/site/site.xml b/israfil-foundation-container/src/site/site.xml
new file mode 100644
index 0000000..d580c65
--- /dev/null
+++ b/israfil-foundation-container/src/site/site.xml
@@ -0,0 +1,20 @@
+<project>
+ <body>
+ <menu name="Parent">
+ <item name="${parent.name}" href="../index.html"/>
+ </menu>
+ <menu name="Overview">
+ <item name="Introduction" href="index.html"/>
+ <item name="Usage" href="usage.html"/>
+ <item name="Lifecycle" href="lifecycle.html"/>
+ <!-- <item name="FAQ" href="faq.html"/> -->
+ </menu>
+ <!--
+ <menu name="Examples">
+ <item name="Simple Flex app in a WAR project" href="examples/simple_war_project.html"/>
+ <item name="Flex app with extra params" href="examples/extra_parameters_project.html"/>
+ </menu>
+ -->
+ ${reports}
+ </body>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java
new file mode 100644
index 0000000..ab0e624
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class ContainerTest {
+
+ AbstractContainer container = null;
+ AbstractContainer child = null;
+
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() {
+ container = new AbstractContainer() {
+ public void start() { }
+ public Object getComponent(Object key) { return getStoredComponent(key); }
+ };
+ child = new AbstractContainer(container) {
+ public void start() { }
+ public Object getComponent(Object key) { return getStoredComponent(key); }
+ };
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() {
+ child = null;
+ container = null;
+ }
+
+ @Test
+ public void testContainerWithSingleComponent() {
+ FakeComponent component = new FakeComponent1();
+ container.store(FakeComponent.class, component);
+ Assert.assertSame(container.getComponent(FakeComponent.class), component);
+ }
+
+ @Test
+ public void testContainerWithMultipleComponents() {
+ FakeComponent component = new FakeComponent1();
+ FakeDependentComponent component2 = new FakeDependentComponent(component);
+ container.store(FakeComponent.class, component);
+ container.store(FakeDependentComponent.class, component2);
+ Assert.assertSame(container.getComponent(FakeComponent.class), component);
+ Assert.assertSame(container.getComponent(FakeDependentComponent.class), component2);
+ }
+
+ @Test(expectedExceptions=ComponentAlreadyRegisteredError.class)
+ public void testContainerWithDuplicateComponents() {
+ FakeComponent component1 = new FakeComponent1();
+ FakeComponent component2 = new FakeComponent2();
+ container.store(FakeComponent.class,component1);
+ container.store(FakeComponent.class,component2);
+ }
+
+ @Test
+ public void testContainerWithRepeatedRegistrationsOfTheSameComponent() {
+ FakeComponent component1 = new FakeComponent1();
+ container.store(FakeComponent.class,component1);
+ container.store(FakeComponent.class,component1);
+ }
+
+ @Test
+ public void testContainerWithParent() {
+ FakeComponent component1 = new FakeComponent1();
+ container.store(FakeComponent.class,component1);
+ Assert.assertTrue(child.hasComponent(FakeComponent.class));
+ Assert.assertSame(child.getComponent(FakeComponent.class), component1);
+ }
+
+ @Test(expectedExceptions=ComponentAlreadyRegisteredError.class)
+ public void testDuplicateRegistrationWithFirstObjectInParent() {
+ FakeComponent component1 = new FakeComponent1();
+ FakeComponent component2 = new FakeComponent2();
+ container.store(FakeComponent.class,component1);
+ child.store(FakeComponent.class,component2);
+ }
+
+ @Test
+ public void testDuplicateComponentsInPeerContainers() {
+ AbstractContainer child2 = new AbstractContainer(container) {
+ public void start() { }
+ public Object getComponent(Object key) { return getStoredComponent(key); }
+ };
+ FakeComponent component1 = new FakeComponent1();
+ FakeComponent component2 = new FakeComponent2();
+ child.store(FakeComponent.class,component1);
+ child2.store(FakeComponent.class,component2);
+ Assert.assertTrue(child.hasComponent(FakeComponent.class));
+ Assert.assertSame(child.getComponent(FakeComponent.class), component1);
+ Assert.assertNotSame(child2.getComponent(FakeComponent.class), component1);
+ Assert.assertTrue(child2.hasComponent(FakeComponent.class));
+ Assert.assertSame(child2.getComponent(FakeComponent.class), component2);
+ Assert.assertNotSame(child2.getComponent(FakeComponent.class), component1);
+ Assert.assertFalse(container.hasComponent(FakeComponent.class));
+ }
+
+ public abstract class FakeComponent {
+ public abstract boolean isTrue();
+ }
+ public class FakeComponent1 extends FakeComponent {
+ public boolean isTrue() { return false; }
+ }
+ public class FakeComponent2 extends FakeComponent {
+ public boolean isTrue() { return false; }
+ }
+ public class FakeDependentComponent {
+ private final FakeComponent fake;
+ public FakeDependentComponent(FakeComponent component) {
+ this.fake = component;
+ }
+ public boolean isTrue() { return fake.isTrue(); }
+ }
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java
new file mode 100644
index 0000000..1d108b0
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+
+import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter;
+import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter;
+import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError;
+import net.israfil.foundation.container.error.CouldNotCreateComponentError;
+import net.israfil.foundation.container.error.UnsatisfiedDependencyError;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class DefaultContainerTest {
+
+
+ public DefaultContainer createContainer() { return new DefaultContainer(); }
+ public DefaultContainer createContainer(boolean tf) { return new DefaultContainer(tf); }
+ public DefaultContainer createContainer(Container c) { return new DefaultContainer(c); }
+ public DefaultContainer createContainer(Container c, boolean tf) { return new DefaultContainer(c,tf); }
+ public TestableContainer createTestableContainer() { return new TestableDefaultContainer(); }
+
+ @Test
+ public void testAutoWiringContainer() {
+ TestableContainer container = createTestableContainer();
+ container.registerType(A.class, A1.class);
+ container.registerType(B.class,B.adapter);
+ container.registerType(D.class,D.adapter); // out of order
+ container.registerType(C.class, new AbstractAutoWiringAdapter(
+ C.class,
+ new Object[] {A.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new C((A)param[0]);
+ }
+ });
+ container.start();
+ Assert.assertFalse(container.isStored(A.class));
+ Assert.assertNotNull(container.getComponent(A.class));
+ Assert.assertTrue(container.isStored(A.class));
+ Assert.assertFalse(container.isStored(B.class));
+ Assert.assertNotNull(container.getComponent(B.class));
+ Assert.assertTrue(container.isStored(B.class));
+ Assert.assertFalse(container.isStored(C.class));
+ Assert.assertFalse(container.isStored(D.class));
+ Assert.assertNotNull(container.getComponent(D.class));
+ Assert.assertTrue(container.isStored(C.class));
+ Assert.assertTrue(container.isStored(D.class));
+ }
+
+ @Test(expectedExceptions=UnsatisfiedDependencyError.class)
+ public void testMissingDependenciesFailingLate() {
+ AutoWiringAdaptableContainer container = createContainer();
+ container.registerType(B.class,B.adapter);
+ container.start();
+ Assert.assertTrue(container.isRunning());
+ container.getComponent(B.class);
+ }
+
+ @Test
+ public void testDelayedFailureWithMissingDependencies() {
+ AutoWiringAdaptableContainer container = createContainer();
+ container.registerType(B.class,B.adapter);
+ container.start();
+ }
+
+ @Test(expectedExceptions=UnsatisfiedDependencyError.class)
+ public void testMissingDependenciesFailingEarly() {
+ AutoWiringAdaptableContainer container = createContainer(true);
+ container.registerType(B.class,B.adapter);
+ container.start();
+ }
+
+ @Test
+ public void testMultipleStartups() {
+ AutoWiringAdaptableContainer container = createContainer(true);
+ container.registerType(A.class,A1.class);
+ container.registerType(B.class,B.adapter);
+ container.start();
+ Assert.assertTrue(container.isRunning());
+ container.start(); // no error.
+ }
+
+ @Test(expectedExceptions=RuntimeException.class)
+ public void testStartupWithUnstartedParent() {
+ AutoWiringAdaptableContainer parent = createContainer();
+ AutoWiringAdaptableContainer child = createContainer(parent);
+ parent.registerType(A.class,A1.class);
+ child.registerType(B.class,B.adapter);
+ child.start(); // failed to start parent.
+ }
+
+ @Test(expectedExceptions=ComponentAlreadyRegisteredError.class)
+ public void testDuplicateRegistration() {
+ AutoWiringAdaptableContainer container = createContainer();
+ container.registerType(A.class,A1.class);
+ container.registerType(A.class,new AutoWiringAdapter() {
+ public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException {
+ return null;
+ }
+ public Object[] dependencies() { return null; }
+ public Class getType() { return null; }
+ });
+ }
+
+ @Test(expectedExceptions=RuntimeException.class)
+ public void testRegistryFailureAfterStart() {
+ AutoWiringAdaptableContainer container = createContainer();
+ container.registerType(A.class,A1.class);
+ container.registerType(B.class,B.adapter);
+ container.start();
+ container.registerType(D.class,D.adapter);
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testIllegalAccessDuringConstruction() {
+ AutoWiringAdaptableContainer container = createContainer(true);
+ container.registerType(ComponentWithProtectedConstructor.class,ComponentWithProtectedConstructor.class);
+ container.start();
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testInstantiationErrorDuringConstruction() {
+ AutoWiringAdaptableContainer container = createContainer(true);
+ container.registerType(A.class,A.class);
+ container.start();
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testNullComponentCreation() {
+ AutoWiringAdaptableContainer container = createContainer(true);
+ container.registerType(A.class,new IndependentAutoWiringAdapter(A.class) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return null;
+ }
+ });
+ container.start();
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testArbitraryErrorInComponentCreation() {
+ AutoWiringAdaptableContainer container = createContainer(true);
+ container.registerType(A.class,new IndependentAutoWiringAdapter(A.class) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ throw new RuntimeException("Random error");
+ }
+ });
+ container.start();
+ }
+
+
+ @Test
+ public void testAutowiringWithDependencyInParentContainerWithEarlyInstantiation() {
+ AutoWiringAdaptableContainer parent = createContainer(true);
+ AutoWiringAdaptableContainer child = createContainer(parent,true);
+ parent.registerType(A.class,A1.class);
+ child.registerType(B.class,B.adapter);
+ parent.start();
+ child.start();
+ Assert.assertNotNull(child.getComponent(B.class));
+ }
+
+ @Test
+ public void testAutowiringWithDependencyInParentContainerWithLateIntantiation() {
+ AutoWiringAdaptableContainer parent = createContainer();
+ AutoWiringAdaptableContainer child = createContainer(parent);
+ parent.registerType(A.class,A1.class);
+ child.registerType(B.class,B.adapter);
+ parent.start();
+ child.start();
+ Assert.assertNotNull(child.getComponent(B.class));
+ }
+
+ public static abstract class A {
+ }
+ public static class A1 extends A {
+ }
+ public static class B {
+ private final A a;
+ public B(A a) {
+ if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments.");
+ this.a = a;
+ }
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ B.class,
+ new Object[] {A.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new B((A)param[0]);
+ }
+ };
+ }
+ public static class C {
+ private final A a;
+ public C(A a) {
+ if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments.");
+ this.a = a;
+ }
+ }
+ public static class D {
+ private final C c;
+ public D(C c) {
+ if (c==null) throw new IllegalArgumentException("D cannot support null constructor arguments.");
+ this.c = c;
+ }
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ D.class,
+ new Object[] {C.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new D((C)param[0]);
+ }
+ };
+ }
+
+ public static class ComponentWithProtectedConstructor {
+ protected ComponentWithProtectedConstructor() {}
+ }
+
+ public static interface TestableContainer extends AutoWiringAdaptableContainer {
+ public boolean isStored(Object key);
+ }
+
+ public static class TestableDefaultContainer extends DefaultContainer implements TestableContainer {
+ public boolean isStored(Object key) {
+ return super.isStored(key);
+ }
+ }
+
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java
new file mode 100644
index 0000000..4e69610
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+
+
+public class LegacyContainerTest extends DefaultContainerTest {
+
+ public DefaultContainer createContainer() { return new DefaultAutoWiringAdaptableContainer(); }
+ public DefaultContainer createContainer(boolean tf) { return new DefaultAutoWiringAdaptableContainer(tf); }
+ public DefaultContainer createContainer(Container c) { return new DefaultAutoWiringAdaptableContainer(c); }
+ public DefaultContainer createContainer(Container c, boolean tf) { return new DefaultAutoWiringAdaptableContainer(c,tf); }
+ public TestableContainer createTestableContainer() { return new TestableLegacyContainer(); }
+
+ public static class TestableLegacyContainer extends DefaultAutoWiringAdaptableContainer implements TestableContainer {
+ public boolean isStored(Object key) {
+ return super.isStored(key);
+ }
+ }
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java
new file mode 100644
index 0000000..920f17c
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter;
+import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class LifecycleTest {
+
+ @Test()
+ public void testAbstractStartable() {
+ Startable s = new AbstractStartable() {};
+ Assert.assertFalse(s.isRunning());
+ s.start();
+ Assert.assertTrue(s.isRunning());
+ }
+
+ @Test()
+ public void testStartupOfSingleComponent() {
+ AutoWiringAdaptableContainer container = new DefaultContainer();
+ final A1 a1 = new A1();
+ container.registerType(A.class, new IndependentAutoWiringAdapter(A1.class) {
+ public Object create(Object[] args) { return a1; }
+ });
+ Assert.assertFalse(a1.isRunning());
+ container.start();
+ container.getComponent(A.class);
+ Assert.assertTrue(a1.isRunning());
+ }
+
+ @Test()
+ public void testStartupOfStartedComponent() {
+ AutoWiringAdaptableContainer container = new DefaultContainer();
+ final A2 a2 = new A2();
+ a2.start();
+ container.registerType(A.class, new IndependentAutoWiringAdapter(A.class) {
+ public Object create(Object[] args) { return a2; }
+ });
+ container.start();
+ container.getComponent(A.class);
+ Assert.assertEquals(a2.invoked,1);
+ }
+
+ @Test()
+ public void testStartupOfMultipleComponents() {
+ AutoWiringAdaptableContainer container = new DefaultContainer();
+ final A1 a1 = new A1();
+ final C c = new C(a1);
+ container.registerType(A.class, new IndependentAutoWiringAdapter(A1.class) {
+ public Object create(Object[] args) { return a1; }
+ });
+ container.registerType(B.class, B.adapter);
+ container.registerType(C.class, new AbstractAutoWiringAdapter(
+ C.class,
+ new Object[] {A.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return c;
+ }
+ });
+ Assert.assertFalse(a1.isRunning());
+ Assert.assertFalse(c.isRunning());
+ container.start();
+ container.getComponent(A.class);
+ Assert.assertFalse(c.isRunning());
+ Assert.assertTrue(a1.isRunning());
+ container.getComponent(C.class);
+ Assert.assertTrue(c.isRunning());
+ Assert.assertTrue(a1.isRunning());
+ }
+
+ public static interface A {
+ }
+
+ public static class A1 extends AbstractStartable implements A {
+ public void start() { super.start(); }
+ }
+
+ public static class A2 extends AbstractStartable implements A {
+ public int invoked = 0;
+ public void start() {
+ super.start();
+ invoked++;
+ }
+ }
+
+ public static class B {
+ private final A a;
+ public B(A a) {
+ if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments.");
+ this.a = a;
+ }
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ B.class,
+ new Object[] {A.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new B((A)param[0]);
+ }
+ };
+ }
+ public static class C extends AbstractStartable implements Startable{
+ private final A a;
+ public C(A a) {
+ if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments.");
+ this.a = a;
+ }
+ public void start() { super.start(); }
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ C.class,
+ new Object[] {A.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new C((A)param[0]);
+ }
+ };
+ }
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java
new file mode 100644
index 0000000..dabc119
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container;
+
+import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class MultiThreadedAutoWiringContainerTest {
+
+ @Test()
+ public void testMissingDependenciesWiringEarly() {
+ AutoWiringAdaptableContainer container = new DefaultContainer(true);
+ container.registerType(A.class,A1.class);
+ container.registerType(B.class,B.adapter);
+ container.start();
+ Assert.assertNotNull(container.getComponent(B.class));
+ }
+
+ public static abstract class A {
+ }
+ public static class A1 extends A {
+ }
+ public static class B {
+ private final A a;
+ public B(A a) {
+ if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments.");
+ this.a = a;
+ }
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ B.class,
+ new Object[] {A.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new B((A)param[0]);
+ }
+ };
+ }
+ public static class C {
+ private final A a;
+ public C(A a) {
+ if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments.");
+ this.a = a;
+ }
+ }
+ public static class D {
+ private final C c;
+ public D(C c) {
+ if (c==null) throw new IllegalArgumentException("D cannot support null constructor arguments.");
+ this.c = c;
+ }
+ public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter(
+ D.class,
+ new Object[] {C.class}
+ ) {
+ public Object create(Object[] param) throws IllegalAccessException, InstantiationException {
+ return new D((C)param[0]);
+ }
+ };
+ }
+
+ public static class E {
+ protected E() {}
+ }
+
+ public static class TestableAutoWiringAdaptableContainer extends DefaultContainer {
+ public boolean isStored(Object key) {
+ return super.isStored(key);
+ }
+ }
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java
new file mode 100644
index 0000000..62150ed
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.adapters;
+
+import net.israfil.foundation.container.AutoWiringAdapter;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Tests
+ * @author cgruber
+ *
+ */
+public class AdaptersTest {
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void testIndependentAutoWiringAdapterWithNullType() {
+ new IndependentAutoWiringAdapter(null);
+ }
+
+ @Test
+ public void testIndependentAutoWiringAdapterWithEmptyParamters() throws Exception {
+ AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class);
+ Fake fake = (Fake)awa.create(new Object[0]);
+ Assert.assertNotNull(fake);
+ }
+
+ @Test
+ public void testIndependentAutoWiringAdapterWithNullParamters() throws Exception {
+ AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class);
+ Fake fake = (Fake)awa.create(null);
+ Assert.assertNotNull(fake); // should not reach this assert.
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void testIndependentAutoWiringAdapterWithNonEmptyParamters() throws Exception {
+ AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class);
+ Object[] parameters = new Object[1];
+ parameters[0] = "A";
+ Fake fake = (Fake)awa.create(parameters);
+ Assert.assertNotNull(fake); // should not reach this assert.
+ }
+
+ public static class Fake {
+ public Fake() {}
+ }
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java
new file mode 100644
index 0000000..fdaa7fa
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+import org.testng.annotations.Test;
+
+
+
+public class ComponentAlreadyRegisteredErrorTest {
+
+ @Test(expectedExceptions=ComponentAlreadyRegisteredError.class)
+ public void testSimpleErrorThrow() throws Throwable {
+ Throwable error = new ComponentAlreadyRegisteredError();
+ throw error;
+ }
+
+ @Test(expectedExceptions=ComponentAlreadyRegisteredError.class)
+ public void testSimpleErrorThrowWithString() throws Throwable {
+ Throwable error = new ComponentAlreadyRegisteredError("test");
+ throw error;
+ }
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java
new file mode 100644
index 0000000..87d43a4
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+import org.testng.annotations.Test;
+
+
+
+public class CouldNotCreateComponentTest {
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testSimpleErrorThrow() throws Throwable {
+ Throwable error = new CouldNotCreateComponentError();
+ throw error;
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testSimpleErrorThrowWithString() throws Throwable {
+ Throwable error = new CouldNotCreateComponentError("test");
+ throw error;
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testSimpleErrorThrowWithThrowable() {
+ RuntimeException error = new CouldNotCreateComponentError(
+ new RuntimeException("test2")
+ );
+ throw error;
+ }
+
+ @Test(expectedExceptions=CouldNotCreateComponentError.class)
+ public void testSimpleErrorThrowWithStringAndThrowable() {
+ RuntimeException error = new CouldNotCreateComponentError(
+ "test",
+ new RuntimeException("test2")
+ );
+ throw error;
+ }
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java
new file mode 100644
index 0000000..fc2fd93
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+import org.testng.annotations.Test;
+
+
+
+public class CyclicalDependencyErrorTest {
+
+ @Test(expectedExceptions=CyclicalDependencyError.class)
+ public void testSimpleErrorThrow() throws Throwable {
+ Throwable error = new CyclicalDependencyError();
+ throw error;
+ }
+
+ @Test(expectedExceptions=CyclicalDependencyError.class)
+ public void testSimpleErrorThrowWithString() throws Throwable {
+ Throwable error = new CyclicalDependencyError("test");
+ throw error;
+ }
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java
new file mode 100644
index 0000000..c668b5d
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.error;
+
+import org.testng.annotations.Test;
+
+
+
+public class UnsatisfiedDependencyErrorTest {
+
+ @Test(expectedExceptions=UnsatisfiedDependencyError.class)
+ public void testSimpleErrorThrow() throws Throwable {
+ Throwable error = new UnsatisfiedDependencyError();
+ throw error;
+ }
+
+ @Test(expectedExceptions=UnsatisfiedDependencyError.class)
+ public void testSimpleErrorThrowWithString() throws Throwable {
+ Throwable error = new UnsatisfiedDependencyError("test");
+ throw error;
+ }
+
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java
new file mode 100644
index 0000000..781ad92
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.israfil.foundation.container.AutoWiringAdapter;
+import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter;
+import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter;
+import net.israfil.foundation.container.error.CyclicalDependencyError;
+
+import org.testng.annotations.Test;
+
+
+public class CyclicalDependencyDetectionTest {
+
+ @Test()
+ public void testCircularDependencyCheckWithNonCyclicGraph() {
+ // setup non-circular graph.
+ Map<Object,Object> registry = new HashMap<Object,Object>();
+ registry.put("a", new FakeAutoWireAdapter(new Object[]{"b","e","d"}));
+ registry.put("b", new FakeAutoWireAdapter(new Object[]{"f","c"}));
+ registry.put("c", new IndependentAutoWiringAdapter(Object.class));
+ registry.put("d", new FakeAutoWireAdapter(new Object[]{"e"}));
+ registry.put("e", new FakeAutoWireAdapter(new Object[]{"c"}));
+ registry.put("f", new IndependentAutoWiringAdapter(Object.class));
+ NonDuplicateStack<Object> nds = new NonDuplicateStack<Object>();
+ for (Object key : registry.keySet()) {
+ nds.push(key);
+ CyclicalReferenceDetectionUtil.detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(key));
+ nds.pop();
+ }
+ }
+
+ @Test(expectedExceptions=CyclicalDependencyError.class)
+ public void testCircularDependencyCheckWithCyclicalGraph() {
+ // setup circular graph.
+ Map<Object,Object> registry = new HashMap<Object,Object>();
+ registry.put("a", new FakeAutoWireAdapter(new Object[]{"b","e","d"}));
+ registry.put("b", new FakeAutoWireAdapter(new Object[]{"f","c"}));
+ registry.put("c", new FakeAutoWireAdapter(new Object[]{"d"}));
+ registry.put("d", new FakeAutoWireAdapter(new Object[]{"e"}));
+ registry.put("e", new FakeAutoWireAdapter(new Object[]{"c"}));
+ registry.put("f", new IndependentAutoWiringAdapter(Object.class));
+ NonDuplicateStack<Object> nds = new NonDuplicateStack<Object>();
+ for (Object key : registry.keySet()) {
+ nds.push(key);
+ CyclicalReferenceDetectionUtil.detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(key));
+ nds.pop();
+ }
+ }
+
+
+ public static class FakeAutoWireAdapter extends AbstractAutoWiringAdapter {
+ public FakeAutoWireAdapter(Object[] dependencies) {
+ super(Object.class, dependencies);
+ }
+ public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException {
+ return null;
+ }
+ }
+}
diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java
new file mode 100644
index 0000000..a67afb0
--- /dev/null
+++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.container.util;
+
+import java.util.Stack;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class NonDuplicateStackTest {
+
+ @Test()
+ public void testBasicStackBehaviour() {
+ String s1 = "Hi.";
+ String s2 = "Hi";
+ String s3 = "Bye.";
+ Stack<Object> stack = new NonDuplicateStack<Object>();
+ stack.push(s1);
+ stack.push(s2);
+ stack.push(s3);
+ Assert.assertSame(stack.pop(),s3);
+ Assert.assertSame(stack.pop(),s2);
+ Assert.assertSame(stack.pop(),s1);
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void testDuplicateHandlingByObjectRef() {
+ Object o1 = new Object();
+ Object o2 = new Object();
+ Object o3 = new Object();
+ Stack<Object> stack = new NonDuplicateStack<Object>();
+ stack.push(o1);
+ stack.push(o2);
+ stack.push(o3);
+ stack.push(o2);
+ }
+
+ @Test(expectedExceptions=IllegalArgumentException.class)
+ public void testDuplicateHandlingByValue() {
+ String s1 = "Hi.";
+ String s2 = "Hi";
+ String s3 = "Bye.";
+ String s4 = "Hi";
+ Stack<Object> stack = new NonDuplicateStack<Object>();
+ stack.push(s1);
+ stack.push(s2);
+ stack.push(s3);
+ stack.push(s4);
+ }
+
+}
diff --git a/israfil-foundation-core/pom.xml b/israfil-foundation-core/pom.xml
new file mode 100644
index 0000000..5bf65f4
--- /dev/null
+++ b/israfil-foundation-core/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-core</artifactId>
+ <name>Israfil Foundation Core Classes</name>
+ <version>1.0.2-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ </project> \ No newline at end of file
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java
new file mode 100755
index 0000000..203793c
--- /dev/null
+++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2006-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2006-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An attribute used to tag the copyright year, owner, and license. This
+ * is purely for documentation purposes, and it has only a SOURCE scope.
+ *
+ * For example:
+ * <pre>
+ * @Copyright(years={"2003","2004","2005"} owner="Israfil Consulting Services Corporation" license="BSD")
+ * </pre>
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ *
+ * @deprecated
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+public @interface Copyright {
+ String[] years();
+ String owner();
+ String license();
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java
new file mode 100644
index 0000000..e87b86a
--- /dev/null
+++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Counter.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+
+/**
+ * A simple counter interface
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Counter {
+
+ public int getCount();
+
+ public void increment();
+
+ public void decrement();
+
+ public void reset();
+
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java
new file mode 100644
index 0000000..042f623
--- /dev/null
+++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SimpleCounter.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+
+/**
+ * A simple counter interface
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class SimpleCounter implements Counter {
+
+ private int count = 0;
+
+ public int getCount() { return count; }
+
+ public void increment() { count++; }
+
+ public void decrement() { count--; }
+
+ public void reset() { count = 0; }
+
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java
new file mode 100644
index 0000000..edde901
--- /dev/null
+++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Strings.java 617 2008-04-14 13:46:15Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+import java.util.Arrays;
+
+/**
+ * A Utility class that provides general string manipulation help.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: christianedwardgruber $
+ * @version $Revision: 617 $
+ */
+public class Strings {
+
+ public static String camel(String string) {
+ if (string == null) return null;
+ if (string.length() < 1) return string;
+ StringBuffer sb = new StringBuffer(string);
+ sb.replace(0,1,sb.substring(0,1).toUpperCase());
+ return sb.toString();
+ }
+
+ public static String camelAllWords(String string, String separator) {
+ StringBuffer sb = new StringBuffer();
+ boolean first = true;
+ for (String _string : string.split(separator)) {
+ if (!first) sb.append(separator);
+ else first = false;
+ sb.append(camel(_string));
+ }
+ return sb.toString();
+ }
+
+ public static String concatenate(String separator, Iterable<String> strings) {
+ if (strings == null) return "";
+ boolean first = true;
+ StringBuffer sb = new StringBuffer();
+ for (String string : strings) {
+ if (first) {
+ first = false;
+ sb.append(string);
+ } else {
+ sb.append(separator).append(string);
+ }
+ }
+ return sb.toString();
+ }
+ public static String concatenate(String separator, String ... strings) {
+ if (strings == null) return "";
+ return concatenate(separator,Arrays.asList(strings));
+ }
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java
new file mode 100644
index 0000000..f720fe9
--- /dev/null
+++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 644 2009-01-04 18:02:21Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+/**
+ * A Utility class that provides type-conversion facilities. For
+ * example, this class provides well-deliniated logic for taking
+ * a generic object and converting it into another concrete type, such
+ * as a String. Another example would be transforming the string "yes"
+ * into a boolean in a well-defined, well-ordered way.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: christianedwardgruber $
+ * @version $Revision: 644 $
+ */
+public class Types {
+
+ private static final byte BOOLEAN_FALSE_NUMERIC = 0;
+ private static final byte BOOLEAN_TRUE_NUMERIC = 1;
+
+ /**
+ * A delegate interface that, if provided to the convert(String,Class,Converter)
+ * method will add fallback conversions. This allows the existing
+ * convert method to be extended without subclassing, overriding, or
+ * modifying source.
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+ public static interface Converter {
+ public Object convert(Object val, Class<?> aClass);
+ }
+
+ /**
+ * A method to convert an object to another object of a given type.
+ * @param value The object to be converted.
+ * @param aClass The class to which you wish to convert the object.
+ * @return The converted object.
+ */
+ public static Object convert(Object value, Class<?> aClass) {
+ return convert(value,aClass,null);
+ }
+
+ /**
+ * A method to convert an object to another object of a given type.
+ * @param value The object to be converted.
+ * @param aClass The class to which you wish to convert the object.
+ * @param converter An optional delegate that will convert the object if it fails - for extensibility.
+ * @return The converted object.
+ */
+ public static Object convert(Object value, Class<?> aClass,
+ Converter converter) {
+ if (value == null) return null;
+ if (aClass == null) throw new IllegalArgumentException("Cannot convert to a null class.");
+ if (Void.class.isAssignableFrom(aClass)) throw new IllegalArgumentException("Cannot convert to void.");
+ if (aClass.isInstance(value) ) return value;
+
+ if (aClass.isAssignableFrom(String.class)) {
+
+ // TODO: Insert any specific conversions
+ return String.valueOf(value);
+ } else if (Boolean.class.isAssignableFrom(aClass)) {
+ if (value instanceof String) {
+ if (((String)value).equalsIgnoreCase("Yes")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("True")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("Y")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("T")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("1")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("Aye")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("Yar")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("No")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("False")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("N")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("F")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("0")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("Avast")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("Nay")) return Boolean.FALSE;
+ throw new IllegalArgumentException("Cannot convert value '"+value+"' to a java.lang.Boolean");
+ }
+ if(value instanceof Number) {
+ return (((Number)value).intValue() != 0) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ } else if (aClass.isAssignableFrom(Byte.class)) {
+ if (value instanceof String) return Byte.valueOf((String)value);
+ if (value instanceof Number) return new Byte(((Number)value).byteValue());
+ if (value instanceof Boolean) return new Byte(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Short.class)) {
+ if (value instanceof String) return Short.valueOf((String)value);
+ if (value instanceof Number) return new Short(((Number)value).shortValue());
+ if (value instanceof Boolean) return new Short(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Integer.class)) {
+ if (value instanceof String) return Integer.valueOf((String)value);
+ if (value instanceof Number) return new Integer(((Number)value).intValue());
+ if (value instanceof Boolean) return new Integer(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Long.class)) {
+ if (value instanceof String) return Long.valueOf((String)value);
+ if (value instanceof Number) return new Long(((Number)value).longValue());
+ if (value instanceof Boolean) return new Long(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Float.class)) {
+ if (value instanceof String) return Float.valueOf((String)value);
+ if (value instanceof Number) return new Float(((Number)value).floatValue());
+ if (value instanceof Boolean) return new Float(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Double.class)) {
+ if (value instanceof String) return Double.valueOf((String)value);
+ if (value instanceof Number) return new Double(((Number)value).doubleValue());
+ if (value instanceof Boolean) return new Double(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Character.class)) {
+ if (value instanceof String) return new Character(((String)value).charAt(0));
+ if (value instanceof Number) return new Character((char)((Number)value).byteValue());
+ if (value instanceof Boolean) return new Character(((Boolean)value).booleanValue() ? 'T' : 'F');
+ }
+
+ if (value instanceof String) {
+ String stringVal = (String)value;
+ if (Float.class.isAssignableFrom(aClass)) return new Float((String)value);
+ if (Double.class.isAssignableFrom(aClass)) return new Double((String)value);
+ if (Byte.class.isAssignableFrom(aClass)) return new Byte((String)value);
+ if (Short.class.isAssignableFrom(aClass)) return new Short((String)value);
+ if (Integer.class.isAssignableFrom(aClass)) return new Integer((String)value);
+ if (Long.class.isAssignableFrom(aClass)) return new Long((String)value);
+ if (Character.class.isAssignableFrom(aClass)) return new Character(stringVal.charAt(0));
+ }
+
+ if (converter != null) return converter.convert(value,aClass);
+ throw new IllegalArgumentException("Don't know how to convert a String to a " + aClass);
+ }
+
+ public static Object convert(boolean object, Class<?> aClass) {
+ return convert(new Boolean(object),aClass);
+ }
+
+ public static Object convert(byte object, Class<?> aClass) {
+ return convert(new Byte(object),aClass);
+ }
+
+ public static Object convert(short object, Class<?> aClass) {
+ return convert(new Short(object),aClass);
+ }
+
+ public static Object convert(int object, Class<?> aClass) {
+ return convert(new Integer(object),aClass);
+ }
+
+ public static Object convert(long object, Class<?> aClass) {
+ return convert(new Long(object),aClass);
+ }
+
+ public static Object convert(float object, Class<?> aClass) {
+ return convert(new Float(object),aClass);
+ }
+
+ public static Object convert(double object, Class<?> aClass) {
+ return convert(new Double(object),aClass);
+ }
+
+ public static Object convert(char object, Class<?> aClass) {
+ return convert(new Character(object),aClass);
+ }
+
+ public static boolean convertToBoolean(Object object) {
+ return ((Boolean)convert(object,Boolean.class)).booleanValue();
+ }
+
+ public static byte convertToByte(Object object) {
+ return ((Number)convert(object,Byte.class)).byteValue();
+ }
+
+ public static short convertToShort(Object object) {
+ return ((Number)convert(object,Short.class)).shortValue();
+ }
+
+ public static int convertToInt(Object object) {
+ return ((Number)convert(object,Integer.class)).intValue();
+ }
+
+ public static long convertToLong(Object object) {
+ return ((Number)convert(object,Long.class)).longValue();
+ }
+
+ public static float convertToFloat(Object object) {
+ return ((Number)convert(object,Float.class)).floatValue();
+ }
+
+ public static double convertToDouble(Object object) {
+ return ((Number)convert(object,Double.class)).doubleValue();
+ }
+
+ public static char convertToChar(Object object) {
+ return ((Character)convert(object,Character.class)).charValue();
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/conf/testng.xml b/israfil-foundation-core/src/test/conf/testng.xml
new file mode 100644
index 0000000..45ec021
--- /dev/null
+++ b/israfil-foundation-core/src/test/conf/testng.xml
@@ -0,0 +1,24 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
+<!--
+ Copyright 2007, 2008 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.
+-->
+
+<suite name="Israfil Foundation Core" thread-count="5" annotations="1.5" verbose="2" parallel="tests">
+ <test name="core">
+ <packages>
+ <package name="net.israfil.foundation.core"/>
+ </packages>
+ </test>
+</suite>
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java
new file mode 100644
index 0000000..fc9c3d7
--- /dev/null
+++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2006-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SimpleCounterTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.annotations.Test;
+
+
+
+public class SimpleCounterTest{
+
+ @Test
+ public void testCounter() {
+ Counter c = new SimpleCounter();
+ assert c.getCount() == 0;
+ c.increment();
+ assert c.getCount() == 1;
+ c.increment();
+ assert c.getCount() == 2;
+ c.decrement();
+ assert c.getCount() == 1;
+ c.decrement();
+ assert c.getCount() == 0;
+ c.decrement();
+ assert c.getCount() == -1;
+ c.reset();
+ assert c.getCount() == 0;
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java
new file mode 100644
index 0000000..8c67260
--- /dev/null
+++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: StringsTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class StringsTest {
+ @Test
+ public void testCamel() {
+ assert "BlahFoo".equals(Strings.camel("blahFoo"));
+ assert "FooBar".equals(Strings.camel("FooBar"));
+ }
+
+ @Test
+ public void testCamelAllWords() {
+ assert "BlahFoo BlahBlahFoo".equals(Strings.camelAllWords("blahFoo blahBlahFoo", " "));
+ assert "FooBar::Foo::Bar::Bash".equals(Strings.camelAllWords("FooBar::foo::bar::bash", "::"));
+ }
+
+ @Test
+ public void testConcatenate() {
+ Assert.assertEquals("a:b:c:d",Strings.concatenate(":", "a","b","c","d"));
+ }
+
+ @Test
+ public void testConcatenateNull() {
+ Assert.assertEquals("",Strings.concatenate(":",(String[])null));
+ }
+ @Test
+ public void testConcatenateEmpty() {
+ Assert.assertEquals("",Strings.concatenate(":"));
+ }
+
+ @Test
+ public void testConcatenateIterable() {
+ List<String> strings = new ArrayList<String>();
+ strings.add("a");
+ strings.add("b");
+ strings.add("c");
+ strings.add("d");
+ Assert.assertEquals("a:b:c:d",Strings.concatenate(":", strings));
+ }
+
+ @Test
+ public void testConcatenateNullIterable() {
+ Assert.assertEquals("",Strings.concatenate(":",(Iterable<String>)null));
+ }
+ @Test
+ public void testEmpty() {
+ Assert.assertEquals("",Strings.concatenate(":", new ArrayList<String>()));
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java
new file mode 100644
index 0000000..cffbc4f
--- /dev/null
+++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: TypesFromBooleanTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.annotations.Test;
+
+
+public class TypesFromBooleanTest {
+
+ @Test
+ public void testConvertBooleanToboolean() {
+ assert Types.convertToBoolean(Boolean.TRUE) == true;
+ assert Types.convertToBoolean(Boolean.FALSE) == false;
+ }
+ @Test
+ public void testConvertBooleanToBoolean() {
+ assert new Boolean(true).equals(Types.convert(Boolean.TRUE,Boolean.class));
+ assert new Boolean(false).equals(Types.convert(Boolean.FALSE, Boolean.class));
+ }
+ @Test
+ public void testConvertBooleanToString() {
+ assert "true".equals(Types.convert(Boolean.TRUE, String.class));
+ assert "false".equals(Types.convert(Boolean.FALSE, String.class));
+ }
+ @Test
+ public void testConvertBooleanToByte() {
+ assert new Byte((byte)1).equals(Types.convert(Boolean.TRUE, Byte.class));
+ assert new Byte((byte)0).equals(Types.convert(Boolean.FALSE, Byte.class));
+ }
+ @Test
+ public void testConvertBooleanToShort() {
+ assert new Short((short)1).equals(Types.convert(Boolean.TRUE, Short.class));
+ assert new Short((short)0).equals(Types.convert(Boolean.FALSE, Short.class));
+ }
+ @Test
+ public void testConvertBooleanToInteger() {
+ assert new Integer(1).equals(Types.convert(Boolean.TRUE, Integer.class));
+ assert new Integer(0).equals(Types.convert(Boolean.FALSE, Integer.class));
+ }
+ @Test
+ public void testConvertBooleanToLong() {
+ assert new Long(1).equals(Types.convert(Boolean.TRUE, Long.class));
+ assert new Long(0).equals(Types.convert(Boolean.FALSE, Long.class));
+ }
+ @Test
+ public void testConvertBooleanToFloat() {
+ assert new Float(1.0).equals(Types.convert(Boolean.TRUE, Float.class));
+ assert new Float(0.0).equals(Types.convert(Boolean.FALSE, Float.class));
+ }
+ @Test
+ public void testConvertBooleanToDouble() {
+ assert new Double(1.0d).equals(Types.convert(Boolean.TRUE, Double.class));
+ assert new Double(0.0d).equals(Types.convert(Boolean.FALSE, Double.class));
+ }
+ @Test
+ public void testConvertBooleanToCharacter() {
+ assert new Character('T').equals(Types.convert(Boolean.TRUE, Character.class));
+ assert new Character('F').equals(Types.convert(Boolean.FALSE, Character.class));
+ }}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java
new file mode 100644
index 0000000..ba32b95
--- /dev/null
+++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: TypesFromNumberTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.annotations.Test;
+
+
+
+//@Copyright(years={"2006"},owner="Israfil Consulting Services Corporation",license="BSD")
+public class TypesFromNumberTest {
+
+ @Test
+ public void testConvertNumberToCharacter() {
+ throw new org.testng.SkipException("Not yet implemented");
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java
new file mode 100644
index 0000000..2648d4f
--- /dev/null
+++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: TypesFromStringTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TypesFromStringTest {
+
+ @Test
+ public void testConvertStringToboolean() {
+ Assert.assertTrue(Types.convertToBoolean("true"));
+ Assert.assertTrue(Types.convertToBoolean("t"));
+ Assert.assertTrue(Types.convertToBoolean("T"));
+ Assert.assertTrue(Types.convertToBoolean("True"));
+ Assert.assertTrue(Types.convertToBoolean("TrUe"));
+ Assert.assertTrue(Types.convertToBoolean("Yes"));
+ Assert.assertTrue(Types.convertToBoolean("y"));
+ Assert.assertTrue(Types.convertToBoolean("yes"));
+ Assert.assertTrue(Types.convertToBoolean("aye"));
+ Assert.assertFalse(Types.convertToBoolean("false"));
+ Assert.assertFalse(Types.convertToBoolean("f"));
+ Assert.assertFalse(Types.convertToBoolean("F"));
+ Assert.assertFalse(Types.convertToBoolean("False"));
+ Assert.assertFalse(Types.convertToBoolean("faLSe"));
+ Assert.assertFalse(Types.convertToBoolean("No"));
+ Assert.assertFalse(Types.convertToBoolean("n"));
+ Assert.assertFalse(Types.convertToBoolean("no"));
+ Assert.assertFalse(Types.convertToBoolean("nay"));
+ }
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testConvertEmptyStringToBoolean() {
+ Types.convertToBoolean("");
+ }
+ @Test(expectedExceptions={NullPointerException.class})
+ public void testConvertNullStringToBoolean() {
+ Types.convertToBoolean(null);
+ }
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testConvertNonNumberStringToBoolean() {
+ Types.convertToBoolean("bark");
+ }
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testConvertStringWithLeadingWhitespaceToBoolean() {
+ Types.convertToBoolean(" aye");
+ }
+ /*
+ @Test
+ public void testConvertStringToBoolean() {
+ Assert.assertEquals(new Boolean(true),Types.convert(Boolean.TRUE, Boolean.class));
+ Assert.assertEquals(new Boolean(false),Types.convert(Boolean.FALSE, Boolean.class));
+ }
+ */
+ @Test
+ public void testConvertStringToString() {
+ Assert.assertEquals("a",Types.convert("a", String.class));
+ Assert.assertSame("a",Types.convert("a", String.class));
+ Assert.assertFalse("A".equals(Types.convert("a", String.class)));
+ }
+ /*
+ @Test
+ public void testConvertBooleanToByte() {
+ Assert.assertEquals(new Byte((byte)1),Types.convert(Boolean.TRUE, Byte.class));
+ Assert.assertEquals(new Byte((byte)0),Types.convert(Boolean.FALSE, Byte.class));
+ }
+ @Test
+ public void testConvertBooleanToShort() {
+ Assert.assertEquals(new Short((short)1),Types.convert(Boolean.TRUE, Short.class));
+ Assert.assertEquals(new Short((short)0),Types.convert(Boolean.FALSE, Short.class));
+ }
+ @Test
+ public void testConvertBooleanToInteger() {
+ Assert.assertEquals(new Integer(1),Types.convert(Boolean.TRUE, Integer.class));
+ Assert.assertEquals(new Integer(0),Types.convert(Boolean.FALSE, Integer.class));
+ }
+ @Test
+ public void testConvertBooleanToLong() {
+ Assert.assertEquals(new Long(1),Types.convert(Boolean.TRUE, Long.class));
+ Assert.assertEquals(new Long(0),Types.convert(Boolean.FALSE, Long.class));
+ }
+ @Test
+ public void testConvertBooleanToFloat() {
+ Assert.assertEquals(new Float(1.0),Types.convert(Boolean.TRUE, Float.class));
+ Assert.assertEquals(new Float(0.0),Types.convert(Boolean.FALSE, Float.class));
+ }
+ @Test
+ public void testConvertBooleanToDouble() {
+ Assert.assertEquals(new Double(1.0d),Types.convert(Boolean.TRUE, Double.class));
+ Assert.assertEquals(new Double(0.0d),Types.convert(Boolean.FALSE, Double.class));
+ }
+ @Test
+ public void testConvertBooleanToCharacter() {
+ Assert.assertEquals(new Character('T'),Types.convert(Boolean.TRUE, Character.class));
+ Assert.assertEquals(new Character('F'),Types.convert(Boolean.FALSE, Character.class));
+ }
+ */
+
+}
diff --git a/israfil-foundation-dynamic/pom.xml b/israfil-foundation-dynamic/pom.xml
new file mode 100644
index 0000000..fdea908
--- /dev/null
+++ b/israfil-foundation-dynamic/pom.xml
@@ -0,0 +1,33 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-dynamic</artifactId>
+ <name>Israfil Foundation Dynamic Invocation</name>
+ <version>1.0.3-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-collections</artifactId>
+ <version>1.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-core</artifactId>
+ <version>[1.0.0,1.1)</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java
new file mode 100644
index 0000000..e1bdb8b
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Dynamic.java 14 2006-01-27 23:50:37Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+
+/**
+ * A simple interface that defines the ability to perform and detect
+ * arbitrary methods, by use of a "selector" string. The selector
+ * is a string constructed of a method name and an arbitrary number of
+ * classes representing parameter types. These are then concatenated
+ * with a ":" separator. The resulting string represents a full
+ * method signature, without reference to the implementing class. This
+ * allows arbitrary classes to be interrogated as to the validity of a
+ * given method call (i.e. do they or their parents implement it). It
+ * also then allows the method with the given signature to be invoked.
+ *
+ * For example:
+ * <code>
+ * if (a.respondsTo("doThing:java.lang.String"))
+ * a.perform("doThing:java.lang.String",aString);
+ * </code>
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Dynamic {
+
+ public Object perform(String selector, Object ... parameters);
+
+ public boolean respondsTo(String selector);
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java
new file mode 100644
index 0000000..3beda20
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicObject.java 92 2006-08-04 12:39:25Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Method;
+
+
+/**
+ * An abstract superclass that implements the Dynamic interface, with
+ * all the necessary lookup logic. It also implements static equivalents of
+ * the Dynamic methods.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class DynamicObject implements Dynamic {
+ //private static Logger logger = Logger.getLogger(DynamicObject.class.getName());
+
+
+ /**
+ * @see org.israfil.maveric.Dynamic#perform(java.lang.String, java.lang.Object[])
+ */
+ public Object perform(String selector, Object ... parameters) {
+ return DynamicUtil.performOn(this,selector,parameters);
+ }
+
+ /**
+ * @see org.israfil.maveric.Dynamic#respondsTo(java.lang.String)
+ */
+ public boolean respondsTo(String selector) {
+ return DynamicUtil.respondsTo(this,selector);
+ }
+
+ protected Method getMethodForSelector(String selector) {
+ return DynamicUtil.getMethodForSelector(this,selector);
+ }
+
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java
new file mode 100644
index 0000000..9c165bc
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicUtil.java 91 2006-08-03 21:38:24Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.collections.ArrayUtils;
+
+/**
+ * Utilities used for the implementation of Dynamic and
+ * related interfaces.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public final class DynamicUtil {
+ private static Logger logger = Logger.getLogger(DynamicUtil.class.getName());
+
+ private DynamicUtil() {}
+
+ static Map<String, Class<?>> _primitiveTypes = new HashMap<String, Class<?>>();
+ static Map<Class<?>, Class<?>> _primitiveTypeEquivalents = new HashMap<Class<?>, Class<?>>();
+ static Map<Class<?>, Class<?>> _boxedTypeEquivalents = new HashMap<Class<?>, Class<?>>();
+ static {
+ _primitiveTypes.put("boolean",boolean.class);
+ _primitiveTypeEquivalents.put(Boolean.class,boolean.class);
+ _boxedTypeEquivalents.put(boolean.class,Boolean.class);
+ _primitiveTypes.put("int",int.class);
+ _primitiveTypeEquivalents.put(Integer.class,int.class);
+ _boxedTypeEquivalents.put(int.class,Integer.class);
+ _primitiveTypes.put("long",long.class);
+ _primitiveTypeEquivalents.put(Long.class,long.class);
+ _boxedTypeEquivalents.put(long.class,Long.class);
+ _primitiveTypes.put("short",short.class);
+ _primitiveTypeEquivalents.put(Short.class,short.class);
+ _boxedTypeEquivalents.put(short.class,Short.class);
+ _primitiveTypes.put("byte",byte.class);
+ _primitiveTypeEquivalents.put(Byte.class,byte.class);
+ _boxedTypeEquivalents.put(byte.class,Byte.class);
+ _primitiveTypes.put("char",char.class);
+ _primitiveTypeEquivalents.put(Character.class,char.class);
+ _boxedTypeEquivalents.put(char.class,Character.class);
+ _primitiveTypes.put("double",double.class);
+ _primitiveTypeEquivalents.put(Double.class,double.class);
+ _boxedTypeEquivalents.put(double.class,Double.class);
+ _primitiveTypes.put("float",float.class);
+ _primitiveTypeEquivalents.put(Float.class,float.class);
+ _boxedTypeEquivalents.put(float.class,Float.class);
+ }
+ public static boolean hasPrimitiveTypeEquivalent(Class<?> c) {
+ return _primitiveTypeEquivalents.containsKey(c);
+ }
+
+ public static Class<?> getPrimitiveTypeEquivalent(Class<?> c) {
+ return _primitiveTypeEquivalents.get(c);
+ }
+
+ public static boolean hasBoxedTypeEquivalent(Class<?> c) {
+ return _boxedTypeEquivalents.containsKey(c);
+ }
+
+ public static Class<?> getBoxedTypeEquivalent(Class<?> c) {
+ return _boxedTypeEquivalents.get(c);
+ }
+
+ protected static final Map<Class<?>, Set<Class<?>>> classes = new HashMap<Class<?>, Set<Class<?>>>();
+
+ public static Set<Class<?>> getAllParentTypes(Class<?> c) {
+ if (!classes.containsKey(c)) {
+ Set<Class<?>> parents = new HashSet<Class<?>>();
+ for (Class<?> cType = c; cType != Object.class && cType != null; cType = cType
+ .getSuperclass()) {
+ parents.add(cType);
+ addSuperInterfaces(parents,cType);
+ }
+ parents.add(Object.class);
+ parents.remove(c);
+ classes.put(c,parents);
+ }
+ return classes.get(c);
+ }
+
+ public static void addSuperInterfaces(Set<Class<?>> set, Class<?> c) {
+ if (c == null || c.getInterfaces() == null) return;
+ for (Class<?> i : c.getInterfaces()) {
+ set.add(i);
+ addSuperInterfaces(set,i);
+ }
+ }
+
+ /**
+ * Conveniently get a field from an object, automatically trapping
+ * exceptions and returning the Field or null if no such field exists.
+ */
+ public static Field getField(Object receiver, String attributeName) {
+ Field f = null;
+ try {
+ f = receiver.getClass().getField(attributeName);
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ return f;
+ }
+
+
+
+ /**
+ * @see org.israfil.maveric.Dynamic#respondsTo(java.lang.String)
+ */
+ public static boolean respondsTo(Object receiver, String selector) {
+ return (getMethodForSelector(receiver,selector) != null);
+ }
+
+ public static Method getMethodForSelector(Object receiver, String selector) {
+ if (receiver instanceof Class)
+ return getMethodForSelector((Class<?>) receiver, selector);
+ return getMethodForSelector(receiver.getClass(),selector);
+ }
+
+ public static Method getMethodForSelector(Class<?> receiverClass,
+ String selector) {
+ try {
+ return _getMethodForSelector(receiverClass,selector);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ protected static Method _getMethodForSelector(Class<?> receiverClass,
+ String selector) throws ClassNotFoundException,
+ NoSuchMethodException {
+ StringTokenizer st = new StringTokenizer(selector,":");
+ Class<?>[] paramTypes = new Class[st.countTokens() - 1];
+ String methodName = st.nextToken();
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ for (int i = 0; st.hasMoreTokens(); i++) {
+ String className = st.nextToken();
+ if (DynamicUtil._primitiveTypes.containsKey(className))
+ paramTypes[i] = (Class<?>) DynamicUtil._primitiveTypes
+ .get(className);
+ else paramTypes[i] = loader.loadClass(className);
+ }
+ return receiverClass.getMethod(methodName,paramTypes);
+ }
+
+ /**
+ * @see org.israfil.maveric.Dynamic#perform(java.lang.String, java.lang.Object[])
+ */
+ public static Object performOn(Object receiver, String selector, Object ... parameters) {
+ if (parameters == null) parameters = new Object[]{};
+ Method m = getMethodForSelector(receiver,selector);
+ try {
+ if (m != null) return m.invoke(receiver,parameters);
+ //else return null;
+ else throw new NoSuchMethodError("No public method defined with selector \""+selector+"\"");
+ } catch (InvocationTargetException ite) {
+ logger.log(Level.FINE,ite.getClass().getName()+" thrown attempting to invoke selector: " + selector + " on "+receiver,ite);
+ if (ite.getCause() != null) throw new RuntimeException(ite.getCause());
+ else throw new RuntimeException(ite);
+ } catch (IllegalAccessException iae) {
+ logger.log(Level.FINE,iae.getClass().getName()+" thrown attempting to invoke selector: " + selector + " on "+receiver,iae);
+ throw new RuntimeException(iae);
+ }
+ }
+
+ /**
+ * Construct an object of the given named class with the provided
+ * constructor parameters. If there is no such class or no
+ * constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param className The fully qualified name of a Class object to be instantiated.
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ public static Object construct(String className, Object ... parameters) {
+ try {
+ Class<?> clazz = Thread.currentThread().getContextClassLoader()
+ .loadClass(className);
+ return construct(clazz,parameters);
+ } catch (ClassNotFoundException e) {
+ logger.log(Level.FINE,e.getClass().getName()+" thrown attempting to construct a " + className + ".", e);
+ return null;
+ }
+ }
+ /**
+ * Construct an object of the given class with the provided
+ * constructor parameters. If there is no such class or no
+ * constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param c A Class object to be instantiated.
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ public static <T> T construct(Class<T> c, Object ... parameters) {
+ Class<?> [] parmTypes = new Class<?>[parameters.length];
+ for (int i = 0; i < parmTypes.length; i++) {
+ parmTypes[i] = parameters[i].getClass();
+ }
+ return construct(c,parmTypes,parameters);
+ }
+
+ /**
+ * Construct an object of the given named class with the provided
+ * constructor parameter types and values. If there is no such class
+ * or no constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param className The fully qualified name of a Class object to be instantiated.
+ * @param parameterTypes The types that form the desired constructor's method signature
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ public static Object construct(String className, Class<?>[] parameterTypes,
+ Object... parameters) {
+ try {
+ Class<?> clazz = Thread.currentThread().getContextClassLoader()
+ .loadClass(className);
+ return construct(clazz, parameterTypes,parameters);
+ } catch (ClassNotFoundException e) {
+ logger.log(Level.FINE,e.getClass().getName()+" thrown attempting to construct a " + className + ".", e);
+ return null;
+ }
+ }
+
+ /**
+ * Construct an object of the given class with the provided
+ * constructor parameter types and values. If there is no such class
+ * or no constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param c A Class object to be instantiated.
+ * @param parameterTypes The types that form the desired constructor's method signature
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T construct(Class<T> c, Class<?>[] parameterTypes,
+ Object... parameters) {
+ try {
+ Constructor<T>[] constructors = (Constructor<T>[]) c.getDeclaredConstructors();
+ for (Constructor<T> constructor : constructors) {
+ if (ArrayUtils.equivalent(parameterTypes,constructor.getParameterTypes())) {
+ return (T)constructor.newInstance(parameters);
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ logger.log(Level.FINE,e.getClass().getName()+" thrown attempting to construct a " + c.getName() + ".", e);
+ return null;
+ }
+ }
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java
new file mode 100644
index 0000000..202bd11
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyAccessible.java 23 2006-02-01 17:17:31Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+
+/**
+ * A generic accessor interface. By this means any attribute should be
+ * retrievable by using the provided methods, as well as the existence of
+ * an accessor method can be detected.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface DynamicallyAccessible extends Dynamic{
+
+ public boolean hasAttribute(String attributeName);
+ public Object get(String attributeName);
+ public abstract boolean hasAccessor(String attributeName);
+
+} \ No newline at end of file
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java
new file mode 100644
index 0000000..fd376a7
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyAccessibleObject.java 76 2006-08-03 15:37:05Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.core.Strings;
+
+/**
+ * An implementation of the DynamicallyAccessible interface with the
+ * appropriate infrastructure for retrieving field data, via accessors if
+ * such are implemented, or directly from the field where not.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 76 $
+ */
+public abstract class DynamicallyAccessibleObject extends DynamicObject implements DynamicallyAccessible {
+ private static Logger logger = Logger.getLogger(DynamicallyAccessibleObject.class.getName());
+
+ public Object get(String attributeName) {
+ return get(this,attributeName);
+ }
+
+ public static Object get(Object receiver, String attributeName) {
+ try {
+ return _get(receiver, attributeName);
+ } catch (NoSuchFieldException e) {
+ logger.log(Level.FINE,"Object attempted to dynamically access a non-existant or unreadable field.",e);
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ logger.log(Level.FINE,"Object attempted to dynamically access a inaccessible field.",e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** @deprecated This method is deprecated in favour of the static _get(receiver, attributeName) */
+ Object _get(String attributeName) throws NoSuchFieldException, IllegalAccessException {
+ return _get(this,attributeName);
+ }
+
+ /**
+ * Internal _get method that throws all the exceptions, to be wrapped by public methods
+ * so that the various exceptions can be given meaning in different contexts (such
+ * as fetching data, vs. testing for the existance of something.
+ *
+ * @param attributeName
+ * @return
+ * @throws NoSuchFieldException
+ * @throws IllegalAccessException
+ */
+ static Object _get(Object receiver, String attributeName) throws NoSuchFieldException, IllegalAccessException {
+ if (hasAccessor(receiver,attributeName)) return DynamicUtil.performOn(receiver,_getAccessorSelector(receiver,attributeName), new Object[]{});
+ return receiver.getClass().getField(attributeName).get(receiver);
+ }
+
+ /**
+ * Determines whether an attribute of the given name exists on this object's
+ * definition, or if not, if there is a javabeans-style accessor named
+ * appropriately for that attribute. Put another way, determines whether
+ * a get() call would work against this attribute name.
+ *
+ * The existing implementation is inefficient, but simple to maintain.
+ */
+ public boolean hasAttribute(String attributeName) {
+ return hasAttribute(this,attributeName);
+ }
+
+ public static boolean hasAttribute(Object receiver, String attributeName) {
+ try {
+ _get(receiver,attributeName);
+ return true;
+ } catch (NoSuchFieldException e) {
+ logger.log(Level.FINEST,"Object attempted to dynamically access a non-existant or unreadable field.",e);
+ return false;
+ } catch (IllegalAccessException e) {
+ logger.log(Level.FINEST,"Object attempted to dynamically access a inaccessible field.",e);
+ return false;
+ }
+ }
+
+ protected static final String[] accessPrefixes = new String[] { "get","is" };
+
+ /** @deprecated This method is deprecated in favour of the static _getAccessorSelector(receiver,attribute) */
+ protected String getAccessorSelector(String attributeName) { return _getAccessorSelector(this,attributeName); }
+
+ protected static String _getAccessorSelector(Object receiver, String attributeName) {
+ if (attributeName == null || attributeName.equals("")) return null;
+ String camelAttr = camel(attributeName);
+ for (String prefix : accessPrefixes) {
+ String selector = prefix+camelAttr;
+ if (DynamicUtil.respondsTo(receiver,selector)) return selector;
+ }
+ // No accessor, try a NeXTSTEP-style accessor, named the same as the property.
+ if (DynamicUtil.respondsTo(receiver,attributeName)) return attributeName;
+ return null;
+ }
+
+ public boolean hasAccessor(String attributeName) {
+ return hasAccessor(this,attributeName);
+ }
+
+ public static boolean hasAccessor(Object receiver, String attributeName) {
+ return _getAccessorSelector(receiver,attributeName) != null;
+ }
+
+ /** @deprecated This method has been moved to net.israfil.foundation.core.Strings.camel(String) */
+ public static String camel(String string) {
+ return Strings.camel(string);
+ }
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java
new file mode 100644
index 0000000..49b2a5d
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyMutable.java 39 2006-02-23 00:01:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+
+/**
+ * A generic mutator interface. By this means any attribute should be
+ * mutable by using the provided methods. Additionally, the existence of
+ * a mutator method can be detected.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface DynamicallyMutable extends DynamicallyAccessible{
+
+ public void set(String attributeName, Object attributeValue);
+
+ public void set(String attributeName, Object attributeValue, Class<?> type);
+
+ public void setNull(String attributeName, Class<?> type);
+
+ public abstract boolean hasMutator(String attributeName, Class<?> type);
+
+} \ No newline at end of file
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java
new file mode 100644
index 0000000..63b301d
--- /dev/null
+++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyMutableObject.java 127 2006-11-09 18:04:43Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.core.Strings;
+import net.israfil.foundation.core.Types;
+
+/**
+ * An abstract class which implements the DynamicallyMutableObject
+ * infrastructure. It sets a field's value, by mutator method if such
+ * exists, or directly if none such exists.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ *
+ */
+public abstract class DynamicallyMutableObject extends DynamicallyAccessibleObject implements DynamicallyMutable {
+ private static Logger logger = Logger.getLogger(DynamicallyMutableObject.class.getName());
+
+
+ public void setNull(String attributeName, Class<?> valueType) {
+ setNull(this,attributeName,valueType);
+ }
+ public void setNull(Object target, String attributeName, Class<?> valueType) {
+ if (valueType == null)
+ throw new IllegalArgumentException("Cannot give a valueType of null for setNull(String,Class) method.");
+ set(target,attributeName, null, valueType);
+ }
+
+ public void set(String attributeName,Object value) {
+ set(this,attributeName,value);
+ }
+ public static void set(Object target, String attributeName,Object value) {
+ if (value == null) set(target,attributeName, value, null);
+ else set(target,attributeName, value, value.getClass());
+ }
+
+ public void set(String attributeName, Object value, Class<?> valueType) {
+ set(this,attributeName,value,valueType);
+ }
+ public static void set(Object target, String attributeName, Object value,
+ Class<?> valueType) {
+ if (value == null) {
+ if (valueType != null && valueType.isPrimitive()) throw new IllegalArgumentException("Attempted to set null on a variable or accessor for attribute '"+attributeName+"' of primitive type: " + valueType);
+ String selector = getMutatorSelector(target,attributeName,valueType);
+ if (selector != null) {
+ Method m = DynamicUtil.getMethodForSelector(target,selector);
+ Class<?>[] parmTypes = m.getParameterTypes();
+ if (parmTypes[0].isPrimitive())
+ throw new IllegalArgumentException("Attempted to set null using an accessor for attribute '"+attributeName+"' of primitive type: " + parmTypes[0]);
+ DynamicUtil.performOn(target,selector,new Object[]{value});
+ } else {
+ Field f = DynamicUtil.getField(target,attributeName);
+ if (f == null || f.getType().isPrimitive())
+ throw new IllegalArgumentException("Attempted to set null but could not find a set"+Strings.camel(attributeName)+" method with a single non-primitive type.");
+ else
+ _setField(target,attributeName,valueType);
+ }
+ } else /* value != null */ {
+ if (valueType == null) valueType = value.getClass();
+ if (hasMutator(target,attributeName,valueType)) {
+ DynamicUtil.performOn(target,getMutatorSelector(target,attributeName,valueType),new Object[]{value});
+ return;
+ } else if(hasMutator(target,attributeName,DynamicUtil.getPrimitiveTypeEquivalent(valueType))) {
+ DynamicUtil.performOn(target,getMutatorSelector(target,attributeName,DynamicUtil.getPrimitiveTypeEquivalent(valueType)),new Object[]{value});
+ return;
+ } else {
+ _setField(target,attributeName,value);
+ }
+ }
+ }
+
+ protected void _setField(String attributeName,Object value) {
+ _setField(this,attributeName,value);
+ }
+
+ protected static void _setField(Object target, String attributeName,Object value) {
+ Field f = DynamicUtil.getField(target,attributeName);
+ try {
+ if (f == null) {
+ RuntimeException rte = new RuntimeException("Could not find field named " + attributeName,
+ new NoSuchFieldException(target + " has no property " + attributeName));
+ logger.log(Level.FINEST,"Failed to set field.",rte);
+ throw rte;
+ }
+ f.set(target,Types.convert(value,f.getType()));
+ } catch (IllegalAccessException e) {
+ logger.log(Level.FINEST,"Object attempted to dynamically access a inaccessible field.",e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected static final String mutatePrefix = "set";
+ protected String getMutatorSelector(String attributeName, Class<?> type) {
+ return getMutatorSelector(this,attributeName,type);
+ }
+ protected static String getMutatorSelector(Object target,
+ String attributeName, Class<?> type) {
+ if (attributeName == null || attributeName.equals("")) return null;
+ String camelAttr = Strings.camel(attributeName);
+ String selector = null;
+ if (type == null) {
+ Method method = _tryToFindMutator(target,attributeName);
+ if (method == null) {
+ return null;
+ } else /* method != null */ {
+ if (method.getParameterTypes().length != 1) return null;
+ else return "set"+Strings.camel(attributeName)+":"+method.getParameterTypes()[0].getName();
+ }
+ } else /* type != null */ {
+
+ String tmp = mutatePrefix+camelAttr+":"+type.getName();
+ if (DynamicUtil.respondsTo(target,tmp)) selector = tmp;
+ for (Class<?> c : DynamicUtil.getAllParentTypes(type)) {
+ tmp = mutatePrefix + camelAttr + ":" + c.getName();
+ if (DynamicUtil.respondsTo(target, tmp))
+ selector = tmp;
+ }
+ }
+ return selector;
+ }
+
+ protected static Method _tryToFindMutator(Object target, String attributeName) {
+ Method method = null;
+ Method[] methods = target.getClass().getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if (methods[i].getName().equals("set"+Strings.camel(attributeName))) {
+ if (method == null) method = methods[i];
+ else throw new IllegalArgumentException("Attempted to find "+mutatePrefix+Strings.camel(attributeName) + " without a given type, but more than one such method exists. Should use set(String,Object,Class)");
+ }
+ }
+ return method;
+ }
+
+ protected static Method _tryToFindMutator(Object target,
+ String attributeName, Class<?> type) {
+ if (type == null) throw new IllegalArgumentException("Must set a type, or use _tryToFindMutator(Object,String).");
+ String methodName = mutatePrefix+Strings.camel(attributeName);
+ Method m = DynamicUtil.getMethodForSelector(target,methodName+":"+type.getName());
+ for (Class<?> c : DynamicUtil.getAllParentTypes(type)) {
+ m = DynamicUtil.getMethodForSelector(target,methodName+":"+c.getName());
+ }
+ return m;
+ }
+
+ public static Method getMutator(Object target, String attributeName,
+ Class<?> type) {
+ if (type == null) {
+ return _tryToFindMutator(target,attributeName);
+ } else {
+ return _tryToFindMutator(target,attributeName,type);
+ }
+ }
+
+ public boolean hasMutator(String attributeName, Class<?> type) {
+ return hasMutator(this,attributeName,type);
+ }
+ public static boolean hasMutator(Object target, String attributeName,
+ Class<?> type) {
+ return getMutatorSelector(target,attributeName,type) != null;
+ }
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java
new file mode 100644
index 0000000..a5b7a90
--- /dev/null
+++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicObjectTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+@Test
+public class DynamicObjectTest {
+
+ private static final String TEST_STRING1 = "String1";
+ private static final String TEST_STRING2 = "String2";
+
+ DynamicTestObject testDO;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ testDO = new DynamicTestObject();
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ testDO = null;
+ }
+
+ public void testPerformMethods() {
+ Assert.assertTrue((Boolean)testDO.perform("action"));
+ Assert.assertEquals(TEST_STRING1,testDO.perform("action:java.lang.String",TEST_STRING1));
+ Assert.assertEquals(TEST_STRING2,testDO.perform("action:java.lang.String:boolean",
+ new Object[] {TEST_STRING2,Boolean.TRUE}));
+ Assert.assertEquals(TEST_STRING2+TEST_STRING2,testDO.perform("action:java.lang.String:boolean",new Object[] {TEST_STRING2,Boolean.FALSE}));
+ Assert.assertNull(testDO.perform("action:java.util.Date",new Object[] {new Date()}));
+ }
+
+ @Test(expectedExceptions={NoSuchMethodError.class})
+ public void testPerformAgainstProtectedMethod() {
+ testDO.perform("action:boolean",new Object[] {Boolean.TRUE});
+ }
+
+ @Test(expectedExceptions={NoSuchMethodError.class})
+ public void testPerformAgainstPackageFriendlyMethod() {
+ testDO.perform("action:java.lang.Float",new Object[] {1.5f});
+ }
+
+ @Test(expectedExceptions={NoSuchMethodError.class})
+ public void testPerformAgainstPrivateMethod() {
+ testDO.perform("privateAction");
+ }
+
+ public void testRespondsTo() {
+ Assert.assertTrue(testDO.respondsTo("action"));
+ Assert.assertFalse(testDO.respondsTo("noAction"));
+ Assert.assertTrue(testDO.respondsTo("action:java.lang.String"));
+ Assert.assertFalse(testDO.respondsTo("action:java.lang.Integer"));
+ Assert.assertTrue(testDO.respondsTo("action:java.lang.String:"+boolean.class.getName()));
+ Assert.assertFalse(testDO.respondsTo("action:java.lang.Integer:java.lang.String"));
+ Assert.assertFalse(testDO.respondsTo("action:boolean"));
+ Assert.assertFalse(testDO.respondsTo("action:java.lang.Float"));
+ Assert.assertTrue(testDO.respondsTo("action:int"));
+ }
+
+ public void testGetMethodForSelector() {
+ Method m = testDO.getMethodForSelector("action:java.lang.String");
+ Assert.assertNotNull(m);
+ Assert.assertEquals("action",m.getName());
+ Assert.assertEquals(String.class,m.getParameterTypes()[0]);
+ }
+
+ public class DynamicTestObject extends DynamicObject {
+ public boolean action() { return !privateAction(); /* false */ }
+ public String action(String foo) { return foo; }
+ public String action(String foo, boolean bool) {
+ if (bool) return foo;
+ else return foo+foo;
+ }
+ public void action(Date foo) { if (foo==null);return; }
+ protected boolean action(boolean b) { return b; }
+ Float action(Float f) { return f; }
+ public int action(int i) { return i; }
+ private boolean privateAction() { return false; }
+ }
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java
new file mode 100644
index 0000000..31d11a7
--- /dev/null
+++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicUtilTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class DynamicUtilTest {
+
+ public void testAddSuperinterfaces1() {
+ Class<?> clz = IA.class;
+ Set<Class<?>> cSet = new HashSet<Class<?>>();
+ DynamicUtil.addSuperInterfaces(cSet,clz);
+ Assert.assertEquals(0,cSet.size());
+ }
+ public void testAddSuperinterfaces2() {
+ Class<?> clz = IC.class;
+ Set<Class<?>> cSet = new HashSet<Class<?>>();
+ DynamicUtil.addSuperInterfaces(cSet,clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertEquals(1,cSet.size());
+ }
+ public void testClassLookupForA() {
+ Class<?> clz = A.class;
+ Set<Class<?>> cSet = DynamicUtil.getAllParentTypes(clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertTrue(cSet.contains(Object.class),"Should have type Object");
+ Assert.assertEquals(2,cSet.size());
+ }
+ public void testClassLookupForB() {
+ Class<?> clz = B.class;
+ Set<Class<?>> cSet = DynamicUtil.getAllParentTypes(clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertTrue(cSet.contains(A.class),"Should have type A");
+ Assert.assertTrue(cSet.contains(IB.class),"Should have type IB");
+ Assert.assertTrue(cSet.contains(Object.class),"Should have type Object");
+ Assert.assertEquals(4,cSet.size());
+ }
+ public void testClassLookupForC() {
+ Class<?> clz = C.class;
+ Set<Class<?>> cSet = DynamicUtil.getAllParentTypes(clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertTrue(cSet.contains(IC.class),"Should have type IC");
+ Assert.assertTrue(cSet.contains(Object.class),"Should have type Object");
+ Assert.assertFalse(cSet.contains(A.class),"Should not have type A");
+ Assert.assertEquals(3,cSet.size());
+ }
+
+ public void testRespondsTo() {
+ Object obj = new TestObject();
+ Assert.assertTrue(DynamicUtil.respondsTo(obj,"action:java.lang.String"));
+ Assert.assertFalse(DynamicUtil.respondsTo(obj,"action"));
+ Assert.assertFalse(DynamicUtil.respondsTo(obj,"action:boolean"));
+ Assert.assertTrue(DynamicUtil.respondsTo(obj,"equals:java.lang.Object"));
+ }
+
+ public void testHasPrimitiveTypeEquivalent() {
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Boolean.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Integer.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Long.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Short.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Byte.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Double.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Character.class));
+ Assert.assertFalse(DynamicUtil.hasPrimitiveTypeEquivalent(String.class));
+ }
+
+ public void testGetMethodForSelectorObjectString() {
+ Method m = null;
+ Object obj = new TestObject();
+
+ m = DynamicUtil.getMethodForSelector(obj,"action:java.lang.String");
+ Assert.assertNotNull(m);
+
+ m = DynamicUtil.getMethodForSelector(obj,"action:boolean");
+ Assert.assertNull(m);
+
+ // force a test of getMethodForSelector(Object,String) with a class
+ m = DynamicUtil.getMethodForSelector((Object)obj.getClass(),"action:java.lang.String");
+ // force a test of getMethodForSelector(Class<?>,String)
+ m = DynamicUtil.getMethodForSelector((Class<?>) obj.getClass(),
+ "action:java.lang.String");
+ Assert.assertNotNull(m);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testConstructWithClass() {
+ ArrayList<String> al = DynamicUtil.construct(ArrayList.class);
+ Assert.assertNotNull(al);
+ Assert.assertEquals(ArrayList.class,al.getClass());
+ }
+ @SuppressWarnings("unchecked")
+ public void testConstructWithString() {
+ ArrayList<String> al = (ArrayList<String>)DynamicUtil.construct("java.util.ArrayList");
+ Assert.assertNotNull(al);
+ Assert.assertEquals(ArrayList.class,al.getClass());
+ }
+
+ public void testGetMethodForSelectorClassString() {
+ Object obj = new TestObject();
+ Assert.assertNotNull(DynamicUtil.getMethodForSelector(obj.getClass(),"action:java.lang.String"));
+ }
+
+ public interface IA {}
+ public interface IB {}
+ public interface IC extends IA {}
+
+ public class A implements IA {}
+ public class B extends A implements IB {}
+ public class C implements IC {}
+
+ public class TestObject {
+ public void action(String s) {}
+ }
+
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java
new file mode 100644
index 0000000..94c9edb
--- /dev/null
+++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyAccessibleTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class DynamicallyAccessibleTest {
+
+ TestAccessibleObject testDBO;
+ String var1 = "value1";
+ String var1Name = "publicVariable";
+ String var2 = "value2";
+ String var2Name = "publicVariableWithAccessor";
+ String var3 = "value3";
+ String var3Name = "privateVariable";
+ boolean var4 = false;
+ String var4Name = "booleanVariable";
+ int var5 = 5;
+ String var5Name = "intVariable";
+ boolean var6 = true;
+ String var6Name = "isTrue";
+
+ @BeforeMethod
+ protected void setUp() {
+ testDBO = new TestAccessibleObject(var1,var2,var3,var4,var5,var6);
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ testDBO = null;
+ }
+
+ public void testHasAccessor() {
+ Assert.assertFalse(testDBO.hasAccessor(var1Name));
+ Assert.assertTrue(testDBO.hasAccessor(var2Name));
+ Assert.assertTrue(testDBO.hasAccessor(var3Name));
+ Assert.assertTrue(testDBO.hasAccessor(var4Name));
+ Assert.assertTrue(testDBO.hasAccessor(var5Name));
+ }
+
+ public void testHasAttribute() {
+ Assert.assertTrue(testDBO.hasAttribute("publicVariable"));
+ Assert.assertTrue(testDBO.hasAttribute("publicVariableWithAccessor"));
+ Assert.assertTrue(testDBO.hasAttribute("privateVariable"));
+ Assert.assertTrue(testDBO.hasAttribute("booleanVariable"));
+ Assert.assertFalse(testDBO.hasAttribute("oddlyNamedIntVariable"));
+ Assert.assertTrue(testDBO.hasAttribute("aFinalStaticString"));
+ }
+
+ public void testGet() {
+ Assert.assertEquals(var1,testDBO.get(var1Name));
+ Assert.assertEquals(var2,testDBO.get(var2Name));
+ Assert.assertEquals(var3,testDBO.get(var3Name));
+ Assert.assertEquals(var4,testDBO.get(var4Name));
+ Assert.assertEquals(var5,testDBO.get(var5Name));
+ Assert.assertEquals(var6,testDBO.get(var6Name));
+ }
+
+ public void testHasAccessorStatic() {
+ Assert.assertFalse(DynamicallyAccessibleObject.hasAccessor(testDBO,var1Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var2Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var3Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var4Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var5Name));
+ }
+
+ public void testHasAttributeStatic() {
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"publicVariable"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"publicVariableWithAccessor"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"privateVariable"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"booleanVariable"));
+ Assert.assertFalse(DynamicallyAccessibleObject.hasAttribute(testDBO,"oddlyNamedIntVariable"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"aFinalStaticString"));
+ }
+
+ public void testGetStatic() {
+ Assert.assertEquals(var1,DynamicallyAccessibleObject.get(testDBO,var1Name));
+ Assert.assertEquals(var2,DynamicallyAccessibleObject.get(testDBO,var2Name));
+ Assert.assertEquals(var3,DynamicallyAccessibleObject.get(testDBO,var3Name));
+ Assert.assertEquals(new Boolean(var4),DynamicallyAccessibleObject.get(testDBO,var4Name));
+ Assert.assertEquals(new Integer(var5),DynamicallyAccessibleObject.get(testDBO,var5Name));
+ }
+
+ @Test(expectedExceptions={RuntimeException.class})
+ public void testGetWithNoFieldOrAccessor() {
+ testDBO.get("nonExistantVariable");
+ }
+
+
+ public static class TestAccessibleObject extends DynamicallyAccessibleObject {
+
+ public String publicVariable;
+ public String publicVariableWithAccessor;
+ private String privateVariable;
+ private boolean booleanVariable;
+ private int oddlyNamedIntVariable;
+ public static final String aFinalStaticString = "foo";
+ private boolean isTrue;
+
+ public TestAccessibleObject() {}
+
+ public TestAccessibleObject(String publicVar,
+ String publicVarWithAcc,
+ String privateVar,
+ boolean booleanVar,
+ int intVar,
+ boolean isTrue) {
+ this.publicVariable = publicVar;
+ this.publicVariableWithAccessor = publicVarWithAcc;
+ this.privateVariable = privateVar;
+ this.booleanVariable = booleanVar;
+ this.oddlyNamedIntVariable = intVar;
+ this.isTrue = isTrue;
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ publicVariable = null;
+ publicVariableWithAccessor = null;
+ privateVariable = null;
+ super.finalize();
+ }
+ public String getPublicVariableWithAccessor()
+ { return publicVariableWithAccessor;}
+
+ public String getPrivateVariable() { return privateVariable; }
+ public boolean getBooleanVariable() { return booleanVariable; }
+ public int getIntVariable() { return oddlyNamedIntVariable; }
+ public boolean isTrue() { return isTrue; }
+ }
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java
new file mode 100644
index 0000000..9bc9103
--- /dev/null
+++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyMutableTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import net.israfil.foundation.core.Strings;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class DynamicallyMutableTest {
+
+ MutableTestObject testMO;
+ String var1 = "value1";
+ String var1Name = "publicVariable";
+ String var2 = "value2";
+ String var2Name = "publicVariableWithAccessor";
+ String var3 = "value3";
+ String var3Name = "privateVariable";
+ Boolean var4 = false;
+ String var4Name = "booleanVariable";
+ Integer var5 = 5;
+ String var5Name = "intVariable";
+ boolean var6 = true;
+ String var6Name = "primitiveBoolean";
+ int var7 = 9;
+ String var7Name = "primitiveInt";
+
+ MutableTestObject2 mto2;
+
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ testMO = new MutableTestObject();
+ mto2 = new MutableTestObject2();
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ testMO = null;
+ mto2 = null;
+ }
+
+ public void testHasMutator() {
+ Assert.assertFalse(testMO.hasMutator(var1Name,var1.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var2Name,var2.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var3Name,var3.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var4Name,var4.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var5Name,var5.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var6Name,boolean.class));
+ Assert.assertTrue(testMO.hasMutator(var7Name,int.class));
+
+ }
+
+ public void testSet() {
+ testMO.set(var1Name,var1);
+ testMO.set(var2Name,var2);
+ testMO.set(var3Name,var3);
+ testMO.set(var4Name,var4);
+ testMO.set(var5Name,var5);
+ testMO.set(var6Name,var6);
+ testMO.set(var7Name,var7);
+ Assert.assertEquals(var1,testMO.get(var1Name));
+ Assert.assertEquals(var2,testMO.get(var2Name));
+ Assert.assertEquals(var3,testMO.get(var3Name));
+ Assert.assertEquals(var4,testMO.get(var4Name));
+ Assert.assertEquals(var5,testMO.get(var5Name));
+ }
+
+ @Test(expectedExceptions={RuntimeException.class})
+ public void testSetWithNoFieldOrAccessor() {
+ testMO.set("nonExistantVariable","aString");
+ }
+
+ public void testCamel() {
+ Assert.assertEquals("BlahFoo",Strings.camel("blahFoo"));
+ Assert.assertEquals("FooBar",Strings.camel("FooBar"));
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetWithNullAndNoParameterSetMethod() {
+ mto2.set("a",null);
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetWithNullWithTooManySetMethods() {
+ mto2.set("b",null);
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetWithNullAndSolitarySinglePrimitiveParameter() {
+ mto2.set("c",null);
+ }
+
+ public void testSetWithNullAndSolitarySingleNonPrimitiveParameter() {
+ mto2.set("d",null);
+ Assert.assertTrue(mto2.d_String_WasTouched);
+ }
+
+ public void testSetNullWithTypeAndSolitarySingleNonPrimitiveParameter() {
+ mto2.setNull("b",Integer.class);
+ Assert.assertTrue(mto2.b_Integer_WasTouched);
+ mto2.setNull("b",String.class);
+ Assert.assertTrue(mto2.b_String_WasTouched);
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetNullWithTypeAndSolitarySinglePrimitiveParameter() {
+ mto2.setNull("b",boolean.class);
+ }
+
+ public class MutableTestObject2 extends DynamicallyMutableObject {
+
+ public boolean a_WasTouched = false;
+ public boolean b_Integer_WasTouched = false;
+ public boolean b_String_WasTouched = false;
+ public boolean b_boolean_WasTouched = false;
+ public boolean c_boolean_WasTouched = false;
+ public boolean d_String_WasTouched = false;
+
+ public boolean c;
+
+ public void setA() {a_WasTouched = true;}
+
+ public void setB(String s) {b_String_WasTouched = true;}
+ public void setB(Integer i) {b_Integer_WasTouched = true;}
+ public void setB(boolean b) {b_boolean_WasTouched = true;}
+
+ public void setC(boolean b) {c_boolean_WasTouched = true;}
+
+ public void setD(String s) {d_String_WasTouched = true;}
+
+ }
+
+ public class MutableTestObject extends DynamicallyMutableObject {
+
+ public String publicVariable;
+ public String publicVariableWithAccessor;
+ private String privateVariable;
+ private boolean booleanVariable;
+ private int oddlyNamedIntVariable;
+
+ public MutableTestObject() {
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ publicVariable = null;
+ publicVariableWithAccessor = null;
+ privateVariable = null;
+ super.finalize();
+ }
+
+ public void setPublicVariableWithAccessor(String s)
+ { publicVariableWithAccessor = s; }
+
+ public void setPrivateVariable(String s) { privateVariable = s; }
+ public String getPrivateVariable() { return privateVariable; }
+
+ public void setBooleanVariable(Boolean b) { booleanVariable = b; }
+ public boolean getBooleanVariable() { return booleanVariable; }
+
+ public void setIntVariable(Integer i) { oddlyNamedIntVariable = i; }
+ public Integer getIntVariable() { return oddlyNamedIntVariable; }
+
+ public void setPrimitiveInt(int i) {}
+ public void setPrimitiveBoolean(boolean b) {}
+ }
+}
diff --git a/israfil-foundation-lifecycle/pom.xml b/israfil-foundation-lifecycle/pom.xml
new file mode 100644
index 0000000..7bed4a7
--- /dev/null
+++ b/israfil-foundation-lifecycle/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-lifecycle</artifactId>
+ <name>Israfil Foundation Lifecycle Classes and Interfaces</name>
+ <version>1.0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2007</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java
new file mode 100644
index 0000000..131e23e
--- /dev/null
+++ b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2006-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.lifecycle;
+
+
+/**
+ * An object that is consumes objects of a given type.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Consumer<T> {
+
+ /**
+ * Consumes an item of type T.
+ *
+ * @param item The item to be consumed.
+ */
+ public void consume(T item);
+
+}
diff --git a/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java
new file mode 100644
index 0000000..9ae0035
--- /dev/null
+++ b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2006-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2006-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.lifecycle;
+
+
+/**
+ * An object that is a source (producer) of objects
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Producer<T> {
+
+ /**
+ * Produces an item of type T upon request.
+ */
+ public T produce();
+
+}
diff --git a/israfil-foundation-notification/pom.xml b/israfil-foundation-notification/pom.xml
new file mode 100644
index 0000000..344acda
--- /dev/null
+++ b/israfil-foundation-notification/pom.xml
@@ -0,0 +1,28 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-notification</artifactId>
+ <name>Israfil Foundation Notification System</name>
+ <version>1.0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-dynamic</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java
new file mode 100644
index 0000000..acf60b8
--- /dev/null
+++ b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Notification.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.notification;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An encapsulated notification, used within a NotificationCentre
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class Notification {
+ private static Map<String,Object> EMPTY_INFO = Collections.unmodifiableMap(new HashMap<String,Object>());
+
+ public final Object sender;
+ public final String notification;
+ public final Map<String,Object> info;
+ public Notification(Object sender, String notification) {
+ this(sender,notification,EMPTY_INFO);
+ }
+ public Notification(Object sender, String notification, Map<String,Object> info) {
+ this.sender = sender;
+ this.notification = notification;
+ this.info = info;
+ }
+}
diff --git a/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java
new file mode 100644
index 0000000..8261d12
--- /dev/null
+++ b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: NotificationCentre.java 125 2006-11-09 15:51:38Z cgruber $
+ */
+package net.israfil.foundation.notification;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import net.israfil.foundation.dynamic.DynamicUtil;
+
+/**
+ * A nextstep-like central notification system.
+ * @author cgruber
+ */
+public class NotificationCentre {
+
+ private static NotificationCentre _shared = new NotificationCentre();
+
+ private Set<ObservationSpec> observers = new HashSet<ObservationSpec>();
+
+ protected NotificationCentre() {
+ }
+
+ public static NotificationCentre defaultCentre() {
+ return _shared;
+ }
+
+ /**
+ * This registers an object as an observer of notifications. The object
+ * registers interest in either a particular named notification, or a
+ * particular object who may issue the notifications, or the union of the
+ * two. The following table lists the possible combinations:
+ * <table>
+ * <tr>
+ * <th>Notification Name</th>
+ * <th>Sender Object</th>
+ * <th>Effect</th>
+ * </tr>
+ * <tr>
+ * <td>null</td>
+ * <td>a sender</td>
+ * <th>Notifications (of any name) from this sender are observed</th>
+ * </tr>
+ * <tr>
+ * <td>notification string</td>
+ * <td>null</td>
+ * <th>Notifications with this name (from any sender) are observed.</th>
+ * </tr>
+ * <tr>
+ * <td>notification string</td>
+ * <td>a sender</td>
+ * <th>Only notifications with this name and originating from this sender are observed</th>
+ * </tr>
+ * <tr>
+ * <td>null</td>
+ * <td>null</td>
+ * <th>All Notifications from any source will be sent (big performance drag)</th>
+ * </tr>
+ * </table>
+ * @param observer The object instance that wants to be registered
+ * @param callbackSignature Must be a method that takes a single Object parameter which will be a Notification at run-time, or a single Notification parameter
+ * @param notification The name of the notification to watch for (if any)
+ * @param sender The name of the object to whose notifications should be paid attention. (if any)
+ */
+ public void addObserver(Object observer,
+ String callbackSignature,
+ String notification,
+ Object sender){
+ if (observer == null) return;
+ if (callbackSignature == null)
+ throw new IllegalArgumentException("Reciever did not pass in a callback method.");
+ if (!checkSignature(observer,callbackSignature))
+ throw new IllegalArgumentException("Reciever does not implement specified callback method.");
+ observers.add(new ObservationSpec(sender,notification, callbackSignature, observer));
+
+ }
+ /** Post a notification with the given nam and notifier. */
+ public void postNotification(Notification notification) {
+ for (ObservationSpec obs : this.observers) {
+ obs.postNotification(notification);
+ }
+ }
+ /** Post a notification with the given name, notifier, and with additional
+ * context information presented in a java.util.Map. */
+ public void postNotification(Object sender,String notification) {
+ postNotification(new Notification(sender,notification));
+ }
+ /** Post a notification with the given name, notifier, and with additional
+ * context information presented in a java.util.Map. */
+ public void postNotification(Object sender,String notification, Map<String,Object> info) {
+ postNotification(new Notification(sender,notification,info));
+ }
+ /** Removes an observer from any notofications with either or both a
+ * provided notification string, or notifier
+ */
+ public void removeObserver(Object observer, String notification, Object sender) {
+ for (ObservationSpec obs : observers) {
+ if (obs.observer == observer &&
+ obs.sender == sender &&
+ (obs.notification == null || obs.notification.equals(notification))){
+ observers.remove(obs);
+ }
+ }
+ }
+ public void clearObservers() {
+ observers.clear();
+ }
+
+ private boolean checkSignature(Object receiver,String selector) {
+ if (!DynamicUtil.respondsTo(receiver,selector)) return false;
+ StringTokenizer st = new StringTokenizer(selector,":");
+ if (st.countTokens() != 2) return false;
+ st.nextToken();
+ String parameter = st.nextToken();
+ if (Notification.class.getName().equals(parameter)) return true;
+ if (Object.class.getName().equals(parameter)) return true;
+ return false;
+ }
+
+ /**
+ * TODO Use WeakReferences
+ */
+ public class ObservationSpec {
+ public final Object sender;
+ public final String notification;
+ public final String callback;
+ public final Object observer;
+ private final int _hashCode;
+ public ObservationSpec(Object sender,String notification,String callback, Object observer) {
+ if (observer == null)
+ throw new IllegalArgumentException("Both sender and notification cannot be null");
+ this.sender = sender;
+ this.notification = notification;
+ this.callback = callback;
+ this.observer = observer;
+
+ // Pre-calculate hash
+ int code = 13;
+ if (sender != null) code *= sender.hashCode();
+ if (notification != null) code *= notification.hashCode();
+ code *= observer.hashCode();
+ this._hashCode = code;
+ }
+ public void postNotification(Notification notification) {
+ if (this.sender == null && this.notification == null) {
+ _post(notification);
+ } else if (this.sender == null) {
+ if (notification.notification.equals(this.notification))
+ _post(notification);
+ } else if (this.notification == null) {
+ if (notification.sender.equals(this.sender))
+ _post(notification);
+ } else {
+ if (notification.notification.equals(this.notification) && notification.sender.equals(this.sender))
+ _post(notification);
+ }
+ }
+ private void _post(Notification notification) {
+ DynamicUtil.performOn(this.observer,callback,new Object[]{notification} );
+ }
+
+ @Override
+ public int hashCode() {
+ return _hashCode;
+ }
+ }
+
+}
diff --git a/israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java b/israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java
new file mode 100644
index 0000000..beb310e
--- /dev/null
+++ b/israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: NotificationCentreTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.notification;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.israfil.foundation.core.Copyright;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * @author cgruber
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+@Copyright(years={"2003","2004","2005","2006"},owner="Israfil Consulting Services Corporation",license="BSD")
+@Test
+public class NotificationCentreTest{
+
+ private static String NOTIFICATION_1 = "notification1";
+ private static String NOTIFICATION_2 = "notification2";
+ private static String NOTIFICATION_3 = "notification3";
+
+ private static String INFO_KEY = "key";
+ private static String INFO_VALUE = "value";
+
+
+ public boolean didReceiveNotifyWithNotification = false;
+ public boolean didReceiveNotifyWithObject = false;
+ public boolean didReceiveNotifyOtherWithObject = false;
+
+ public Map<String,Object> info = null;
+
+ NotificationCentre centre = null;
+ ObserverFixture observer = null;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ centre = NotificationCentre.defaultCentre();
+ observer = new ObserverFixture();
+ didReceiveNotifyWithNotification = false;
+ didReceiveNotifyWithObject = false;
+ didReceiveNotifyOtherWithObject = false;
+ info = new HashMap<String,Object>();
+ info.put(INFO_KEY,INFO_VALUE);
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ centre.clearObservers();
+ centre = null;
+ observer = null;
+ info = null;
+ }
+
+ /*
+ * Test for void postNotification(Notification)
+ */
+ public void testPostNotificationNotification() {
+ Notification n1 = new Notification(this,NOTIFICATION_1);
+ Notification n2 = new Notification(this,NOTIFICATION_2);
+ Notification n3 = new Notification(this,NOTIFICATION_3);
+ centre.postNotification(n1);
+ Assert.assertFalse(didReceiveNotifyWithNotification);
+ Assert.assertFalse(observer.notification == n1);
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ centre.postNotification(n2);
+ Assert.assertTrue(didReceiveNotifyWithNotification);
+ Assert.assertTrue(observer.notification == n2);
+
+ // register as global
+ centre.removeObserver(observer,null,null);
+ centre.postNotification(n3);
+ Assert.assertFalse(observer.notification == n3);
+ }
+
+ /*
+ * Test for void postNotification(Object, String)
+ */
+ public void testPostNotificationObjectString() {
+ centre.postNotification(this,NOTIFICATION_1);
+ Assert.assertFalse(didReceiveNotifyWithNotification);
+ Assert.assertEquals(null,observer.notification);
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ centre.postNotification(this,NOTIFICATION_2);
+ Assert.assertTrue(didReceiveNotifyWithNotification);
+ Assert.assertEquals(NOTIFICATION_2,observer.notification.notification);
+ }
+
+ /*
+ * Test for void postNotification(Object, String, Map)
+ */
+ public void testPostNotificationObjectStringMap() {
+ centre.postNotification(this,NOTIFICATION_1,info);
+ Assert.assertFalse(didReceiveNotifyWithNotification);
+ Assert.assertEquals(null,observer.notification);
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ centre.postNotification(this,NOTIFICATION_2,info);
+ Assert.assertTrue(didReceiveNotifyWithNotification);
+ Assert.assertEquals(NOTIFICATION_2,observer.notification.notification);
+ Assert.assertEquals(INFO_VALUE,observer.notification.info.get(INFO_KEY));
+ }
+
+ /*
+ * Test for void removeObserver(Object, String, Object)
+ */
+ public void testRemoveObserverObjectStringObject() {
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ // remove right away (we know addObserver works from other tests.
+ centre.removeObserver(observer,null,null);
+ centre.postNotification(this,NOTIFICATION_1,info);
+ Assert.assertEquals(null,observer.notification);
+ }
+
+ public class ObserverFixture {
+ public Notification notification = null;
+ public void notify(Notification n) {
+ NotificationCentreTest sender = (NotificationCentreTest)n.sender;
+ sender.didReceiveNotifyWithNotification = true;
+ this.notification = n;
+ }
+ public void notify(Object o) {
+ Notification n = (Notification)o;
+ NotificationCentreTest sender = (NotificationCentreTest)n.sender;
+ sender.didReceiveNotifyWithObject = true;
+ this.notification = n;
+ }
+ public void notifyOther(Object o) {
+ Notification n = (Notification)o;
+ NotificationCentreTest sender = (NotificationCentreTest)n.sender;
+ sender.didReceiveNotifyWithObject = true;
+ this.notification = n;
+ }
+ public void finalize() throws Throwable {
+ notification = null;
+ super.finalize();
+ }
+ }
+
+}
diff --git a/israfil-foundation-nspace/pom.xml b/israfil-foundation-nspace/pom.xml
new file mode 100644
index 0000000..969dae5
--- /dev/null
+++ b/israfil-foundation-nspace/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-nspace</artifactId>
+ <name>Israfil Foundation N-Dimensional Array</name>
+ <version>0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java
new file mode 100755
index 0000000..620124a
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: Coordinate.java 254 2003-02-10 16:01:01Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Logically an array of tuples
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 254 $
+ */
+public interface Coordinate {
+
+ /**
+ * A single empty Coordinate, which can be passed in to point-NSpaces, where
+ * no dimension constraint is required.
+ */
+ public final static Coordinate EMPTY =
+ new Coordinate() {
+ private final Set<String> dim = new HashSet<String>();
+
+ public Set<String> getDimensions() {
+ return dim;
+ }
+ public long getDimensionality() { return 0; }
+ public String getOrdinal(String dimensionName) {
+ if (false) dimensionName.hashCode(); //quiet compiler warning.
+ return null;
+ }
+ };
+
+ /**
+ * Returns a set of names of contained dimensions.
+ * @return Set
+ */
+ public Set<String> getDimensions();
+
+ /**
+ * Returns the number of dimensions
+ * @return long
+ */
+ public long getDimensionality();
+
+ /**
+ * Returns the ordinal of the given named dimension..
+ * @return Set
+ */
+ public String getOrdinal(String dimensionName);
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java
new file mode 100755
index 0000000..f4e73bb
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: Dimension.java 260 2005-05-15 13:08:53Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * A named set of positions within an nspace
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 260 $
+ */
+public interface Dimension extends Set<String> {
+
+ /**
+ * Returns the name of the position
+ * @return String
+ */
+ public String getName();
+
+
+ void getWithNSpace(NSpace space);
+ void abandonNSpace(NSpace space);
+ void getWithNSpaces(Collection<NSpace> spaces);
+ void abandonNSpaces(Collection<NSpace> spaces);
+
+ public Dimension addPosition(String s);
+ public Dimension deletePosition(String s);
+
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java
new file mode 100755
index 0000000..e53397a
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: DimensionExistsException.java 249 2003-02-02 03:33:46Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+/**
+ * Thrown if a dimension is added to an NSpace which already defines a
+ * Dimension with that name.
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 249 $
+ */
+public class DimensionExistsException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -801633377290441235L;
+
+ /**
+ * Constructor for DimensionExistsException.
+ */
+ public DimensionExistsException() {
+ super();
+ }
+
+ /**
+ * Constructor for DimensionExistsException.
+ * @param arg0
+ */
+ public DimensionExistsException(String arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java
new file mode 100755
index 0000000..3a12d31
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: InvalidDimensionalityException.java 249 2003-02-02 03:33:46Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+/**
+ * Thrown when the provided Coodinate inadequately specifies, or incorrectly
+ * specifies the dimensions relative to the NSpace. Primarily used with
+ * setters.
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 249 $
+ */
+public class InvalidDimensionalityException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5349982487272515716L;
+
+ /**
+ * Constructor for InvalidDimensionalityException.
+ */
+ public InvalidDimensionalityException() {
+ super();
+ }
+
+ /**
+ * Constructor for InvalidDimensionalityException.
+ * @param arg0
+ */
+ public InvalidDimensionalityException(String arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java
new file mode 100755
index 0000000..196f4e9
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: NSpace.java 259 2004-08-23 21:30:01Z mberteig $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Set;
+
+/**
+ * An N-Dimensional Space representation, such that:
+ * <ol>
+ * <li>Each dimension is named</li>
+ * <li>Each co-ordinate is specified using names not numbers <subscript>IOW:
+ * Domain of each dim. is specified as an ordered set of names
+ * </subscript></li>
+ * <li>Number of dimensions can change throughout lifecycle</li>
+ * <li>Dimensions
+ * </ol>
+ * <p>
+ * A SparseNSpace represents a set of tuples of the form (D1,D2,D3,...,Dn;V)
+ * where Dx represents a location in dimension x and V represents a value in
+ * the n-dimensional space at a location specified by the dimensional locations
+ * D1..Dn. Dimensions can be added or removed at any time with well-defined
+ * results.</p>
+ * <p><strong>Note:</strong> Maybe have origin</p>
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 259 $
+ */
+public interface NSpace {
+
+ /*
+ * Content Management
+ */
+
+ /**
+ * Returns an NSpace such that each coordinate of the receiver that contains the values of the passed in
+ * coordinate becomes a part of the resulting NSpace. The dimensionality of the resulting NSpace is the difference
+ * of the dimensionality of the receiver and the coordinate. E.g. say we have 3-NSpace with dimensions (D1,D2,D3)
+ * and data [0,0,0;A], [0,1,0;B], [1,0,0;C], [1,1,0;D]. If we lookup a coordinate with dimensions (D2,D3) and values
+ * [0,0] we will get a resulting 1-NSpace with dimension (D1) and data [0;A], [1;C].
+ */
+ public NSpace lookup(Coordinate c);
+
+ /**
+ * Returns an NSpace such that each coordinate of the receiver that contains the values of the passed in
+ * coordinate is not a part of the resulting NSpace. The dimensionality of the resulting NSpace is the dimensionality
+ * of the receiver. E.g. say we have 3-NSpace with dimensions (D1,D2,D3)
+ * and data [0,0,0;A], [0,1,0;B], [1,0,0;C], [1,1,0;D]. If we slice with a coordinate with dimensions (D2,D3) and values
+ * [0,0] we will get a resulting 3-NSpace with dimension (D1,D2,D3) and data [0,1,0;B], [1,1,0;D].
+ */
+ public NSpace slice(Coordinate c);
+
+ /**
+ * Returns an array of NSpace instances such that for each ordinal in Dimension d, there is an NSpace in the array
+ * of dimensionality one less than the receiver that contains the data from the receiver that contains the ordinal.
+ * E.g. say we have 3-NSpace with dimensions (D1,D2,D3)
+ * and data [0,0,0;A], [0,1,0;B], [1,0,0;C], [1,1,0;D].
+ * then slicing on dimension D2 would give us two 2-NSpaces with dimensions (D1,D3):
+ * [0,0;A], [1,0;C] and
+ * [0,0;B], [1,0;D]
+ * @param d the dimension to use to make the cuts in the receiver
+ * @return all the sub-NSpaces, one for each ordinal of d
+ */
+ public NSpace[] slice(Dimension d);
+
+ /**
+ * Returns true if NSpace contains zero dimensions, or if the size of each
+ * dimension == 1.
+ * @return boolean
+ */
+ public boolean isPoint();
+ public Object getValue(Coordinate c);
+
+ public NSpace setValue(Coordinate c, Object value)
+ throws InvalidDimensionalityException;
+ public NSpace setValue(Coordinate c, NSpace value)
+ throws InvalidDimensionalityException;
+
+ /*
+ * Dimension Management
+ */
+ public Dimension createDimension(String name, String initialSlot)
+ throws DimensionExistsException;
+ public void deleteDimension(Dimension dimension);
+ public Set<Dimension> getDimensions();
+ public Dimension getDimension(String name);
+
+ /*
+ * Notifications
+ */
+
+ void dimensionAddedPosition(Dimension dimension,String position);
+ void dimensionRemovedPosition(Dimension dimension, String position);
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java
new file mode 100755
index 0000000..52250fa
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java
@@ -0,0 +1,225 @@
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author cgruber
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class SimpleDimension implements Dimension {
+
+ private final String name;
+ private final Set<String> positions = new HashSet<String>();
+ private final Set<NSpace> spaces = new HashSet<NSpace>();
+
+ public SimpleDimension() {
+ name = null;
+ }
+
+ public SimpleDimension(String name, String ordinal) {
+ this.name = name;
+ positions.add(ordinal);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#getName()
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @see java.util.Collection#size()
+ */
+ public int size() {
+ return this.positions.size();
+ }
+
+ /**
+ * @see java.util.Collection#isEmpty()
+ */
+ public boolean isEmpty() {
+ throw new UnsupportedOperationException("Dimension cannot have no positions. Remove the dimension.");
+ }
+
+ /**
+ * @see java.util.Collection#contains(java.lang.Object)
+ */
+ public boolean contains(Object positions) {
+ return this.positions.contains(positions);
+ }
+
+ /**
+ * @see java.util.Collection#iterator()
+ */
+ public Iterator<String> iterator() {
+ return this.positions.iterator();
+ }
+
+ /**
+ * @see java.util.Collection#toArray()
+ */
+ public String[] toArray() {
+ return this.positions.toArray(new String[size()]);
+ }
+
+ /**
+ * @see java.util.Collection#toArray(java.lang.Object)
+ */
+ public <T> T[] toArray(T[] array) {
+ return this.positions.toArray(array);
+ }
+
+ /**
+ * @see java.util.Collection#add(java.lang.Object)
+ */
+ public boolean add(String
+ position) {
+ boolean result = this.positions.add(position);
+ notifyAddPosition((String)position);
+ return result;
+ }
+
+ /**
+ * @see java.util.Collection#remove(java.lang.Object)
+ */
+ public boolean remove(Object position) {
+ boolean result = this.positions.remove(position);
+ notifyRemovePosition((String)position);
+ return result;
+ }
+
+ /**
+ * @see java.util.Collection#containsAll(java.util.Collection)
+ */
+ public boolean containsAll(Collection<?> positions) {
+ return this.positions.containsAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#addAll(java.util.Collection)
+ */
+ public boolean addAll(Collection<? extends String> positions) {
+ return this.positions.addAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#retainAll(java.util.Collection)
+ */
+ public boolean retainAll(Collection<?> positions) {
+ return this.positions.retainAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#removeAll(java.util.Collection)
+ */
+ public boolean removeAll(Collection<?> positions) {
+ return this.positions.removeAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#clear()
+ */
+ public void clear() {
+ throw new UnsupportedOperationException("Dimensions must always have one ordinal");
+ }
+
+
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#abandonNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void abandonNSpace(NSpace n) {
+ this.spaces.remove(n);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#getWithNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void getWithNSpace(NSpace n) {
+ this.spaces.add(n);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#abandonNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void abandonNSpaces(Collection<NSpace> spaces) {
+ this.spaces.removeAll(spaces);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#getWithNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void getWithNSpaces(Collection<NSpace> spaces) {
+ this.spaces.addAll(spaces);
+ }
+
+ private void notifyAddPosition(String position) {
+ for (NSpace space : spaces) {
+ space.dimensionAddedPosition(this,position);
+ }
+ }
+
+ private void notifyRemovePosition(String position) {
+ for (NSpace space : spaces) {
+ space.dimensionRemovedPosition(this,position);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private void notifyAddPositions(Collection<String> positions) {
+
+ }
+
+ @SuppressWarnings("unused")
+ private void notifyRemovePositions(Collection<String> positions) {
+
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(super.toString());
+ sb.append(" [");
+ sb.append(name);
+ sb.append("] {");
+ for (String s : positions) sb.append(s);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#addPosition(java.lang.String)
+ */
+ public Dimension addPosition(String s) {
+ add(s);
+ return this;
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#deletePosition(java.lang.String)
+ */
+ public Dimension deletePosition(String s) {
+ remove(s);
+ return this;
+ }
+
+
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java
new file mode 100755
index 0000000..4c48842
--- /dev/null
+++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: SparseNSpace.java 260 2005-05-15 13:08:53Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An implementatino of NSpace that is sparsely populated.
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 260 $
+ */
+public class SparseNSpace implements NSpace {
+
+ private final Set<Dimension> dimensions = new HashSet<Dimension>();
+
+ public SparseNSpace() {
+ super();
+ }
+
+ public SparseNSpace(Set<Dimension> initialDimensions) {
+ this();
+ for (Dimension d : dimensions) {
+ // This is temporary, until we have an internal protected mutator.
+ dimensions.add(d);
+ }
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#createDimension(java.lang.String, java.lang.String)
+ */
+ public Dimension createDimension(String name, String initialSlot)
+ throws DimensionExistsException {
+ Dimension d = new SimpleDimension(name,initialSlot);
+ dimensions.add(d);
+ return d;
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#deleteDimension(org.frugenplat.framework.nspace.Dimension)
+ */
+ public void deleteDimension(Dimension dimension) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#dimensionAddedPosition(org.frugenplat.framework.nspace.Dimension, java.lang.String)
+ */
+ public void dimensionAddedPosition(Dimension dimension, String position) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#dimensionRemovedPosition(org.frugenplat.framework.nspace.Dimension, java.lang.String)
+ */
+ public void dimensionRemovedPosition(
+ Dimension dimension,
+ String position) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#getDimension(java.lang.String)
+ */
+ public Dimension getDimension(String name) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns an immutable set of dimensions for inspection..
+ * @see org.frugenplat.framework.nspace.NSpace#getDimensions()
+ */
+ public Set<Dimension> getDimensions() {
+ return Collections.unmodifiableSet(dimensions);
+ }
+
+ /**
+ * Exposes the internal dimensions set to any children
+ * @return Set
+ */
+ protected Set<Dimension> getInternalDimensions() {
+ return dimensions;
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#getValue()
+ */
+ public Object getValue(Coordinate c) {
+ // SparseNSpace s = _slice(c);
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ Object _findValue() {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#isPoint()
+ */
+ public boolean isPoint() {
+ if (dimensions.size() == 0) return true;
+ else {
+ boolean hasThinDimensions = true;
+ for(Dimension d : dimensions){
+ hasThinDimensions = hasThinDimensions &&
+ (d.size() == 1);
+ }
+ return hasThinDimensions;
+ }
+
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#lookup(org.frugenplat.framework.nspace.Coordinate)
+ */
+ public NSpace lookup(Coordinate c) {
+ return _lookup(c);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#setValue(org.frugenplat.framework.nspace.Coordinate, org.frugenplat.framework.nspace.NSpace)
+ */
+ public NSpace setValue(Coordinate c, NSpace value)
+ throws InvalidDimensionalityException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#setValue(org.frugenplat.framework.nspace.Coordinate, java.lang.Object)
+ */
+ public NSpace setValue(Coordinate c, Object value)
+ throws InvalidDimensionalityException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#slice(org.frugenplat.framework.nspace.Coordinate)
+ */
+ public NSpace slice(Coordinate c) {
+ return _slice(c);
+ }
+
+ private SparseNSpace _lookup(Coordinate c) {
+ if (c.equals(Coordinate.EMPTY)) return this;
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ private SparseNSpace _slice(Coordinate c) {
+ if (c.equals(Coordinate.EMPTY)) return this;
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+ /* (non-Javadoc)
+ * @see org.frugenplat.framework.nspace.NSpace#slice(org.frugenplat.framework.nspace.Dimension)
+ */
+ public NSpace[] slice(Dimension d) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/israfil-foundation-nspace/src/site/apt/Specification.apt b/israfil-foundation-nspace/src/site/apt/Specification.apt
new file mode 100755
index 0000000..5da06ac
--- /dev/null
+++ b/israfil-foundation-nspace/src/site/apt/Specification.apt
@@ -0,0 +1,63 @@
+This doc defines the theoretical nature of an NSpace and Sparse NSpace implementation.
+
+
+
+NSpace
+
+ Definition:
+ - N-Dimensional Space representation
+ - NSpace is set of Dimensions
+ - Dimension is a set of Positions
+ - Each dimension is named
+ - Each co-ordinate is specified using names not numbers
+ IOW: Domain of each dim. is specified as a set of names
+ - Number of dimensions can change throughout lifecycle
+ - Dimensions are not ordered in a Space.
+ - Positions are not ordered in a Dimension
+ - value at fully-qualified-coordinate is of type Object
+
+
+ Operations
+ - When looking up co-ordinate - specify dimension + position
+ - 2 kinds of search (lookup and extract)
+
+ Questions:
+ - can an NSpace hold an (NSpace)value
+
+
+Dimension
+
+ Definition
+
+SparseNSpace
+
+ Characteristics:
+
+
+
+ Questions
+
+Example:
+
+ lookup()
+ Given a 5Space
+ specify 3 ordinates in lookup
+ Get a 5Space (3 dims have size of 1)
+
+ extractSlice()
+ Given a 5Space
+ specify 3 ordinates in lookup
+ Get a 2Space
+
+ getDimensions()
+ returns a set of Dimensions
+
+ getDimension(String name)
+ returns a set of Positions
+
+ space.addDimension(Dimension dimension, String origin)
+ all the points in the current system have to know of new dim.
+
+
+
+
diff --git a/israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd b/israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd
new file mode 100755
index 0000000..dae310b
--- /dev/null
+++ b/israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd
@@ -0,0 +1,58 @@
+<editmodel:ClassDiagramEditModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:editmodel="editmodel.xmi" size="1088,378" id="fenestratedcgruberSparseNSpace0" metadata="nsuml-1.4" initialized="true">
+ <children xsi:type="editmodel:InterfaceEditModel" location="73,103" size="184,265" id="fenestratedcgruberSparseNSpace2" runTimeClassModel="fenestratedcgruberSparseNSpace54;fenestratedcgruberSparseNSpace73;fenestratedcgruberSparseNSpace7;fenestratedcgruberSparseNSpace121;fenestratedcgruberSparseNSpace32;fenestratedcgruberSparseNSpace123;fenestratedcgruberSparseNSpace13;fenestratedcgruberSparseNSpace119;fenestratedcgruberSparseNSpace116;fenestratedcgruberSparseNSpace21;fenestratedcgruberSparseNSpace69;fenestratedcgruberSparseNSpace30">
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name">
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace54"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace116"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace69"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace73"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace32"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace30"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace121"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace21"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace119"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace7"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace13"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace123"/>
+ </children>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ </children>
+ <children xsi:type="editmodel:InterfaceEditModel" location="304,226" size="140,139" id="fenestratedcgruberSparseNSpace36" runTimeClassModel="fenestratedcgruberSparseNSpace161;fenestratedcgruberSparseNSpace156;fenestratedcgruberSparseNSpace427;fenestratedcgruberSparseNSpace164;fenestratedcgruberSparseNSpace158;fenestratedcgruberSparseNSpace167;fenestratedcgruberSparseNSpace430">
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ <children xsi:type="editmodel:CompartmentEditModel" size="121,94" viewSorter="Name">
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace161"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace167"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace427"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace430"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace156"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace158"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace164"/>
+ </children>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ </children>
+ <children xsi:type="editmodel:InterfaceEditModel" location="311,47" size="137,103" id="fenestratedcgruberSparseNSpace150" runTimeClassModel="fenestratedcgruberSparseNSpace171;fenestratedcgruberSparseNSpace175;fenestratedcgruberSparseNSpace173;fenestratedcgruberSparseNSpace177">
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ <children xsi:type="editmodel:CompartmentEditModel" size="118,58" viewSorter="Name">
+ <children xsi:type="editmodel:MethodEditModel" location="299,84" id="fenestratedcgruberSparseNSpace175"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace173"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace177"/>
+ </children>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ </children>
+ <children xsi:type="editmodel:ClassEditModel" location="528,39" size="213,33" id="fenestratedcgruberSparseNSpace258" runTimeClassModel="fenestratedcgruberSparseNSpace419;fenestratedcgruberSparseNSpace417">
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name">
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace419"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace417"/>
+ </children>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ </children>
+ <children xsi:type="editmodel:ClassEditModel" location="487,158" size="247,33" id="fenestratedcgruberSparseNSpace261" runTimeClassModel="fenestratedcgruberSparseNSpace414;fenestratedcgruberSparseNSpace412">
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name">
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace414"/>
+ <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace412"/>
+ </children>
+ <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/>
+ </children>
+</editmodel:ClassDiagramEditModel>
diff --git a/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java
new file mode 100755
index 0000000..cd2d4d4
--- /dev/null
+++ b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java
@@ -0,0 +1,211 @@
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ * @author cgruber
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+@Test
+public class SimpleDimensionTest {
+
+ Object o1 = "TestValue1";
+ String d1Name = "TestDimension1";
+ String ordinal1 = "TestOrdinal1";
+ String ordinal2 = "TestOrdinal2";
+ String ordinal3 = "TestOrdinal3";
+
+ /**
+ * test {@link Dimension.Dimension(String,String) Dimension(String,String)}
+ */
+ public void testConstructor_String_String() {
+ Dimension d = new SimpleDimension(d1Name, ordinal1);
+ Assert.assertEquals(d1Name,d.getName(),"Name doesn't equal provided string.");
+ Assert.assertTrue(d.size() == 1,"Size is not equal to 1");
+
+ }
+
+
+ /**
+ * test {@link Dimension.getName() getName()}
+ */
+ public void testGetName() {
+ Dimension d = new SimpleDimension(d1Name, ordinal1);
+ Assert.assertEquals(d1Name,d.getName());
+ }
+
+ /**
+ * test {@link Dimension.register(NSpace) register(NSpace)}
+ */
+ public void testRegister_NSpace() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.deregister(NSpace) deregister(NSpace)}
+ */
+ public void testDeregister_NSpace() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.register(NSpace[]) register(NSpace[])}
+ */
+ public void testRegister_NSpaceArray() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.deregister(NSpace[]) deregister(NSpace[])}
+ */
+ public void testDeregister_NSpaceArray() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.add(Object) add(Object)}
+ */
+ public void testAdd_Object() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ d.add(ordinal2);
+ Assert.assertTrue(d.contains(ordinal2),"Dimension doesn't contain added position.");
+ }
+
+ /**
+ * test {@link Dimension.addAll(Collection) addAll(Collection)}
+ */
+ public void testAddAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal2);
+ c.add(ordinal3);
+
+ d.addAll(c);
+ Assert.assertTrue(d.contains(ordinal2),"Dimension doesn't contain added position.");
+ Assert.assertTrue(d.contains(ordinal3),"Dimension doesn't contain added position.");
+ }
+
+ @Test(expectedExceptions={UnsupportedOperationException.class})
+ public void testClear() {
+ new SimpleDimension(d1Name,ordinal1).clear();
+ }
+
+ /**
+ * test {@link Dimension.containsAll(Collection) containsAll(Collection)}
+ */
+ public void testContainsAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ d.add(ordinal2);
+
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal1);
+ c.add(ordinal2);
+ Assert.assertTrue(d.containsAll(c),"Dimension doesn't contain added positions.");
+
+ d = new SimpleDimension(d1Name,ordinal1);
+ Assert.assertFalse(d.containsAll(c),"Dimension claims to contain positions it shouldn't.");
+ }
+
+ @Test(expectedExceptions={UnsupportedOperationException.class})
+ public void testIsEmpty() {
+ new SimpleDimension(d1Name,ordinal1).isEmpty();
+ }
+
+ /**
+ * test {@link Dimension.iterator() iterator()}
+ */
+ public void testIterator() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ Iterator<String> i = d.iterator();
+ Assert.assertEquals(ordinal1,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+
+ /**
+ * test (@link Dimension.remove(Object) remove(Object)}
+ */
+ public void testRemove_Object() {
+ String toBeRemoved = ordinal2;
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(toBeRemoved);
+ Assert.assertTrue(d.contains(toBeRemoved));
+ d.remove(toBeRemoved);
+ Assert.assertFalse(d.contains(toBeRemoved));
+ }
+
+ /**
+ * test {@link Dimension.removeAll(Collection) removeAll(Collection)}
+ * TODO: This should test removing every position
+ */
+ public void testRemoveAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(ordinal2)
+ .addPosition(ordinal3);
+
+ Assert.assertTrue(d.contains(ordinal2));
+ Assert.assertTrue(d.contains(ordinal3));
+
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal2);
+ c.add(ordinal3);
+ d.removeAll(c);
+ Assert.assertEquals(d.size(),1);
+ }
+
+ /**
+ * test {@link Dimension.retainAll(Collection) retainAll(Collection)}
+ */
+ public void testRetainAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(ordinal2)
+ .addPosition(ordinal3);
+
+ Assert.assertTrue(d.contains(ordinal2));
+ Assert.assertTrue(d.contains(ordinal3));
+
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal2);
+ c.add(ordinal3);
+ d.retainAll(c);
+ Assert.assertEquals(d.size(),2);
+ }
+
+ /**
+ * test {@link Dimensions.size() size()}
+ */
+ public void testSize() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(ordinal2)
+ .addPosition(ordinal3);
+ Assert.assertEquals(d.size(),3);
+ }
+
+ /**
+ * test {@link Dimensions.toArray() toArray()}
+ */
+ public void testToArray() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ String[] sa = (String[])d.toArray();
+ Assert.assertEquals(sa[0],ordinal1);
+ }
+
+ /**
+ * test {@link Dimension.toArray(Object[]) toArray(Object[])}
+ */
+ public void testToArray_ObjectArray() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ String[] sa = (String[])d.toArray(new String[d.size()]);
+ Assert.assertEquals(sa[0],ordinal1);
+ }
+
+}
diff --git a/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java
new file mode 100755
index 0000000..b291a23
--- /dev/null
+++ b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: SparseNSpaceTest.java 261 2005-05-15 13:36:26Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 261 $
+ */
+@Test
+public class SparseNSpaceTest {
+
+ public void testCreateDimension_String_String() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testDeleteDimension_Dimension() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testDimensionAddedPosition() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testDimensionRemovedPosition() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testGetDimension_String() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testGetDimensions() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testGetValue() throws InvalidDimensionalityException {
+ NSpace space = new SparseNSpace();
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testIsPoint() throws DimensionExistsException {
+ NSpace space = new SparseNSpace();
+ Assert.assertTrue(space.isPoint());
+
+ // Create two "thin" dimensions.
+ space.createDimension("TestDimension1","TestOrdinal");
+ space.createDimension("TestDimension2","TestOrdinal");
+
+ Assert.assertTrue(space.isPoint());
+ /*
+ space.createDimension("TestDimension3","TestOrdinal1")
+ .addPosition("TestOrdinal2");
+ Assert.assertFalse(space.isPoint());
+ */
+ }
+
+ public void testLookup_Coordinate() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /*
+ * Test for NSpace setValue(Coordinate, NSpace)
+ */
+ public void testSetValue_Coordinate_NSpace() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /*
+ * Test for NSpace setValue(Coordinate, Object)
+ */
+ public void testSetValue_Coordinate_Object() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testSlice() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+}
diff --git a/israfil-foundation-testing/pom.xml b/israfil-foundation-testing/pom.xml
new file mode 100644
index 0000000..1eecf29
--- /dev/null
+++ b/israfil-foundation-testing/pom.xml
@@ -0,0 +1,21 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-testing</artifactId>
+ <name>Israfil Foundation Testing Helpers and Fakes</name>
+ <version>1.0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <inceptionYear>2003</inceptionYear>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java
new file mode 100644
index 0000000..4de4a63
--- /dev/null
+++ b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java
@@ -0,0 +1,1350 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSet.java 517M 2007-07-09 20:00:15Z (local) $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.ColSpec;
+
+/**
+ * A Mock implementation of ResultSet that takes an array of column
+ * names and an array or rows, where rows are arrays of data. A Mock
+ * ResultSet can be used in unit testing where database access needs
+ * to be stubbed out.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class MockResultSet implements ResultSet {
+
+ public MockResultSetMetaData metadata;
+
+ protected List<Row> data;
+ public List<Row> getData() { return data; }
+ int cursorPosition = 0;
+ boolean insertRow = false;
+ private final static int BEFOREFIRST = 0;
+ private final int AFTERLAST;
+ protected int concurrency = CONCUR_READ_ONLY;
+ protected int fetchDirection = FETCH_UNKNOWN;
+ protected int fetchSize = 0;
+ protected Statement statement = null;
+ protected boolean wasNull = false;
+ boolean open = false;
+
+ private MockResultSet(int size) {
+ AFTERLAST = size+1;
+ }
+
+ /**
+ * The main constructor, which takes an array of strings representing
+ * the columns of the supposed DataReader, and an array of string arrays
+ * representing the row data. With this, one can simulate a call to the
+ * database.
+ *
+ * @param columns the columns to be simulated
+ * @param rows the rows to be simulated
+ *
+ */
+ public MockResultSet(String[] columns, Object[][] rows) {
+ this((rows==null)?0:rows.length);
+ metadata = new MockResultSetMetaData(columns);
+ primeRows(rows);
+ }
+
+ /**
+ * The main constructor, which takes an array of strings representing
+ * the columns of the supposed DataReader, and an array of string arrays
+ * representing the row data. With this, one can simulate a call to the
+ * database.
+ *
+ * @param columns the columns to be simulated
+ * @param rows the rows to be simulated
+ *
+ */
+ public MockResultSet(ColSpec[] columns, Object[][] rows) {
+ this((rows==null)?0:rows.length);
+ metadata = new MockResultSetMetaData(columns);
+ primeRows(rows);
+ }
+
+ /**
+ * Private method that takes given row data and populates the internal
+ * structures with said data.
+ * @param rows
+ */
+ private void primeRows(Object[][] rows) {
+ if (rows == null) rows = new String[][]{};
+ try {
+ data = new ArrayList<Row>(metadata.getColumnCount());
+ for (int rowNum = 0; rowNum < rows.length; rowNum++) {
+ data.add(new Row(metadata,new ArrayList<Object>(Arrays.asList(rows[rowNum]))));
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ cursorPosition = 0;
+ open = true;
+ }
+
+ public void finalize() throws Throwable {
+ data = null;
+ metadata = null;
+ super.finalize();
+ }
+
+ /**
+ * Moves the cursor to the given row number in this ResultSet object.
+ *
+ * If the row number is positive, the cursor moves to the given row number
+ * with respect to the beginning of the result set. The first row is row 1,
+ * the second is row 2, and so on.
+ *
+ * If the given row number is negative, the cursor moves to an absolute row
+ * position with respect to the end of the result set. For example, calling
+ * the method absolute(-1) positions the cursor on the last row; calling the
+ * method absolute(-2) moves the cursor to the next-to-last row, and so on.
+ *
+ * An attempt to position the cursor beyond the first/last row in the result
+ * set leaves the cursor before the first row or after the last row.
+ *
+ * Note: Calling absolute(1) is the same as calling first(). Calling
+ * absolute(-1) is the same as calling last().
+ *
+ * @param row - the number of the row to which the cursor should move. A positive number indicates the row number counting from the beginning of the result set; a negative number indicates the row number counting from the end of the result set
+ * @return true if the cursor is on the result set; false otherwise
+ */
+ public boolean absolute(int row) throws SQLException {
+ // the number of the row to which the cursor should move.
+ // A positive number indicates the row number counting from
+ // the beginning of the result set; a negative number indicates
+ // the row number counting from the end of the result set.
+ if (row > 0) {
+ if (BEFOREFIRST + row < AFTERLAST) {
+ cursorPosition = BEFOREFIRST + row;
+ return true;
+ } else {
+ cursorPosition = AFTERLAST;
+ return false;
+ }
+ } else if (row < 0) {
+ if (AFTERLAST + row > BEFOREFIRST) {
+ cursorPosition = AFTERLAST + row;
+ return true;
+ } else {
+ cursorPosition = BEFOREFIRST;
+ return false;
+ }
+ } else /* offset == 0 */ {
+ // This is essentially beforeFirst();
+ cursorPosition = 0;
+ return false;
+ }
+ }
+
+ public void afterLast() throws SQLException {
+ absolute(data.size()+1);
+ }
+
+ public void beforeFirst() throws SQLException {
+ absolute(0);
+ }
+
+ public void cancelRowUpdates() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void clearWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void close() throws SQLException {
+ open = false;
+ }
+
+ public void deleteRow() throws SQLException {
+ if (insertRow) throw new SQLException("Cannot delete the insert row.");
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int findColumn(String column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public boolean first() throws SQLException {
+ return absolute(1);
+ }
+
+ public Object getInternalValue(int rowNumber, int column) {
+ try {
+ return processAccessedObject(data.get(rowNumber-1).get(column));
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+
+ public Object getInternalValue(int rowNumber, String column) {
+ try {
+ return processAccessedObject(data.get(rowNumber-1).get(column));
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+
+ public Object processAccessedObject(Object o) {
+ if (o == null) wasNull = true;
+ return o;
+ }
+
+ public Array getArray(int column) throws SQLException {
+ return (Array)getInternalValue(cursorPosition,column);
+ }
+
+ public Array getArray(String column) throws SQLException {
+ return (Array)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getAsciiStream(int column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getAsciiStream(String column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public BigDecimal getBigDecimal(int column, int scale) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ bd.setScale(scale);
+ return bd;
+ }
+
+ public BigDecimal getBigDecimal(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ return bd;
+ }
+
+ public BigDecimal getBigDecimal(String column, int scale) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ bd.setScale(scale);
+ return bd;
+ }
+
+ public BigDecimal getBigDecimal(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ return bd;
+ }
+
+ public InputStream getBinaryStream(int column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getBinaryStream(String column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public Blob getBlob(int column) throws SQLException {
+ return new MockBlob(getBytes(column));
+ }
+
+ public Blob getBlob(String column) throws SQLException {
+ return new MockBlob(getBytes(column));
+ }
+
+ public boolean getBoolean(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return false;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) return ((Number)o).byteValue() != 0;
+ else return Boolean.valueOf(String.valueOf(o));
+ }
+
+ public boolean getBoolean(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return false;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) return ((Number)o).byteValue() != 0;
+ else return Boolean.valueOf(String.valueOf(o));
+ }
+
+ public byte getByte(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).byteValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (byte)1 : (byte)0 ;
+ } else return Byte.valueOf(String.valueOf(o));
+ }
+
+ public byte getByte(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).byteValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (byte)1 : (byte)0 ;
+ } else return Byte.valueOf(String.valueOf(o));
+ }
+
+ public byte[] getBytes(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public byte[] getBytes(String column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Reader getCharacterStream(int column) throws SQLException {
+ return (Reader)getInternalValue(cursorPosition,column);
+ }
+
+ public Reader getCharacterStream(String column) throws SQLException {
+ return (Reader)getInternalValue(cursorPosition,column);
+ }
+
+ public Clob getClob(int column) throws SQLException {
+ return (Clob)getInternalValue(cursorPosition,column);
+ }
+
+ public Clob getClob(String column) throws SQLException {
+ return (Clob)getInternalValue(cursorPosition,column);
+ }
+
+ public int getConcurrency() throws SQLException {
+ return concurrency;
+ }
+
+ public void setConcurrency(int concurrency) {
+ this.concurrency = concurrency;
+ }
+ public String getCursorName() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Date getDate(int column, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Date getDate(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Date) return (Date)o;
+ if (o instanceof java.util.Date)
+ return new Date(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Date(((Calendar)o).getTimeInMillis());
+ return Date.valueOf(String.valueOf(o));
+ }
+
+ public Date getDate(String column, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Date getDate(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Date) return (Date)o;
+ if (o instanceof java.util.Date)
+ return new Date(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Date(((Calendar)o).getTimeInMillis());
+ return Date.valueOf(String.valueOf(o));
+ }
+
+ public double getDouble(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).doubleValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 : 0 ;
+ } else return Double.valueOf(String.valueOf(o));
+ }
+
+ public double getDouble(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).doubleValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 : 0 ;
+ } else return Double.valueOf(String.valueOf(o));
+ }
+
+ public int getFetchDirection() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getFetchSize() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public float getFloat(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).floatValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Float.valueOf(String.valueOf(o));
+ }
+
+ public float getFloat(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).floatValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Float.valueOf(String.valueOf(o));
+ }
+
+ public int getInt(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).intValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Integer.valueOf(String.valueOf(o));
+ }
+
+ public int getInt(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).intValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Integer.valueOf(String.valueOf(o));
+ }
+
+ public long getLong(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).longValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Long.valueOf(String.valueOf(o));
+ }
+
+ public long getLong(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).longValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Long.valueOf(String.valueOf(o));
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return metadata;
+ }
+
+ public Object getObject(int column, Map<String, Class<?>> mapping) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public Object getObject(int column) throws SQLException {
+ return (Object)getInternalValue(cursorPosition,column);
+ }
+
+ public Object getObject(String column, Map<String, Class<?>> mapping) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public Object getObject(String column) throws SQLException {
+ return (Object)getInternalValue(cursorPosition,column);
+ }
+
+ public Ref getRef(int column) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public Ref getRef(String column) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public int getRow() throws SQLException {
+ return (cursorPosition > BEFOREFIRST && cursorPosition < AFTERLAST) ? cursorPosition : 0;
+ }
+
+ public short getShort(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).shortValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (short)1 : (short)0 ;
+ } else return Short.valueOf(String.valueOf(o));
+ }
+
+ public short getShort(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).shortValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (short)1 : (short)0 ;
+ } else return Short.valueOf(String.valueOf(o));
+ }
+
+ public Statement getStatement() throws SQLException {
+ return null;
+ }
+
+ public String getString(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ return (o == null) ? null : String.valueOf(o);
+ }
+
+ public String getString(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ return (o == null) ? null : String.valueOf(o);
+ }
+
+ public Time getTime(int column, Calendar cal) throws SQLException {
+ return (Time)getInternalValue(cursorPosition,column);
+ }
+
+ public Time getTime(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Time) return (Time)o;
+ if (o instanceof java.util.Date)
+ return new Time(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Time(((Calendar)o).getTimeInMillis());
+ return Time.valueOf(String.valueOf(o));
+ }
+
+ public Time getTime(String column, Calendar cal) throws SQLException {
+ return (Time)getInternalValue(cursorPosition,column);
+ }
+
+ public Time getTime(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Time) return (Time)o;
+ if (o instanceof java.util.Date)
+ return new Time(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Time(((Calendar)o).getTimeInMillis());
+ return Time.valueOf(String.valueOf(o));
+ }
+
+ public Timestamp getTimestamp(int column, Calendar cal) throws SQLException {
+ return (Timestamp)getInternalValue(cursorPosition,column);
+ }
+
+ public Timestamp getTimestamp(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Timestamp) return (Timestamp)o;
+ if (o instanceof java.util.Date)
+ return new Timestamp(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Timestamp(((Calendar)o).getTimeInMillis());
+ return Timestamp.valueOf(String.valueOf(o));
+ }
+
+ public Timestamp getTimestamp(String column, Calendar cal) throws SQLException {
+ return (Timestamp)getInternalValue(cursorPosition,column);
+ }
+
+ public Timestamp getTimestamp(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Timestamp) return (Timestamp)o;
+ if (o instanceof java.util.Date)
+ return new Timestamp(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Timestamp(((Calendar)o).getTimeInMillis());
+ return Timestamp.valueOf(String.valueOf(o));
+ }
+
+ public int getType() throws SQLException {
+ return TYPE_SCROLL_INSENSITIVE;
+ }
+
+ public InputStream getUnicodeStream(int column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getUnicodeStream(String column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public URL getURL(int column) throws SQLException {
+ return (URL)getInternalValue(cursorPosition,column);
+ }
+
+ public URL getURL(String column) throws SQLException {
+ return (URL)getInternalValue(cursorPosition,column);
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void insertRow() throws SQLException {
+ if (!insertRow) throw new SQLException("Cannot insert any row except the insert row.");
+ // TODO: Add logic to check nullability.
+
+ }
+
+ public boolean isAfterLast() throws SQLException {
+ return cursorPosition >= AFTERLAST;
+ }
+
+ public boolean isBeforeFirst() throws SQLException {
+ return cursorPosition <= BEFOREFIRST;
+ }
+
+ public boolean isFirst() throws SQLException {
+ return data.size() > 0 && !insertRow && cursorPosition == BEFOREFIRST + 1;
+ }
+
+ public boolean isLast() throws SQLException {
+ return data.size() > 0 && !insertRow && cursorPosition == AFTERLAST - 1;
+ }
+
+ public boolean last() throws SQLException {
+ return absolute(-1);
+ }
+
+ public void moveToCurrentRow() throws SQLException {
+ insertRow = false;
+ }
+
+ public void moveToInsertRow() throws SQLException {
+ insertRow = true;
+ }
+
+ public boolean next() throws SQLException {
+ return relative(1);
+ }
+
+ public boolean previous() throws SQLException {
+ return relative(-1);
+ }
+
+ public void refreshRow() throws SQLException {
+ // TODO: blow away update row
+
+ }
+
+ public boolean relative(int offset) throws SQLException {
+ return absolute(cursorPosition+offset);
+ }
+
+ public boolean rowDeleted() throws SQLException {
+ // TODO: Possibly implement deletion detection
+ return false;
+ }
+
+ public boolean rowInserted() throws SQLException {
+ // TODO: Possibly implement insertion detection
+ return false;
+ }
+
+ public boolean rowUpdated() throws SQLException {
+ // TODO: Possibly implement update detection.
+ return false;
+ }
+
+ public void setFetchDirection(int direction) throws SQLException {
+ this.fetchDirection = direction;
+ }
+
+ public void setFetchSize(int rows) throws SQLException {
+ if (rows < 0 || (this.statement != null && rows > statement.getMaxRows()))
+ throw new SQLException("Fetch size less than zero or greater than statement's maximum rows.");
+ else this.fetchSize = rows;
+ }
+
+ public void updateArray(int column, Array x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateArray(String column, Array x) throws SQLException {
+ updateArray(findColumn(column),x);
+ }
+
+ public void updateAsciiStream(int column, InputStream x, int length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateAsciiStream(String column, InputStream x, int length) throws SQLException {
+ updateAsciiStream(findColumn(column),x,length);
+ }
+
+ public void updateBigDecimal(int column, BigDecimal x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBigDecimal(String column, BigDecimal x) throws SQLException {
+ updateBigDecimal(findColumn(column),x);
+ }
+
+ public void updateBinaryStream(int column, InputStream x, int length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBinaryStream(String column, InputStream x, int length) throws SQLException {
+ updateBinaryStream(findColumn(column),x,length);
+ }
+
+ public void updateBlob(int column, Blob x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBlob(String column, Blob x) throws SQLException {
+ updateBlob(findColumn(column),x);
+ }
+
+ public void updateBoolean(int column, boolean x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBoolean(String column, boolean x) throws SQLException {
+ updateBoolean(findColumn(column),x);
+ }
+
+ public void updateByte(int column, byte x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateByte(String column, byte x) throws SQLException {
+ updateByte(findColumn(column),x);
+ }
+
+ public void updateBytes(int column, byte[] x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBytes(String column, byte[] x) throws SQLException {
+ updateBytes(findColumn(column),x);
+ }
+
+ public void updateCharacterStream(int column, Reader x, int length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateCharacterStream(String column, Reader reader, int length) throws SQLException {
+ updateCharacterStream(findColumn(column),reader,length);
+ }
+
+ public void updateClob(int column, Clob x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateClob(String column, Clob x) throws SQLException {
+ updateClob(findColumn(column),x);
+ }
+
+ public void updateDate(int column, Date x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateDate(String column, Date x) throws SQLException {
+ updateDate(findColumn(column),x);
+ }
+
+ public void updateDouble(int column, double x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateDouble(String column, double x) throws SQLException {
+ updateDouble(findColumn(column),x);
+ }
+
+ public void updateFloat(int column, float x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateFloat(String column, float x) throws SQLException {
+ updateFloat(findColumn(column),x);
+ }
+
+ public void updateInt(int column, int x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateInt(String column, int x) throws SQLException {
+ updateInt(findColumn(column),x);
+ }
+
+ public void updateLong(int column, long x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateLong(String column, long x) throws SQLException {
+ updateLong(findColumn(column),x);
+ }
+
+ public void updateNull(int column) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateNull(String column) throws SQLException {
+ updateNull(findColumn(column));
+ }
+
+ public void updateObject(int column, Object x, int scale) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateObject(int column, Object x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateObject(String column, Object x, int scale) throws SQLException {
+ updateObject(findColumn(column),x,scale);
+ }
+
+ public void updateObject(String column, Object x) throws SQLException {
+ updateObject(findColumn(column),x);
+ }
+
+ public void updateRef(int column, Ref x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateRef(String column, Ref x) throws SQLException {
+ updateRef(findColumn(column),x);
+ }
+
+ public void updateRow() throws SQLException {
+ // TODO: Implement update call.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void updateShort(int column, short x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateShort(String column, short x) throws SQLException {
+ updateShort(findColumn(column),x);
+ }
+
+ public void updateString(int column, String x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateString(String column, String x) throws SQLException {
+ updateString(findColumn(column),x);
+ }
+
+ public void updateTime(int column, Time x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateTime(String column, Time x) throws SQLException {
+ updateTime(findColumn(column),x);
+ }
+
+ public void updateTimestamp(int column, Timestamp x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateTimestamp(String column, Timestamp x) throws SQLException {
+ updateTimestamp(findColumn(column),x);
+ }
+
+ public boolean wasNull() throws SQLException {
+ // TODO: Implement very awkward wasNull() method.
+ return false;
+ }
+
+
+ class MockBlob implements Blob {
+
+ private byte[] bytes;
+
+ public MockBlob(byte[] bytes) {
+ this.bytes=bytes;
+ }
+
+ public InputStream getBinaryStream() throws SQLException {
+ // TODO Implement getBinaryStream()
+ return null;
+ }
+
+ public byte[] getBytes(long pos, int length) throws SQLException {
+ // TODO Implement getBinaryStream()
+ if (false) bytes.hashCode();
+ return null;
+ }
+
+ public long length() throws SQLException {
+ // TODO Implement length()
+ return 0;
+ }
+
+ public long position(Blob pattern, long start) throws SQLException {
+ // TODO Implement position(Blob,long)
+ return 0;
+ }
+
+ public long position(byte[] pattern, long start) throws SQLException {
+ // TODO Implement position(byte[],long)
+ return 0;
+ }
+
+ public OutputStream setBinaryStream(long pos) throws SQLException {
+ // TODO Implement setBinaryStream(long)
+ return null;
+ }
+
+ public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {
+ // TODO Implement setBytes(long,byte[],int,int)
+ return 0;
+ }
+
+ public int setBytes(long pos, byte[] bytes) throws SQLException {
+ // TODO Implement setBytes(long,byte[])
+ return 0;
+ }
+
+ public void truncate(long len) throws SQLException {
+ // TODO Implement truncate(long)
+ }
+
+ @Override
+ public void free() throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public InputStream getBinaryStream(long pos, long length) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ }
+
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public RowId getRowId(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public RowId getRowId(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void updateRowId(int columnIndex, RowId x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateRowId(String columnLabel, RowId x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void updateNString(int columnIndex, String nString) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNString(String columnLabel, String nString) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public NClob getNClob(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public NClob getNClob(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public SQLXML getSQLXML(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public SQLXML getSQLXML(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getNString(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getNString(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Reader getNCharacterStream(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Reader getNCharacterStream(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ };
+
+}
diff --git a/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java
new file mode 100644
index 0000000..2a6b67c
--- /dev/null
+++ b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSetMetaData.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.math.BigDecimal;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * An implementation of DatabaseMetaData that partners with ResultSet to
+ * provide database-disconnected fixed results for testing via the JDBC
+ * APIs.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class MockResultSetMetaData implements ResultSetMetaData {
+
+ public static int ZERO_ORDER_LIST_OFFSET = 1;
+ List<ColSpec> columns;
+
+ MockResultSetMetaData(String ... columns) {
+ if (columns == null) throw new IllegalArgumentException("Cannot construct a MockResultSet with no columns.");
+ ColSpec[] colspecs = new ColSpec[columns.length];
+ for (int i = 0 ; i < columns.length ; i++) {
+ colspecs[i] = new ColSpec(columns[i]);
+ }
+ prepColumns(colspecs);
+ }
+
+ MockResultSetMetaData(ColSpec ... columns) {
+ prepColumns(columns);
+ }
+
+ private void prepColumns(ColSpec ... columns) {
+ if (columns == null || columns.length <= 0)
+ throw new IllegalArgumentException("Cannot construct a MockResultSet with no columns.");
+ this.columns = new ArrayList<ColSpec>(Arrays.asList(columns));
+ }
+
+ public void finalize() throws Throwable {
+ columns = null;
+ }
+
+ /**
+ * Given a column name, this method returns the number of the column, or 0 if
+ * no such column exists.
+ *
+ * @param name
+ * @return
+ */
+ public int getColumnNumber(String name) {
+ for (int i = 1; i <= columns.size(); i++)
+ if (columns.get(i-ZERO_ORDER_LIST_OFFSET).name.equalsIgnoreCase(name)) return i;
+ return 0;
+ }
+
+ public String getCatalogName(int column) throws SQLException {
+ return "";
+ }
+
+ public String getColumnClassName(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getColumnCount() throws SQLException {
+ return columns.size();
+ }
+
+ public int getColumnDisplaySize(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).width;
+ }
+
+ public String getColumnLabel(int column) throws SQLException {
+ if (column < 1) throw new IllegalArgumentException("Column number must be greater than 0.");
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).name;
+ }
+
+ public String getColumnName(int column) throws SQLException {
+ if (column < 1) throw new IllegalArgumentException("Column number must be greater than 0.");
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).name;
+ }
+
+ public int getColumnType(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).type.sqltype;
+ }
+
+ public String getColumnTypeName(int column) throws SQLException {
+ return columns.get(column).type.name();
+ }
+
+ public int getPrecision(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).precision;
+ }
+
+ public int getScale(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).scale;
+ }
+
+ public String getSchemaName(int column) throws SQLException {
+ return "";
+ }
+
+ public String getTableName(int column) throws SQLException {
+ return "";
+ }
+
+ public boolean isAutoIncrement(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isCaseSensitive(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isCurrency(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isDefinitelyWritable(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int isNullable(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).nullable ? ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls;
+ }
+
+ public boolean isReadOnly(int column) throws SQLException {
+ return true;
+ }
+
+ public boolean isSearchable(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public boolean isSigned(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isWritable(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public static class ColSpec {
+ public final String name;
+ public final DBType type;
+ public final int width;
+ public final int precision;
+ public final int scale;
+ public final boolean nullable;
+
+ public ColSpec(String name) {
+ this.name = name;
+ this.type = DBType.OBJECT;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, boolean nullable) {
+ this.name = name;
+ this.type = DBType.OBJECT;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = nullable;
+ }
+ public ColSpec(String name, DBType type) {
+ this.name = name;
+ this.type = type;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, DBType type, boolean nullable) {
+ this.name = name;
+ this.type = type;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = nullable;
+ }
+ public ColSpec(String name, DBType type, int width) {
+ this.name = name;
+ this.type = type;
+ this.width = width;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, DBType type, int precision, int scale) {
+ this.name = name;
+ this.type = type;
+ this.precision = precision;
+ this.scale = scale;
+ this.width = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, DBType type, int width, boolean nullable) {
+ this.name = name;
+ this.type = type;
+ this.width = width;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = nullable;
+ }
+ public ColSpec(String name, DBType type, int precision, int scale, boolean nullable) {
+ this.name = name;
+ this.type = type;
+ this.precision = precision;
+ this.scale = scale;
+ this.width = 0;
+ this.nullable = nullable;
+ }
+ }
+
+ public enum DBTypeGroup {
+ Time(0), Number(1), String(2), Complex(3), Other(4);
+ public int value;
+ private DBTypeGroup(int i) {
+ value = i;
+ }
+ }
+
+ public enum DBType {
+ BLOB(byte[].class,Types.BLOB,DBTypeGroup.Other),
+ BIT(boolean.class,Types.BIT,DBTypeGroup.Number),
+ CHAR(char.class,Types.CHAR,DBTypeGroup.Number),
+ DECIMAL(BigDecimal.class,Types.DECIMAL,DBTypeGroup.Number),
+ FLOAT(float.class,Types.FLOAT,DBTypeGroup.Number),
+ DOUBLE(double.class,Types.DOUBLE,DBTypeGroup.Number),
+ SHORT(short.class,Types.SMALLINT,DBTypeGroup.Number),
+ INTEGER(int.class,Types.INTEGER,DBTypeGroup.Number),
+ LONG(long.class,Types.BIGINT,DBTypeGroup.Number),
+ BYTE(byte.class,Types.TINYINT,DBTypeGroup.Number),
+ STRING(String.class,Types.VARCHAR,DBTypeGroup.String),
+ TIMESTAMP(Timestamp.class,Types.TIMESTAMP,DBTypeGroup.Time),
+ OBJECT(Object.class,Types.JAVA_OBJECT,DBTypeGroup.Complex);
+
+ public final Class<?> javaClass;
+ public final int sqltype;
+ public final DBTypeGroup group;
+ private DBType(Class<?> javaClass, int sqltype, DBTypeGroup group) {
+ this.javaClass = javaClass;
+ this.sqltype = sqltype;
+ this.group = group;
+ }
+ public static DBType valueOf(int sqlType) {
+ switch (sqlType) {
+ case Types.BLOB:
+ case Types.CLOB:
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY: return DBType.BLOB;
+
+ case Types.BIGINT: return DBType.LONG;
+
+ case Types.BOOLEAN:
+ case Types.BIT: return DBType.BIT;
+
+ case Types.CHAR: return DBType.CHAR;
+ case Types.DOUBLE: return DBType.DOUBLE;
+ case Types.FLOAT: return DBType.FLOAT;
+ case Types.INTEGER: return DBType.INTEGER;
+ case Types.SMALLINT: return DBType.SHORT;
+ case Types.TINYINT: return DBType.BYTE;
+
+ case Types.NUMERIC:
+ case Types.REAL:
+ case Types.DECIMAL: return DBType.DECIMAL;
+
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR: return DBType.STRING;
+
+ case Types.DATE:
+ case Types.TIME:
+ case Types.TIMESTAMP: return DBType.TIMESTAMP;
+
+ case Types.JAVA_OBJECT:
+ case Types.ARRAY:
+ case Types.STRUCT: return DBType.OBJECT;
+
+ case Types.REF:
+ case Types.DISTINCT:
+ case Types.NULL:
+ case Types.OTHER:
+ case Types.DATALINK:
+ default:
+ throw new IllegalArgumentException("Unsupported JDBC type");
+ }
+
+ }
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
diff --git a/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java
new file mode 100644
index 0000000..e48e342
--- /dev/null
+++ b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Row.java 27 2006-02-13 19:40:43Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * An object representing row data in a MockResultSet.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class Row {
+
+ MockResultSetMetaData metadata = null;
+ List<Object> data;
+
+ int cursorPosition;
+ final boolean insertRow;
+ public boolean dirty = true;
+
+ public Row(MockResultSetMetaData metadata, List<Object> rowData) {
+ this(metadata,rowData,false);
+ }
+
+ public Row(MockResultSetMetaData metadata, List<Object> rowData, boolean isInsertRow) {
+ this.metadata = metadata;
+ this.data = rowData;
+ this.insertRow = isInsertRow;
+ this.dirty = false;
+ }
+
+ public void finalize() throws Throwable {
+ data = null;
+ metadata = null;
+ super.finalize();
+ }
+
+ public void validateColumn(int i) throws SQLException {
+ if (i <= 0 || i > metadata.columns.size()) throw new SQLException("No such column #" + i);
+ }
+
+ public List<Object> getData() { return data; }
+
+ public Object get(int i) throws SQLException {
+ validateColumn(i);
+ return data.get(i-1);
+ }
+
+ public Object get(String columnName) throws SQLException {
+ return get(metadata.getColumnNumber(columnName));
+ }
+
+ public void set(int i,Object o) throws SQLException {
+ validateColumn(i);
+ data.set(i-1,o);
+ dirty = true;
+ }
+
+ public void set(String columnName,Object o) throws SQLException {
+ set(metadata.getColumnNumber(columnName),o);
+ }
+
+ public boolean isDirty() {
+ return dirty;
+ }
+}
diff --git a/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java
new file mode 100644
index 0000000..8a2d7c8
--- /dev/null
+++ b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSetMetaDataTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.sql.SQLException;
+
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.ColSpec;
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.DBType;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+public class MockResultSetMetaDataTest {
+
+
+ public MockResultSetMetaDataTest() {
+ super();
+ }
+
+ @Test
+ public void testResultSetMetaDataCreation() throws SQLException {
+ String colA = "colA", colB = "colB", colC = "colC";
+ String[] cols = { colA, colB, colC };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(cols);
+ Assert.assertEquals(3,rsmd.getColumnCount());
+ Assert.assertEquals(colA,rsmd.getColumnName(1));
+ Assert.assertEquals(colB,rsmd.getColumnName(2));
+ Assert.assertEquals(colC,rsmd.getColumnName(3));
+ }
+
+ @Test
+ public void testResultSetMetaDataColumnReferencing() throws SQLException {
+ String colA = "colA", colB = "colB", colC = "colC";
+ String[] cols = { colA, colB, colC };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(cols);
+
+ Assert.assertEquals(3,rsmd.getColumnCount());
+
+ Assert.assertEquals(colA,rsmd.getColumnName(1));
+ Assert.assertEquals(colB,rsmd.getColumnName(2));
+ Assert.assertEquals(colC,rsmd.getColumnName(3));
+
+ Assert.assertEquals(1,rsmd.getColumnNumber(colA));
+ Assert.assertEquals(2,rsmd.getColumnNumber(colB));
+ Assert.assertEquals(3,rsmd.getColumnNumber(colC));
+ }
+
+ @Test
+ public void testResultSetMetaDataCreationWithColDefs() throws SQLException {
+ ColSpec colA = new ColSpec("colA", DBType.STRING, 12 );
+ ColSpec colB = new ColSpec("colB", DBType.INTEGER, 5, 0 );
+ ColSpec colC = new ColSpec("colC", DBType.DECIMAL, 3, 5, false);
+ ColSpec colD = new ColSpec("colD", DBType.STRING, 4, false);
+ ColSpec[] cols = { colA, colB, colC, colD };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(cols);
+ Assert.assertEquals(4,rsmd.getColumnCount());
+
+ Assert.assertEquals(colA.name,rsmd.getColumnName(1));
+ Assert.assertEquals(colB.name,rsmd.getColumnName(2));
+ Assert.assertEquals(colC.name,rsmd.getColumnName(3));
+ Assert.assertEquals(colD.name,rsmd.getColumnName(4));
+
+ Assert.assertEquals(colA.type.sqltype,rsmd.getColumnType(1));
+ Assert.assertEquals(colB.type.sqltype,rsmd.getColumnType(2));
+ Assert.assertEquals(colC.type.sqltype,rsmd.getColumnType(3));
+ Assert.assertEquals(colD.type.sqltype,rsmd.getColumnType(4));
+
+ Assert.assertEquals(colA.width,rsmd.getColumnDisplaySize(1));
+ Assert.assertEquals(colB.precision,rsmd.getPrecision(2));
+ Assert.assertEquals(colB.scale,rsmd.getScale(2));
+ Assert.assertEquals(colC.precision,rsmd.getPrecision(3));
+ Assert.assertEquals(colC.scale,rsmd.getScale(3));
+ Assert.assertEquals(colD.width,rsmd.getColumnDisplaySize(4));
+ }
+
+}
diff --git a/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java
new file mode 100644
index 0000000..7dfcbcb
--- /dev/null
+++ b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java
@@ -0,0 +1,263 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSetTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Ref;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.ColSpec;
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.DBType;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+public class MockResultSetTest {
+
+ ColSpec colA, colB, colC, colD, colE,
+ colF, colG, colH, colI, colJ,
+ colK;
+ ColSpec[] cols;
+ Object[][] data;
+ MockResultSet mrs;
+
+ public MockResultSetTest() {
+ super();
+ }
+
+ @SuppressWarnings("deprecation")
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ colA = new ColSpec("colA", DBType.STRING, 12 );
+ colB = new ColSpec("colB", DBType.INTEGER);
+ colC = new ColSpec("colC", DBType.SHORT);
+ colD = new ColSpec("colD", DBType.LONG);
+ colE = new ColSpec("colE", DBType.BIT);
+ colF = new ColSpec("colF", DBType.BYTE);
+ colG = new ColSpec("colG", DBType.FLOAT);
+ colH = new ColSpec("colH", DBType.DOUBLE);
+ colI = new ColSpec("colI", DBType.DECIMAL, 3, 5, false);
+ colJ = new ColSpec("colJ", DBType.TIMESTAMP,true);
+ colK = new ColSpec("colK", DBType.OBJECT);
+ cols = new ColSpec[]{ colA, colB, colC, colD, colE};
+
+ data = new Object[][] {
+ { "str1", 254, (short)355, 921124432352L,
+ true, 0x44, 3.1415f, 9.994d,
+ new BigDecimal(4.45), Calendar.getInstance(), null },
+ { "str2", -922, (short)9283, 1910382394511L,
+ true, 0x94, null, -0.994d,
+ new BigDecimal(-229444.452322), new Date(2005,04,02), colE },
+ { null, 011, (short)4242, 4992830402903L,
+ false, 0x4a, 9.95d, 0.0d,
+ new BigDecimal(0.0), null, null },
+ };
+
+ mrs = new MockResultSet(cols,data);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ colA = colB = colC = colD = colE = null;
+ data = null;
+ mrs = null;
+ }
+
+ /** Should simply not throw an exception */
+ @Test
+ public void testResultSetCreationWithStrings() throws SQLException {
+ String[] cols2 = { "colA", "colB", "colC" };
+ mrs = new MockResultSet(cols2,data);
+ List<Row> dataMap = mrs.getData();
+ for (int i = 0; i < data.length ; i++) {
+ Row row = dataMap.get(i);
+ Assert.assertEquals(data[i][0], row.get("colA"));
+ Assert.assertEquals(data[i][1], row.get("colB"));
+ Assert.assertEquals(data[i][2], row.get("colC"));
+ }
+ }
+
+ @Test
+ public void testResultSetCreationWithNull() throws SQLException {
+ mrs = new MockResultSet(cols,null);
+ Assert.assertEquals(0,mrs.getData().size());
+ }
+
+ @Test
+ public void testResultSetAbsoluteNavigation() throws SQLException {
+ Assert.assertFalse(mrs.absolute(0));
+ Assert.assertTrue(mrs.absolute(1));
+ Assert.assertTrue(mrs.absolute(2));
+ Assert.assertTrue(mrs.absolute(3));
+ Assert.assertFalse(mrs.absolute(4));
+ Assert.assertFalse(mrs.absolute(5));
+
+ Assert.assertTrue(mrs.absolute(-1));
+ Assert.assertEquals(3,mrs.getRow());
+ Assert.assertTrue(mrs.absolute(-2));
+ Assert.assertEquals(2,mrs.getRow());
+ Assert.assertTrue(mrs.absolute(-3));
+ Assert.assertEquals(1,mrs.getRow());
+ Assert.assertFalse(mrs.absolute(-4));
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertFalse(mrs.absolute(-5));
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertTrue(mrs.isBeforeFirst());
+
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertFalse(mrs.isAfterLast());
+ mrs.first();
+ Assert.assertEquals(1,mrs.getRow());
+ Assert.assertFalse(mrs.isBeforeFirst());
+ Assert.assertFalse(mrs.isAfterLast());
+ mrs.last();
+ Assert.assertEquals(3,mrs.getRow());
+ Assert.assertFalse(mrs.isBeforeFirst());
+ Assert.assertFalse(mrs.isAfterLast());
+ mrs.afterLast();
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertFalse(mrs.isBeforeFirst());
+ Assert.assertTrue(mrs.isAfterLast());
+ }
+
+ @Test
+ public void testResultSetRelativeNavigation() throws SQLException {
+ mrs.beforeFirst();
+ Assert.assertTrue(mrs.isBeforeFirst());
+ Assert.assertTrue(mrs.next());
+ Assert.assertTrue(mrs.next());
+ Assert.assertTrue(mrs.next());
+ Assert.assertFalse(mrs.next());
+ Assert.assertTrue(mrs.isAfterLast());
+ Assert.assertTrue(mrs.previous());
+ Assert.assertTrue(mrs.previous());
+ Assert.assertTrue(mrs.previous());
+ Assert.assertFalse(mrs.previous());
+ Assert.assertTrue(mrs.isBeforeFirst());
+ }
+
+
+
+ /**
+ * Test each group of accessors depending on the type.
+ */
+ @Test
+ public void testResultSetGetOperations() throws Throwable {
+ String[] ptypes = { "java.lang.String", "int" };
+ Class<?>[][] classes = {
+ { Timestamp.class, Time.class, Date.class },
+ { short.class, long.class, int.class, float.class,
+ double.class, BigDecimal.class, boolean.class, byte.class },
+ { String.class },
+ { Object.class },
+ { byte[].class, Reader.class, Clob.class, Ref.class,
+ InputStream.class, InputStream.class, Array.class, Blob.class }
+ };
+ String[][] props = { { "Timestamp", "Time", "Date" },
+ { "Short", "Long", "Int", "Float",
+ "Double", "BigDecimal", "Boolean", "Byte" },
+ { "String" },
+ { "Object" },
+ { "Bytes", "CharacterStream", "Clob", "Ref",
+ "BinaryStream", "AsciiStream", "Array", "Blob" } };
+ mrs.beforeFirst();
+ System.out.println("Count:"+props.length);
+ while(mrs.next()) {
+ for (int colNo = 0 ; colNo < cols.length ; colNo++) {
+ ColSpec col = cols[colNo];
+ for (int i = 0; i < props[col.type.group.value].length ; i++) {
+ for (String ptype : ptypes) { // try both int and string column access
+ //System.out.println(col.name + ":col.type.group=" + col.type.group + "(" + col.type.group.value + ")" + ":method=get" + props[col.type.group.value][i] + "(" + ptype + "):data=" + data[mrs.getRow()-1][colNo] );
+ try {
+ // Do this the unsafe way so we don't use DynamicUtil and can avoid the dependency.
+ Method m = mrs.getClass().getMethod("get"+props[col.type.group.value][i],new Class[] { String.class });
+ Object obj = m.invoke(mrs, col.name );
+
+ Class<?> expectedClass = _boxedTypeEquivalents
+ .containsKey(classes[col.type.group.value][i]) ?
+ _boxedTypeEquivalents.get(classes[col.type.group.value][i]) :
+ classes[col.type.group.value][i];
+ Assert.assertEquals(expectedClass,obj.getClass());
+ Assert.assertTrue(expectedClass.isAssignableFrom(obj.getClass()));
+ } catch (ClassCastException e) {
+ //e.printStackTrace();
+ } catch (RuntimeException e) {
+ if (e.getCause() != null && !e.getCause().getClass().equals(ClassCastException.class)) throw e;
+ }
+
+ }
+ }
+ }
+ }
+ }
+ static Map<Class<?>, Class<?>> _boxedTypeEquivalents = new HashMap<Class<?>, Class<?>>();
+ static {
+ _boxedTypeEquivalents.put(boolean.class,Boolean.class);
+ _boxedTypeEquivalents.put(int.class,Integer.class);
+ _boxedTypeEquivalents.put(long.class,Long.class);
+ _boxedTypeEquivalents.put(short.class,Short.class);
+ _boxedTypeEquivalents.put(byte.class,Byte.class);
+ _boxedTypeEquivalents.put(char.class,Character.class);
+ _boxedTypeEquivalents.put(double.class,Double.class);
+ _boxedTypeEquivalents.put(float.class,Float.class);
+ }
+
+
+}
+
+
+
+
+
diff --git a/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java
new file mode 100644
index 0000000..215a282
--- /dev/null
+++ b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: RowTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+public class RowTest {
+
+ Row row;
+ String[] columns = { "ColumnA", "ColumnB", "ColumnC" };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(columns);
+ String valc = "Value C";
+ List<Object> data = Arrays.asList(new Object[] {"Value A", "Value B", null});
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ row = new Row(rsmd, data);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ row = null;
+ }
+
+ /* Should simply not throw an exception */
+ public void testSetWithInt() throws SQLException {
+ Assert.assertEquals(null,row.get(3));
+ row.set(3,valc);
+ Assert.assertEquals(valc,row.get(3));
+ }
+
+ /* Should simply not throw an exception */
+ public void testSetWithString() throws SQLException {
+ Assert.assertEquals(null,row.get("ColumnC"));
+ row.set("ColumnC",valc);
+ Assert.assertEquals(valc,row.get("ColumnC"));
+ }
+}
+
+
+
+
+
diff --git a/israfil-foundation-valuemodel/pom.xml b/israfil-foundation-valuemodel/pom.xml
new file mode 100644
index 0000000..13aed6c
--- /dev/null
+++ b/israfil-foundation-valuemodel/pom.xml
@@ -0,0 +1,30 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ </parent>
+ <artifactId>israfil-foundation-valuemodel</artifactId>
+ <name>Israfil Foundation Value Model Classes</name>
+ <description>
+ Classes which implement and support a SmallTalk-style valuemodel architecture.
+ </description>
+ <version>1.0.1-SNAPSHOT</version>
+ <url>http://www.israfil.net/projects/foundation/${artifactId}</url>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>israfil-foundation-dynamic</artifactId>
+ <version>1.0.1</version>
+ </dependency>
+ </dependencies>
+</project> \ No newline at end of file
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java
new file mode 100644
index 0000000..74d4dd1
--- /dev/null
+++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * $Id$
+ * $Revision$
+ *
+ */
+package net.israfil.foundation.valuemodel;
+
+
+/**
+ * A smalltalk-style generic value accessor/mutator system, where individual
+ * items are accessed through a single value
+ *
+ * @author Original: <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Recent: $Author$
+ *
+ */
+public interface MutableValue<E> extends Value<E>, Vetoable {
+
+ public void set(E value);
+
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java
new file mode 100644
index 0000000..574c8cf
--- /dev/null
+++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2003-2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.valuemodel;
+
+/**
+ * An interface for objects that can notify observers of changes to itself. The
+ * changing object should call the provided callback signature, with the
+ * parameter being the object that was changed in its new state.
+ *
+ * Using a dynamic selector rather than a strong interface allows code
+ * to be notified of the change even if it was not constructed with the
+ * notification interface, though it does need to match the signature.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 129 $
+ */
+public interface Observable {
+
+ /** Add an observer to this object, with a callback method spec that will
+ * be invoked upon a data change. The callback method should contain three
+ * object parameters, one for the sender, one for the old value, and one for
+ * the new value. The meaning of the value (same object, copy, values, etc.)
+ * is left to the implementation object and the observers.
+ */
+ public void addObservers(String callback, Object ... observers);
+ /**
+ * Remove observer from observable object.
+ */
+ public void removeObservers(Object ... observers);
+
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java
new file mode 100644
index 0000000..8c545bd
--- /dev/null
+++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * $Id$
+ * $Revision$
+ *
+ */
+package net.israfil.foundation.valuemodel;
+
+/**
+ * A smalltalk-style generic value accessor/mutator system, where individual
+ * items are accessed through a single value
+ *
+ * @author Original: <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Recent: $Author$
+ *
+ */
+public interface Value<E> extends Observable {
+
+ public E get();
+
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java
new file mode 100644
index 0000000..55f23c3
--- /dev/null
+++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java
@@ -0,0 +1,108 @@
+/*
+ * Created on Dec 8, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package net.israfil.foundation.valuemodel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.israfil.foundation.dynamic.DynamicUtil;
+
+
+/**
+ * @author cgruber
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class ValueHolder<E> implements MutableValue<E> {
+
+ private E _value = null;
+ private Map<Integer, ObserverHolder> _observers = new HashMap<Integer, ObserverHolder>();
+ private Map<Integer, VetoerHolder> _vetoers = new HashMap<Integer, VetoerHolder>();
+
+ public ValueHolder(E o) {
+ set(o);
+ }
+
+ protected ValueHolder() { }
+
+ public E get() {
+ return _value;
+ }
+
+ public void set(E newValue) {
+ boolean approved = true;
+ E oldValue = _value;
+ for (VetoerHolder vetoer : _vetoers.values()) {
+ approved &= vetoer.evaluate(this, oldValue, newValue);
+ }
+
+ if (!approved) return;
+ else _value = newValue;
+ for (ObserverHolder observer : _observers.values()) {
+ observer.notify(this, oldValue, newValue);
+ }
+
+ }
+
+ /**
+ * @see org.israfil.maveric.Observable#addObserver(java.lang.Object, java.lang.String)
+ */
+ public void addObservers(String callback, Object ... observers) {
+ for (Object observer : observers) {
+ _observers.put(observer.hashCode(),new ObserverHolder(observer,callback));
+ }
+ }
+
+ /**
+ * @see org.israfil.maveric.Observable#removeObserver(java.lang.Object)
+ */
+ public void removeObservers(Object ... observers) {
+ for (Object observer : observers) {
+ _observers.remove(observer.hashCode());
+ }
+ }
+ /**
+ * @see org.israfil.maveric.Vetoable#addVetoer(java.lang.Object, java.lang.String)
+ */
+ public void addVetoers(String callback, Object ... vetoers) {
+ for (Object vetoer : vetoers) {
+ _vetoers.put(vetoer.hashCode(),new VetoerHolder(vetoer,callback));
+ }
+ }
+
+ /**
+ * @see org.israfil.maveric.Vetoable#removeVetoer(java.lang.Object)
+ */
+ public void removeVetoers(Object ... vetoers) {
+ for (Object vetoer : vetoers) {
+ _vetoers.remove(vetoer.hashCode());
+ }
+ }
+
+ protected class CallbackObjectHolder {
+ public final Object receiver;
+ protected final String callback;
+ public CallbackObjectHolder(Object receiver, String callback) {
+ this.receiver = receiver;
+ this.callback = callback;
+ }
+ }
+ protected class ObserverHolder extends CallbackObjectHolder {
+ public ObserverHolder(Object observer, String callback) { super(observer, callback); }
+ public void notify(Object notifier, Object oldValue, Object newValue) {
+ DynamicUtil.performOn(receiver,callback,new Object[]{notifier, oldValue , newValue});
+ }
+ }
+ protected class VetoerHolder extends CallbackObjectHolder {
+ public VetoerHolder(Object vetoer, String callback) { super(vetoer, callback); }
+ public Boolean evaluate(Object notifier, Object oldValue, Object newValue) {
+ Boolean result = (Boolean)DynamicUtil.performOn(receiver,callback,new Object[]{notifier,oldValue,newValue});
+ return (result == null) ? true : result.booleanValue();
+ }
+ }
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java
new file mode 100644
index 0000000..5369287
--- /dev/null
+++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2003-2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.valuemodel;
+
+/**
+ * An interface for objects that can notify observers of changes to itself
+ * before the change. The objects thus notified can veto the change. The
+ * specific behaviour for vetoing is undefined and is dependent upon the
+ * particular implementation of the vetoable object and its vetoers.
+ * The changing object should call the provided callback signature, with the
+ * parameter being the object that was changed in its new state. The vetoer
+ * is responsible for knowing what it needs to know in order to validate or
+ * veto the change.
+ *
+ * Using a dynamic selector rather than a strong interface allows code
+ * to be notified of the change even if it was not constructed with the
+ * notification interface, though it does need to match the signature.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 129 $
+ */
+public interface Vetoable {
+
+ /** Add one or more vetoers to this object, with a callback method spec
+ * that will be invoked upon a data change. The callback method should
+ * contain three parameters. The first is the notification source (the
+ * holder or whatever), the second the old value, and the third the new
+ * value. It also should return a boolean approving the change (or
+ * returning false to veto it)
+ */
+ public void addVetoers(String callback, Object ... approvers);
+
+ /**
+ * Remove one or more vetoers from vetoable object.
+ */
+ public void removeVetoers(Object ... approvers);
+
+}
diff --git a/israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java b/israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java
new file mode 100644
index 0000000..271c4a0
--- /dev/null
+++ b/israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2003-2008Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.valuemodel;
+
+import net.israfil.foundation.core.Copyright;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for ValueHolder
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 129 $
+ */
+@Copyright(years={"2003","2004","2005","2006","2007","2008"},owner="Israfil Consulting Services Corporation",license="BSD")
+@Test
+public class ValueHolderTest {
+
+ private String stringValue = null;
+ private Integer integerValue = null;
+ private ValueHolder<String> stringValueHolder = null;
+ private ValueHolder<Integer> integerValueHolder = null;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ stringValue = "String Value";
+ integerValue = new Integer(5);
+ stringValueHolder = new ValueHolder<String>(stringValue);
+ integerValueHolder = new ValueHolder<Integer>(integerValue);
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ stringValue = null;
+ integerValue = null;
+ stringValueHolder = null;
+ integerValueHolder = null;
+ }
+
+ /*
+ * Test for void ValueHolder(Object)
+ */
+ public void testValueHolderObject() {
+ String valueString = "Value";
+ ValueHolder<String>valueHolder = new ValueHolder<String>(valueString);
+ Assert.assertEquals(valueString,valueHolder.get());
+ }
+
+ public void testGetValue() {
+ Assert.assertEquals(stringValue,stringValueHolder.get());
+ Assert.assertEquals(integerValue,integerValueHolder.get());
+ }
+
+ public void testSetValueObject() {
+ String stringValue2 = "String Value 2";
+ stringValueHolder.set(stringValue2);
+ Assert.assertEquals(stringValue2,stringValueHolder.get());
+ }
+
+ public void testAddObserverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addObservers("notifyMe:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.set(stringValue2);
+ Assert.assertTrue(callback.notified);
+ }
+ public void testRemoveObserverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addObservers("notifyMe:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.removeObservers(callback);
+ stringValueHolder.set(stringValue2);
+ Assert.assertFalse(callback.notified);
+ }
+ public void testAddApproverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addVetoers("approve:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.set(stringValue2);
+ Assert.assertEquals(stringValue2,stringValueHolder.get());
+
+ callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addVetoers("approve:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.set(stringValue2);
+ stringValueHolder.set(stringValue);
+ Assert.assertEquals(stringValue2,stringValueHolder.get());
+ Assert.assertFalse(stringValue.equals(stringValueHolder.get()));
+ }
+ public void testRemoveApproverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addVetoers("approve:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.removeVetoers(callback);
+ stringValueHolder.set(stringValue2);
+ stringValueHolder.set(stringValue);
+ Assert.assertEquals(stringValue,stringValueHolder.get());
+ Assert.assertFalse(stringValue2.equals(stringValueHolder.get()));
+ }
+ public void finalize() throws Throwable {
+ stringValue = null;
+ integerValue = null;
+ stringValueHolder = null;
+ integerValueHolder = null;
+ super.finalize();
+ }
+
+ public class CallbackObject<E> {
+ private final MutableValue<E> valueModel;
+ public boolean notified = false;
+ public Object oldValue = null;
+ public Object newValue = null;
+ public CallbackObject(MutableValue<E> valueModel) {
+ this.valueModel = valueModel;
+ }
+ public void notifyMe(Object sender, Object oldValue, Object newValue) {
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ Assert.assertEquals(this.valueModel,sender);
+ notified = true;
+ }
+ public boolean approve(Object sender, Object oldValue, Object newValue) {
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ Assert.assertEquals(this.valueModel,sender);
+ if (!newValue.equals(stringValue)) return true;
+ return false;
+ }
+ public void finalize() throws Throwable {
+ this.oldValue = null;
+ this.newValue = null;
+ super.finalize();
+ }
+ }
+}
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..fdefa44
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,151 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>net.israfil.foundation</groupId>
+ <artifactId>israfil-foundation-all</artifactId>
+ <version>5-SNAPSHOT</version>
+ <packaging>pom</packaging>
+ <name>Israfil Foundation: All</name>
+ <description>Foundation Frameworks from Israfil Consulting Services</description>
+ <inceptionYear>2006</inceptionYear>
+ <url>http://www.israfil.net/projects/foundation</url>
+ <modules>
+ <module>israfil-foundation-core</module>
+ <module>israfil-foundation-dynamic</module>
+ <module>israfil-foundation-cache</module>
+ <module>israfil-foundation-collections</module>
+ <module>israfil-foundation-container</module>
+ <module>israfil-foundation-concurrent</module>
+ <module>israfil-foundation-lifecycle</module>
+ <module>israfil-foundation-notification</module>
+ <module>israfil-foundation-testing</module>
+ <module>israfil-foundation-nspace</module>
+ <module>israfil-foundation-valuemodel</module>
+ </modules>
+ <licenses>
+ <license>
+ <name>BSD</name>
+ <distribution>repo</distribution>
+ <url>http://www.israfil.net/israfil-license-bsd.txt</url>
+ <comments>A simple open-source license with minimal restrictions</comments>
+ </license>
+ </licenses>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-release-plugin</artifactId>
+ <configuration>
+ <tagBase>https://israfil-foundation.googlecode.com/svn/tags/RELEASE</tagBase>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <executions>
+ <execution><goals><goal>clean</goal></goals></execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>11</source>
+ <target>11</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>5.7</version>
+ <classifier>jdk15</classifier>
+ <exclusions>
+ <exclusion>
+ <artifactId>junit</artifactId>
+ <groupId>junit</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock</artifactId>
+ <version>2.4.0</version>
+ </dependency>
+ </dependencies>
+ <distributionManagement>
+ <!-- use the following if you're not using a snapshot version. -->
+ <repository>
+ <id>israfil</id>
+ <name>Israfil Deploy</name>
+ <url>scp://repo.israfil.net/var/www/vhosts/repo.israfil.net/htdocs/maven2</url>
+ </repository>
+ <!-- use the following if you ARE using a snapshot version. -->
+ <snapshotRepository>
+ <id>israfil</id>
+ <name>Israfil Snapshot</name>
+ <url>scp://repo.israfil.net/var/www/vhosts/repo.israfil.net/htdocs/maven2-snapshots</url>
+ </snapshotRepository>
+ <site>
+ <id>website</id>
+ <url>scp://projects.israfil.net/var/www/vhosts/projects.israfil.net/htdocs/foundation</url>
+ </site>
+ </distributionManagement>
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>jxr-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>surefire-report-maven-plugin</artifactId>
+ <configuration>
+ <forkMode>always</forkMode>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>taglist-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>jdepend-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>com.google.testability-explorer</groupId>
+ <artifactId>maven2-testability-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <configuration>
+ <xmlOutput>false</xmlOutput>
+ <threshold>Normal</threshold>
+ <effort>Default</effort>
+ <!--
+ <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile>
+ <includeFilterFile>findbugs-include.xml</includeFilterFile>
+ -->
+ <visitors>FindDeadLocalStores,UnreadFields</visitors>
+ <omitVisitors>FindDeadLocalStores,UnreadFields</omitVisitors>
+ <!-- <pluginList>/libs/fb-contrib/fb-contrib-2.8.0.jar</pluginList> -->
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <scm>
+ <connection>scm:svn:http://israfil-foundation.googlecode.com/svn/trunk</connection>
+ <developerConnection>scm:svn:https://israfil-foundation.googlecode.com/svn/trunk</developerConnection>
+ <url>http://israfil-foundation.googlecode.com/svn</url>
+ </scm>
+</project>
diff --git a/tools/scripts/mvn-deploy-files b/tools/scripts/mvn-deploy-files
new file mode 100755
index 0000000..a972753
--- /dev/null
+++ b/tools/scripts/mvn-deploy-files
@@ -0,0 +1,185 @@
+#!/bin/sh
+#
+# Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+# Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+# All Rights Reserved
+#
+# This software is licensed under a Berkeley Standard Distribution license
+# equivalent (BSD license) as defined below:
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+# OF SUCH DAMAGE.
+#
+# $Id$
+#
+
+command=`basename $0`
+
+original_command_line="${@}"
+
+#set -x
+
+function usage () {
+
+ echo "usage: ${command} [-t <type>] [-e <ext>] [--test] -u <repo_url> -g <group_id> -v <version> <file> [<file>...] "
+ echo "Options: -t --type <type> sets the maven 2 packaging type "
+ echo " -e --ext <extension> the file extension (defaults to type) "
+ echo " -u --url <repo_url> the url to the deployment repository "
+ echo " -g --group <group_id> the groupId to which the artifacts will be deployed "
+ echo " -v --version <version> the version to which the artifacts will be deployed "
+ echo " -e --ext <extension> the file extension (defaults to type) "
+ echo " -p --poms <pomsfolder> a folder with poms, structured \${groupId}/\${artifactId}/\${version} "
+ echo " -o --pom-overrides determines whether a discovered pom file will override group/artifact/version "
+ echo " --test run the app without invoking maven, for testing "
+
+}
+
+function validate () {
+ valid="true"
+ echo ""
+
+ if [ ! -n "${files}" ]; then
+ echo "[${command}] No files to deploy." ; valid="false"
+ fi
+
+ if [ "${repository_url}" = "" ]; then
+ echo "[${command}] Missing repository url." ; valid="false"
+ fi
+ if [ "${group_id}" = "" ]; then
+ echo "[${command}] Missing group id." ; valid="false"
+ fi
+ if [ "${version}" = "" ]; then
+ echo "[${command}] Missing version." ; valid="false"
+ fi
+ if [ "${poms_dir}" != "" -a ! -d "${poms_dir}" ]; then
+ echo "[${command}] ${poms_dir} is not a valid directory" ; valid="false"
+ fi
+ if [ "${valid}" = "false" ]; then
+ echo "" ; usage ; exit 1
+ fi
+}
+
+# set initial defaults
+type="jar"
+test="false"
+extension=__DEFAULT__
+repository_url=""
+group_id=""
+version=""
+poms_dir=""
+pom_overrides="false"
+done="false"
+export repository group_id version
+
+# loop through possible commands.
+until [ "${done}" = "true" ]; do
+
+ if [ "${1}" = "-t" -o "${1}" = "--type" ]; then
+ shift
+ type="${1}"
+ shift
+ elif [ "${1}" = "-e" -o "${1}" = "--ext" ]; then
+ shift
+ extension="${1}"
+ shift
+ elif [ "${1}" = "--test" ]; then
+ shift
+ test=true
+ elif [ "${1}" = "-u" -o "${1}" = "--url" ]; then
+ shift
+ repository_url="${1}"
+ shift
+ elif [ "${1}" = "-g" -o "${1}" = "--group" ]; then
+ shift
+ group_id="${1}"
+ shift
+ elif [ "${1}" = "-v" -o "${1}" = "--version" ]; then
+ shift
+ version="${1}"
+ shift
+ elif [ "${1}" = "-p" -o "${1}" = "--poms" ]; then
+ shift
+ poms_dir="${1}"
+ shift
+ elif [ "${1}" = "-o" -o "${1}" = "--pom-overrides" ]; then
+ shift
+ pom_overrides=true
+ else
+ # assume we're into files now.
+ done="true"
+ fi
+
+done
+files=${@}
+
+# Validate whether key variables are set
+validate
+
+# Given validated parameters, attend to any dynamic default settings.
+if [ "${extension}" = "__DEFAULT__" ]; then
+ extension=${type}
+fi
+if [ "${poms_dir}" = "" ]; then
+ poms_dir=.
+fi
+
+
+echo ""
+echo "Deploying ${type} artifacts into repository ${repository_url} with group ${group_id}."
+echo "Deploying files: ${files}"
+echo ""
+
+for file in ${files} ; do
+
+ if [ ! -f "${file}" ]; then
+ echo "" && echo "[${command}] Cannot find file ${file}. Skipping..." && echo ""
+ break;
+ fi
+
+ artifact_id=`basename ${file} .${extension}`
+
+ # two ways to spec, or both.
+ pom_file=${poms_dir}/${group_id}/${artifact_id}/${version}/${artifact_id}-${version}.pom
+ artifact_spec="-DgroupId=${group_id} -DartifactId=${artifact_id} -Dversion=${version} -Dpackaging=${type}"
+
+ echo -n "Deploying artifact: ${group_id}:${artifact_id}:${type}:${version} to ${repository_url}"
+ if [ -f ${pom_file} ]; then
+ echo " with ${pom_file}"
+ pom_arg="-DpomFile=${pom_file}"
+ if [ "${pom_overrides}" = "true" ]; then
+ artifact_spec=""
+ fi
+ fi
+
+
+ cmd="mvn --batch-mode deploy:deploy-file -Durl=${repository_url} ${artifact_spec} -Dfile=${file} ${pom_arg}"
+
+ if [ "${test}" = "true" ]; then
+ echo "cmd: ${cmd}"
+ else
+ ${cmd}
+ fi
+
+done
+
+
diff --git a/tools/scripts/mvn-deploy-wlp92-jars b/tools/scripts/mvn-deploy-wlp92-jars
new file mode 100755
index 0000000..415d825
--- /dev/null
+++ b/tools/scripts/mvn-deploy-wlp92-jars
@@ -0,0 +1,158 @@
+#!/bin/sh
+#
+# Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+# Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+# All Rights Reserved
+#
+# This software is licensed under a Berkeley Standard Distribution license
+# equivalent (BSD license) as defined below:
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+# may be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+# OF SUCH DAMAGE.
+#
+# $Id$
+#
+
+command=`basename $0`
+cmd_dir=`dirname $0`
+
+#set -x
+
+function usage () {
+
+ echo "usage: ${command} [--test]-u <repo_url> -b <bea_home> [-p <poms_folder>] "
+ echo "Options: -u --url <repo_url> the url to the deployment repository "
+ echo " -b --bea-home <bea_home> the BEA_HOME folder "
+ echo " -p --poms <pomsfolder> a folder with poms, structured \${groupId}/\${artifactId}/\${version} "
+ Echo " --test run the app without invoking maven, for testing "
+
+}
+
+function validate () {
+ valid="true"
+ echo ""
+ if [ "${bea_home}" = "" ]; then
+ echo "${command} requires that a bea home folder be given" ; valid="false"
+ elif [ ! -d "${bea_home}" ]; then
+ echo "BEA home folder ${bea_home} is not a valid directory." ; valid="false"
+ fi
+ if [ "${repository_url}" = "" ]; then
+ echo "${command} requires a repository URL" ; valid="false"
+ fi
+ if [ "${poms_dir}" != "" -a ! -d ${poms_dir} ]; then
+ echo "${poms_dir} is not a valid directory" ; valid="false"
+ fi
+ if [ "${valid}" = "false" ]; then
+ echo "" ; usage ; exit 1
+ fi
+}
+
+# loop through possible commands.
+until [ "${done}" = "true" ]; do
+
+ if [ "${1}" = "-b" -o "${1}" = "--bea-home" ]; then
+ shift
+ bea_home="${1}"
+ shift
+ elif [ "${1}" = "-u" -o "${1}" = "--url" ]; then
+ shift
+ repository_url="${1}"
+ shift
+ elif [ "${1}" = "--test" ]; then
+ shift
+ test="true"
+ else
+ # assume we're into files now.
+ done="true"
+ fi
+
+done
+
+
+validate
+
+echo "Installing BEA weblogic portal 9.2 folders from ${bea_home} to ${repository_url}"
+echo ""
+
+function install () {
+ group_id=$1
+ shift
+ if [ "${test}" = "true" ]; then do_test="--test" ; fi
+ ${cmd_dir}/mvn-deploy-files -u ${repository_url} -g ${group_id} -v 9.2 ${do_test} $@
+}
+
+function installFromJ2EELibrary () {
+ j2eeLibrary=$1
+ shift
+ group_id=$1
+ shift
+ if [ "${test}" = "true" ]; then do_test="--test" ; fi
+ curdir=`pwd`
+ tmpdir=`mktemp.exe -d -p ${curdir}`
+ cd ${tmpdir}
+ jar -xf ${curdir}/${j2eeLibrary}
+ ${cmd_dir}/mvn-deploy-files -u ${repository_url} -g ${group_id} -v 9.2 ${do_test} $@
+ cd ${curdir}
+ rm -r ${tmpdir}
+}
+
+
+# Visitor Tools
+cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-tools-visitor-web-lib.war com.bea.weblogic.portal.visitor WEB-INF/lib/*.jar
+
+# The big one.
+cd ${bea_home}/weblogic92/server/lib && install com.bea.weblogic.server weblogic*.jar
+cd ${bea_home}/weblogic92/server/lib && install com.bea.weblogic.server *api.jar
+
+# The workshop stuff - important for ant support.
+cd ${bea_home}/weblogic92/workshop/lib && install com.bea.weblogic.workshop *.jar
+
+# Critical beehive/netui stuff
+cd ${bea_home}/weblogic92/beehive/weblogic-beehive/lib/netui && install com.bea.weblogic.beehive.netui *.jar
+cd ${bea_home}/weblogic92/beehive/weblogic-beehive/lib/controls && install com.bea.weblogic.beehive.controls *.jar
+cd ${bea_home}/weblogic92/beehive/weblogic-beehive/lib/controls/runtime && install com.bea.weblogic.beehive.controls.runtime *.jar
+
+# The portal platform
+cd ${bea_home}/weblogic92/platform/lib/wlp && install com.bea.weblogic.portal.core *.jar
+cd ${bea_home}/weblogic92/platform/lib/p13n && install com.bea.weblogic.portal.p13n *.jar
+cd ${bea_home}/weblogic92/common/deployable-libraries/ && installFromJ2EELibrary p13n-app-lib.ear com.bea.weblogic.portal.p13n APP-INF/lib/*.jar *.jar
+
+# Console and netuix stuff.
+cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.portal.core netuix_servlet.jar
+cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-framework-full-web-lib.war com.bea.weblogic.portal.core WEB-INF/lib/netuix_servlet-full.jar
+cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.portal.core struts-adapter.jar
+cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-framework-full-app-lib.ear com.bea.weblogic.portal.core netuix.jar
+cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.server console.jar
+
+cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-tools-app-lib.ear com.bea.weblogic.portal.core APP-INF/lib/tools-framework.jar APP-INF/lib/wlptools_en.jar
+
+# Taglibs
+cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.server *_taglib.jar
+cd ${bea_home}/weblogic92/portal/lib/netuix/web && install com.bea.weblogic.portal *_taglib.jar
+cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.common.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar
+cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.im.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar
+cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.p13n.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar
+cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.wsrp.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar
+
+
+