From 7c279747beb43c7e88633a6228a155a30e6834f7 Mon Sep 17 00:00:00 2001 From: Benjamin Culkin Date: Mon, 27 May 2024 11:38:33 -0400 Subject: Initial import --- .gitignore | 7 + israfil-foundation-cache/pom.xml | 29 + .../java/net/israfil/foundation/caching/Cache.java | 54 + .../net/israfil/foundation/caching/Fetcher.java | 46 + .../israfil/foundation/caching/FetcherCache.java | 48 + .../israfil/foundation/caching/GenericCache.java | 96 ++ .../foundation/caching/GenericFetcherCache.java | 124 ++ .../israfil/foundation/caching/ObjectFactory.java | 46 + .../foundation/caching/GenericCacheTest.java | 124 ++ israfil-foundation-collections/pom.xml | 29 + .../israfil/foundation/collections/ArraySet.java | 105 ++ .../israfil/foundation/collections/ArrayUtils.java | 113 ++ .../foundation/collections/IterableResultSet.java | 132 ++ .../collections/RandomOrderIterable.java | 72 ++ .../collections/RandomOrderIterator.java | 94 ++ .../foundation/collections/ReciprocalHashMap.java | 202 +++ .../foundation/collections/ReciprocalMap.java | 49 + .../foundation/collections/SoloCollection.java | 66 + .../foundation/collections/ArraySetTest.java | 125 ++ .../foundation/collections/ArrayUtilsTest.java | 107 ++ .../collections/IterableResultSetTest.java | 97 ++ .../collections/RandomOrderIteratorTest.java | 104 ++ .../collections/ReciprocalHashMapTest.java | 70 + .../foundation/collections/SoloCollectionTest.java | 55 + israfil-foundation-concurrent/pom.xml | 28 + .../foundation/concurrent/AbstractGated.java | 64 + .../foundation/concurrent/AbstractPipe.java | 77 ++ .../foundation/concurrent/AbstractPump.java | 82 ++ .../foundation/concurrent/AbstractWorker.java | 212 +++ .../foundation/concurrent/CollectingPump.java | 109 ++ .../foundation/concurrent/ConcurrentConsumer.java | 70 + .../foundation/concurrent/ConcurrentProducer.java | 62 + .../foundation/concurrent/DistributingPump.java | 101 ++ .../net/israfil/foundation/concurrent/Gated.java | 53 + .../foundation/concurrent/OneShotWorker.java | 71 + .../net/israfil/foundation/concurrent/Pipe.java | 50 + .../foundation/concurrent/ProcessingPipe.java | 90 ++ .../israfil/foundation/concurrent/Processor.java | 49 + .../foundation/concurrent/RepeatingWorker.java | 97 ++ .../concurrent/RuntimeInterruptedException.java | 64 + .../israfil/foundation/concurrent/SimplePipe.java | 74 ++ .../israfil/foundation/concurrent/SimplePump.java | 85 ++ .../net/israfil/foundation/concurrent/Worker.java | 104 ++ .../consumers/LoggingStringConsumer.java | 61 + .../concurrent/producers/ReaderStringProducer.java | 79 ++ .../foundation/concurrent/timing/Timeout.java | 68 + .../foundation/concurrent/AbstractWorkerTest.java | 121 ++ .../foundation/concurrent/OneShotWorkerTest.java | 93 ++ .../israfil/foundation/concurrent/PumpTest.java | 218 ++++ .../foundation/concurrent/RepeatingWorkerTest.java | 53 + .../consumers/LoggingStringConsumerTest.java | 81 ++ .../producers/ReaderStringProducerTest.java | 74 ++ israfil-foundation-container/pom.xml | 21 + .../foundation/container/AbstractContainer.java | 98 ++ .../foundation/container/AbstractStartable.java | 55 + .../container/AutoWiringAdaptableContainer.java | 64 + .../foundation/container/AutoWiringAdapter.java | 69 + .../israfil/foundation/container/Container.java | 80 ++ .../DefaultAutoWiringAdaptableContainer.java | 63 + .../foundation/container/DefaultContainer.java | 216 ++++ .../israfil/foundation/container/Startable.java | 57 + .../adapters/AbstractAutoWiringAdapter.java | 62 + .../adapters/IndependentAutoWiringAdapter.java | 64 + .../error/ComponentAlreadyRegisteredError.java | 48 + .../error/CouldNotCreateComponentError.java | 58 + .../container/error/CyclicalDependencyError.java | 48 + .../error/UnsatisfiedDependencyError.java | 48 + .../util/CyclicalReferenceDetectionUtil.java | 62 + .../container/util/NonDuplicateStack.java | 55 + .../src/site/apt/index.apt | 45 + .../src/site/apt/lifecycle.apt | 111 ++ .../src/site/apt/usage.apt | 106 ++ israfil-foundation-container/src/site/site.xml | 20 + .../foundation/container/ContainerTest.java | 150 +++ .../foundation/container/DefaultContainerTest.java | 263 ++++ .../foundation/container/LegacyContainerTest.java | 52 + .../foundation/container/LifecycleTest.java | 154 +++ .../MultiThreadedAutoWiringContainerTest.java | 104 ++ .../container/adapters/AdaptersTest.java | 79 ++ .../error/ComponentAlreadyRegisteredErrorTest.java | 54 + .../error/CouldNotCreateComponentTest.java | 71 + .../error/CyclicalDependencyErrorTest.java | 54 + .../error/UnsatisfiedDependencyErrorTest.java | 54 + .../util/CyclicalDependencyDetectionTest.java | 94 ++ .../container/util/NonDuplicateStackTest.java | 83 ++ israfil-foundation-core/pom.xml | 21 + .../net/israfil/foundation/core/Copyright.java | 59 + .../java/net/israfil/foundation/core/Counter.java | 52 + .../net/israfil/foundation/core/SimpleCounter.java | 54 + .../java/net/israfil/foundation/core/Strings.java | 58 + .../java/net/israfil/foundation/core/Types.java | 195 +++ israfil-foundation-core/src/test/conf/testng.xml | 24 + .../israfil/foundation/core/SimpleCounterTest.java | 61 + .../net/israfil/foundation/core/StringsTest.java | 90 ++ .../foundation/core/TypesFromBooleanTest.java | 91 ++ .../foundation/core/TypesFromNumberTest.java | 49 + .../foundation/core/TypesFromStringTest.java | 131 ++ israfil-foundation-dynamic/pom.xml | 33 + .../net/israfil/foundation/dynamic/Dynamic.java | 62 + .../israfil/foundation/dynamic/DynamicObject.java | 69 + .../israfil/foundation/dynamic/DynamicUtil.java | 297 +++++ .../foundation/dynamic/DynamicallyAccessible.java | 50 + .../dynamic/DynamicallyAccessibleObject.java | 144 +++ .../foundation/dynamic/DynamicallyMutable.java | 54 + .../dynamic/DynamicallyMutableObject.java | 197 +++ .../foundation/dynamic/DynamicObjectTest.java | 120 ++ .../foundation/dynamic/DynamicUtilTest.java | 160 +++ .../dynamic/DynamicallyAccessibleTest.java | 174 +++ .../foundation/dynamic/DynamicallyMutableTest.java | 210 +++ israfil-foundation-lifecycle/pom.xml | 21 + .../net/israfil/foundation/lifecycle/Consumer.java | 51 + .../net/israfil/foundation/lifecycle/Producer.java | 49 + israfil-foundation-notification/pom.xml | 28 + .../foundation/notification/Notification.java | 59 + .../notification/NotificationCentre.java | 200 +++ .../notification/NotificationCentreTest.java | 180 +++ israfil-foundation-nspace/pom.xml | 21 + .../foundation/collections/nspace/Coordinate.java | 56 + .../foundation/collections/nspace/Dimension.java | 36 + .../nspace/DimensionExistsException.java | 38 + .../nspace/InvalidDimensionalityException.java | 39 + .../foundation/collections/nspace/NSpace.java | 98 ++ .../collections/nspace/SimpleDimension.java | 225 ++++ .../collections/nspace/SparseNSpace.java | 165 +++ .../src/site/apt/Specification.apt | 63 + .../resources/org.frugenplat.framework.nspace.ucd | 58 + .../collections/nspace/SimpleDimensionTest.java | 211 +++ .../collections/nspace/SparseNSpaceTest.java | 87 ++ israfil-foundation-testing/pom.xml | 21 + .../israfil/foundation/mock/sql/MockResultSet.java | 1350 ++++++++++++++++++++ .../foundation/mock/sql/MockResultSetMetaData.java | 342 +++++ .../java/net/israfil/foundation/mock/sql/Row.java | 98 ++ .../mock/sql/MockResultSetMetaDataTest.java | 113 ++ .../foundation/mock/sql/MockResultSetTest.java | 263 ++++ .../net/israfil/foundation/mock/sql/RowTest.java | 86 ++ israfil-foundation-valuemodel/pom.xml | 30 + .../foundation/valuemodel/MutableValue.java | 23 + .../israfil/foundation/valuemodel/Observable.java | 37 + .../net/israfil/foundation/valuemodel/Value.java | 22 + .../israfil/foundation/valuemodel/ValueHolder.java | 108 ++ .../israfil/foundation/valuemodel/Vetoable.java | 44 + .../foundation/valuemodel/ValueHolderTest.java | 143 +++ pom.xml | 151 +++ tools/scripts/mvn-deploy-files | 185 +++ tools/scripts/mvn-deploy-wlp92-jars | 158 +++ 145 files changed, 14360 insertions(+) create mode 100644 .gitignore create mode 100644 israfil-foundation-cache/pom.xml create mode 100644 israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java create mode 100644 israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java create mode 100644 israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java create mode 100644 israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java create mode 100644 israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java create mode 100644 israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java create mode 100644 israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java create mode 100644 israfil-foundation-collections/pom.xml create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java create mode 100644 israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java create mode 100644 israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java create mode 100644 israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java create mode 100644 israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java create mode 100644 israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java create mode 100644 israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java create mode 100644 israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java create mode 100644 israfil-foundation-concurrent/pom.xml create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java create mode 100644 israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java create mode 100644 israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java create mode 100644 israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java create mode 100644 israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java create mode 100644 israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java create mode 100644 israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java create mode 100644 israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java create mode 100644 israfil-foundation-container/pom.xml create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java create mode 100644 israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java create mode 100755 israfil-foundation-container/src/site/apt/index.apt create mode 100644 israfil-foundation-container/src/site/apt/lifecycle.apt create mode 100644 israfil-foundation-container/src/site/apt/usage.apt create mode 100644 israfil-foundation-container/src/site/site.xml create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java create mode 100644 israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java create mode 100644 israfil-foundation-core/pom.xml create mode 100755 israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java create mode 100644 israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java create mode 100644 israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java create mode 100644 israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java create mode 100644 israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java create mode 100644 israfil-foundation-core/src/test/conf/testng.xml create mode 100644 israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java create mode 100644 israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java create mode 100644 israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java create mode 100644 israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java create mode 100644 israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java create mode 100644 israfil-foundation-dynamic/pom.xml create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java create mode 100644 israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java create mode 100644 israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java create mode 100644 israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java create mode 100644 israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java create mode 100644 israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java create mode 100644 israfil-foundation-lifecycle/pom.xml create mode 100644 israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java create mode 100644 israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java create mode 100644 israfil-foundation-notification/pom.xml create mode 100644 israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java create mode 100644 israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java create mode 100644 israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java create mode 100644 israfil-foundation-nspace/pom.xml create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java create mode 100755 israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java create mode 100755 israfil-foundation-nspace/src/site/apt/Specification.apt create mode 100755 israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd create mode 100755 israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java create mode 100755 israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java create mode 100644 israfil-foundation-testing/pom.xml create mode 100644 israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java create mode 100644 israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java create mode 100644 israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java create mode 100644 israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java create mode 100644 israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java create mode 100644 israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java create mode 100644 israfil-foundation-valuemodel/pom.xml create mode 100644 israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java create mode 100644 israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java create mode 100644 israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java create mode 100644 israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java create mode 100644 israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java create mode 100644 israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java create mode 100644 pom.xml create mode 100755 tools/scripts/mvn-deploy-files create mode 100755 tools/scripts/mvn-deploy-wlp92-jars 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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-cache + Israfil Foundation Lightweight Caching + 1.0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + ${project.groupId} + israfil-foundation-core + [1.0.0,1.1) + test + + + \ 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 Christian Edward Gruber + */ +public interface Cache { + + public String getId(); + + public ObjectFactory getFactory(); + + public void setFactory(ObjectFactory 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public class GenericCache implements Cache { + + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + + private String id; + + private ObjectFactory factory; + + private Map _caches = new HashMap(); + + 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 getFactory() { + return factory; + } + + public void purge(K... path) { + // TODO Auto-generated method stub + + } + + public void setFactory(ObjectFactory 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 Christian Edward Gruber + */ +public class GenericFetcherCache implements FetcherCache { + + private Map _caches = new HashMap(); + + /** + * 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 cache = _getLocationInMap(_caches,new ArrayList(_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 pathList = _prepPathList(cacheName,path); + Map cache = _getLocationInMap(_caches,new ArrayList(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 _prepPathList(String cacheName,String[] pathElements) { + List pathList; + if (pathElements == null || pathElements.length < 1) { + pathList = new ArrayList(); + } else { + // Need to make this explicitly an arrayList, so that + // add(index,value) will work. + pathList = new ArrayList(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 _getLocationInMap( + Map currentMap, List cachePath) { + if (cachePath == null || cachePath.size() < 1) return currentMap; + String cacheName = (String)cachePath.remove(0); // pull the first one + + Object cacheObject = (Map)currentMap.get(cacheName); + if (cacheObject == null) { + cacheObject = new HashMap(); + 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 cache = (Map)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 Christian Edward Gruber + */ +public interface ObjectFactory { + + 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 Christian Edward Gruber + * @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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-collections + Israfil Foundation Collections Extras + 1.0.3-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + ${project.groupId} + israfil-foundation-testing + 1.0.0 + test + + + \ 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 Christian Edward Gruber + */ +public class ArraySet extends AbstractSet { + + private transient ArrayList internalList; + + public ArraySet() { + internalList = new ArrayList(); + } + + public ArraySet(int initialCapacity) { + internalList = new ArrayList(initialCapacity); + } + + public ArraySet(Collection col) { + internalList = new ArrayList(col); + Iterator i = col.iterator(); + while (i.hasNext()) { + internalList.add(i.next()); + } + } + + @Override + public Iterator 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 Christian Edward Gruber + */ +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. + *
+     *   public class Foo {
+     *       public T[] getArray() {
+     *   		T[] array = new T[a];
+     * 	     }
+     *   }
+     * 
+ * + * 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[] aggregate(E[] resultBucket, E[] ... arrays) + { + logger.log(Level.FINER,Array.newInstance(arrays.getClass().getComponentType(),0).getClass().getCanonicalName()); + List resultList = new ArrayList(); + 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 Christian Edward Gruber + */ +public class IterableResultSet implements Iterable> { + + protected static final Map iterables = new WeakHashMap(); + protected final WeakReference 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(result); + } + + public Iterator> 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> { + 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 next() { + try { + Map row = new HashMap(); + 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 Christian Edward Gruber + */ +public class RandomOrderIterable implements Iterable { + + private Collection _collection; + private Random _random = null; + + public RandomOrderIterable(Collection collection) { + _collection = collection; + } + + public RandomOrderIterable(Collection collection, Random random) { + this(collection); + _random = random; + } + + public Iterator iterator() { + return new RandomOrderIterator(_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 Christian Edward Gruber + */ +public class RandomOrderIterator implements Iterator { + + private transient List _collection; + + private transient Random _random = new SecureRandom(); + + private transient List _indexes; + + + public RandomOrderIterator(Collection collection) { + _collection = new ArrayList(collection); + _indexes = new LinkedList(); + for (int i = 0; i < _collection.size();i++) { + _indexes.add(i); // populate index source. + } + } + + public RandomOrderIterator(Collection 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 Christian Edward Gruber + * + */ +public class ReciprocalHashMap extends java.util.AbstractMap + implements ReciprocalMap { + + Set> entrySetByKey = new HashSet>(); + Set> entrySetByValue = new HashSet>(); + + @Override + public Set> entrySet() { + return entrySetByKey; + } + + public Set> 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 getEntryByValue(V value) { + Iterator> i = entrySetByValue().iterator(); + if (value==null) { + while (i.hasNext()) { + Entry e = i.next(); + if (e.getKey()==null) return e; + } + } else { + while (i.hasNext()) { + Entry e = i.next(); + if (value.equals(e.getKey())) return e; + } + } + return null; + } + public Entry getEntryByKey(K value) { + Iterator> i = entrySet().iterator(); + if (value==null) { + while (i.hasNext()) { + Entry e = i.next(); + if (e.getKey()==null) return e; + } + } else { + while (i.hasNext()) { + Entry e = i.next(); + if (value.equals(e.getKey())) return e; + } + } + return null; + } + + public K getKey(V value) { + Entry e = getEntryByValue(value); + return (e == null) ? null : e.getValue(); + } + + public V getValue(K key) { + Entry e = getEntryByKey(key); + return (e == null) ? null : e.getValue(); + } + + public K removeByValue(V value) { + Entry valEntry = getEntryByValue(value); + Entry 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 keyEntry = getEntryByKey(key); + Entry 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 keyEntry = getEntryByKey(key); + Entry valueEntry = getEntryByValue(value); + + V oldValue = null; + + if (keyEntry != null) { + Entry inverseKeyEntry = getEntryByValue(keyEntry.getValue()); + keyEntry.getKey(); + entrySetByKey.remove(keyEntry); + entrySetByValue.remove(inverseKeyEntry); + } + if (valueEntry != null) { + Entry inverseValueEntry = getEntryByKey(valueEntry.getValue()); + oldValue = valueEntry.getKey(); + entrySetByValue.remove(valueEntry); + entrySetByKey.remove(inverseValueEntry); + } + entrySetByKey.add(new ReciprocalEntry(key,value)); + entrySetByValue.add(new ReciprocalEntry(value,key)); + + return oldValue; + } + + static class ReciprocalEntry implements Entry { + 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 e = (Map.Entry)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 Christian Edward Gruber + */ +public interface ReciprocalMap extends Map { + 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 Christian Edward Gruber + */ +//@Copyright(years={"2006"},owner="Israfil Consulting Services Corporation",license="BSD") + +public class SoloCollection extends AbstractCollection { + protected final E o; + public SoloCollection(E o) { + super(); + this.o = o; + } + + public Iterator iterator() { + return new Iterator() { + 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 Christian Edward Gruber + * @author Latest: $Author: cgruber $ + * @version $Revision: 76 $ + */ +@Test +public class ArraySetTest { + + ArraySet stringSet; + String string1 = "String1"; + String string2 = "String2"; + String string3 = "String3"; + + @BeforeMethod + protected void setUp() throws Exception { + stringSet = new ArraySet(); + } + + @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 iter = stringSet.iterator(); + Assert.assertEquals(string1,iter.next()); + Assert.assertEquals(string2,iter.next()); + Assert.assertEquals(string3,iter.next()); + } + + public void testAddAllFromArrayList() { + List list = new ArrayList(); + 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 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 iter = stringSet.iterator(); + Assert.assertEquals(string1,iter.next()); + Assert.assertEquals(string3,iter.next()); + } + + public void testCreateWithCapacity() { + stringSet = new ArraySet(3); + stringSet.add(string1); + Assert.assertEquals(string1,stringSet.iterator().next()); + } + + public void testCreateWithCollection() { + ArrayList list = new ArrayList(); + list.add(string1); + list.add(string2); + list.add(string1); + stringSet = new ArraySet(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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @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 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 Christian Edward Gruber + * @author Latest: $Author: cgruber $ + * @version $Revision: 76 $ + */ +@Test +public class RandomOrderIteratorTest { + + Collection c; + final String string1 = "String1"; + final String string2 = "String2"; + final String string3 = "String3"; + + @BeforeMethod + protected void setUp() throws Exception { + c = new ArrayList(); + c.add(string1); + c.add(string2); + c.add(string3); + } + + @AfterMethod + public void tearDown() throws Exception { + c = null; + } + + public void testRandomIteratorWithSeed0() { + Iterator i = new RandomOrderIterator(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 i = new RandomOrderIterator(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 i = new RandomOrderIterator(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 Christian Edward Gruber + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class ReciprocalHashMapTest { + + public void testSimpleCase() throws Throwable { + ReciprocalHashMap map = new ReciprocalHashMap(); + 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 Christian Edward Gruber + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class SoloCollectionTest { + + public void testSingleCollection() { + Object o = new Object(); + SoloCollection sc = new SoloCollection(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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-concurrent + Israfil Foundation Concurrency Classes + 1.0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + ${project.groupId} + israfil-foundation-lifecycle + 1.0.0 + + + \ 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public abstract class AbstractPipe extends AbstractGated implements Pipe { + + protected BlockingQueue queue; + + public AbstractPipe() {} + + public BlockingQueue getQueue() { return queue; } + public void setQueue(BlockingQueue 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 Christian Edward Gruber + */ +public abstract class AbstractPump 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public class CollectingPump extends AbstractPump { + + protected Collection> producers = null; + protected ConcurrentConsumer consumer = null; + private List> producersArray = null; + private int currentItem; + + public CollectingPump() {} + + public CollectingPump(String name, Collection> producers, ConcurrentConsumer 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> getProducers() { return producers; } + + public void setProducers(Collection> producers) { + if (this.isRunning()) + throw new IllegalStateException("Cannot set producers while this pump is not stopped."); + this.producers = producers; + } + + public ConcurrentConsumer getConsumer() { return consumer; } + + public void setConsumer(ConcurrentConsumer 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>(producers); // get consistent list. + return init; + } + + @Override + protected void process() throws InterruptedException { + ConcurrentProducer 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 Christian Edward Gruber + */ +public interface ConcurrentConsumer extends Consumer { + + /** + * Consumes an item of type T. This version will block until + * interrupted. To keep conformity with Consumer, 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 Christian Edward Gruber + */ +public interface ConcurrentProducer extends Producer { + + /** + * 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, 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 Christian Edward Gruber + */ +public class DistributingPump extends AbstractPump { + + protected ConcurrentProducer producer; + protected Collection> consumers; + private List> consumersArray = null; + private int currentItem; + + public DistributingPump() {} + + public DistributingPump(String name, ConcurrentProducer producer, Collection> 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 getProducer() { return producer; } + + public void setProducer(ConcurrentProducer producer) { this.producer = producer; } + + public Collection> getConsumers() { return consumers; } + + public void setConsumers(Collection> 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>(consumers); // get consistent list. + return init; + } + + @Override + protected void process() throws InterruptedException { + ConcurrentConsumer 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public interface Pipe extends ConcurrentProducer, ConcurrentConsumer, 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 Christian Edward Gruber + */ +public class ProcessingPipe extends AbstractPipe { + + protected Processor processor; + protected Integer timeout; + protected TimeUnit timeoutUnit; + + public ProcessingPipe() {} + + public Processor getProcessor() { return processor; } + public void setProcessor(Processor 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 Christian Edward Gruber + */ +public interface Processor { + + 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public class SimplePipe extends AbstractPipe { + + 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 Christian Edward Gruber + */ +public class SimplePump extends AbstractPump { + + protected ConcurrentProducer producer; + protected ConcurrentConsumer consumer; + + public SimplePump() {} + + public SimplePump(String name, ConcurrentProducer producer, ConcurrentConsumer 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 getProducer() { return producer; } + + public void setProducer(ConcurrentProducer producer) { this.producer = producer; } + + public ConcurrentConsumer getConsumer() { return consumer; } + + public void setConsumer(ConcurrentConsumer 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public class LoggingStringConsumer implements ConcurrentConsumer { + 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 Christian Edward Gruber + */ +public class ReaderStringProducer implements ConcurrentProducer { + 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class PumpTest { + + + public void testSimplePump() throws InterruptedException { + SimplePump pump = new SimplePump(); + pump.setTimeout(10000L); + MockProducer p = new MockProducer(); + final MockConsumer c = new MockConsumer(); + 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 pump = new CollectingPump(); + MockProducer p1 = new MockProducer(); + MockProducer p2 = new MockProducer(); + MockProducer p3 = new MockProducer(); + final MockConsumer c = new MockConsumer(); + pump.setConsumer(c); + List> producers = new ArrayList>(); + 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 pump = new DistributingPump(); + MockProducer p = new MockProducer(); + MockConsumer c1 = new MockConsumer(); + MockConsumer c2 = new MockConsumer(); + MockConsumer c3 = new MockConsumer(); + List> consumers = new ArrayList>(); + 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 extends MockStringPipeComponent implements ConcurrentProducer { + 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 extends MockStringPipeComponent implements ConcurrentConsumer { + 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 { + 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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @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 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 Christian Edward Gruber + * @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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-container + Israfil Foundation Trivial IoC Container + 1.0.0-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2008 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + \ 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 Christian Edward Gruber + * + */ +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 Injectable.class.isAssignableFrom(type); + * 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + * + */ +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 registry = new HashMap(); + + 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public class NonDuplicateStack extends Stack { + + 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 @@ + + + + + + + + + + + + + ${reports} + + \ 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 registry = new HashMap(); + 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 nds = new NonDuplicateStack(); + 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 registry = new HashMap(); + 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 nds = new NonDuplicateStack(); + 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 stack = new NonDuplicateStack(); + 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 stack = new NonDuplicateStack(); + 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 stack = new NonDuplicateStack(); + 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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-core + Israfil Foundation Core Classes + 1.0.2-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + \ 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: + *
+ *   @Copyright(years={"2003","2004","2005"} owner="Israfil Consulting Services Corporation" license="BSD")
+ * 
+ * + * @author Christian Edward Gruber + * + * @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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + * @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 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 Christian Edward Gruber + * @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 Christian Edward Gruber + */ + 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 @@ + + + + + + + + + + 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 strings = new ArrayList(); + 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)null)); + } + @Test + public void testEmpty() { + Assert.assertEquals("",Strings.concatenate(":", new ArrayList())); + } + +} 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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-dynamic + Israfil Foundation Dynamic Invocation + 1.0.3-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + ${project.groupId} + israfil-foundation-collections + 1.0.2 + + + ${project.groupId} + israfil-foundation-core + [1.0.0,1.1) + + + \ 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: + * + * if (a.respondsTo("doThing:java.lang.String")) + * a.perform("doThing:java.lang.String",aString); + * + * + * @author Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +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 Christian Edward Gruber + */ +public final class DynamicUtil { + private static Logger logger = Logger.getLogger(DynamicUtil.class.getName()); + + private DynamicUtil() {} + + static Map> _primitiveTypes = new HashMap>(); + static Map, Class> _primitiveTypeEquivalents = new HashMap, Class>(); + static Map, Class> _boxedTypeEquivalents = new HashMap, 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, Set>> classes = new HashMap, Set>>(); + + public static Set> getAllParentTypes(Class c) { + if (!classes.containsKey(c)) { + Set> parents = new HashSet>(); + 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> 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 construct(Class 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 construct(Class c, Class[] parameterTypes, + Object... parameters) { + try { + Constructor[] constructors = (Constructor[]) c.getDeclaredConstructors(); + for (Constructor 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 Christian Edward Gruber + */ +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 Christian Edward Gruber + * @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 Christian Edward Gruber + */ +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 Christian Edward Gruber + * + */ +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 Christian Edward Gruber + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class DynamicUtilTest { + + public void testAddSuperinterfaces1() { + Class clz = IA.class; + Set> cSet = new HashSet>(); + DynamicUtil.addSuperInterfaces(cSet,clz); + Assert.assertEquals(0,cSet.size()); + } + public void testAddSuperinterfaces2() { + Class clz = IC.class; + Set> cSet = new HashSet>(); + 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> 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> 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> 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 al = DynamicUtil.construct(ArrayList.class); + Assert.assertNotNull(al); + Assert.assertEquals(ArrayList.class,al.getClass()); + } + @SuppressWarnings("unchecked") + public void testConstructWithString() { + ArrayList al = (ArrayList)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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-lifecycle + Israfil Foundation Lifecycle Classes and Interfaces + 1.0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2007 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + \ 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 Christian Edward Gruber + */ +public interface Consumer { + + /** + * 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 Christian Edward Gruber + */ +public interface Producer { + + /** + * 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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-notification + Israfil Foundation Notification System + 1.0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + ${project.groupId} + israfil-foundation-dynamic + 1.0.1 + + + \ 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 Christian Edward Gruber + */ +public class Notification { + private static Map EMPTY_INFO = Collections.unmodifiableMap(new HashMap()); + + public final Object sender; + public final String notification; + public final Map info; + public Notification(Object sender, String notification) { + this(sender,notification,EMPTY_INFO); + } + public Notification(Object sender, String notification, Map 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 observers = new HashSet(); + + 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: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Notification NameSender ObjectEffect
nulla senderNotifications (of any name) from this sender are observed
notification stringnullNotifications with this name (from any sender) are observed.
notification stringa senderOnly notifications with this name and originating from this sender are observed
nullnullAll Notifications from any source will be sent (big performance drag)
+ * @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 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 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(); + 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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-nspace + Israfil Foundation N-Dimensional Array + 0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + \ 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 Mishkin Berteig + * @author Christian Gruber + * @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 dim = new HashSet(); + + public Set 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 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 Mishkin Berteig + * @author Christian Gruber + * @version $Revision: 260 $ + */ +public interface Dimension extends Set { + + /** + * Returns the name of the position + * @return String + */ + public String getName(); + + + void getWithNSpace(NSpace space); + void abandonNSpace(NSpace space); + void getWithNSpaces(Collection spaces); + void abandonNSpaces(Collection 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 Mishkin Berteig + * @author Christian Gruber + * @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 Mishkin Berteig + * @author Christian Gruber + * @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: + *
    + *
  1. Each dimension is named
  2. + *
  3. Each co-ordinate is specified using names not numbers IOW: + * Domain of each dim. is specified as an ordered set of names + *
  4. + *
  5. Number of dimensions can change throughout lifecycle
  6. + *
  7. Dimensions + *
+ *

+ * 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.

+ *

Note: Maybe have origin

+ * + * @author Mishkin Berteig + * @author Christian Gruber + * @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 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 positions = new HashSet(); + private final Set spaces = new HashSet(); + + 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 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[] 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 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 spaces) { + this.spaces.removeAll(spaces); + } + + /** + * @see org.frugenplat.framework.nspace.Dimension#getWithNSpace(org.frugenplat.framework.nspace.NSpace) + */ + public void getWithNSpaces(Collection 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 positions) { + + } + + @SuppressWarnings("unused") + private void notifyRemovePositions(Collection 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 Mishkin Berteig + * @author Christian Gruber + * @version $Revision: 260 $ + */ +public class SparseNSpace implements NSpace { + + private final Set dimensions = new HashSet(); + + public SparseNSpace() { + super(); + } + + public SparseNSpace(Set 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 getDimensions() { + return Collections.unmodifiableSet(dimensions); + } + + /** + * Exposes the internal dimensions set to any children + * @return Set + */ + protected Set 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 c = new HashSet(); + 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 c = new HashSet(); + 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 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 c = new HashSet(); + 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 c = new HashSet(); + 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 Mishkin Berteig + * @author Christian Gruber + * @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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-testing + Israfil Foundation Testing Helpers and Fakes + 1.0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + 2003 + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + \ 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 Christian Edward Gruber + */ +public class MockResultSet implements ResultSet { + + public MockResultSetMetaData metadata; + + protected List data; + public List 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(metadata.getColumnCount()); + for (int rowNum = 0; rowNum < rows.length; rowNum++) { + data.add(new Row(metadata,new ArrayList(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> 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> 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 unwrap(Class 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 getObject(int columnIndex, Class type) throws SQLException { + // TODO Auto-generated method stub + return null; + } + + @Override + public T getObject(String columnLabel, Class 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 Christian Edward Gruber + */ +public class MockResultSetMetaData implements ResultSetMetaData { + + public static int ZERO_ORDER_LIST_OFFSET = 1; + List 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(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 unwrap(Class 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 Christian Edward Gruber + */ +public class Row { + + MockResultSetMetaData metadata = null; + List data; + + int cursorPosition; + final boolean insertRow; + public boolean dirty = true; + + public Row(MockResultSetMetaData metadata, List rowData) { + this(metadata,rowData,false); + } + + public Row(MockResultSetMetaData metadata, List 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 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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @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 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> _boxedTypeEquivalents = new HashMap, 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 Christian Edward Gruber + * @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 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 @@ + + 4.0.0 + + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + + israfil-foundation-valuemodel + Israfil Foundation Value Model Classes + + Classes which implement and support a SmallTalk-style valuemodel architecture. + + 1.0.1-SNAPSHOT + http://www.israfil.net/projects/foundation/${artifactId} + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + ${project.groupId} + israfil-foundation-dynamic + 1.0.1 + + + \ 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: Christian Edward Gruber + * @author Recent: $Author$ + * + */ +public interface MutableValue extends Value, 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 Christian Edward Gruber + * @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: Christian Edward Gruber + * @author Recent: $Author$ + * + */ +public interface Value 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 implements MutableValue { + + private E _value = null; + private Map _observers = new HashMap(); + private Map _vetoers = new HashMap(); + + 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 Christian Edward Gruber + * @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 Christian Edward Gruber + * @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 stringValueHolder = null; + private ValueHolder integerValueHolder = null; + + @BeforeMethod + protected void setUp() throws Exception { + stringValue = "String Value"; + integerValue = new Integer(5); + stringValueHolder = new ValueHolder(stringValue); + integerValueHolder = new ValueHolder(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"; + ValueHoldervalueHolder = new ValueHolder(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 callback = new CallbackObject(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 callback = new CallbackObject(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 callback = new CallbackObject(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(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 callback = new CallbackObject(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 { + private final MutableValue valueModel; + public boolean notified = false; + public Object oldValue = null; + public Object newValue = null; + public CallbackObject(MutableValue 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 @@ + + 4.0.0 + net.israfil.foundation + israfil-foundation-all + 5-SNAPSHOT + pom + Israfil Foundation: All + Foundation Frameworks from Israfil Consulting Services + 2006 + http://www.israfil.net/projects/foundation + + israfil-foundation-core + israfil-foundation-dynamic + israfil-foundation-cache + israfil-foundation-collections + israfil-foundation-container + israfil-foundation-concurrent + israfil-foundation-lifecycle + israfil-foundation-notification + israfil-foundation-testing + israfil-foundation-nspace + israfil-foundation-valuemodel + + + + BSD + repo + http://www.israfil.net/israfil-license-bsd.txt + A simple open-source license with minimal restrictions + + + + + + maven-release-plugin + + https://israfil-foundation.googlecode.com/svn/tags/RELEASE + + + + org.codehaus.mojo + cobertura-maven-plugin + + clean + + + + maven-compiler-plugin + + 11 + 11 + + + + + + + org.testng + testng + 5.7 + jdk15 + + + junit + junit + + + + + org.jmock + jmock + 2.4.0 + + + + + + israfil + Israfil Deploy + scp://repo.israfil.net/var/www/vhosts/repo.israfil.net/htdocs/maven2 + + + + israfil + Israfil Snapshot + scp://repo.israfil.net/var/www/vhosts/repo.israfil.net/htdocs/maven2-snapshots + + + website + scp://projects.israfil.net/var/www/vhosts/projects.israfil.net/htdocs/foundation + + + + + + maven-javadoc-plugin + + + org.codehaus.mojo + jxr-maven-plugin + + + org.codehaus.mojo + surefire-report-maven-plugin + + always + + + + org.codehaus.mojo + cobertura-maven-plugin + + + org.codehaus.mojo + taglist-maven-plugin + + + org.codehaus.mojo + jdepend-maven-plugin + + + maven-checkstyle-plugin + + + com.google.testability-explorer + maven2-testability-plugin + + + org.codehaus.mojo + findbugs-maven-plugin + + false + Normal + Default + + FindDeadLocalStores,UnreadFields + FindDeadLocalStores,UnreadFields + + + + + + + scm:svn:http://israfil-foundation.googlecode.com/svn/trunk + scm:svn:https://israfil-foundation.googlecode.com/svn/trunk + http://israfil-foundation.googlecode.com/svn + + 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 ] [-e ] [--test] -u -g -v [...] " + echo "Options: -t --type sets the maven 2 packaging type " + echo " -e --ext the file extension (defaults to type) " + echo " -u --url the url to the deployment repository " + echo " -g --group the groupId to which the artifacts will be deployed " + echo " -v --version the version to which the artifacts will be deployed " + echo " -e --ext the file extension (defaults to type) " + echo " -p --poms 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 -b [-p ] " + echo "Options: -u --url the url to the deployment repository " + echo " -b --bea-home the BEA_HOME folder " + echo " -p --poms 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 + + + -- cgit v1.2.3