diff options
| author | Benjamin Culkin <scorpress@gmail.com> | 2024-05-27 11:38:33 -0400 |
|---|---|---|
| committer | Benjamin Culkin <scorpress@gmail.com> | 2024-05-27 11:38:33 -0400 |
| commit | 7c279747beb43c7e88633a6228a155a30e6834f7 (patch) | |
| tree | 511176048944fa7332dc1a163a6148c46e7c61b3 | |
Initial import
145 files changed, 14360 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f5a48b --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +.settings +.svn +.project +target/ +.classpath +.wtpmodules diff --git a/israfil-foundation-cache/pom.xml b/israfil-foundation-cache/pom.xml new file mode 100644 index 0000000..4167e2e --- /dev/null +++ b/israfil-foundation-cache/pom.xml @@ -0,0 +1,29 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-cache</artifactId> + <name>Israfil Foundation Lightweight Caching</name> + <version>1.0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-core</artifactId> + <version>[1.0.0,1.1)</version> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java new file mode 100644 index 0000000..2ad96cf --- /dev/null +++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Cache.java @@ -0,0 +1,54 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Cache.java 499 2007-05-15 19:16:17Z christianedwardgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * A cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface Cache<K,T> {
+
+ public String getId();
+
+ public ObjectFactory<T> getFactory();
+
+ public void setFactory(ObjectFactory<T> factory);
+
+ public T get(K ... path) ;
+
+ public void purge(K ... path);
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java new file mode 100644 index 0000000..06b9a29 --- /dev/null +++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/Fetcher.java @@ -0,0 +1,46 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Fetcher.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * The main application class for the Quote Refresh Service.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface Fetcher {
+
+ public void fetch();
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java new file mode 100644 index 0000000..0bdccc1 --- /dev/null +++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/FetcherCache.java @@ -0,0 +1,48 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Cache.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * A cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface FetcherCache {
+
+ public Object get(Fetcher fetcher, String cacheName, String itemKey, String ... path) ;
+
+ void set(String cacheName, String itemKey, Object value, String ... path);
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java new file mode 100644 index 0000000..37530a0 --- /dev/null +++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericCache.java @@ -0,0 +1,96 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: GenericCache.java 499 2007-05-15 19:16:17Z christianedwardgruber $
+ */
+package net.israfil.foundation.caching;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+
+/**
+ * A non-thread-safe cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class GenericCache<K,T> implements Cache <K,T>{
+
+ private final ReadWriteLock lock = new ReentrantReadWriteLock();
+
+ private String id;
+
+ private ObjectFactory<T> factory;
+
+ private Map<K[],T> _caches = new HashMap<K[],T>();
+
+ public GenericCache(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Retrieves an object from a path in the cache
+ * @param An array of path items identifying the path through the map keys.
+ */
+ public T get(K ... path) {
+
+ // Get the item from the map
+
+ return null;
+ }
+
+ public ObjectFactory<T> getFactory() {
+ return factory;
+ }
+
+ public void purge(K... path) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setFactory(ObjectFactory<T> factory) {
+ try {
+ lock.writeLock().lock();
+ this.factory = factory;
+
+ } finally {
+ lock.writeLock().unlock();
+ }
+ }
+
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java new file mode 100644 index 0000000..ce42bc2 --- /dev/null +++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/GenericFetcherCache.java @@ -0,0 +1,124 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: GenericCache.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * A non-thread-safe cache object
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class GenericFetcherCache implements FetcherCache {
+
+ private Map<String,Object> _caches = new HashMap<String,Object>();
+
+ /**
+ * Retrieves an object from a path in the cache
+ * @param cacheName A string identifying from which cache the object will be retrieved
+ * @param An array of path items identifying the path through the map keys.
+ */
+ public Object get(Fetcher fetcher, String cacheName, String itemKey, String ... path) {
+
+ // Fetch the map containing the item.
+ Map<String,Object> cache = _getLocationInMap(_caches,new ArrayList<String>(_prepPathList(cacheName,path)));
+
+ // Get the item from the map
+ Object o = cache.get((itemKey==null) ? "__NULL__" : itemKey);
+ if (o == null) {
+ // Item doesn't exist, so try to fetch, then retrieve again.
+ fetcher.fetch();
+ o = cache.get((itemKey==null) ? "__NULL__" : itemKey);
+ }
+ return o;
+ }
+
+
+ /**
+ * A method to set values within the cache, to be used by Fetcher implementations
+ * in setting up the cache when they fetch.
+ */
+ public void set(String cacheName, String itemKey, Object value, String ... path) {
+ List<String> pathList = _prepPathList(cacheName,path);
+ Map<String,Object> cache = _getLocationInMap(_caches,new ArrayList<String>(pathList));
+ cache.put(itemKey,value);
+ }
+
+ /**
+ * Creates a List that contains the pathelements, starting from the
+ * cache name down to the bottom, but excluding the actual final path
+ * item.
+ */
+ static List<String> _prepPathList(String cacheName,String[] pathElements) {
+ List<String> pathList;
+ if (pathElements == null || pathElements.length < 1) {
+ pathList = new ArrayList<String>();
+ } else {
+ // Need to make this explicitly an arrayList, so that
+ // add(index,value) will work.
+ pathList = new ArrayList<String>(Arrays.asList(pathElements));
+ }
+ pathList.add(0,cacheName);
+ return pathList;
+ }
+
+ /**
+ * Recursively traverses the cache map, creating maps at path locations
+ * where they do not already exist.
+ */
+ @SuppressWarnings("unchecked")
+ static Map<String, Object> _getLocationInMap(
+ Map<String, Object> currentMap, List<String> cachePath) {
+ if (cachePath == null || cachePath.size() < 1) return currentMap;
+ String cacheName = (String)cachePath.remove(0); // pull the first one
+
+ Object cacheObject = (Map<String,Object>)currentMap.get(cacheName);
+ if (cacheObject == null) {
+ cacheObject = new HashMap<String,Object>();
+ currentMap.put(cacheName,cacheObject);
+ }
+ if (! (cacheObject instanceof Map))
+ throw new IllegalArgumentException("Attempted to find a map at location ("+cachePath+") in cache ("+cacheName+"), but found a " + cacheObject.getClass().getName() + ".");
+ Map<String,Object> cache = (Map<String,Object>)cacheObject;
+
+ return _getLocationInMap(cache,cachePath);
+ }
+
+
+}
diff --git a/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java new file mode 100644 index 0000000..b16ee1c --- /dev/null +++ b/israfil-foundation-cache/src/main/java/net/israfil/foundation/caching/ObjectFactory.java @@ -0,0 +1,46 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Fetcher.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.caching;
+
+
+/**
+ * The main application class for the Quote Refresh Service.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface ObjectFactory <T> {
+
+ public T produce(Object ... parameters);
+
+}
diff --git a/israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java b/israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java new file mode 100644 index 0000000..2ea505c --- /dev/null +++ b/israfil-foundation-cache/src/test/java/net/israfil/foundation/caching/GenericCacheTest.java @@ -0,0 +1,124 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: GenericCacheTest.java 499 2007-05-15 19:16:17Z christianedwardgruber $
+ */
+package net.israfil.foundation.caching;
+
+import net.israfil.foundation.core.Counter;
+import net.israfil.foundation.core.SimpleCounter;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: christianedwardgruber $
+ * @version $Revision: 499 $
+ */
+@Test
+public class GenericCacheTest {
+
+ Object o;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ o = "AnObject";
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ o = null;
+ }
+
+ public void testGenericCache() {
+ final Counter fetchCount = new SimpleCounter();
+ final FetcherCache c = new GenericFetcherCache();
+ Assert.assertEquals(0,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o);
+ fetchCount.increment();
+ }
+ },"testCache","testItem"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o);
+ fetchCount.increment();
+ }
+ },"testCache","testItem"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ }
+
+ public void testGenericCacheWithSubcache() {
+ final Counter fetchCount = new SimpleCounter();
+ final FetcherCache c = new GenericFetcherCache();
+ Assert.assertEquals(0,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ }
+
+ public void testGenericCacheWithDeepSubcache() {
+ final Counter fetchCount = new SimpleCounter();
+ final FetcherCache c = new GenericFetcherCache();
+ Assert.assertEquals(0,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache","subSubCache","subSubSubCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache","subSubCache","subSubSubCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ Assert.assertEquals(o,c.get(new Fetcher(){
+ public void fetch() {
+ c.set("testCache","testItem",o,"subCache","subSubCache","subSubSubCache");
+ fetchCount.increment();
+ }
+ },"testCache","testItem","subCache","subSubCache","subSubSubCache"));
+ Assert.assertEquals(1,fetchCount.getCount());
+ }
+}
diff --git a/israfil-foundation-collections/pom.xml b/israfil-foundation-collections/pom.xml new file mode 100644 index 0000000..72014ea --- /dev/null +++ b/israfil-foundation-collections/pom.xml @@ -0,0 +1,29 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-collections</artifactId> + <name>Israfil Foundation Collections Extras</name> + <version>1.0.3-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-testing</artifactId> + <version>1.0.0</version> + <scope>test</scope> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java new file mode 100644 index 0000000..3447adc --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArraySet.java @@ -0,0 +1,105 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArraySet.java 76 2006-08-03 15:37:05Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.AbstractSet;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * An ArrayList backed Set implementation, whose primary purpose is
+ * to provide a Set that maintains the order of elements based on
+ * indexes and/or the order in which items are added. Most
+ * particularly it's to guarrantee deterministic results of an
+ * iterator, where the iterator provides each element in the order
+ * of the underlying list.
+ *
+ * Unlike a LinkedHashSet, this implementation leaves a duplicate
+ * element in its original position. It's performance characteristics
+ * on input are similar, since a comparison still has to happen
+ * for de-dupliation, but obtaining the item by index is constant time.
+ *
+ * TODO: Consider making this a SortedSet, using the list order as the guarrantee. Not sure if it's a legit use of the API.
+ * @See java.util.LinkedHashSet
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class ArraySet<E> extends AbstractSet<E> {
+
+ private transient ArrayList<E> internalList;
+
+ public ArraySet() {
+ internalList = new ArrayList<E>();
+ }
+
+ public ArraySet(int initialCapacity) {
+ internalList = new ArrayList<E>(initialCapacity);
+ }
+
+ public ArraySet(Collection<E> col) {
+ internalList = new ArrayList<E>(col);
+ Iterator<E> i = col.iterator();
+ while (i.hasNext()) {
+ internalList.add(i.next());
+ }
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return internalList.iterator();
+ }
+
+ @Override
+ public int size() {
+ return internalList.size();
+ }
+
+ @Override
+ public boolean add(E o) {
+ if (internalList.contains(o)) return false;
+ else {
+ internalList.add(o);
+ return true;
+ }
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return internalList.remove(o);
+ }
+
+ public E get(Integer index) {
+ return internalList.get(index);
+ }
+}
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java new file mode 100644 index 0000000..880de92 --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ArrayUtils.java @@ -0,0 +1,113 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArrayUtils.java 48 2006-02-23 06:11:53Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An array utility class. This class is generic, so its usage is similar
+ * to the following:
+ * Foo[] foo1 = new Foo[]{ aFoo, bFoo, cFoo };
+ * Foo[] foo2 = new Foo[]{ dFoo, eFoo, fFoo };
+ * Foo[] fooResult = ArrayUtils.add(new Foo[],foo1,foo2);
+ *
+ * fooResult would be equivalent: new Foo[]{ aFoo, bFoo, cFoo, dFoo, eFoo, fFoo }
+ *
+ * This util is mostly helpful for putting together large batches of like
+ * arrays into a long single array, such as large groups of parameter lists
+ * or whatever.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class ArrayUtils {
+ private static final Logger logger = Logger.getLogger(ArrayUtils.class.getName());
+
+ /**
+ * Adds arrays of like type creating a new array containing
+ * all elements of the added arrays. Note that you have to
+ * pass in a typed array, because you can't create an array
+ * from a generic type in the code.
+ *
+ * i.e. you can't do this with Generics.
+ * <pre>
+ * public class Foo<T> {
+ * public T[] getArray() {
+ * T[] array = new T[a];
+ * }
+ * }
+ * </pre>
+ *
+ * However, as described in the tests, you can simply pass
+ * it an empty array of that type.
+ *
+ * @param resultBucket An array of the type you are attempting to aggregate. Can be empty. If it has sufficient space, it will be used for the aggregated result.
+ * @param arrays The arrays to be aggregated.
+ * @return An array of the provided type, containing the aggregated contents of the provided arrays.
+ */
+ public static <E> E[] aggregate(E[] resultBucket, E[] ... arrays)
+ {
+ logger.log(Level.FINER,Array.newInstance(arrays.getClass().getComponentType(),0).getClass().getCanonicalName());
+ List<E> resultList = new ArrayList<E>();
+ for (E[] t : arrays) {
+ for (E element : t) {
+ resultList.add(element);
+ }
+ }
+ logger.log(Level.FINER,resultList.toString());
+ return (E[])resultList.toArray(resultBucket);
+ }
+
+ /**
+ * A method that tests the eqivalence (content equality) of
+ * two arrays.
+ * @param a1
+ * @param a2
+ * @return
+ */
+ public static boolean equivalent(Object[] o1, Object[] o2) {
+ if (o1 == null && (o2 == null || o2.length == 0)) return true;
+ if (o2 == null && o1.length == 0) return true;
+ if (o1.length != o2.length) return false;
+ for (int i = 0; i < o1.length; i++) {
+ if (o1[i] != o2[i]) return false;
+ }
+ return true;
+ }
+
+}
+
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java new file mode 100644 index 0000000..9258c6f --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/IterableResultSet.java @@ -0,0 +1,132 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: IterableResultSet.java 26 2006-02-13 16:35:44Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.lang.ref.WeakReference;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A simple wrapper that provides an Iterable implementation back-ended
+ * by a result-set. Allows a ResultSet to be used in a JDK 5.0 extended
+ * for-loop syntax.
+ *
+ * No result set can have more than one Iterable wrapper around it at a time.
+ * However, it is impossible for this object to know implicitly when it is
+ * no longer required (to free the reference). Therefore, when this
+ * wrapper is concluded, it should be disposed of via the dispose() method.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class IterableResultSet implements Iterable<Map<String,Object>> {
+
+ protected static final Map<ResultSet,IterableResultSet> iterables = new WeakHashMap<ResultSet,IterableResultSet>();
+ protected final WeakReference<ResultSet> resultRef;
+
+ public IterableResultSet(ResultSet result) {
+ if (iterables.containsKey(result)) throw new RuntimeException("Cannot have two IterableResultSet wrappers around the same resultset.");
+ this.resultRef = new WeakReference<ResultSet>(result);
+ }
+
+ public Iterator<Map<String,Object>> iterator() {
+ if (resultRef.get() == null) throw new RuntimeException("ResultSet object not available to iterate.");
+ return new ResultSetIterator(resultRef.get());
+ }
+
+ public void dispose() {
+ ResultSet rs = resultRef.get();
+ if (rs == null) return;
+ if (iterables.containsKey(rs)) {
+ iterables.get(rs).dispose();
+ }
+ resultRef.clear();
+ }
+
+ public static class ResultSetIterator implements Iterator<Map<String,Object>> {
+ private static final Logger logger = Logger.getLogger(ResultSetIterator.class.getName());
+ protected ResultSet result;
+
+ boolean hasNext = true;
+
+
+ public ResultSetIterator(ResultSet result) {
+ this.result = result;
+ try {
+ hasNext = result.first();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public boolean hasNext() {
+ return hasNext;
+ }
+
+ public Map<String,Object> next() {
+ try {
+ Map<String,Object> row = new HashMap<String,Object>();
+ for(int i = 1; i <= result.getMetaData().getColumnCount(); i++) {
+ row.put(result.getMetaData().getColumnName(i),result.getObject(i));
+ }
+ hasNext = result.next();
+ return row;
+ } catch (SQLException e) {
+ logger.log(Level.FINER,"SQLException thrown while iterating across result set.",e);
+ return null;
+ }
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("Removal of records from underlying result set not supported.");
+ }
+
+ public void dispose() {
+ if (iterables.containsKey(result)) iterables.remove(result);
+ result = null;
+ }
+
+ public void finalize() throws Throwable {
+ dispose();
+ super.finalize();
+ }
+ }
+}
+
+
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java new file mode 100644 index 0000000..3b5656d --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterable.java @@ -0,0 +1,72 @@ +/*
+ * Copyright (c) 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: IterableResultSet.java 26 2006-02-13 16:35:44Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.security.SecureRandom;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Random;
+
+/**
+ * A simple wrapper that provides an Iterable implementation that wraps
+ * a collection and returns a RandomOrderIterator when asked for an iterator.
+ *
+ * No result set can have more than one Iterable wrapper around it at a time.
+ * However, it is impossible for this object to know implicitly when it is
+ * no longer required (to free the reference). Therefore, when this
+ * wrapper is concluded, it should be disposed of via the dispose() method.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class RandomOrderIterable<E> implements Iterable<E> {
+
+ private Collection<E> _collection;
+ private Random _random = null;
+
+ public RandomOrderIterable(Collection<E> collection) {
+ _collection = collection;
+ }
+
+ public RandomOrderIterable(Collection<E> collection, Random random) {
+ this(collection);
+ _random = random;
+ }
+
+ public Iterator<E> iterator() {
+ return new RandomOrderIterator<E>(_collection,(_random == null) ? new SecureRandom() : _random);
+ }
+
+}
+
+
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java new file mode 100644 index 0000000..8b97e4a --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/RandomOrderIterator.java @@ -0,0 +1,94 @@ +/*
+ * Copyright (c) 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArraySet.java 76 2006-08-03 15:37:05Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * An iterator that is constructed from a collection and returns the
+ * contents of the collection in random order. Note that this is
+ * an iterator over a copy of the collection, not the collection
+ * itself, so remove() is not supported, and underlying changes
+ * to the original collection will not be reflected in this iterator.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class RandomOrderIterator<E> implements Iterator<E> {
+
+ private transient List<E> _collection;
+
+ private transient Random _random = new SecureRandom();
+
+ private transient List<Integer> _indexes;
+
+
+ public RandomOrderIterator(Collection<E> collection) {
+ _collection = new ArrayList<E>(collection);
+ _indexes = new LinkedList<Integer>();
+ for (int i = 0; i < _collection.size();i++) {
+ _indexes.add(i); // populate index source.
+ }
+ }
+
+ public RandomOrderIterator(Collection<E> collection, Random random) {
+ this(collection);
+ this._random = random;
+ }
+
+ public boolean hasNext() {
+ return _indexes.size() > 0;
+ }
+
+ public E next() {
+ Integer index = _indexes.remove(_random.nextInt(_indexes.size()));
+ return _collection.get(index);
+ }
+
+ /**
+ * Because of the means required to track the current node,
+ * removing anything from the underlying collection is not supported.
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+
+
+}
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java new file mode 100644 index 0000000..0ac0164 --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalHashMap.java @@ -0,0 +1,202 @@ +/*
+ * Copyright (c) 2003, Christian Edward Gruber
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ReciprocalHashMap.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A two-way map, backed by java.util.HashMaps, where each key matches one
+ * value and is unique, and where each value maps to a key, and is unique
+ * among all values.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ *
+ */
+public class ReciprocalHashMap<K,V> extends java.util.AbstractMap<K,V>
+ implements ReciprocalMap<K,V> {
+
+ Set<Map.Entry<K,V>> entrySetByKey = new HashSet<Map.Entry<K,V>>();
+ Set<Map.Entry<V,K>> entrySetByValue = new HashSet<Map.Entry<V,K>>();
+
+ @Override
+ public Set<Map.Entry<K,V>> entrySet() {
+ return entrySetByKey;
+ }
+
+ public Set<Map.Entry<V,K>> entrySetByValue() {
+ return entrySetByValue;
+ }
+
+ public boolean contains(K key, V value) {
+ V value1 = get(key);
+ if (value == value1) return true;
+ else if (value == null) return false; // assume null == null handled.
+ else return value.equals(value1);
+ }
+
+ public Entry<V,K> getEntryByValue(V value) {
+ Iterator<Entry<V,K>> i = entrySetByValue().iterator();
+ if (value==null) {
+ while (i.hasNext()) {
+ Entry<V,K> e = i.next();
+ if (e.getKey()==null) return e;
+ }
+ } else {
+ while (i.hasNext()) {
+ Entry<V,K> e = i.next();
+ if (value.equals(e.getKey())) return e;
+ }
+ }
+ return null;
+ }
+ public Entry<K,V> getEntryByKey(K value) {
+ Iterator<Entry<K,V>> i = entrySet().iterator();
+ if (value==null) {
+ while (i.hasNext()) {
+ Entry<K,V> e = i.next();
+ if (e.getKey()==null) return e;
+ }
+ } else {
+ while (i.hasNext()) {
+ Entry<K,V> e = i.next();
+ if (value.equals(e.getKey())) return e;
+ }
+ }
+ return null;
+ }
+
+ public K getKey(V value) {
+ Entry<V,K> e = getEntryByValue(value);
+ return (e == null) ? null : e.getValue();
+ }
+
+ public V getValue(K key) {
+ Entry<K,V> e = getEntryByKey(key);
+ return (e == null) ? null : e.getValue();
+ }
+
+ public K removeByValue(V value) {
+ Entry<V,K> valEntry = getEntryByValue(value);
+ Entry<K,V> keyEntry = getEntryByKey(valEntry.getValue());
+ if (keyEntry != null) entrySetByKey.remove(keyEntry);
+ if (valEntry != null) entrySetByValue.remove(valEntry);
+ return keyEntry.getKey();
+ }
+
+ public V removeByKey(K key) {
+ Entry<K,V> keyEntry = getEntryByKey(key);
+ Entry<V,K> valEntry = getEntryByValue(keyEntry.getValue());
+ if (keyEntry != null) entrySetByKey.remove(keyEntry);
+ if (valEntry != null) entrySetByValue.remove(valEntry);
+ return valEntry.getKey();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override public V remove(Object key) {
+ return this.removeByKey((K)key);
+ }
+
+
+ @Override public V put(K key, V value) {
+ Entry<K,V> keyEntry = getEntryByKey(key);
+ Entry<V,K> valueEntry = getEntryByValue(value);
+
+ V oldValue = null;
+
+ if (keyEntry != null) {
+ Entry<V,K> inverseKeyEntry = getEntryByValue(keyEntry.getValue());
+ keyEntry.getKey();
+ entrySetByKey.remove(keyEntry);
+ entrySetByValue.remove(inverseKeyEntry);
+ }
+ if (valueEntry != null) {
+ Entry<K,V> inverseValueEntry = getEntryByKey(valueEntry.getValue());
+ oldValue = valueEntry.getKey();
+ entrySetByValue.remove(valueEntry);
+ entrySetByKey.remove(inverseValueEntry);
+ }
+ entrySetByKey.add(new ReciprocalEntry<K,V>(key,value));
+ entrySetByValue.add(new ReciprocalEntry<V,K>(value,key));
+
+ return oldValue;
+ }
+
+ static class ReciprocalEntry<K, V> implements Entry<K, V> {
+ private K key;
+ private V value;
+
+ public ReciprocalEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public K getKey() { return key; }
+
+ public V getValue() { return value; }
+
+ public V setValue(V value) {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ public int hashCode() {
+ return ((key == null) ? 0 : key.hashCode()) ^
+ ((value == null) ? 0 : value.hashCode());
+ }
+
+ @Override public String toString() {
+ return "ReciprocalEntry[" + key + "=" + value + "]";
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Map.Entry)) return false;
+ try {
+ Map.Entry<K,V> e = (Map.Entry<K,V>)o;
+ return safeEquals(key, e.getKey()) && safeEquals(value, e.getValue());
+ } catch (ClassCastException cce) {
+ return false;
+ }
+ }
+
+ private static boolean safeEquals(Object o1, Object o2) {
+ return (o1 == null ? o2 == null : o1.equals(o2));
+ }
+ }
+
+}
\ No newline at end of file diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java new file mode 100644 index 0000000..687d3ed --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/ReciprocalMap.java @@ -0,0 +1,49 @@ +/*
+ * Copyright (c) 2003, Christian Edward Gruber
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ReciprocalMap.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.Map;
+
+/**
+ * Interface for a two-way map, where each key matches one value and is unique,
+ * and where each value maps to a key, and is unique among all values.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public interface ReciprocalMap<K,V> extends Map<K,V> {
+ public boolean contains( K key, V value );
+ public K getKey( V value );
+ public K removeByValue( V value );
+ public V getValue( K key );
+ public V removeByKey( K key );
+}
diff --git a/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java new file mode 100644 index 0000000..83a9f66 --- /dev/null +++ b/israfil-foundation-collections/src/main/java/net/israfil/foundation/collections/SoloCollection.java @@ -0,0 +1,66 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: ArraySet.java 19 2006-01-30 21:52:52Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.AbstractCollection;
+import java.util.Iterator;
+
+/**
+ * A simple unmodifyable implementation of Collection that takes a single (possibly
+ * null) constructor parameter. The collection then "contains" this single object.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+//@Copyright(years={"2006"},owner="Israfil Consulting Services Corporation",license="BSD")
+
+public class SoloCollection<E> extends AbstractCollection<E> {
+ protected final E o;
+ public SoloCollection(E o) {
+ super();
+ this.o = o;
+ }
+
+ public Iterator<E> iterator() {
+ return new Iterator<E>() {
+ boolean beforeFirst = true;
+ public boolean hasNext() { return beforeFirst; }
+ public E next() { beforeFirst = false; return o; }
+ public void remove() {
+ throw new UnsupportedOperationException("Cannot remove from a singleton colelction");
+ }
+ };
+ }
+
+ public int size() { return 1; }
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java new file mode 100644 index 0000000..5e804e4 --- /dev/null +++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArraySetTest.java @@ -0,0 +1,125 @@ +/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 76 $
+ */
+@Test
+public class ArraySetTest {
+
+ ArraySet<String> stringSet;
+ String string1 = "String1";
+ String string2 = "String2";
+ String string3 = "String3";
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ stringSet = new ArraySet<String>();
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ stringSet = null;
+ }
+
+ public void testBasicArrayAndListBehaviour() {
+ Assert.assertEquals(0,stringSet.size());
+ stringSet.add(string1);
+ stringSet.add(string2);
+ stringSet.add(string3);
+ Assert.assertEquals(3,stringSet.size());
+ stringSet.add(string2);
+ Assert.assertEquals(3,stringSet.size());
+ Iterator<String> iter = stringSet.iterator();
+ Assert.assertEquals(string1,iter.next());
+ Assert.assertEquals(string2,iter.next());
+ Assert.assertEquals(string3,iter.next());
+ }
+
+ public void testAddAllFromArrayList() {
+ List<String> list = new ArrayList<String>();
+ list.add(string1);
+ list.add(string2);
+ list.add(string3);
+ list.add(string2);
+ Assert.assertEquals(4,list.size());
+ stringSet.addAll(list);
+ Assert.assertEquals(3,stringSet.size());
+ Iterator<String> iter = stringSet.iterator();
+ Assert.assertEquals(string1,iter.next());
+ Assert.assertEquals(string2,iter.next());
+ Assert.assertEquals(string3,iter.next());
+ }
+
+ public void testRemove() {
+ Assert.assertEquals(0,stringSet.size());
+ stringSet.add(string1);
+ stringSet.add(string2);
+ stringSet.add(string3);
+ Assert.assertEquals(3,stringSet.size());
+ stringSet.remove(string2);
+ Assert.assertEquals(2,stringSet.size());
+ Iterator<String> iter = stringSet.iterator();
+ Assert.assertEquals(string1,iter.next());
+ Assert.assertEquals(string3,iter.next());
+ }
+
+ public void testCreateWithCapacity() {
+ stringSet = new ArraySet<String>(3);
+ stringSet.add(string1);
+ Assert.assertEquals(string1,stringSet.iterator().next());
+ }
+
+ public void testCreateWithCollection() {
+ ArrayList<String> list = new ArrayList<String>();
+ list.add(string1);
+ list.add(string2);
+ list.add(string1);
+ stringSet = new ArraySet<String>(list);
+ Assert.assertEquals(string1,stringSet.iterator().next());
+ }
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java new file mode 100644 index 0000000..3d7edec --- /dev/null +++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ArrayUtilsTest.java @@ -0,0 +1,107 @@ +/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 48 $
+ */
+@Test
+public class ArrayUtilsTest {
+
+ final String s1 = "s1",s2 = "s1",s3 = "s1",s4 = "s1",
+ s5 = "s1",s6 = "s1",s7 = "s1";
+
+ public void testArrayUtilOrder1() {
+ String[] sArray1 = new String[] { s1,s2,s3 };
+ String[] sArray2 = new String[] { s4,s5 };
+ String[] sArray3 = new String[] { s6,s7 };
+ String[] saResult = ArrayUtils.aggregate(new String[] {},sArray1,sArray2,sArray3);
+ String[] expected = new String[]{s1,s2,s3,s4,s5,s6,s7};
+ for (int i = 0; i < saResult.length ; i++ ) {
+ Assert.assertEquals(expected[i],saResult[i]);
+ }
+ Assert.assertEquals(String[].class,saResult.getClass());
+ }
+
+ public void testArrayUtilOrder2() {
+ String[] sArray2 = new String[] { s1,s2,s3 };
+ String[] sArray1 = new String[] { s4,s5 };
+ String[] sArray3 = new String[] { s6,s7 };
+ String[] saResult = ArrayUtils.aggregate(new String[] {},sArray1,sArray2,sArray3);
+ String[] expected = new String[]{s4,s5,s1,s2,s3,s6,s7};
+ for (int i = 0; i < saResult.length ; i++ ) {
+ Assert.assertEquals(expected[i],saResult[i]);
+ }
+ Assert.assertEquals(String[].class,saResult.getClass());
+ }
+
+ public void testVaryingTypeAddition() {
+ TestA tA1 = new TestA("tA1");
+ TestA[] tAa1 = new TestA[] { tA1 };
+ TestB tB1 = new TestB("tB1");
+ TestB[] tBa1 = new TestB[] { tB1 };
+ TestA[] result = ArrayUtils.aggregate(new TestA[]{},tAa1,tBa1);
+ Assert.assertEquals(2,result.length);
+ Assert.assertEquals(TestA[].class,result.getClass());
+ }
+
+ public void testStringArrayAggregation() {
+ String[] sa1 = { "s1", "s2" };
+ String[] sa2 = { "s3", "s4" };
+ String[] sa3 = ArrayUtils.aggregate(new String[]{},sa1,sa2);
+ Assert.assertEquals(sa1[0],sa3[0]);
+ Assert.assertEquals(sa1[1],sa3[1]);
+ Assert.assertEquals(sa2[0],sa3[2]);
+ Assert.assertEquals(sa2[1],sa3[3]);
+ }
+
+
+ public class TestA {
+ public final String text;
+ public TestA(String text) {
+ this.text = text;
+ }
+ }
+ public class TestB extends TestA {
+ public TestB(String ext) {
+ super(ext);
+ }
+ }
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java new file mode 100644 index 0000000..ae04d14 --- /dev/null +++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/IterableResultSetTest.java @@ -0,0 +1,97 @@ +/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.sql.ResultSet;
+import java.util.Map;
+
+import net.israfil.foundation.mock.sql.MockResultSet;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 26 $
+ */
+@Test
+public class IterableResultSetTest {
+
+ String colA = "columnA", colB = "columnB" , colC = "columnC";
+ String[] columns = { colA, colB, colC };
+ Object[][] rows = { { new Integer(0), "cBr0", new Float(2.56f) },
+ { new Integer(1), "cBr1", new Float(4.45f) },
+ { new Integer(2), "cBr2", new Float(9.15f) },
+ { new Integer(3), "cBr3", new Float(-25.45f) } };
+
+ IterableResultSet irs;
+ ResultSet rs;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ rs = new MockResultSet(columns,rows);
+ irs = new IterableResultSet( rs );
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ rs = null;
+ irs = null;
+ }
+
+ @Test(expectedExceptions={UnsupportedOperationException.class})
+ public void testRemove() {
+ irs.iterator().remove();
+ }
+
+ public void testIterableRSInAction() throws Throwable {
+ rs.last();
+ IterableResultSet irs = new IterableResultSet(rs);
+ int rowCount = 0;
+ for (Map<String,Object> row : irs) {
+ rowCount++;
+ for(int colNum = 0; colNum < columns.length; colNum++) {
+ Assert.assertEquals(rows[rowCount-1][colNum],row.get(columns[colNum]));
+ }
+ }
+ Assert.assertEquals(4,rowCount);
+ irs.dispose();
+ }
+
+
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java new file mode 100644 index 0000000..3b7de37 --- /dev/null +++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/RandomOrderIteratorTest.java @@ -0,0 +1,104 @@ +/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Random;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 76 $
+ */
+@Test
+public class RandomOrderIteratorTest {
+
+ Collection<String> c;
+ final String string1 = "String1";
+ final String string2 = "String2";
+ final String string3 = "String3";
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ c = new ArrayList<String>();
+ c.add(string1);
+ c.add(string2);
+ c.add(string3);
+ }
+
+ @AfterMethod
+ public void tearDown() throws Exception {
+ c = null;
+ }
+
+ public void testRandomIteratorWithSeed0() {
+ Iterator<String> i = new RandomOrderIterator<String>(c,new Random(0l));
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string1,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string3,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string2,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+ public void testRandomIteratorWithSeed5() {
+ Iterator<String> i = new RandomOrderIterator<String>(c,new Random(5l));
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string3,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string1,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string2,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+ public void testRandomIteratorWithSeed92283842() {
+ Iterator<String> i = new RandomOrderIterator<String>(c,new Random(92283842l));
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string2,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string3,i.next());
+ Assert.assertTrue(i.hasNext());
+ Assert.assertSame(string1,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java new file mode 100644 index 0000000..b49dfe8 --- /dev/null +++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/ReciprocalHashMapTest.java @@ -0,0 +1,70 @@ +/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class ReciprocalHashMapTest {
+
+ public void testSimpleCase() throws Throwable {
+ ReciprocalHashMap<String,Integer> map = new ReciprocalHashMap<String,Integer>();
+ Assert.assertNotNull(map);
+ map.put("Five",5);
+ Assert.assertEquals(1,map.size());
+ Assert.assertTrue(map.contains("Five",5));
+ Assert.assertEquals("Five",map.getKey(5));
+ Assert.assertEquals((Integer)5,map.getValue("Five"));
+ Assert.assertEquals((Integer)5,map.get("Five"));
+
+ map.put("Three",5);
+ Assert.assertEquals("Three",map.getKey(5));
+ Assert.assertEquals((Integer)5,map.getValue("Three"));
+ Assert.assertEquals(null,map.getValue("Five"));
+ Assert.assertEquals(1,map.size());
+
+ map.put("Five",4);
+ Assert.assertEquals("Five",map.getKey(4));
+ Assert.assertEquals((Integer)4,map.getValue("Five"));
+ Assert.assertEquals(2,map.size());
+ }
+
+}
diff --git a/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java new file mode 100644 index 0000000..0c91598 --- /dev/null +++ b/israfil-foundation-collections/src/test/java/net/israfil/foundation/collections/SoloCollectionTest.java @@ -0,0 +1,55 @@ +/*
+ * Copyright (c) 2003 - 2008 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SoloCollectionTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.collections;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class SoloCollectionTest {
+
+ public void testSingleCollection() {
+ Object o = new Object();
+ SoloCollection<Object> sc = new SoloCollection<Object>(o);
+ Assert.assertNotNull(sc.iterator());
+ Assert.assertTrue(sc.contains(o));
+ Assert.assertEquals(o,sc.iterator().next());
+ }
+}
diff --git a/israfil-foundation-concurrent/pom.xml b/israfil-foundation-concurrent/pom.xml new file mode 100644 index 0000000..98b100a --- /dev/null +++ b/israfil-foundation-concurrent/pom.xml @@ -0,0 +1,28 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-concurrent</artifactId> + <name>Israfil Foundation Concurrency Classes</name> + <version>1.0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-lifecycle</artifactId> + <version>1.0.0</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java new file mode 100644 index 0000000..2389c95 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractGated.java @@ -0,0 +1,64 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractGated implements Gated {
+
+ private GateState state = GateState.Close;
+
+ public AbstractGated() {}
+
+ public void close() {
+ this.state = GateState.Close;
+ }
+
+ public GateState getState() {
+ return state;
+ }
+
+ public void open() {
+ this.state = GateState.Open;
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java new file mode 100644 index 0000000..4c5226a --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPipe.java @@ -0,0 +1,77 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractPipe<I,O> extends AbstractGated implements Pipe<I,O> {
+
+ protected BlockingQueue<I> queue;
+
+ public AbstractPipe() {}
+
+ public BlockingQueue<I> getQueue() { return queue; }
+ public void setQueue(BlockingQueue<I> queue) { this.queue = queue; }
+
+ public void consume(I item) {
+ try {
+ this.consume(item,0,null);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public O produce() {
+ try {
+ return this.produce(0,null);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected static void validateTimeout(long timeout, TimeUnit unit) {
+ if (timeout > 0 && unit == null)
+ throw new IllegalArgumentException("Cannot set a timeout with a null TimeUnit");
+ }
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java new file mode 100644 index 0000000..df1d757 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractPump.java @@ -0,0 +1,82 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public abstract class AbstractPump<T> extends RepeatingWorker {
+
+ protected Long timeout = 0L;
+ protected TimeUnit timeoutUnit = TimeUnit.MILLISECONDS;
+
+ public AbstractPump() {}
+
+ public AbstractPump(String name, long timeout, TimeUnit timeoutUnit) {
+ super(name);
+ this.timeout = timeout;
+ this.timeoutUnit = timeoutUnit;
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (this.timeout == null)
+ throw new IllegalStateException("Timeoutunit cannot be null.");
+ if (this.timeoutUnit == null)
+ throw new IllegalStateException("Timeoutunit cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public long getTimeout() { return timeout; }
+
+ public void setTimeout(long timeout) { this.timeout = timeout; }
+
+ public TimeUnit getTimeoutUnit() { return timeoutUnit; }
+
+ public void setTimeoutUnit(TimeUnit timeoutUnit) {
+ this.timeoutUnit = timeoutUnit;
+ }
+
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java new file mode 100644 index 0000000..14e51a0 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/AbstractWorker.java @@ -0,0 +1,212 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Worker.java 401 2007-01-26 02:05:20Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * An object that wraps a Thread and performs units of work within that
+ * thread.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class AbstractWorker implements Runnable, Worker {
+ private static Logger logger = Logger.getLogger(AbstractWorker.class.getName());
+
+ private Thread _thread = null;
+ private String _name = this.getClass().getName();
+ private Throwable _error = null;
+
+ private WorkerState state = WorkerState.Stopped;
+
+ public AbstractWorker() { }
+
+ public AbstractWorker(String name) {
+ this._name = name;
+ }
+
+ /**
+ * Runnable.run() implementation.
+ *
+ */
+ public void run() {
+ try {
+ //execute lifecycle
+ state = WorkerState.Starting;
+ _thread = Thread.currentThread();
+ _thread.setName(_name);
+ _error = null;
+ if (init()) {
+ state = WorkerState.Running;
+ executeLifecycle();
+ }
+ state = WorkerState.Stopping;
+ deinit();
+ state = WorkerState.Stopped;
+ } catch (InterruptedException e){
+ state = WorkerState.Stopped;
+ logger.log(Level.FINE,this.getName() + " interrupted, setting stopped state.",e);
+ _error = e;
+ } catch (RuntimeInterruptedException e){
+ state = WorkerState.Stopped;
+ logger.log(Level.FINE,this.getName() + " interrupted, setting stopped state.",e);
+ _error=e;
+ } catch (Throwable e){
+ state = WorkerState.Stopped;
+ logger.log(Level.SEVERE,e.getClass().getName() + " thrown within run() method of " +
+ this.getName() + ", setting stopped state.",e);
+ _error = e;
+ }
+ }
+
+ abstract void executeLifecycle() throws InterruptedException;
+
+ // Lifecycle phases
+
+ protected boolean init() throws InterruptedException {
+ validate();
+ return _thread != null && _thread.isAlive();
+ }
+
+ protected void preProcess() throws InterruptedException { }
+
+ protected abstract void process() throws InterruptedException;
+
+ protected void postProcess() throws InterruptedException { }
+
+ protected void deinit() throws InterruptedException { }
+
+ protected void validate() {
+ if (getName() == null || getName().equals(""))
+ throw new IllegalStateException(getClass().getName() + " cannot start without a name.");
+ }
+
+ //
+ // SIGNALING
+ //
+ // TODO: Validate signaling.
+ // TODO: Implement cleaner signaling.
+ //
+
+ public boolean isRunning() {
+ return _thread != null && _thread.isAlive() && state == WorkerState.Running;
+ }
+ public boolean isStopping(){
+ return state == WorkerState.Stopping;
+ }
+ public boolean isStarting(){
+ return state == WorkerState.Starting;
+ }
+ public boolean isStopped(){
+ return state == WorkerState.Stopped;
+ }
+
+ // Accessors
+
+ public Thread getThread() { return _thread; }
+
+ public String getName() { return _name; }
+
+ public void setName(String name) { this._name = name; }
+
+ /**
+ * If the worker has stopped due to a thrown error, it should be captured
+ * and available via this method. This method will throw an IllegalStateException
+ * if called when the worker is not in a Stopped state.
+ *
+ */
+ public Throwable getError() {
+ if (!isStopped()) throw new IllegalStateException("No error available when worker not stopped.");
+ else return this._error;
+ }
+ /**
+ * Start the worker
+ * @return boolean Did the Worker startup properly.
+ */
+ public boolean start() {
+ try {
+ if (!isStopped())
+ throw new IllegalStateException("Attempted to start a worker that wasn't stopped");
+ Thread t = new Thread(this);
+ t.start();
+ Thread.yield();
+ return true;
+ } catch (Exception e) {
+ logger.log(Level.INFO,this.getName() + "Thread failed to start",e);
+ return false;
+ }
+ }
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after 20ms if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop() throws InterruptedException{
+ stop(20);
+ }
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds) throws InterruptedException{
+ if (state == WorkerState.Stopped) return; // succeed fast.
+ state = WorkerState.Stopping;
+ if (getThread() != null) getThread().join(timeout_miliseconds);
+ hardStop();
+ }
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds,int timeout_nanoseconds) throws InterruptedException{
+ if (state == WorkerState.Stopped) return; // succeed fast.
+ state = WorkerState.Stopping;
+ if (getThread() != null) getThread().join(timeout_miliseconds,timeout_nanoseconds);
+ hardStop();
+ }
+
+ protected void hardStop() {
+ if (isStopped() || getThread() == null) return;
+ getThread().interrupt();
+ this._thread = null;
+ this.state = WorkerState.Stopped;
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java new file mode 100644 index 0000000..3ed37af --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/CollectingPump.java @@ -0,0 +1,109 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class CollectingPump<T> extends AbstractPump<T> {
+
+ protected Collection<ConcurrentProducer<T>> producers = null;
+ protected ConcurrentConsumer<T> consumer = null;
+ private List<ConcurrentProducer<T>> producersArray = null;
+ private int currentItem;
+
+ public CollectingPump() {}
+
+ public CollectingPump(String name, Collection<ConcurrentProducer<T>> producers, ConcurrentConsumer<T> consumer,
+ long timeout, TimeUnit timeoutUnit) {
+ super(name,timeout,timeoutUnit);
+ setProducers(producers);
+ setConsumer(consumer);
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (getConsumer() == null)
+ throw new IllegalStateException("consumer cannot be null.");
+ if (getProducers() == null || getProducers().size() == 0)
+ throw new IllegalStateException("producers cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public Collection<ConcurrentProducer<T>> getProducers() { return producers; }
+
+ public void setProducers(Collection<ConcurrentProducer<T>> producers) {
+ if (this.isRunning())
+ throw new IllegalStateException("Cannot set producers while this pump is not stopped.");
+ this.producers = producers;
+ }
+
+ public ConcurrentConsumer<T> getConsumer() { return consumer; }
+
+ public void setConsumer(ConcurrentConsumer<T> consumer) {
+ if (!this.isStopped())
+ throw new IllegalStateException("Cannot set consumer while this pump is not stopped.");
+ this.consumer = consumer;
+ }
+
+ @Override
+ protected boolean init() throws InterruptedException {
+ boolean init = super.init() && this.getConsumer() != null &&
+ this.getProducers() != null && this.getProducers().size() > 0;
+ if (!init) return init; // fail fast.
+ producersArray = new ArrayList<ConcurrentProducer<T>>(producers); // get consistent list.
+ return init;
+ }
+
+ @Override
+ protected void process() throws InterruptedException {
+ ConcurrentProducer<T> producer = producersArray.get(currentItem++);
+ if (currentItem >= producersArray.size()) currentItem = 0;
+ consumer.consume(producer.produce());
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java new file mode 100644 index 0000000..c3bf409 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentConsumer.java @@ -0,0 +1,70 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Sink.java 356 2007-01-21 04:17:47Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.lifecycle.Consumer;
+
+/**
+ * A Consumer that overloads consume() with timeout values.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface ConcurrentConsumer<T> extends Consumer<T> {
+
+ /**
+ * Consumes an item of type T. This version will block until
+ * interrupted. To keep conformity with Consumer<T>, if
+ * interrupted, a RuntimeInterruptedException should be thrown.
+ * This is an unchecked exception.
+ *
+ * @param item The item to be consumed.
+ */
+ public void consume(T item);
+
+
+ /**
+ * Consumes an item of type T. If the consumer is not ready, then it will
+ * block the call until the timeout has been reached or the method is
+ * interrupted.If the object is closed, then this method will return
+ * null. This method will never return null except when it is closed.
+ *
+ * @param item The item to be consumed.
+ * @param timeout The length of time consume should attempt to operate.
+ * @param timeoutUnit The unit by which timeout should be interpreted.
+ */
+ public void consume(T item, long timeout, TimeUnit timeoutUnit) throws InterruptedException;
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java new file mode 100644 index 0000000..2298b87 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ConcurrentProducer.java @@ -0,0 +1,62 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 355 2007-01-21 02:41:03Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.lifecycle.Producer;
+
+/**
+ * An object that is a source (producer) of objects
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface ConcurrentProducer<T> extends Producer<T> {
+
+ /**
+ * Produces an item of type T. If the producer is not ready, then it will
+ * block the call until the timeout is interrupted. To keep conformity with
+ * Producer<T>, if interrupted, a RuntimeInterruptedException should be thrown.
+ * This is an unchecked exception.
+ */
+ public T produce();
+
+ /**
+ * Produces an item of type T. If the producer is not ready, then it will
+ * block the call until the timeout is reached or the method is
+ * interrupted.
+ */
+ public T produce(long timeout, TimeUnit unit) throws InterruptedException;
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java new file mode 100644 index 0000000..ecce5db --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/DistributingPump.java @@ -0,0 +1,101 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class DistributingPump<T> extends AbstractPump<T> {
+
+ protected ConcurrentProducer<T> producer;
+ protected Collection<ConcurrentConsumer<T>> consumers;
+ private List<ConcurrentConsumer<T>> consumersArray = null;
+ private int currentItem;
+
+ public DistributingPump() {}
+
+ public DistributingPump(String name, ConcurrentProducer<T> producer, Collection<ConcurrentConsumer<T>> consumers,
+ long timeout, TimeUnit timeoutUnit) {
+ super(name,timeout,timeoutUnit);
+ setProducer(producer);
+ setConsumers(consumers);
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (getProducer() == null)
+ throw new IllegalStateException("consumer cannot be null.");
+ if (getConsumers() == null || getConsumers().size() == 0)
+ throw new IllegalStateException("producers cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public ConcurrentProducer<T> getProducer() { return producer; }
+
+ public void setProducer(ConcurrentProducer<T> producer) { this.producer = producer; }
+
+ public Collection<ConcurrentConsumer<T>> getConsumers() { return consumers; }
+
+ public void setConsumers(Collection<ConcurrentConsumer<T>> consumers) { this.consumers = consumers; }
+
+ @Override
+ protected boolean init() throws InterruptedException {
+ boolean init = super.init() && this.getProducer() != null &&
+ this.getConsumers() != null && this.getConsumers().size() > 0;
+ if (!init) return init; // fail fast.
+ consumersArray = new ArrayList<ConcurrentConsumer<T>>(consumers); // get consistent list.
+ return init;
+ }
+
+ @Override
+ protected void process() throws InterruptedException {
+ ConcurrentConsumer<T> consumer = consumersArray.get(currentItem++);
+ if (currentItem >= consumersArray.size()) currentItem = 0;
+ consumer.consume(producer.produce());
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java new file mode 100644 index 0000000..18a2acf --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Gated.java @@ -0,0 +1,53 @@ +/*
+ * Copyright (c) 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * A Gated object is one which can be in an open or closed state, and which
+ * provides operations to set the state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Gated {
+
+ public void open();
+
+ public void close();
+
+ public GateState getState();
+
+ public static enum GateState { Open, Close }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java new file mode 100644 index 0000000..3c6f196 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/OneShotWorker.java @@ -0,0 +1,71 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: OneShotWorker.java 365 2007-01-22 04:36:55Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.logging.Logger;
+
+/**
+ * A Worker sub-class that implements a one-shot lifecycle, performing any
+ * initialization, pre-actions, the desired work, any post-work actions, and
+ * any de-initialization.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class OneShotWorker extends AbstractWorker {
+
+ private static Logger logger = Logger.getLogger(OneShotWorker.class.getName());
+
+ public OneShotWorker() { }
+
+ public OneShotWorker(String name) {
+ super(name);
+ }
+
+ public void executeLifecycle() throws InterruptedException {
+ logger.finer(getName() + " about to pre-process.");
+ preProcess();
+ logger.finer(getName() + " completed pre-processing.");
+ logger.finer(getName() + " about to process.");
+ process();
+ logger.finer(getName() + " completed processing.");
+ logger.finer(getName() + " about to post-process.");
+ postProcess();
+ logger.finer(getName() + " completed post-processing.");
+ }
+
+ public void preProcess() { }
+
+ public void postProcess() { }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java new file mode 100644 index 0000000..9789f25 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Pipe.java @@ -0,0 +1,50 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Pipe<I,O> extends ConcurrentProducer<O>, ConcurrentConsumer<I>, Gated {
+
+
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java new file mode 100644 index 0000000..2e23c2a --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/ProcessingPipe.java @@ -0,0 +1,90 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that consumes an object and processes it, then produces the result
+ * upon request. If the processor has no item in processing, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class ProcessingPipe<I,O> extends AbstractPipe<I,O> {
+
+ protected Processor<I,O> processor;
+ protected Integer timeout;
+ protected TimeUnit timeoutUnit;
+
+ public ProcessingPipe() {}
+
+ public Processor<I,O> getProcessor() { return processor; }
+ public void setProcessor(Processor<I,O> processor) {
+ this.processor = processor;
+ }
+ public Integer getTimeout() { return timeout; }
+ public void setTimeout(Integer timeout) { this.timeout = timeout; }
+ public TimeUnit getTimeoutUnit() { return timeoutUnit; }
+ public void setTimeoutUnit(TimeUnit timeoutUnit) {
+ this.timeoutUnit = timeoutUnit;
+ }
+
+ public void consume(I item, long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ try {
+ if (timeout > 0) getQueue().offer(item,timeout,unit);
+ else getQueue().put(item);
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ }
+
+ public O produce(long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ O processedItem = null;
+ try {
+ if (timeout > 0)
+ processedItem = this.processor.process(getQueue().poll(timeout,unit),getTimeout(),getTimeoutUnit());
+ else
+ processedItem = this.processor.process(getQueue().poll(),getTimeout(),getTimeoutUnit());
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ return processedItem;
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java new file mode 100644 index 0000000..90a5cc7 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Processor.java @@ -0,0 +1,49 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that proceses an item and returns a result.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Processor<I,O> {
+
+ public O process(I item) throws InterruptedException;
+
+ public O process(I item, long timeout, TimeUnit timeoutUnit) throws InterruptedException;
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java new file mode 100644 index 0000000..a6588fc --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RepeatingWorker.java @@ -0,0 +1,97 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: RepeatingWorker.java 367 2007-01-22 23:02:28Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * A Worker sub-class that implements a slightly different lifecycle. In
+ * particular, it iterates based on a continuProcessing() signalling method.
+ * It also implements pre and post processing logic in case any per-iteration
+ * setup and tear-down is required.
+ *
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class RepeatingWorker extends AbstractWorker {
+
+ private static Logger logger = Logger.getLogger(RepeatingWorker.class.getName());
+
+ public RepeatingWorker() { }
+
+ public RepeatingWorker(String name) { super(name); }
+
+ public void executeLifecycle() throws InterruptedException {
+ do {
+ logger.finer(getName() + " about to pre-process.");
+ preProcess();
+ logger.finer(getName() + " completed pre-processing.");
+ logger.finer(getName() + " about to process.");
+ process();
+ logger.finer(getName() + " completed processing.");
+ logger.finer(getName() + " about to post-process.");
+ postProcess();
+ logger.finer(getName() + " completed post-processing.");
+ Thread.yield();
+ } while (continueProcessing() && delay());
+ }
+
+ public abstract boolean continueProcessing() throws InterruptedException;
+
+ /**
+ * @return long Number of milliseconds to delay between iterations
+ */
+ public abstract long iterationDelay();
+
+ /**
+ * Returns boolean only so it can be used in a while statement. delay()
+ * simply sleeps as long as iterationDelay() indicates, then returns true,
+ * unless interrupted in which case it returns false.
+ */
+ private boolean delay() {
+ try {
+ Thread.sleep(iterationDelay());
+ return true;
+ } catch (InterruptedException e) {
+ logger.log(Level.WARNING, getName() + " interrupted.",e);
+ return false;
+ }
+ }
+
+ public void preProcess() { }
+
+ public void postProcess() { }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java new file mode 100644 index 0000000..ee05a44 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/RuntimeInterruptedException.java @@ -0,0 +1,64 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: OneShotWorker.java 365 2007-01-22 04:36:55Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * A runtime (unchecked) equivalent to InterruptedException
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class RuntimeInterruptedException extends RuntimeException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -667612054120346668L;
+
+ public RuntimeInterruptedException() {
+ super();
+ }
+
+ public RuntimeInterruptedException(String s) {
+ super(s);
+ }
+
+ public RuntimeInterruptedException(String s, Throwable cause) {
+ super(s,cause);
+ }
+
+ public RuntimeInterruptedException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java new file mode 100644 index 0000000..d1383fb --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePipe.java @@ -0,0 +1,74 @@ +/*
+ * Copyright (c) 2006, 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2006, 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that consumes an object and queues it, then produces the object
+ * upon request. If the processor has an unfilled queue, it may consume
+ * an item. If the processor has an item it produces it when requested. In
+ * the converse cases the behaviour of the object depends on whether the
+ * processor is in its on state or its off state.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class SimplePipe<I> extends AbstractPipe<I,I> {
+
+ public SimplePipe() {}
+
+ public void consume(I item, long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ try {
+ if (timeout > 0) getQueue().offer(item,timeout,unit);
+ else getQueue().put(item);
+ } catch (InterruptedException e) {
+ throw e;
+ }
+ }
+
+ public I produce(long timeout, TimeUnit unit) throws InterruptedException {
+ validateTimeout(timeout,unit);
+ try {
+ if (timeout > 0)
+ return getQueue().poll(timeout,unit);
+ else
+ return getQueue().poll();
+ } catch (InterruptedException e) {
+ throw e;
+ }
+
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java new file mode 100644 index 0000000..4b9b11a --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/SimplePump.java @@ -0,0 +1,85 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SimplePump.java 367 2007-01-22 23:02:28Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A worker that repeats and draws items from a producer and feeds it to a consumer
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class SimplePump<T> extends AbstractPump<T> {
+
+ protected ConcurrentProducer<T> producer;
+ protected ConcurrentConsumer<T> consumer;
+
+ public SimplePump() {}
+
+ public SimplePump(String name, ConcurrentProducer<T> producer, ConcurrentConsumer<T> consumer,
+ long timeout, TimeUnit timeoutUnit) {
+ super(name,timeout,timeoutUnit);
+ setProducer(producer);
+ setConsumer(consumer);
+ }
+
+ @Override
+ protected void validate() {
+ super.validate();
+ if (getConsumer() == null)
+ throw new IllegalStateException("consumer cannot be null.");
+ if (getProducer() == null )
+ throw new IllegalStateException("producer cannot be null.");
+ }
+
+ @Override
+ public boolean continueProcessing() { return isRunning(); }
+
+ @Override
+ public long iterationDelay() { return 0; }
+
+ public ConcurrentProducer<T> getProducer() { return producer; }
+
+ public void setProducer(ConcurrentProducer<T> producer) { this.producer = producer; }
+
+ public ConcurrentConsumer<T> getConsumer() { return consumer; }
+
+ public void setConsumer(ConcurrentConsumer<T> consumer) { this.consumer = consumer; }
+
+ @Override
+ protected void process() throws InterruptedException {
+ consumer.consume(producer.produce());
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java new file mode 100644 index 0000000..697d466 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/Worker.java @@ -0,0 +1,104 @@ +/*
+ * Copyright (c) 2003 - 2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Worker.java 401 2007-01-26 02:05:20Z cgruber $
+ */
+package net.israfil.foundation.concurrent;
+
+
+/**
+ * An object that wraps a Thread and performs units of work within that
+ * thread. Very handy for concurrent development.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Worker {
+
+
+
+ //
+ // SIGNALING
+ //
+ // TODO: Validate signaling.
+ // TODO: Implement cleaner signaling.
+ //
+
+ public boolean isRunning();
+
+ public boolean isStopping();
+
+ public boolean isStarting();
+
+ public boolean isStopped();
+
+ // Accessors
+
+ public String getName();
+
+ /**
+ * If the worker has stopped due to a thrown error, it should be captured
+ * and available via this method. This method will throw an IllegalStateException
+ * if called when the worker is not in a Stopped state.
+ *
+ */
+ public Throwable getError();
+
+ /**
+ * Start the worker
+ * @return boolean Did the Worker startup properly.
+ */
+ public boolean start();
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after 20ms if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop() throws InterruptedException;
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds) throws InterruptedException;
+
+ /**
+ * Attempts to gracefully shutdown the worker, but interrupts the
+ * thread after a given timeout if the worker does not stop on its own.
+ * @throws InterruptedException
+ */
+ public void stop(long timeout_miliseconds,int timeout_nanoseconds) throws InterruptedException;
+
+ public static enum WorkerState {
+ Stopped,Starting,Running,Stopping
+ }
+}
diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java new file mode 100644 index 0000000..7fd2121 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumer.java @@ -0,0 +1,61 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Dynamic.java 14 2006-01-27 23:50:37Z cgruber $
+ */
+package net.israfil.foundation.concurrent.consumers;
+
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.concurrent.ConcurrentConsumer;
+
+/**
+ * A consumer that consumes strings and sends them to a provided logger at a
+ * provided level.
+ *
+ * @author <a href="cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class LoggingStringConsumer implements ConcurrentConsumer<String> {
+ private Logger logger;
+ private Level level;
+ public LoggingStringConsumer(Logger logger,Level level) {
+ this.logger = logger;
+ this.level = level;
+ }
+ public void consume(String item) {
+ logger.log(level,item);
+ }
+ public void consume(String item, long timeout, TimeUnit unit) throws InterruptedException {
+ throw new UnsupportedOperationException("Timeouts not supported. Use consume(String)");
+ }
+}
\ No newline at end of file diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java new file mode 100644 index 0000000..f232b00 --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/producers/ReaderStringProducer.java @@ -0,0 +1,79 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Dynamic.java 14 2006-01-27 23:50:37Z cgruber $
+ */
+package net.israfil.foundation.concurrent.producers;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.CharBuffer;
+import java.util.concurrent.TimeUnit;
+
+import net.israfil.foundation.concurrent.ConcurrentProducer;
+
+/**
+ * A provider that reads an input stream and creates strings out of lines
+ * of text.
+ *
+ * @author <a href="cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class ReaderStringProducer implements ConcurrentProducer<String> {
+ Reader reader = null;
+ public ReaderStringProducer(Reader reader) {
+ this.reader = reader;
+ }
+ public String produce() {
+ CharBuffer cb = CharBuffer.allocate(1024);
+ int count = 0;
+ try {
+ int val = reader.read();
+ while (val != -1) {
+ cb.append( (char)val );
+ count++;
+ if ((char)val == '\n') break;
+ val = reader.read();
+ }
+ if (count == 0 && val == -1) return null;
+ } catch (IOException e) { return null; }
+ char[] finalarray = new char[count];
+ cb.position(0);
+ cb.get(finalarray);
+ return new String(finalarray);
+ }
+ public String produce(long timeout, TimeUnit unit) throws InterruptedException {
+ throw new UnsupportedOperationException("Timeouts not supported. Use produce()");
+ }
+
+
+
+ }
+
\ No newline at end of file diff --git a/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java new file mode 100644 index 0000000..0abe15b --- /dev/null +++ b/israfil-foundation-concurrent/src/main/java/net/israfil/foundation/concurrent/timing/Timeout.java @@ -0,0 +1,68 @@ +/*
+ * Copyright (c) 2003 - 2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003 - 2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Pump.java 362 2007-01-21 06:37:33Z cgruber $
+ */
+package net.israfil.foundation.concurrent.timing;
+
+import java.util.concurrent.TimeoutException;
+
+/**
+ * An object that represents a timeout value;
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+public class Timeout {
+
+ private final long startTime;
+ private final long timeout;
+
+ public Timeout(long timeout) {
+ this.timeout = timeout;
+ startTime = System.currentTimeMillis();
+ }
+ public void assertWithinTimeout() throws TimeoutException {
+ long now = System.currentTimeMillis();
+ if (now - startTime > timeout) {
+ throw new TimeoutException("Timeout of " + timeout + "ms exceeded: " + (now - startTime) + "ms.");
+ }
+ }
+ public long getStartTime() {
+ return startTime;
+ }
+ public long getTimeout() {
+ return timeout;
+ }
+ public void sleep(long interval) throws InterruptedException {
+ Thread.sleep(interval);
+ }
+
+}
diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java new file mode 100644 index 0000000..dce834e --- /dev/null +++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/AbstractWorkerTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation + * Copyright (c) 2006 - 2007 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: WorkerTest.java 368 2007-01-22 23:23:03Z cgruber $ + */ +package net.israfil.foundation.concurrent; + +import net.israfil.foundation.concurrent.timing.Timeout; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * A Test Class + * + * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a> + * @author Latest: $Author: cgruber $ + * @version $Revision: 368 $ + */ +@Test +public class AbstractWorkerTest { + + public void testWorker() throws InterruptedException { + FakeWorker w = new FakeWorker("MockWorker"); + Assert.assertNull(w.getThread()); + //Assert.assertEquals("MockWorker",w.getId()); + Assert.assertFalse(w.didInit); + Assert.assertFalse(w.didWork); + Assert.assertFalse(w.didDeInit); + + // startup thread and give it some processor time. + w.start(); + Timeout timeout = new Timeout(10000); + while (!w.isRunning()) { + timeout.sleep(10); + } + + Assert.assertTrue(w.isRunning()); + Assert.assertNotNull(w.getThread()); + Assert.assertTrue(w.getThread().isAlive()); + + // Assert.assert pre-work state. + Assert.assertTrue(w.didInit); + Assert.assertFalse(w.doWork); + Assert.assertFalse(w.didWork); + Assert.assertFalse(w.didDeInit); + + // Signal worker to start work and check state. + w.doWork = true; + timeout = new Timeout(10000); + while (!w.didWork) { + timeout.sleep(10); + } + + w.stop(5000); + Assert.assertTrue(w.didDeInit); + + } + + + public static class FakeWorker extends AbstractWorker { + + public boolean didWork = false, didInit = false, didDeInit = false; + public volatile boolean doWork = false; + + public FakeWorker(String id) { + super(id); + } + + public boolean init() { + didInit = true; + return true; + } + + public void deinit() { + didDeInit = true; + } + + protected void executeLifecycle() throws InterruptedException { + while (!isStopping() && !doWork) Thread.sleep(10); + preProcess(); + process(); + postProcess(); + } + + public void process() throws InterruptedException { + didWork=true; + while(!isStopping()) Thread.sleep(10); + } + + } + +} diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java new file mode 100644 index 0000000..304f219 --- /dev/null +++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/OneShotWorkerTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2006 - 2008 Israfil Consulting Services Corporation + * Copyright (c) 2006 - 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $ + */ +package net.israfil.foundation.concurrent; + +import org.testng.SkipException; +import org.testng.annotations.Test; + +/** + * A Test Class + * + * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a> + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class OneShotWorkerTest { + + public void testOneShotWorker() throws InterruptedException { + throw new SkipException("Unimplemented tests"); + } + + public static class TestOneShotWorker extends OneShotWorker { + + boolean preProcessed = false; + boolean processed = false; + boolean postProcessed = false; + boolean initialized = false; + boolean deinitialized = false; + + @Override + public void postProcess() { + super.postProcess(); + this.postProcessed = true; + } + + @Override + public void preProcess() { + super.preProcess(); + this.preProcessed = true; + } + + @Override + protected void deinit() throws InterruptedException { + // TODO Auto-generated method stub + super.deinit(); + } + + @Override + protected boolean init() throws InterruptedException { + // TODO Auto-generated method stub + return super.init(); + } + + @Override + protected void process() throws InterruptedException { + // TODO Auto-generated method stub + + } + + } + +} diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java new file mode 100644 index 0000000..5d714f8 --- /dev/null +++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/PumpTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation + * Copyright (c) 2006 - 2007 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $ + */ +package net.israfil.foundation.concurrent; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import net.israfil.foundation.concurrent.timing.Timeout; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * A Test Class + * + * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a> + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class PumpTest { + + + public void testSimplePump() throws InterruptedException { + SimplePump<String> pump = new SimplePump<String>(); + pump.setTimeout(10000L); + MockProducer<String> p = new MockProducer<String>(); + final MockConsumer<String> c = new MockConsumer<String>(); + pump.setConsumer(c); + pump.setProducer(p); + Assert.assertNotNull(pump.getConsumer()); + Assert.assertNotNull(pump.getProducer()); + Assert.assertTrue(pump.isStopped()); + pump.start(); + Timeout timeout = new Timeout(20000); + while(!pump.isRunning()) timeout.sleep(5); + Assert.assertNull(p.item); + Assert.assertNull(c.item); + String itemA = "a"; + p.item = itemA; + timeout = new Timeout(20000); + while( c.item == null) { + timeout.sleep(5); + } + Assert.assertEquals(itemA,c.item); + pump.stop(); + Assert.assertTrue(pump.isStopped()); + } + + public void testCollectingPump() throws InterruptedException { + CollectingPump<String> pump = new CollectingPump<String>(); + MockProducer<String> p1 = new MockProducer<String>(); + MockProducer<String> p2 = new MockProducer<String>(); + MockProducer<String> p3 = new MockProducer<String>(); + final MockConsumer<String> c = new MockConsumer<String>(); + pump.setConsumer(c); + List<ConcurrentProducer<String>> producers = new ArrayList<ConcurrentProducer<String>>(); + producers.add(p1); + producers.add(p2); + producers.add(p3); + pump.setProducers(producers); + Assert.assertNotNull(pump.getConsumer()); + Assert.assertNotNull(pump.getProducers()); + Assert.assertTrue(pump.isStopped()); + pump.start(); + Timeout timeout = new Timeout(20000); + while(!pump.isRunning()) timeout.sleep(5); + Assert.assertNull(p1.item); + Assert.assertNull(c.item); + String itemA = "a", itemB = "b", itemC = "c"; + p1.item = itemA; + p2.item = itemB; + p3.item = itemC; + Assert.assertNotNull(p1.item); + Assert.assertNotNull(p2.item); + Assert.assertNotNull(p3.item); + timeout = new Timeout(20000); + while(c.item == null) timeout.sleep(5); + Assert.assertEquals(itemA, c.item); + Assert.assertNull(p1.item); + c.item = null; + timeout = new Timeout(20000); + while(c.item == null) timeout.sleep(5); + Assert.assertEquals(itemB, c.item); + Assert.assertNull(p2.item); + c.item = null; + timeout = new Timeout(20000); + while(c.item == null) timeout.sleep(5); + Assert.assertEquals(itemC, c.item); + Assert.assertNull(p3.item); + c.item = null; + pump.stop(); + Assert.assertTrue(pump.isStopped()); + } + + public void testDistributingPump() throws InterruptedException { + if (true) return; + DistributingPump<String> pump = new DistributingPump<String>(); + MockProducer<String> p = new MockProducer<String>(); + MockConsumer<String> c1 = new MockConsumer<String>(); + MockConsumer<String> c2 = new MockConsumer<String>(); + MockConsumer<String> c3 = new MockConsumer<String>(); + List<ConcurrentConsumer<String>> consumers = new ArrayList<ConcurrentConsumer<String>>(); + consumers.add(c1); + consumers.add(c2); + consumers.add(c3); + pump.setConsumers(consumers); + pump.setProducer(p); + Assert.assertNotNull(pump.getConsumers()); + Assert.assertNotNull(pump.getProducer()); + Assert.assertTrue(pump.isStopped()); + Timeout timeout = new Timeout(500); + while(!pump.isRunning()) timeout.sleep(5); + Assert.assertNull(p.item); + Assert.assertNull(c1.item); + Assert.assertNull(c2.item); + Assert.assertNull(c3.item); + String itemA = "a", itemB = "b", itemC = "c"; + p.item = itemA; + timeout = new Timeout(20000); + while(c1.item == null) timeout.sleep(5); + Assert.assertEquals(itemA,c1.item); + Assert.assertNull(p.item); + p.item = itemB; + timeout = new Timeout(20000); + while(c1.item == null) timeout.sleep(5); + Assert.assertEquals(itemB,c1.item); + Assert.assertNull(p.item); + p.item = itemC; + timeout = new Timeout(20000); + while(c1.item == null) timeout.sleep(5); + Assert.assertEquals(itemC,c1.item); + Assert.assertNull(p.item); + pump.stop(); + Assert.assertTrue(pump.isStopped()); + } + + public static class MockProducer<T> extends MockStringPipeComponent<T> implements ConcurrentProducer<T> { + public T produce() { + try { + return produce(0,null); + } catch (InterruptedException e) { + throw new RuntimeInterruptedException(e); + } + } + public T produce(long timeoutMillis, TimeUnit unit) throws InterruptedException { + Thread.sleep(delay); + Timeout timeout = new Timeout(timeoutMillis); + while (this.item == null && (timeoutMillis < 1 || unit == null)) + timeout.sleep(5); + Long start = System.currentTimeMillis(); + if (this.item == null) return null; // in case of timeouts. + synchronized (this.item) { + T oldItem = this.item; + this.item = null; + return oldItem; + } + } + } + + public static class MockConsumer<T> extends MockStringPipeComponent<T> implements ConcurrentConsumer<T> { + public void consume(T item) { + try { + consume(item,0,null); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + public void consume(T item, long timeoutMillis, TimeUnit unit) throws InterruptedException { + Thread.sleep(delay); + Timeout timeout = new Timeout(timeoutMillis); + while (this.item != null && (timeoutMillis < 1 || unit == null)) + timeout.sleep(5); + this.item = item; + } + } + + public static class MockStringPipeComponent<T> { + public T item = null; + public long delay = 0; + public static boolean timeout(Long start, Long timeout) { + return (System.currentTimeMillis() - start) < timeout; + } + } + +} diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java new file mode 100644 index 0000000..f7b2303 --- /dev/null +++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/RepeatingWorkerTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation + * Copyright (c) 2006 - 2007 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $ + */ +package net.israfil.foundation.concurrent; + +import org.testng.SkipException; +import org.testng.annotations.Test; + +/** + * A Test Class + * + * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a> + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class RepeatingWorkerTest { + + public void testRepeatingWorker() throws InterruptedException { + throw new SkipException("Unimplemented tests"); + } + +} diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java new file mode 100644 index 0000000..a0980ff --- /dev/null +++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/consumers/LoggingStringConsumerTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation + * Copyright (c) 2006 - 2007 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $ + */ +package net.israfil.foundation.concurrent.consumers; + +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import net.israfil.foundation.concurrent.ConcurrentConsumer; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * A Test Class + * + * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a> + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class LoggingStringConsumerTest{ + + + public void testLoggingStringConsumer() throws InterruptedException { + String message1 = "message 1"; + String message2 = "message 2"; + String message3 = "message 3"; + MockLogger log = new MockLogger("MockLogger",null); + ConcurrentConsumer<String> c = new LoggingStringConsumer(log,Level.INFO); + c.consume(message1); + Assert.assertEquals(message1,log.rawMessage); + c.consume(message2); + Assert.assertEquals(message2,log.rawMessage); + c.consume(message3); + Assert.assertEquals(message3,log.rawMessage); + } + + public class MockLogger extends Logger { + String rawMessage = null; + public MockLogger(String name, String resourceBundleName) { + super(name, resourceBundleName); + } + + public void log(LogRecord record) { + rawMessage = record.getMessage(); + } + } + +} diff --git a/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java new file mode 100644 index 0000000..43344e4 --- /dev/null +++ b/israfil-foundation-concurrent/src/test/java/net/israfil/foundation/concurrent/producers/ReaderStringProducerTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006 - 2007 Israfil Consulting Services Corporation + * Copyright (c) 2006 - 2007 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: AllTests.java 13 2006-01-27 23:45:36Z cgruber $ + */ +package net.israfil.foundation.concurrent.producers; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.io.StringReader; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * A Test Class + * + * @author <a href="mailto:cgruber@roundarch.com">Christian Edward Gruber</a> + * @author Latest: $Author: cgruber $ + * @version $Revision: 130 $ + */ +@Test +public class ReaderStringProducerTest { + + + public void testInputStreamStringProducer() throws Exception { + String s1 = "This is a test;\n"; + String s2 = "This is a second test."; + String string = s1+s2; + ReaderStringProducer producer = new ReaderStringProducer( + new StringReader(string) + ); + Assert.assertEquals(s1,producer.produce()); + Assert.assertEquals(s2,producer.produce()); + Assert.assertEquals(null,producer.produce()); + } + + + public static class ReaderInputStream extends InputStream { + private Reader source; + public ReaderInputStream(Reader source) { this.source = source; } + @Override + public int read() throws IOException { return source.read(); } + } +} diff --git a/israfil-foundation-container/pom.xml b/israfil-foundation-container/pom.xml new file mode 100644 index 0000000..742064d --- /dev/null +++ b/israfil-foundation-container/pom.xml @@ -0,0 +1,21 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-container</artifactId> + <name>Israfil Foundation Trivial IoC Container</name> + <version>1.0.0-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2008</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> +</project>
\ No newline at end of file diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java new file mode 100644 index 0000000..fe6a978 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractContainer.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; + +/** + * A convenience abstract class that implements basic component storage and + * lookup, as well as basic component instance assignment. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + * + */ +public abstract class AbstractContainer implements Container { + + private final Map components = new HashMap(); + + private final Container parent; + + private boolean running = false; + + public AbstractContainer() { + parent = null; + } + + public AbstractContainer(Container parent) { + this.parent = parent; + } + + protected boolean isStored(Object key) { + return components.containsKey(key); + } + + public boolean hasComponent(Object key) { + return components.containsKey(key) || (parent != null && parent.hasComponent(key)); + } + + public boolean isRunning() { + return this.running; + } + + public void start() { + this.running = true; + } + + protected Container getParent() { return parent; } + + protected Object getStoredComponent(Object key) { + Object result = components.get(key); + if (result == null && parent != null) + result = parent.getComponent(key); + return result; + } + + protected void store(Object key, Object component) { + if (hasComponent(key)) { + if (getComponent(key) == component) return; + throw new ComponentAlreadyRegisteredError("Object already registered for key: " + key); + } + components.put(key, component); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java new file mode 100644 index 0000000..c4047f1 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AbstractStartable.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A convenience implementation of Startable + */ +public abstract class AbstractStartable implements Startable { + + private boolean started = false; + + /** + * @see Startable.start(); + */ + public void start() { + this.started = true; + } + + /** + * @see Startable.isRunning(); + */ + public boolean isRunning() { return started; } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java new file mode 100644 index 0000000..623851b --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdaptableContainer.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A Container that uses an AutoWiringAdapter to ensure that + * components can be created appropriately with their dependencies + * satisfied automatically. + * + */ +public interface AutoWiringAdaptableContainer extends Container { + + public void start(); + + /** + * Register a component. The component's class must satisfy the + * test <code>Injectable.class.isAssignableFrom(type);</code> + * to ensure that the provided component implements the lifecycle + * mechanisms necessary to auto-wire. + * + */ + public void registerType(Object key, AutoWiringAdapter componentAdapter); + + /** + * Register an independent component. This is a convenience registry + * method for those components without dependencies, and which + * have a default constructor. Only classes which fit these + * criteria should be used in this method. + * + */ + public void registerType(Object key, Class<?> implementation); + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java new file mode 100644 index 0000000..56436a5 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/AutoWiringAdapter.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * An adapter interface that's used in the "AutoWiringContainer" + * to allow the user to specify a component's dependencies upon registration. + * This is not ideal, in that it's not auto-discovered constructor-based + * dependency injection, but since dynamic reflection is not available in the + * J2ME CLDC 1.1 spec, an alternate and generic injection mechanism + * is necessary. Implementors of this interface should be CLDC safe. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public interface AutoWiringAdapter { + + /** + * This method should return a list of keys defining the dependencies + * this object requires to operate, in the order expected by the + * create(Object[]) method. + */ + public Object[] dependencies(); + + /** + * Returns the type that this adapter will create. This should be the + * most concrete (narrowest) common type this adapter will create, if + * there is more than one possibility. + */ + public Class getType(); + + /** + * A method that implementors use to create a component given a set of + * parameters. Callers must return the parameters in the order provided + * by the dependencies() method. + */ + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException; + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java new file mode 100644 index 0000000..0bc0982 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Container.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A container for components that will satisfy requests if the + * component is available. How these component requests are satisfied + * are implementation dependent, as well as how inter-component + * dependencies are resolved. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + * + */ +public interface Container { + + /** + * Returns true if the Component is available and prepared. + * It throws a ContainerNotStarted runtime exception if the this method + * is used before the container is started. + * + * This method must be implemented by implementors of Container in a + * thread-safe and reentrant way. + */ + public boolean hasComponent(Object key); + + /** + * Returns the component named by the key if it is available, or null if no + * such component is available. It throws a ContainerNotStarted runtime + * exception if this method is used before the container is started. + * + * This method must be implemented by implementors of Container in a + * thread-safe and reentrant way. + */ + public Object getComponent(Object key); + + /** + * Begin the lifecycle of the container, after which components should be + * accessible. Implementors should stop any component registration as of + * the start() call. Subsequent start() calls should be ignored. + */ + public void start(); + + /** + * Returns true if the container has been started, and false if it has + * not been started. + */ + public boolean isRunning(); + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java new file mode 100644 index 0000000..89d3b11 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultAutoWiringAdaptableContainer.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2008-2009 Israfil Consulting Services Corporation + * Copyright (c) 2008-2009 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + + + +/** + * A deprecated class that was the old name for DefaultContainer. + * Maintained to reduce API breakage. + * @Deprecated Class renamed to DefaultContainer. + */ +public class DefaultAutoWiringAdaptableContainer extends DefaultContainer { + + public DefaultAutoWiringAdaptableContainer() { + super(); + } + + public DefaultAutoWiringAdaptableContainer(boolean failEarly) { + super(failEarly); + } + + public DefaultAutoWiringAdaptableContainer(Container parent, + boolean failEarly) { + super(parent, failEarly); + } + + public DefaultAutoWiringAdaptableContainer(Container parent) { + super(parent); + } + + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java new file mode 100644 index 0000000..f11dc47 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/DefaultContainer.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import java.util.HashMap; +import java.util.Map; + +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; +import net.israfil.foundation.container.error.CouldNotCreateComponentError; +import net.israfil.foundation.container.error.UnsatisfiedDependencyError; +import net.israfil.foundation.container.util.CyclicalReferenceDetectionUtil; +import net.israfil.foundation.container.util.NonDuplicateStack; + + +/** + * A default implementation of AutoWiringAdaptableContainer, a Container + * that uses an AutoWiringAdapter to ensure that components can be + * created appropriately with their dependencies satisfied automatically. + * + * This adapter is intended for constructor injection, but relies on the + * adapter to perform such. No reflection is used by this class itself. + * + */ +public class DefaultContainer extends AbstractContainer implements AutoWiringAdaptableContainer { + + private Map<Object,Object> registry = new HashMap<Object,Object>(); + + private final boolean failEarly; + + private boolean starting = false; + + private final Object CREATION_MUTEX = new Object(); + + /** + * A default constructor that will throw errors regarding circular + * dependencies at registration time, throw missing dependency errors + * at wire-up (getComponent()) time, and has no parent. + * + * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time. + */ + public DefaultContainer() { + super(); + this.failEarly = false; + } + + /** + * Construct this container such that it detects missing dependencies + * upon invocation of start(). Otherwise, it will fail at wire time, + * rather than at registration time. Circular references will give errors + * at registration time. + * + * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time. + */ + public DefaultContainer(boolean failEarly) { + super(); + this.failEarly = failEarly; + } + + /** + * This method constructs a DefaultAutoWiringAdaptableContainer that + * has a parent container for backup resolution. The parent container + * can be of any type of Container. + * + * @param parent The parent container (optional) + */ + public DefaultContainer(Container parent) { + super(parent); + this.failEarly = false; + } + + /** + * Construct this container such that it detects missing dependencies + * upon invocation of start(). Otherwise, it will fail at wire time, + * rather than at registration time. Circular references will give errors + * at registration time. This method also provides for a parent container. + * The parent container can be of any type of Container. + * + * @param failEarly A boolean to indicate that this container should detect missing or circular dependencies at start() time. + * @param parent The parent Container (optional) + */ + public DefaultContainer(Container parent, boolean failEarly) { + super(parent); + this.failEarly = failEarly; + } + + public synchronized void start() { + if (isRunning() || + starting) return; + if (getParent() != null && !getParent().isRunning()) throw new RuntimeException("Parent container is not started."); + this.starting = true; + if (failEarly) { + for (Object key : registry.keySet()) { + // force get each component, forcing all wiring. + Object ignore = getComponent(key); + if (false) ignore.hashCode(); // cover warning - compiler should remove + } + } + super.start(); + starting = false; + } + + public void registerType(Object key, Class<?> componentType) { + registerType(key,componentType, 0); + } + + protected void registerType(Object key, Class<?> componentType, long timeout) { + registerType(key,new IndependentAutoWiringAdapter(componentType), timeout); + } + + public void registerType(Object key, AutoWiringAdapter componentAdapter) { + registerType(key,componentAdapter,0); + } + + /** + * Registers a component for later instantiation and (optionally) startup. + * + * @param key the key by which this component will be identified in the system + * @param componentAdapter an AutoWiringAdapter for creating this component and listing its dependencies + * @param timeout an (optional) timeout applied to any startup lifecycle + */ + protected void registerType(Object key, AutoWiringAdapter componentAdapter, long timeout) { + if (this.isRunning()) throw new RuntimeException("Cannot register when container is started."); + // FIXME: Figure out whether to support parent registry checking. Probably can't do it. + + if (registry.containsKey(key)) throw new ComponentAlreadyRegisteredError("Component already registered for " + key); + detectCircularDependencies(key,componentAdapter); + registry.put(key, componentAdapter); + } + + private void detectCircularDependencies(Object key,AutoWiringAdapter componentAdapter) { + NonDuplicateStack nds = new NonDuplicateStack(); + nds.push(key); + CyclicalReferenceDetectionUtil.detectCircularDependencies(this.registry, nds, componentAdapter); + } + + /** + * This method wires the object up with its dependencies, providing said + * dependencies to the object's adapter. It also starts the object if its + * startable + * @param originalKey + * @param adapter + * @return + */ + private Object wireObject(Object originalKey, AutoWiringAdapter adapter) { + Object[] dependencies = adapter.dependencies(); + Object[] parameters = new Object[dependencies.length]; + for (int depn = 0; depn < dependencies.length; depn++ ) { + Object key = adapter.dependencies()[depn]; + parameters[depn] = getComponent(key); + if (parameters[depn] == null) throw new UnsatisfiedDependencyError("Could not materialize dependency for key " + key); + } + try { + Object o = adapter.create(parameters); + if (o == null) throw new InstantiationException("Could not create a non-null object. Adapter " + adapter.getClass().getName() + " returned null."); + else { + try { + Startable s = ((Startable)o); + if (!s.isRunning()) s.start(); + } catch (ClassCastException e) {} + return o; + } + } catch (IllegalAccessException e) { + throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e); + } catch (InstantiationException e) { + throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e); + } catch (Throwable e) { + throw new CouldNotCreateComponentError("Could not create component " + originalKey + " of type " + adapter.getType(),e); + } + } + + public Object getComponent(Object key) { + Object component = super.getStoredComponent(key); + if (component == null && registry.containsKey(key)) { + synchronized (CREATION_MUTEX) { + if (component == null) { // in case following thread gets in just after storage. + component = wireObject(key,(AutoWiringAdapter)registry.get(key)); + store(key, component); + } + } + } + return component; + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java new file mode 100644 index 0000000..34b0399 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/Startable.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +/** + * A simple interface that, if implemented, allows a component + * to participate in a startup phase of lifecycle. + */ +public interface Startable { + + /** + * Begin the lifecycle of the component, after which it should be + * usable. This component should only act on its own startup + * lifecycle, and should assume that any components that are + * provided through dependency injection are already started + * before this command is executed. + */ + public void start(); + + /** + * Returns true if the container has been started, and false if it has + * not been started. + */ + public boolean isRunning(); + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java new file mode 100644 index 0000000..6500275 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/AbstractAutoWiringAdapter.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.adapters; + +import net.israfil.foundation.container.AutoWiringAdapter; + +/** + * A convenience implementation of AutoWiringAdapter which can be used + * for those clases that have no dependencies and have a default constructor. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public abstract class AbstractAutoWiringAdapter implements AutoWiringAdapter{ + + private final Object[] dependencies; + + private final Class type; + + public AbstractAutoWiringAdapter(Class type, Object[] dependencies) { + if (type == null) + throw new IllegalArgumentException("An independent component must have a type."); + this.type = type; + this.dependencies = dependencies; + } + + public Object[] dependencies() { return dependencies; } + + public Class getType() { return type; } + + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java new file mode 100644 index 0000000..ff945a8 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/adapters/IndependentAutoWiringAdapter.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.adapters; + +import java.util.Map; + +/** + * A convenience implementation of AutoWiringAdapter which can be used + * for those clases that have no dependencies and have a default constructor. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public class IndependentAutoWiringAdapter extends AbstractAutoWiringAdapter{ + + private static final Object[] NO_DEPENDENCIES = {}; + + public IndependentAutoWiringAdapter(Class type) { + super(type, NO_DEPENDENCIES); + } + + /** + * This method implements AutoWiringAdapter.create() but throws + * a runtime exception if any parameters are passed, and uses + * the default (no parameter) constructor via Class.newInstance(); + * to generate the new instance. + */ + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException { + if (parameters != null && parameters.length > 0) + throw new IllegalArgumentException("Cannot pass any parameters to the creation of an independent component."); + return getType().newInstance(); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java new file mode 100644 index 0000000..a065d81 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredError.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +public class ComponentAlreadyRegisteredError extends RuntimeException { + + private static final long serialVersionUID = 7557424125890830358L; + + public ComponentAlreadyRegisteredError() { + super(); + } + + public ComponentAlreadyRegisteredError(String message) { + super(message); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java new file mode 100644 index 0000000..f8f9563 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CouldNotCreateComponentError.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + + +public class CouldNotCreateComponentError + extends RuntimeException { + + private static final long serialVersionUID = 398473685547742652L; + + public CouldNotCreateComponentError() { + super(); + } + + public CouldNotCreateComponentError(Throwable t) { + super(t); + } + + public CouldNotCreateComponentError(String message) { + super(message); + } + + public CouldNotCreateComponentError(String message, Throwable t) { + super(message,t); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java new file mode 100644 index 0000000..067e364 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/CyclicalDependencyError.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +public class CyclicalDependencyError extends RuntimeException { + + private static final long serialVersionUID = 2260997982445143566L; + + public CyclicalDependencyError() { + super(); + } + + public CyclicalDependencyError(String message) { + super(message); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java new file mode 100644 index 0000000..3110fb9 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/error/UnsatisfiedDependencyError.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +public class UnsatisfiedDependencyError extends RuntimeException { + + private static final long serialVersionUID = 502309807798988770L; + + public UnsatisfiedDependencyError() { + super(); + } + + public UnsatisfiedDependencyError(String message) { + super(message); + } + +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java new file mode 100644 index 0000000..eb9f25c --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/CyclicalReferenceDetectionUtil.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.Map; + +import net.israfil.foundation.container.AutoWiringAdapter; +import net.israfil.foundation.container.error.CyclicalDependencyError; + +/** + * A utility class that provides convenience methods for circular + * reference detection. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public class CyclicalReferenceDetectionUtil { + public static void detectCircularDependencies(Map registry, NonDuplicateStack nds, AutoWiringAdapter componentAdapter) { + Object[] deps = componentAdapter.dependencies(); + for (int i = 0; i < deps.length; i++) { + if (registry.containsKey(deps[i])) { + try { + nds.push(deps[i]); + } catch (IllegalArgumentException e) { + throw new CyclicalDependencyError("Item " + deps[i] + " is involved in a cyclic dependency. The full path is: " + nds); + } + detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(deps[i])); + nds.pop(); + } + } + } +} diff --git a/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java new file mode 100644 index 0000000..d253024 --- /dev/null +++ b/israfil-foundation-container/src/main/java/net/israfil/foundation/container/util/NonDuplicateStack.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.Stack; + +/** + * A simple stack object which throws an IllegalArgumentException if an + * attempt is made to push an object already contained within the stack. + * + * Primarily used for circular reference detection. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public class NonDuplicateStack<T> extends Stack<T> { + + private static final long serialVersionUID = -5777711467165769847L; + + public T push(T item) { + if (contains(item)) throw new IllegalArgumentException("Duplicate item."); + return super.push(item); + } + +} diff --git a/israfil-foundation-container/src/site/apt/index.apt b/israfil-foundation-container/src/site/apt/index.apt new file mode 100755 index 0000000..10a0281 --- /dev/null +++ b/israfil-foundation-container/src/site/apt/index.apt @@ -0,0 +1,45 @@ + ------
+ Israfil Micro-Container
+ ------
+ Christian Edward Gruber
+ ------
+ May 2, 2007
+
+Overview
+
+ The micro-container is an extremely lightweight IoC container supporting
+ dependency injection. It is built with the principles in mind that
+ spawned {{{http://www.picocontainer.org/} pico-container}} but with the
+ explicit constraints to which J2ME applications centered around the
+ CLDC 1.1 are bound. This includes a complete absence of any constructor
+ or method lookup (reflection) or dynamic proxy support.
+
+ Like pico-container, Israfil's micro-container only handles the
+ registration and vending of components, not additional services such as
+ persistence, and the like.
+
+Isn't Micro bigger than Pico?
+
+ Yes, but micro-container wasn't as taken, and israfil-micro is a placeholder
+ for any further frameworks that might be developed in the J2ME footprint.
+ I briefly considered femto-container, but it was too obscure even for me.
+
+Can I use this in commercial or other software?
+
+ Yes. The micro-container, as with all Israfil Micro and Foundation libraries
+ are licensed under the terms of the BSD license, which provides you with a
+ license to distribute with or without modification, and to prepare derivative
+ works, with the sole exception that you retain the notice (specific terms
+ are available in the license page linked from the menu.) The short answer
+ is yes, go for it, it won't cost you a penny, and you won't be obliged to
+ show anyone your code.
+
+How do I use it?
+
+ I recommend looking at pico-container's site for really good theoretical
+ presentations of this kind of software. Tapestry5 also contains an ioc
+ framework par-excellence, and it has some ok docs. Some specific usage
+ documentation for this framework (around staging the container and getting
+ things set up in a practical application) are available in the usage page
+ linked from the menu.
+
\ No newline at end of file diff --git a/israfil-foundation-container/src/site/apt/lifecycle.apt b/israfil-foundation-container/src/site/apt/lifecycle.apt new file mode 100644 index 0000000..3a62be5 --- /dev/null +++ b/israfil-foundation-container/src/site/apt/lifecycle.apt @@ -0,0 +1,111 @@ + ------ + Israfil Micro-Container : Component Lifecycle + ------ + Christian Edward Gruber + ------ + May 2, 2007 + + + Since one bad pattern in java is to engage in all sorts of side behaviours + during construction, components can separate construction from initialization + by implementing the Startable interface. Startable components are started + before they are provided to any caller. + +%{toc} + +The Startable interface + + The Startable interface is quite simple: + +------------------- + +package net.israfil.micro.container; + +public interface Startable { + + public void start(); + + public boolean isRunning(); + +} + +------------------- + + Implementors should start whatever they need to in order to be ready to + accept calls, including marshalling any resources necessary, etc. + + Care should be taken to time-out appropriately, as the container offers + its thread to the component during this initialization, and faulty + initialization can lock the container. + +Registering components with dependencies + + Registration of components with dependencies is a bit more complicated, as it + requires an adapter: + +------------------- + +public void registerType(Object key, AutoWiringAdapter componentAdapter); + +------------------- + + AutoWiringAdapters can be created on the fly, for instance by using an anonymous + inner class that implements AutoWiringAdapter or extending AbstractAutoWiringAdapter: + +------------------- + +container.registerType(ComponentThree.class,new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } +}); + +------------------- + + Another option is to create a constant adapter on the component itself + +------------------- + +public class ComponentThreeImpl implements ComponentThree { + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } + }); + + private final ComponentOne one; + + public ComponentThreeImpl(ComponentOne one) { + this.one = one; + } + + public void doStuff() { one.whatever(); } +} + +------------------- + + Having created this adapter constant, you can then more easily register the + component in the following way: + +------------------- + +container.registerType(ComponentThree.class,ComponentThreeImpl.adapter); + +------------------- + +Retrieving components + + Retrieving components is quite simple, using the getComponent method. + +------------------- + +ComponentThree three = (ComponentThree)container.getComponent(ComponentThree.class); +three.doStuff(); + +------------------- + + diff --git a/israfil-foundation-container/src/site/apt/usage.apt b/israfil-foundation-container/src/site/apt/usage.apt new file mode 100644 index 0000000..54ce418 --- /dev/null +++ b/israfil-foundation-container/src/site/apt/usage.apt @@ -0,0 +1,106 @@ + ------ + Israfil Micro-Container : Usage + ------ + Christian Edward Gruber + ------ + May 2, 2007 + + + The default container is an auto-wiring container which allows for registration + of components quite simply, if they have no dependencies. Components with + dependencies require the use of an adapter which explicitly declares the + dependencies, and provides a builder method which receives the dependencies and + explicitly constructs the component, avoiding any use of reflection, which is + not supported in the CLDC 1.1 profile. + +%{toc} + +Setting up the auto-wiring container. + + Setting up the container should be done early in your entry-point code. + The default container auto-wires components on first use of the component, + unless configured to pre-initialize them. This allows for early creation + of the container and registration of components without incurring the + up-front performance cost. + + Registration for independent components works quite simply: + +------------------- + +AutoWiringAdaptableContainer container = new DefaultAutoWiringAdaptablecContainer(); +container.registerType(ComponentOne.class,ComponentOneImpl.class); +container.registerType(ComponentTwo.class,ComponentTwoImpl.class); + +------------------- + +Registering components with dependencies + + Registration of components with dependencies is a bit more complicated, as it + requires an adapter: + +------------------- + +public void registerType(Object key, AutoWiringAdapter componentAdapter); + +------------------- + + AutoWiringAdapters can be created on the fly, for instance by using an anonymous + inner class that implements AutoWiringAdapter or extending AbstractAutoWiringAdapter: + +------------------- + +container.registerType(ComponentThree.class,new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } +}); + +------------------- + + Another option is to create a constant adapter on the component itself + +------------------- + +public class ComponentThreeImpl implements ComponentThree { + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + ComponentThree.class, new Object[] {ComponentOne.class} + ) { + public Object create(Object[] params) throws IllegalAccessException, InstantiationException { + return new ComponentThreeImpl((ComponentOne)params[0]); + } + }); + + private final ComponentOne one; + + public ComponentThreeImpl(ComponentOne one) { + this.one = one; + } + + public void doStuff() { one.whatever(); } +} + +------------------- + + Having created this adapter constant, you can then more easily register the + component in the following way: + +------------------- + +container.registerType(ComponentThree.class,ComponentThreeImpl.adapter); + +------------------- + +Retrieving components + + Retrieving components is quite simple, using the getComponent method. + +------------------- + +ComponentThree three = (ComponentThree)container.getComponent(ComponentThree.class); +three.doStuff(); + +------------------- + + diff --git a/israfil-foundation-container/src/site/site.xml b/israfil-foundation-container/src/site/site.xml new file mode 100644 index 0000000..d580c65 --- /dev/null +++ b/israfil-foundation-container/src/site/site.xml @@ -0,0 +1,20 @@ +<project>
+ <body>
+ <menu name="Parent"> + <item name="${parent.name}" href="../index.html"/> + </menu> + <menu name="Overview">
+ <item name="Introduction" href="index.html"/>
+ <item name="Usage" href="usage.html"/> + <item name="Lifecycle" href="lifecycle.html"/> + <!-- <item name="FAQ" href="faq.html"/> -->
+ </menu> + <!--
+ <menu name="Examples">
+ <item name="Simple Flex app in a WAR project" href="examples/simple_war_project.html"/> + <item name="Flex app with extra params" href="examples/extra_parameters_project.html"/> + </menu> + -->
+ ${reports}
+ </body>
+</project>
\ No newline at end of file diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java new file mode 100644 index 0000000..ab0e624 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/ContainerTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; + +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +public class ContainerTest { + + AbstractContainer container = null; + AbstractContainer child = null; + + + @BeforeMethod(alwaysRun=true) + public void setUp() { + container = new AbstractContainer() { + public void start() { } + public Object getComponent(Object key) { return getStoredComponent(key); } + }; + child = new AbstractContainer(container) { + public void start() { } + public Object getComponent(Object key) { return getStoredComponent(key); } + }; + } + + @AfterMethod(alwaysRun=true) + public void tearDown() { + child = null; + container = null; + } + + @Test + public void testContainerWithSingleComponent() { + FakeComponent component = new FakeComponent1(); + container.store(FakeComponent.class, component); + Assert.assertSame(container.getComponent(FakeComponent.class), component); + } + + @Test + public void testContainerWithMultipleComponents() { + FakeComponent component = new FakeComponent1(); + FakeDependentComponent component2 = new FakeDependentComponent(component); + container.store(FakeComponent.class, component); + container.store(FakeDependentComponent.class, component2); + Assert.assertSame(container.getComponent(FakeComponent.class), component); + Assert.assertSame(container.getComponent(FakeDependentComponent.class), component2); + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testContainerWithDuplicateComponents() { + FakeComponent component1 = new FakeComponent1(); + FakeComponent component2 = new FakeComponent2(); + container.store(FakeComponent.class,component1); + container.store(FakeComponent.class,component2); + } + + @Test + public void testContainerWithRepeatedRegistrationsOfTheSameComponent() { + FakeComponent component1 = new FakeComponent1(); + container.store(FakeComponent.class,component1); + container.store(FakeComponent.class,component1); + } + + @Test + public void testContainerWithParent() { + FakeComponent component1 = new FakeComponent1(); + container.store(FakeComponent.class,component1); + Assert.assertTrue(child.hasComponent(FakeComponent.class)); + Assert.assertSame(child.getComponent(FakeComponent.class), component1); + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testDuplicateRegistrationWithFirstObjectInParent() { + FakeComponent component1 = new FakeComponent1(); + FakeComponent component2 = new FakeComponent2(); + container.store(FakeComponent.class,component1); + child.store(FakeComponent.class,component2); + } + + @Test + public void testDuplicateComponentsInPeerContainers() { + AbstractContainer child2 = new AbstractContainer(container) { + public void start() { } + public Object getComponent(Object key) { return getStoredComponent(key); } + }; + FakeComponent component1 = new FakeComponent1(); + FakeComponent component2 = new FakeComponent2(); + child.store(FakeComponent.class,component1); + child2.store(FakeComponent.class,component2); + Assert.assertTrue(child.hasComponent(FakeComponent.class)); + Assert.assertSame(child.getComponent(FakeComponent.class), component1); + Assert.assertNotSame(child2.getComponent(FakeComponent.class), component1); + Assert.assertTrue(child2.hasComponent(FakeComponent.class)); + Assert.assertSame(child2.getComponent(FakeComponent.class), component2); + Assert.assertNotSame(child2.getComponent(FakeComponent.class), component1); + Assert.assertFalse(container.hasComponent(FakeComponent.class)); + } + + public abstract class FakeComponent { + public abstract boolean isTrue(); + } + public class FakeComponent1 extends FakeComponent { + public boolean isTrue() { return false; } + } + public class FakeComponent2 extends FakeComponent { + public boolean isTrue() { return false; } + } + public class FakeDependentComponent { + private final FakeComponent fake; + public FakeDependentComponent(FakeComponent component) { + this.fake = component; + } + public boolean isTrue() { return fake.isTrue(); } + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java new file mode 100644 index 0000000..1d108b0 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/DefaultContainerTest.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + + +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; +import net.israfil.foundation.container.error.ComponentAlreadyRegisteredError; +import net.israfil.foundation.container.error.CouldNotCreateComponentError; +import net.israfil.foundation.container.error.UnsatisfiedDependencyError; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class DefaultContainerTest { + + + public DefaultContainer createContainer() { return new DefaultContainer(); } + public DefaultContainer createContainer(boolean tf) { return new DefaultContainer(tf); } + public DefaultContainer createContainer(Container c) { return new DefaultContainer(c); } + public DefaultContainer createContainer(Container c, boolean tf) { return new DefaultContainer(c,tf); } + public TestableContainer createTestableContainer() { return new TestableDefaultContainer(); } + + @Test + public void testAutoWiringContainer() { + TestableContainer container = createTestableContainer(); + container.registerType(A.class, A1.class); + container.registerType(B.class,B.adapter); + container.registerType(D.class,D.adapter); // out of order + container.registerType(C.class, new AbstractAutoWiringAdapter( + C.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new C((A)param[0]); + } + }); + container.start(); + Assert.assertFalse(container.isStored(A.class)); + Assert.assertNotNull(container.getComponent(A.class)); + Assert.assertTrue(container.isStored(A.class)); + Assert.assertFalse(container.isStored(B.class)); + Assert.assertNotNull(container.getComponent(B.class)); + Assert.assertTrue(container.isStored(B.class)); + Assert.assertFalse(container.isStored(C.class)); + Assert.assertFalse(container.isStored(D.class)); + Assert.assertNotNull(container.getComponent(D.class)); + Assert.assertTrue(container.isStored(C.class)); + Assert.assertTrue(container.isStored(D.class)); + } + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testMissingDependenciesFailingLate() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(B.class,B.adapter); + container.start(); + Assert.assertTrue(container.isRunning()); + container.getComponent(B.class); + } + + @Test + public void testDelayedFailureWithMissingDependencies() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(B.class,B.adapter); + container.start(); + } + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testMissingDependenciesFailingEarly() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(B.class,B.adapter); + container.start(); + } + + @Test + public void testMultipleStartups() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,A1.class); + container.registerType(B.class,B.adapter); + container.start(); + Assert.assertTrue(container.isRunning()); + container.start(); // no error. + } + + @Test(expectedExceptions=RuntimeException.class) + public void testStartupWithUnstartedParent() { + AutoWiringAdaptableContainer parent = createContainer(); + AutoWiringAdaptableContainer child = createContainer(parent); + parent.registerType(A.class,A1.class); + child.registerType(B.class,B.adapter); + child.start(); // failed to start parent. + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testDuplicateRegistration() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(A.class,A1.class); + container.registerType(A.class,new AutoWiringAdapter() { + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException { + return null; + } + public Object[] dependencies() { return null; } + public Class getType() { return null; } + }); + } + + @Test(expectedExceptions=RuntimeException.class) + public void testRegistryFailureAfterStart() { + AutoWiringAdaptableContainer container = createContainer(); + container.registerType(A.class,A1.class); + container.registerType(B.class,B.adapter); + container.start(); + container.registerType(D.class,D.adapter); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testIllegalAccessDuringConstruction() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(ComponentWithProtectedConstructor.class,ComponentWithProtectedConstructor.class); + container.start(); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testInstantiationErrorDuringConstruction() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,A.class); + container.start(); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testNullComponentCreation() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,new IndependentAutoWiringAdapter(A.class) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return null; + } + }); + container.start(); + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testArbitraryErrorInComponentCreation() { + AutoWiringAdaptableContainer container = createContainer(true); + container.registerType(A.class,new IndependentAutoWiringAdapter(A.class) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + throw new RuntimeException("Random error"); + } + }); + container.start(); + } + + + @Test + public void testAutowiringWithDependencyInParentContainerWithEarlyInstantiation() { + AutoWiringAdaptableContainer parent = createContainer(true); + AutoWiringAdaptableContainer child = createContainer(parent,true); + parent.registerType(A.class,A1.class); + child.registerType(B.class,B.adapter); + parent.start(); + child.start(); + Assert.assertNotNull(child.getComponent(B.class)); + } + + @Test + public void testAutowiringWithDependencyInParentContainerWithLateIntantiation() { + AutoWiringAdaptableContainer parent = createContainer(); + AutoWiringAdaptableContainer child = createContainer(parent); + parent.registerType(A.class,A1.class); + child.registerType(B.class,B.adapter); + parent.start(); + child.start(); + Assert.assertNotNull(child.getComponent(B.class)); + } + + public static abstract class A { + } + public static class A1 extends A { + } + public static class B { + private final A a; + public B(A a) { + if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments."); + this.a = a; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + B.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new B((A)param[0]); + } + }; + } + public static class C { + private final A a; + public C(A a) { + if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments."); + this.a = a; + } + } + public static class D { + private final C c; + public D(C c) { + if (c==null) throw new IllegalArgumentException("D cannot support null constructor arguments."); + this.c = c; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + D.class, + new Object[] {C.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new D((C)param[0]); + } + }; + } + + public static class ComponentWithProtectedConstructor { + protected ComponentWithProtectedConstructor() {} + } + + public static interface TestableContainer extends AutoWiringAdaptableContainer { + public boolean isStored(Object key); + } + + public static class TestableDefaultContainer extends DefaultContainer implements TestableContainer { + public boolean isStored(Object key) { + return super.isStored(key); + } + } + + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java new file mode 100644 index 0000000..4e69610 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LegacyContainerTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + + + +public class LegacyContainerTest extends DefaultContainerTest { + + public DefaultContainer createContainer() { return new DefaultAutoWiringAdaptableContainer(); } + public DefaultContainer createContainer(boolean tf) { return new DefaultAutoWiringAdaptableContainer(tf); } + public DefaultContainer createContainer(Container c) { return new DefaultAutoWiringAdaptableContainer(c); } + public DefaultContainer createContainer(Container c, boolean tf) { return new DefaultAutoWiringAdaptableContainer(c,tf); } + public TestableContainer createTestableContainer() { return new TestableLegacyContainer(); } + + public static class TestableLegacyContainer extends DefaultAutoWiringAdaptableContainer implements TestableContainer { + public boolean isStored(Object key) { + return super.isStored(key); + } + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java new file mode 100644 index 0000000..920f17c --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/LifecycleTest.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class LifecycleTest { + + @Test() + public void testAbstractStartable() { + Startable s = new AbstractStartable() {}; + Assert.assertFalse(s.isRunning()); + s.start(); + Assert.assertTrue(s.isRunning()); + } + + @Test() + public void testStartupOfSingleComponent() { + AutoWiringAdaptableContainer container = new DefaultContainer(); + final A1 a1 = new A1(); + container.registerType(A.class, new IndependentAutoWiringAdapter(A1.class) { + public Object create(Object[] args) { return a1; } + }); + Assert.assertFalse(a1.isRunning()); + container.start(); + container.getComponent(A.class); + Assert.assertTrue(a1.isRunning()); + } + + @Test() + public void testStartupOfStartedComponent() { + AutoWiringAdaptableContainer container = new DefaultContainer(); + final A2 a2 = new A2(); + a2.start(); + container.registerType(A.class, new IndependentAutoWiringAdapter(A.class) { + public Object create(Object[] args) { return a2; } + }); + container.start(); + container.getComponent(A.class); + Assert.assertEquals(a2.invoked,1); + } + + @Test() + public void testStartupOfMultipleComponents() { + AutoWiringAdaptableContainer container = new DefaultContainer(); + final A1 a1 = new A1(); + final C c = new C(a1); + container.registerType(A.class, new IndependentAutoWiringAdapter(A1.class) { + public Object create(Object[] args) { return a1; } + }); + container.registerType(B.class, B.adapter); + container.registerType(C.class, new AbstractAutoWiringAdapter( + C.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return c; + } + }); + Assert.assertFalse(a1.isRunning()); + Assert.assertFalse(c.isRunning()); + container.start(); + container.getComponent(A.class); + Assert.assertFalse(c.isRunning()); + Assert.assertTrue(a1.isRunning()); + container.getComponent(C.class); + Assert.assertTrue(c.isRunning()); + Assert.assertTrue(a1.isRunning()); + } + + public static interface A { + } + + public static class A1 extends AbstractStartable implements A { + public void start() { super.start(); } + } + + public static class A2 extends AbstractStartable implements A { + public int invoked = 0; + public void start() { + super.start(); + invoked++; + } + } + + public static class B { + private final A a; + public B(A a) { + if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments."); + this.a = a; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + B.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new B((A)param[0]); + } + }; + } + public static class C extends AbstractStartable implements Startable{ + private final A a; + public C(A a) { + if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments."); + this.a = a; + } + public void start() { super.start(); } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + C.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new C((A)param[0]); + } + }; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java new file mode 100644 index 0000000..dabc119 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/MultiThreadedAutoWiringContainerTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container; + +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class MultiThreadedAutoWiringContainerTest { + + @Test() + public void testMissingDependenciesWiringEarly() { + AutoWiringAdaptableContainer container = new DefaultContainer(true); + container.registerType(A.class,A1.class); + container.registerType(B.class,B.adapter); + container.start(); + Assert.assertNotNull(container.getComponent(B.class)); + } + + public static abstract class A { + } + public static class A1 extends A { + } + public static class B { + private final A a; + public B(A a) { + if (a==null) throw new IllegalArgumentException("B cannot support null constructor arguments."); + this.a = a; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + B.class, + new Object[] {A.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new B((A)param[0]); + } + }; + } + public static class C { + private final A a; + public C(A a) { + if (a==null) throw new IllegalArgumentException("C cannot support null constructor arguments."); + this.a = a; + } + } + public static class D { + private final C c; + public D(C c) { + if (c==null) throw new IllegalArgumentException("D cannot support null constructor arguments."); + this.c = c; + } + public static final AutoWiringAdapter adapter = new AbstractAutoWiringAdapter( + D.class, + new Object[] {C.class} + ) { + public Object create(Object[] param) throws IllegalAccessException, InstantiationException { + return new D((C)param[0]); + } + }; + } + + public static class E { + protected E() {} + } + + public static class TestableAutoWiringAdaptableContainer extends DefaultContainer { + public boolean isStored(Object key) { + return super.isStored(key); + } + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java new file mode 100644 index 0000000..62150ed --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/adapters/AdaptersTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.adapters; + +import net.israfil.foundation.container.AutoWiringAdapter; + +import org.testng.Assert; +import org.testng.annotations.Test; + +/** + * Tests + * @author cgruber + * + */ +public class AdaptersTest { + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testIndependentAutoWiringAdapterWithNullType() { + new IndependentAutoWiringAdapter(null); + } + + @Test + public void testIndependentAutoWiringAdapterWithEmptyParamters() throws Exception { + AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class); + Fake fake = (Fake)awa.create(new Object[0]); + Assert.assertNotNull(fake); + } + + @Test + public void testIndependentAutoWiringAdapterWithNullParamters() throws Exception { + AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class); + Fake fake = (Fake)awa.create(null); + Assert.assertNotNull(fake); // should not reach this assert. + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testIndependentAutoWiringAdapterWithNonEmptyParamters() throws Exception { + AutoWiringAdapter awa = new IndependentAutoWiringAdapter(Fake.class); + Object[] parameters = new Object[1]; + parameters[0] = "A"; + Fake fake = (Fake)awa.create(parameters); + Assert.assertNotNull(fake); // should not reach this assert. + } + + public static class Fake { + public Fake() {} + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java new file mode 100644 index 0000000..fdaa7fa --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/ComponentAlreadyRegisteredErrorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class ComponentAlreadyRegisteredErrorTest { + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new ComponentAlreadyRegisteredError(); + throw error; + } + + @Test(expectedExceptions=ComponentAlreadyRegisteredError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new ComponentAlreadyRegisteredError("test"); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java new file mode 100644 index 0000000..87d43a4 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CouldNotCreateComponentTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class CouldNotCreateComponentTest { + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new CouldNotCreateComponentError(); + throw error; + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new CouldNotCreateComponentError("test"); + throw error; + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrowWithThrowable() { + RuntimeException error = new CouldNotCreateComponentError( + new RuntimeException("test2") + ); + throw error; + } + + @Test(expectedExceptions=CouldNotCreateComponentError.class) + public void testSimpleErrorThrowWithStringAndThrowable() { + RuntimeException error = new CouldNotCreateComponentError( + "test", + new RuntimeException("test2") + ); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java new file mode 100644 index 0000000..fc2fd93 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/CyclicalDependencyErrorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class CyclicalDependencyErrorTest { + + @Test(expectedExceptions=CyclicalDependencyError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new CyclicalDependencyError(); + throw error; + } + + @Test(expectedExceptions=CyclicalDependencyError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new CyclicalDependencyError("test"); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java new file mode 100644 index 0000000..c668b5d --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/error/UnsatisfiedDependencyErrorTest.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.error; + +import org.testng.annotations.Test; + + + +public class UnsatisfiedDependencyErrorTest { + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testSimpleErrorThrow() throws Throwable { + Throwable error = new UnsatisfiedDependencyError(); + throw error; + } + + @Test(expectedExceptions=UnsatisfiedDependencyError.class) + public void testSimpleErrorThrowWithString() throws Throwable { + Throwable error = new UnsatisfiedDependencyError("test"); + throw error; + } + +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java new file mode 100644 index 0000000..781ad92 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/CyclicalDependencyDetectionTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.HashMap; +import java.util.Map; + +import net.israfil.foundation.container.AutoWiringAdapter; +import net.israfil.foundation.container.adapters.AbstractAutoWiringAdapter; +import net.israfil.foundation.container.adapters.IndependentAutoWiringAdapter; +import net.israfil.foundation.container.error.CyclicalDependencyError; + +import org.testng.annotations.Test; + + +public class CyclicalDependencyDetectionTest { + + @Test() + public void testCircularDependencyCheckWithNonCyclicGraph() { + // setup non-circular graph. + Map<Object,Object> registry = new HashMap<Object,Object>(); + registry.put("a", new FakeAutoWireAdapter(new Object[]{"b","e","d"})); + registry.put("b", new FakeAutoWireAdapter(new Object[]{"f","c"})); + registry.put("c", new IndependentAutoWiringAdapter(Object.class)); + registry.put("d", new FakeAutoWireAdapter(new Object[]{"e"})); + registry.put("e", new FakeAutoWireAdapter(new Object[]{"c"})); + registry.put("f", new IndependentAutoWiringAdapter(Object.class)); + NonDuplicateStack<Object> nds = new NonDuplicateStack<Object>(); + for (Object key : registry.keySet()) { + nds.push(key); + CyclicalReferenceDetectionUtil.detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(key)); + nds.pop(); + } + } + + @Test(expectedExceptions=CyclicalDependencyError.class) + public void testCircularDependencyCheckWithCyclicalGraph() { + // setup circular graph. + Map<Object,Object> registry = new HashMap<Object,Object>(); + registry.put("a", new FakeAutoWireAdapter(new Object[]{"b","e","d"})); + registry.put("b", new FakeAutoWireAdapter(new Object[]{"f","c"})); + registry.put("c", new FakeAutoWireAdapter(new Object[]{"d"})); + registry.put("d", new FakeAutoWireAdapter(new Object[]{"e"})); + registry.put("e", new FakeAutoWireAdapter(new Object[]{"c"})); + registry.put("f", new IndependentAutoWiringAdapter(Object.class)); + NonDuplicateStack<Object> nds = new NonDuplicateStack<Object>(); + for (Object key : registry.keySet()) { + nds.push(key); + CyclicalReferenceDetectionUtil.detectCircularDependencies(registry, nds, (AutoWiringAdapter)registry.get(key)); + nds.pop(); + } + } + + + public static class FakeAutoWireAdapter extends AbstractAutoWiringAdapter { + public FakeAutoWireAdapter(Object[] dependencies) { + super(Object.class, dependencies); + } + public Object create(Object[] parameters) throws IllegalAccessException, InstantiationException { + return null; + } + } +} diff --git a/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java new file mode 100644 index 0000000..a67afb0 --- /dev/null +++ b/israfil-foundation-container/src/test/java/net/israfil/foundation/container/util/NonDuplicateStackTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2008 Israfil Consulting Services Corporation + * Copyright (c) 2008 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Copyright.java 618 2008-04-14 14:03:03Z christianedwardgruber $ + */ +package net.israfil.foundation.container.util; + +import java.util.Stack; + +import org.testng.Assert; +import org.testng.annotations.Test; + + +public class NonDuplicateStackTest { + + @Test() + public void testBasicStackBehaviour() { + String s1 = "Hi."; + String s2 = "Hi"; + String s3 = "Bye."; + Stack<Object> stack = new NonDuplicateStack<Object>(); + stack.push(s1); + stack.push(s2); + stack.push(s3); + Assert.assertSame(stack.pop(),s3); + Assert.assertSame(stack.pop(),s2); + Assert.assertSame(stack.pop(),s1); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testDuplicateHandlingByObjectRef() { + Object o1 = new Object(); + Object o2 = new Object(); + Object o3 = new Object(); + Stack<Object> stack = new NonDuplicateStack<Object>(); + stack.push(o1); + stack.push(o2); + stack.push(o3); + stack.push(o2); + } + + @Test(expectedExceptions=IllegalArgumentException.class) + public void testDuplicateHandlingByValue() { + String s1 = "Hi."; + String s2 = "Hi"; + String s3 = "Bye."; + String s4 = "Hi"; + Stack<Object> stack = new NonDuplicateStack<Object>(); + stack.push(s1); + stack.push(s2); + stack.push(s3); + stack.push(s4); + } + +} diff --git a/israfil-foundation-core/pom.xml b/israfil-foundation-core/pom.xml new file mode 100644 index 0000000..5bf65f4 --- /dev/null +++ b/israfil-foundation-core/pom.xml @@ -0,0 +1,21 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-core</artifactId> + <name>Israfil Foundation Core Classes</name> + <version>1.0.2-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + </project>
\ No newline at end of file diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java new file mode 100755 index 0000000..203793c --- /dev/null +++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Copyright.java @@ -0,0 +1,59 @@ +/*
+ * Copyright (c) 2006-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2006-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Copyright.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An attribute used to tag the copyright year, owner, and license. This
+ * is purely for documentation purposes, and it has only a SOURCE scope.
+ *
+ * For example:
+ * <pre>
+ * @Copyright(years={"2003","2004","2005"} owner="Israfil Consulting Services Corporation" license="BSD")
+ * </pre>
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ *
+ * @deprecated
+ */
+@Documented
+@Retention(RetentionPolicy.SOURCE)
+public @interface Copyright {
+ String[] years();
+ String owner();
+ String license();
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java new file mode 100644 index 0000000..e87b86a --- /dev/null +++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Counter.java @@ -0,0 +1,52 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Counter.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+
+/**
+ * A simple counter interface
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Counter {
+
+ public int getCount();
+
+ public void increment();
+
+ public void decrement();
+
+ public void reset();
+
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java new file mode 100644 index 0000000..042f623 --- /dev/null +++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/SimpleCounter.java @@ -0,0 +1,54 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SimpleCounter.java 618 2008-04-14 14:03:03Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+
+/**
+ * A simple counter interface
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class SimpleCounter implements Counter {
+
+ private int count = 0;
+
+ public int getCount() { return count; }
+
+ public void increment() { count++; }
+
+ public void decrement() { count--; }
+
+ public void reset() { count = 0; }
+
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java new file mode 100644 index 0000000..edde901 --- /dev/null +++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Strings.java @@ -0,0 +1,58 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Strings.java 617 2008-04-14 13:46:15Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+import java.util.Arrays;
+
+/**
+ * A Utility class that provides general string manipulation help.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: christianedwardgruber $
+ * @version $Revision: 617 $
+ */
+public class Strings {
+
+ public static String camel(String string) {
+ if (string == null) return null;
+ if (string.length() < 1) return string;
+ StringBuffer sb = new StringBuffer(string);
+ sb.replace(0,1,sb.substring(0,1).toUpperCase());
+ return sb.toString();
+ }
+
+ public static String camelAllWords(String string, String separator) {
+ StringBuffer sb = new StringBuffer();
+ boolean first = true;
+ for (String _string : string.split(separator)) {
+ if (!first) sb.append(separator);
+ else first = false;
+ sb.append(camel(_string));
+ }
+ return sb.toString();
+ }
+
+ public static String concatenate(String separator, Iterable<String> strings) {
+ if (strings == null) return "";
+ boolean first = true;
+ StringBuffer sb = new StringBuffer();
+ for (String string : strings) {
+ if (first) {
+ first = false;
+ sb.append(string);
+ } else {
+ sb.append(separator).append(string);
+ }
+ }
+ return sb.toString();
+ }
+ public static String concatenate(String separator, String ... strings) {
+ if (strings == null) return "";
+ return concatenate(separator,Arrays.asList(strings));
+ }
+}
diff --git a/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java new file mode 100644 index 0000000..f720fe9 --- /dev/null +++ b/israfil-foundation-core/src/main/java/net/israfil/foundation/core/Types.java @@ -0,0 +1,195 @@ +/*
+ * Copyright (c) 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 644 2009-01-04 18:02:21Z christianedwardgruber $
+ */
+package net.israfil.foundation.core;
+
+/**
+ * A Utility class that provides type-conversion facilities. For
+ * example, this class provides well-deliniated logic for taking
+ * a generic object and converting it into another concrete type, such
+ * as a String. Another example would be transforming the string "yes"
+ * into a boolean in a well-defined, well-ordered way.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: christianedwardgruber $
+ * @version $Revision: 644 $
+ */
+public class Types {
+
+ private static final byte BOOLEAN_FALSE_NUMERIC = 0;
+ private static final byte BOOLEAN_TRUE_NUMERIC = 1;
+
+ /**
+ * A delegate interface that, if provided to the convert(String,Class,Converter)
+ * method will add fallback conversions. This allows the existing
+ * convert method to be extended without subclassing, overriding, or
+ * modifying source.
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ */
+ public static interface Converter {
+ public Object convert(Object val, Class<?> aClass);
+ }
+
+ /**
+ * A method to convert an object to another object of a given type.
+ * @param value The object to be converted.
+ * @param aClass The class to which you wish to convert the object.
+ * @return The converted object.
+ */
+ public static Object convert(Object value, Class<?> aClass) {
+ return convert(value,aClass,null);
+ }
+
+ /**
+ * A method to convert an object to another object of a given type.
+ * @param value The object to be converted.
+ * @param aClass The class to which you wish to convert the object.
+ * @param converter An optional delegate that will convert the object if it fails - for extensibility.
+ * @return The converted object.
+ */
+ public static Object convert(Object value, Class<?> aClass,
+ Converter converter) {
+ if (value == null) return null;
+ if (aClass == null) throw new IllegalArgumentException("Cannot convert to a null class.");
+ if (Void.class.isAssignableFrom(aClass)) throw new IllegalArgumentException("Cannot convert to void.");
+ if (aClass.isInstance(value) ) return value;
+
+ if (aClass.isAssignableFrom(String.class)) {
+
+ // TODO: Insert any specific conversions
+ return String.valueOf(value);
+ } else if (Boolean.class.isAssignableFrom(aClass)) {
+ if (value instanceof String) {
+ if (((String)value).equalsIgnoreCase("Yes")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("True")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("Y")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("T")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("1")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("Aye")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("Yar")) return Boolean.TRUE;
+ if (((String)value).equalsIgnoreCase("No")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("False")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("N")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("F")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("0")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("Avast")) return Boolean.FALSE;
+ if (((String)value).equalsIgnoreCase("Nay")) return Boolean.FALSE;
+ throw new IllegalArgumentException("Cannot convert value '"+value+"' to a java.lang.Boolean");
+ }
+ if(value instanceof Number) {
+ return (((Number)value).intValue() != 0) ? Boolean.TRUE : Boolean.FALSE;
+ }
+ } else if (aClass.isAssignableFrom(Byte.class)) {
+ if (value instanceof String) return Byte.valueOf((String)value);
+ if (value instanceof Number) return new Byte(((Number)value).byteValue());
+ if (value instanceof Boolean) return new Byte(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Short.class)) {
+ if (value instanceof String) return Short.valueOf((String)value);
+ if (value instanceof Number) return new Short(((Number)value).shortValue());
+ if (value instanceof Boolean) return new Short(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Integer.class)) {
+ if (value instanceof String) return Integer.valueOf((String)value);
+ if (value instanceof Number) return new Integer(((Number)value).intValue());
+ if (value instanceof Boolean) return new Integer(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Long.class)) {
+ if (value instanceof String) return Long.valueOf((String)value);
+ if (value instanceof Number) return new Long(((Number)value).longValue());
+ if (value instanceof Boolean) return new Long(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Float.class)) {
+ if (value instanceof String) return Float.valueOf((String)value);
+ if (value instanceof Number) return new Float(((Number)value).floatValue());
+ if (value instanceof Boolean) return new Float(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Double.class)) {
+ if (value instanceof String) return Double.valueOf((String)value);
+ if (value instanceof Number) return new Double(((Number)value).doubleValue());
+ if (value instanceof Boolean) return new Double(((Boolean)value).booleanValue() ? BOOLEAN_TRUE_NUMERIC : BOOLEAN_FALSE_NUMERIC);
+ } else if (aClass.isAssignableFrom(Character.class)) {
+ if (value instanceof String) return new Character(((String)value).charAt(0));
+ if (value instanceof Number) return new Character((char)((Number)value).byteValue());
+ if (value instanceof Boolean) return new Character(((Boolean)value).booleanValue() ? 'T' : 'F');
+ }
+
+ if (value instanceof String) {
+ String stringVal = (String)value;
+ if (Float.class.isAssignableFrom(aClass)) return new Float((String)value);
+ if (Double.class.isAssignableFrom(aClass)) return new Double((String)value);
+ if (Byte.class.isAssignableFrom(aClass)) return new Byte((String)value);
+ if (Short.class.isAssignableFrom(aClass)) return new Short((String)value);
+ if (Integer.class.isAssignableFrom(aClass)) return new Integer((String)value);
+ if (Long.class.isAssignableFrom(aClass)) return new Long((String)value);
+ if (Character.class.isAssignableFrom(aClass)) return new Character(stringVal.charAt(0));
+ }
+
+ if (converter != null) return converter.convert(value,aClass);
+ throw new IllegalArgumentException("Don't know how to convert a String to a " + aClass);
+ }
+
+ public static Object convert(boolean object, Class<?> aClass) {
+ return convert(new Boolean(object),aClass);
+ }
+
+ public static Object convert(byte object, Class<?> aClass) {
+ return convert(new Byte(object),aClass);
+ }
+
+ public static Object convert(short object, Class<?> aClass) {
+ return convert(new Short(object),aClass);
+ }
+
+ public static Object convert(int object, Class<?> aClass) {
+ return convert(new Integer(object),aClass);
+ }
+
+ public static Object convert(long object, Class<?> aClass) {
+ return convert(new Long(object),aClass);
+ }
+
+ public static Object convert(float object, Class<?> aClass) {
+ return convert(new Float(object),aClass);
+ }
+
+ public static Object convert(double object, Class<?> aClass) {
+ return convert(new Double(object),aClass);
+ }
+
+ public static Object convert(char object, Class<?> aClass) {
+ return convert(new Character(object),aClass);
+ }
+
+ public static boolean convertToBoolean(Object object) {
+ return ((Boolean)convert(object,Boolean.class)).booleanValue();
+ }
+
+ public static byte convertToByte(Object object) {
+ return ((Number)convert(object,Byte.class)).byteValue();
+ }
+
+ public static short convertToShort(Object object) {
+ return ((Number)convert(object,Short.class)).shortValue();
+ }
+
+ public static int convertToInt(Object object) {
+ return ((Number)convert(object,Integer.class)).intValue();
+ }
+
+ public static long convertToLong(Object object) {
+ return ((Number)convert(object,Long.class)).longValue();
+ }
+
+ public static float convertToFloat(Object object) {
+ return ((Number)convert(object,Float.class)).floatValue();
+ }
+
+ public static double convertToDouble(Object object) {
+ return ((Number)convert(object,Double.class)).doubleValue();
+ }
+
+ public static char convertToChar(Object object) {
+ return ((Character)convert(object,Character.class)).charValue();
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/conf/testng.xml b/israfil-foundation-core/src/test/conf/testng.xml new file mode 100644 index 0000000..45ec021 --- /dev/null +++ b/israfil-foundation-core/src/test/conf/testng.xml @@ -0,0 +1,24 @@ +<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"> +<!-- + Copyright 2007, 2008 The Apache Software Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<suite name="Israfil Foundation Core" thread-count="5" annotations="1.5" verbose="2" parallel="tests"> + <test name="core"> + <packages> + <package name="net.israfil.foundation.core"/> + </packages> + </test> +</suite> diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java new file mode 100644 index 0000000..fc9c3d7 --- /dev/null +++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/SimpleCounterTest.java @@ -0,0 +1,61 @@ +/*
+ * Copyright (c) 2006-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2006-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: SimpleCounterTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.annotations.Test;
+
+
+
+public class SimpleCounterTest{
+
+ @Test
+ public void testCounter() {
+ Counter c = new SimpleCounter();
+ assert c.getCount() == 0;
+ c.increment();
+ assert c.getCount() == 1;
+ c.increment();
+ assert c.getCount() == 2;
+ c.decrement();
+ assert c.getCount() == 1;
+ c.decrement();
+ assert c.getCount() == 0;
+ c.decrement();
+ assert c.getCount() == -1;
+ c.reset();
+ assert c.getCount() == 0;
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java new file mode 100644 index 0000000..8c67260 --- /dev/null +++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/StringsTest.java @@ -0,0 +1,90 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: StringsTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class StringsTest {
+ @Test
+ public void testCamel() {
+ assert "BlahFoo".equals(Strings.camel("blahFoo"));
+ assert "FooBar".equals(Strings.camel("FooBar"));
+ }
+
+ @Test
+ public void testCamelAllWords() {
+ assert "BlahFoo BlahBlahFoo".equals(Strings.camelAllWords("blahFoo blahBlahFoo", " "));
+ assert "FooBar::Foo::Bar::Bash".equals(Strings.camelAllWords("FooBar::foo::bar::bash", "::"));
+ }
+
+ @Test
+ public void testConcatenate() {
+ Assert.assertEquals("a:b:c:d",Strings.concatenate(":", "a","b","c","d"));
+ }
+
+ @Test
+ public void testConcatenateNull() {
+ Assert.assertEquals("",Strings.concatenate(":",(String[])null));
+ }
+ @Test
+ public void testConcatenateEmpty() {
+ Assert.assertEquals("",Strings.concatenate(":"));
+ }
+
+ @Test
+ public void testConcatenateIterable() {
+ List<String> strings = new ArrayList<String>();
+ strings.add("a");
+ strings.add("b");
+ strings.add("c");
+ strings.add("d");
+ Assert.assertEquals("a:b:c:d",Strings.concatenate(":", strings));
+ }
+
+ @Test
+ public void testConcatenateNullIterable() {
+ Assert.assertEquals("",Strings.concatenate(":",(Iterable<String>)null));
+ }
+ @Test
+ public void testEmpty() {
+ Assert.assertEquals("",Strings.concatenate(":", new ArrayList<String>()));
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java new file mode 100644 index 0000000..cffbc4f --- /dev/null +++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromBooleanTest.java @@ -0,0 +1,91 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: TypesFromBooleanTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.annotations.Test;
+
+
+public class TypesFromBooleanTest {
+
+ @Test
+ public void testConvertBooleanToboolean() {
+ assert Types.convertToBoolean(Boolean.TRUE) == true;
+ assert Types.convertToBoolean(Boolean.FALSE) == false;
+ }
+ @Test
+ public void testConvertBooleanToBoolean() {
+ assert new Boolean(true).equals(Types.convert(Boolean.TRUE,Boolean.class));
+ assert new Boolean(false).equals(Types.convert(Boolean.FALSE, Boolean.class));
+ }
+ @Test
+ public void testConvertBooleanToString() {
+ assert "true".equals(Types.convert(Boolean.TRUE, String.class));
+ assert "false".equals(Types.convert(Boolean.FALSE, String.class));
+ }
+ @Test
+ public void testConvertBooleanToByte() {
+ assert new Byte((byte)1).equals(Types.convert(Boolean.TRUE, Byte.class));
+ assert new Byte((byte)0).equals(Types.convert(Boolean.FALSE, Byte.class));
+ }
+ @Test
+ public void testConvertBooleanToShort() {
+ assert new Short((short)1).equals(Types.convert(Boolean.TRUE, Short.class));
+ assert new Short((short)0).equals(Types.convert(Boolean.FALSE, Short.class));
+ }
+ @Test
+ public void testConvertBooleanToInteger() {
+ assert new Integer(1).equals(Types.convert(Boolean.TRUE, Integer.class));
+ assert new Integer(0).equals(Types.convert(Boolean.FALSE, Integer.class));
+ }
+ @Test
+ public void testConvertBooleanToLong() {
+ assert new Long(1).equals(Types.convert(Boolean.TRUE, Long.class));
+ assert new Long(0).equals(Types.convert(Boolean.FALSE, Long.class));
+ }
+ @Test
+ public void testConvertBooleanToFloat() {
+ assert new Float(1.0).equals(Types.convert(Boolean.TRUE, Float.class));
+ assert new Float(0.0).equals(Types.convert(Boolean.FALSE, Float.class));
+ }
+ @Test
+ public void testConvertBooleanToDouble() {
+ assert new Double(1.0d).equals(Types.convert(Boolean.TRUE, Double.class));
+ assert new Double(0.0d).equals(Types.convert(Boolean.FALSE, Double.class));
+ }
+ @Test
+ public void testConvertBooleanToCharacter() {
+ assert new Character('T').equals(Types.convert(Boolean.TRUE, Character.class));
+ assert new Character('F').equals(Types.convert(Boolean.FALSE, Character.class));
+ }}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java new file mode 100644 index 0000000..ba32b95 --- /dev/null +++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromNumberTest.java @@ -0,0 +1,49 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: TypesFromNumberTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.annotations.Test;
+
+
+
+//@Copyright(years={"2006"},owner="Israfil Consulting Services Corporation",license="BSD")
+public class TypesFromNumberTest {
+
+ @Test
+ public void testConvertNumberToCharacter() {
+ throw new org.testng.SkipException("Not yet implemented");
+ }
+
+}
diff --git a/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java new file mode 100644 index 0000000..2648d4f --- /dev/null +++ b/israfil-foundation-core/src/test/java/net/israfil/foundation/core/TypesFromStringTest.java @@ -0,0 +1,131 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: TypesFromStringTest.java 640 2009-01-04 16:48:31Z christianedwardgruber $
+ */
+
+package net.israfil.foundation.core;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+
+public class TypesFromStringTest {
+
+ @Test
+ public void testConvertStringToboolean() {
+ Assert.assertTrue(Types.convertToBoolean("true"));
+ Assert.assertTrue(Types.convertToBoolean("t"));
+ Assert.assertTrue(Types.convertToBoolean("T"));
+ Assert.assertTrue(Types.convertToBoolean("True"));
+ Assert.assertTrue(Types.convertToBoolean("TrUe"));
+ Assert.assertTrue(Types.convertToBoolean("Yes"));
+ Assert.assertTrue(Types.convertToBoolean("y"));
+ Assert.assertTrue(Types.convertToBoolean("yes"));
+ Assert.assertTrue(Types.convertToBoolean("aye"));
+ Assert.assertFalse(Types.convertToBoolean("false"));
+ Assert.assertFalse(Types.convertToBoolean("f"));
+ Assert.assertFalse(Types.convertToBoolean("F"));
+ Assert.assertFalse(Types.convertToBoolean("False"));
+ Assert.assertFalse(Types.convertToBoolean("faLSe"));
+ Assert.assertFalse(Types.convertToBoolean("No"));
+ Assert.assertFalse(Types.convertToBoolean("n"));
+ Assert.assertFalse(Types.convertToBoolean("no"));
+ Assert.assertFalse(Types.convertToBoolean("nay"));
+ }
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testConvertEmptyStringToBoolean() {
+ Types.convertToBoolean("");
+ }
+ @Test(expectedExceptions={NullPointerException.class})
+ public void testConvertNullStringToBoolean() {
+ Types.convertToBoolean(null);
+ }
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testConvertNonNumberStringToBoolean() {
+ Types.convertToBoolean("bark");
+ }
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testConvertStringWithLeadingWhitespaceToBoolean() {
+ Types.convertToBoolean(" aye");
+ }
+ /*
+ @Test
+ public void testConvertStringToBoolean() {
+ Assert.assertEquals(new Boolean(true),Types.convert(Boolean.TRUE, Boolean.class));
+ Assert.assertEquals(new Boolean(false),Types.convert(Boolean.FALSE, Boolean.class));
+ }
+ */
+ @Test
+ public void testConvertStringToString() {
+ Assert.assertEquals("a",Types.convert("a", String.class));
+ Assert.assertSame("a",Types.convert("a", String.class));
+ Assert.assertFalse("A".equals(Types.convert("a", String.class)));
+ }
+ /*
+ @Test
+ public void testConvertBooleanToByte() {
+ Assert.assertEquals(new Byte((byte)1),Types.convert(Boolean.TRUE, Byte.class));
+ Assert.assertEquals(new Byte((byte)0),Types.convert(Boolean.FALSE, Byte.class));
+ }
+ @Test
+ public void testConvertBooleanToShort() {
+ Assert.assertEquals(new Short((short)1),Types.convert(Boolean.TRUE, Short.class));
+ Assert.assertEquals(new Short((short)0),Types.convert(Boolean.FALSE, Short.class));
+ }
+ @Test
+ public void testConvertBooleanToInteger() {
+ Assert.assertEquals(new Integer(1),Types.convert(Boolean.TRUE, Integer.class));
+ Assert.assertEquals(new Integer(0),Types.convert(Boolean.FALSE, Integer.class));
+ }
+ @Test
+ public void testConvertBooleanToLong() {
+ Assert.assertEquals(new Long(1),Types.convert(Boolean.TRUE, Long.class));
+ Assert.assertEquals(new Long(0),Types.convert(Boolean.FALSE, Long.class));
+ }
+ @Test
+ public void testConvertBooleanToFloat() {
+ Assert.assertEquals(new Float(1.0),Types.convert(Boolean.TRUE, Float.class));
+ Assert.assertEquals(new Float(0.0),Types.convert(Boolean.FALSE, Float.class));
+ }
+ @Test
+ public void testConvertBooleanToDouble() {
+ Assert.assertEquals(new Double(1.0d),Types.convert(Boolean.TRUE, Double.class));
+ Assert.assertEquals(new Double(0.0d),Types.convert(Boolean.FALSE, Double.class));
+ }
+ @Test
+ public void testConvertBooleanToCharacter() {
+ Assert.assertEquals(new Character('T'),Types.convert(Boolean.TRUE, Character.class));
+ Assert.assertEquals(new Character('F'),Types.convert(Boolean.FALSE, Character.class));
+ }
+ */
+
+}
diff --git a/israfil-foundation-dynamic/pom.xml b/israfil-foundation-dynamic/pom.xml new file mode 100644 index 0000000..fdea908 --- /dev/null +++ b/israfil-foundation-dynamic/pom.xml @@ -0,0 +1,33 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-dynamic</artifactId> + <name>Israfil Foundation Dynamic Invocation</name> + <version>1.0.3-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-collections</artifactId> + <version>1.0.2</version> + </dependency> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-core</artifactId> + <version>[1.0.0,1.1)</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java new file mode 100644 index 0000000..e1bdb8b --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/Dynamic.java @@ -0,0 +1,62 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Dynamic.java 14 2006-01-27 23:50:37Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+
+/**
+ * A simple interface that defines the ability to perform and detect
+ * arbitrary methods, by use of a "selector" string. The selector
+ * is a string constructed of a method name and an arbitrary number of
+ * classes representing parameter types. These are then concatenated
+ * with a ":" separator. The resulting string represents a full
+ * method signature, without reference to the implementing class. This
+ * allows arbitrary classes to be interrogated as to the validity of a
+ * given method call (i.e. do they or their parents implement it). It
+ * also then allows the method with the given signature to be invoked.
+ *
+ * For example:
+ * <code>
+ * if (a.respondsTo("doThing:java.lang.String"))
+ * a.perform("doThing:java.lang.String",aString);
+ * </code>
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface Dynamic {
+
+ public Object perform(String selector, Object ... parameters);
+
+ public boolean respondsTo(String selector);
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java new file mode 100644 index 0000000..3beda20 --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicObject.java @@ -0,0 +1,69 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicObject.java 92 2006-08-04 12:39:25Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Method;
+
+
+/**
+ * An abstract superclass that implements the Dynamic interface, with
+ * all the necessary lookup logic. It also implements static equivalents of
+ * the Dynamic methods.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public abstract class DynamicObject implements Dynamic {
+ //private static Logger logger = Logger.getLogger(DynamicObject.class.getName());
+
+
+ /**
+ * @see org.israfil.maveric.Dynamic#perform(java.lang.String, java.lang.Object[])
+ */
+ public Object perform(String selector, Object ... parameters) {
+ return DynamicUtil.performOn(this,selector,parameters);
+ }
+
+ /**
+ * @see org.israfil.maveric.Dynamic#respondsTo(java.lang.String)
+ */
+ public boolean respondsTo(String selector) {
+ return DynamicUtil.respondsTo(this,selector);
+ }
+
+ protected Method getMethodForSelector(String selector) {
+ return DynamicUtil.getMethodForSelector(this,selector);
+ }
+
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java new file mode 100644 index 0000000..9c165bc --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicUtil.java @@ -0,0 +1,297 @@ +/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicUtil.java 91 2006-08-03 21:38:24Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.collections.ArrayUtils;
+
+/**
+ * Utilities used for the implementation of Dynamic and
+ * related interfaces.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public final class DynamicUtil {
+ private static Logger logger = Logger.getLogger(DynamicUtil.class.getName());
+
+ private DynamicUtil() {}
+
+ static Map<String, Class<?>> _primitiveTypes = new HashMap<String, Class<?>>();
+ static Map<Class<?>, Class<?>> _primitiveTypeEquivalents = new HashMap<Class<?>, Class<?>>();
+ static Map<Class<?>, Class<?>> _boxedTypeEquivalents = new HashMap<Class<?>, Class<?>>();
+ static {
+ _primitiveTypes.put("boolean",boolean.class);
+ _primitiveTypeEquivalents.put(Boolean.class,boolean.class);
+ _boxedTypeEquivalents.put(boolean.class,Boolean.class);
+ _primitiveTypes.put("int",int.class);
+ _primitiveTypeEquivalents.put(Integer.class,int.class);
+ _boxedTypeEquivalents.put(int.class,Integer.class);
+ _primitiveTypes.put("long",long.class);
+ _primitiveTypeEquivalents.put(Long.class,long.class);
+ _boxedTypeEquivalents.put(long.class,Long.class);
+ _primitiveTypes.put("short",short.class);
+ _primitiveTypeEquivalents.put(Short.class,short.class);
+ _boxedTypeEquivalents.put(short.class,Short.class);
+ _primitiveTypes.put("byte",byte.class);
+ _primitiveTypeEquivalents.put(Byte.class,byte.class);
+ _boxedTypeEquivalents.put(byte.class,Byte.class);
+ _primitiveTypes.put("char",char.class);
+ _primitiveTypeEquivalents.put(Character.class,char.class);
+ _boxedTypeEquivalents.put(char.class,Character.class);
+ _primitiveTypes.put("double",double.class);
+ _primitiveTypeEquivalents.put(Double.class,double.class);
+ _boxedTypeEquivalents.put(double.class,Double.class);
+ _primitiveTypes.put("float",float.class);
+ _primitiveTypeEquivalents.put(Float.class,float.class);
+ _boxedTypeEquivalents.put(float.class,Float.class);
+ }
+ public static boolean hasPrimitiveTypeEquivalent(Class<?> c) {
+ return _primitiveTypeEquivalents.containsKey(c);
+ }
+
+ public static Class<?> getPrimitiveTypeEquivalent(Class<?> c) {
+ return _primitiveTypeEquivalents.get(c);
+ }
+
+ public static boolean hasBoxedTypeEquivalent(Class<?> c) {
+ return _boxedTypeEquivalents.containsKey(c);
+ }
+
+ public static Class<?> getBoxedTypeEquivalent(Class<?> c) {
+ return _boxedTypeEquivalents.get(c);
+ }
+
+ protected static final Map<Class<?>, Set<Class<?>>> classes = new HashMap<Class<?>, Set<Class<?>>>();
+
+ public static Set<Class<?>> getAllParentTypes(Class<?> c) {
+ if (!classes.containsKey(c)) {
+ Set<Class<?>> parents = new HashSet<Class<?>>();
+ for (Class<?> cType = c; cType != Object.class && cType != null; cType = cType
+ .getSuperclass()) {
+ parents.add(cType);
+ addSuperInterfaces(parents,cType);
+ }
+ parents.add(Object.class);
+ parents.remove(c);
+ classes.put(c,parents);
+ }
+ return classes.get(c);
+ }
+
+ public static void addSuperInterfaces(Set<Class<?>> set, Class<?> c) {
+ if (c == null || c.getInterfaces() == null) return;
+ for (Class<?> i : c.getInterfaces()) {
+ set.add(i);
+ addSuperInterfaces(set,i);
+ }
+ }
+
+ /**
+ * Conveniently get a field from an object, automatically trapping
+ * exceptions and returning the Field or null if no such field exists.
+ */
+ public static Field getField(Object receiver, String attributeName) {
+ Field f = null;
+ try {
+ f = receiver.getClass().getField(attributeName);
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ return f;
+ }
+
+
+
+ /**
+ * @see org.israfil.maveric.Dynamic#respondsTo(java.lang.String)
+ */
+ public static boolean respondsTo(Object receiver, String selector) {
+ return (getMethodForSelector(receiver,selector) != null);
+ }
+
+ public static Method getMethodForSelector(Object receiver, String selector) {
+ if (receiver instanceof Class)
+ return getMethodForSelector((Class<?>) receiver, selector);
+ return getMethodForSelector(receiver.getClass(),selector);
+ }
+
+ public static Method getMethodForSelector(Class<?> receiverClass,
+ String selector) {
+ try {
+ return _getMethodForSelector(receiverClass,selector);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ return null;
+ }
+ }
+
+ protected static Method _getMethodForSelector(Class<?> receiverClass,
+ String selector) throws ClassNotFoundException,
+ NoSuchMethodException {
+ StringTokenizer st = new StringTokenizer(selector,":");
+ Class<?>[] paramTypes = new Class[st.countTokens() - 1];
+ String methodName = st.nextToken();
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ for (int i = 0; st.hasMoreTokens(); i++) {
+ String className = st.nextToken();
+ if (DynamicUtil._primitiveTypes.containsKey(className))
+ paramTypes[i] = (Class<?>) DynamicUtil._primitiveTypes
+ .get(className);
+ else paramTypes[i] = loader.loadClass(className);
+ }
+ return receiverClass.getMethod(methodName,paramTypes);
+ }
+
+ /**
+ * @see org.israfil.maveric.Dynamic#perform(java.lang.String, java.lang.Object[])
+ */
+ public static Object performOn(Object receiver, String selector, Object ... parameters) {
+ if (parameters == null) parameters = new Object[]{};
+ Method m = getMethodForSelector(receiver,selector);
+ try {
+ if (m != null) return m.invoke(receiver,parameters);
+ //else return null;
+ else throw new NoSuchMethodError("No public method defined with selector \""+selector+"\"");
+ } catch (InvocationTargetException ite) {
+ logger.log(Level.FINE,ite.getClass().getName()+" thrown attempting to invoke selector: " + selector + " on "+receiver,ite);
+ if (ite.getCause() != null) throw new RuntimeException(ite.getCause());
+ else throw new RuntimeException(ite);
+ } catch (IllegalAccessException iae) {
+ logger.log(Level.FINE,iae.getClass().getName()+" thrown attempting to invoke selector: " + selector + " on "+receiver,iae);
+ throw new RuntimeException(iae);
+ }
+ }
+
+ /**
+ * Construct an object of the given named class with the provided
+ * constructor parameters. If there is no such class or no
+ * constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param className The fully qualified name of a Class object to be instantiated.
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ public static Object construct(String className, Object ... parameters) {
+ try {
+ Class<?> clazz = Thread.currentThread().getContextClassLoader()
+ .loadClass(className);
+ return construct(clazz,parameters);
+ } catch (ClassNotFoundException e) {
+ logger.log(Level.FINE,e.getClass().getName()+" thrown attempting to construct a " + className + ".", e);
+ return null;
+ }
+ }
+ /**
+ * Construct an object of the given class with the provided
+ * constructor parameters. If there is no such class or no
+ * constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param c A Class object to be instantiated.
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ public static <T> T construct(Class<T> c, Object ... parameters) {
+ Class<?> [] parmTypes = new Class<?>[parameters.length];
+ for (int i = 0; i < parmTypes.length; i++) {
+ parmTypes[i] = parameters[i].getClass();
+ }
+ return construct(c,parmTypes,parameters);
+ }
+
+ /**
+ * Construct an object of the given named class with the provided
+ * constructor parameter types and values. If there is no such class
+ * or no constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param className The fully qualified name of a Class object to be instantiated.
+ * @param parameterTypes The types that form the desired constructor's method signature
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ public static Object construct(String className, Class<?>[] parameterTypes,
+ Object... parameters) {
+ try {
+ Class<?> clazz = Thread.currentThread().getContextClassLoader()
+ .loadClass(className);
+ return construct(clazz, parameterTypes,parameters);
+ } catch (ClassNotFoundException e) {
+ logger.log(Level.FINE,e.getClass().getName()+" thrown attempting to construct a " + className + ".", e);
+ return null;
+ }
+ }
+
+ /**
+ * Construct an object of the given class with the provided
+ * constructor parameter types and values. If there is no such class
+ * or no constructor is found that is appropriate to these parameters,
+ * the method will return null;
+ *
+ * @param c A Class object to be instantiated.
+ * @param parameterTypes The types that form the desired constructor's method signature
+ * @param parameters Optional parameters for the discovered constructor
+ * @return an instance of the named class, or null if no such class or constructor is found.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T construct(Class<T> c, Class<?>[] parameterTypes,
+ Object... parameters) {
+ try {
+ Constructor<T>[] constructors = (Constructor<T>[]) c.getDeclaredConstructors();
+ for (Constructor<T> constructor : constructors) {
+ if (ArrayUtils.equivalent(parameterTypes,constructor.getParameterTypes())) {
+ return (T)constructor.newInstance(parameters);
+ }
+ }
+ return null;
+ } catch (Exception e) {
+ logger.log(Level.FINE,e.getClass().getName()+" thrown attempting to construct a " + c.getName() + ".", e);
+ return null;
+ }
+ }
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java new file mode 100644 index 0000000..202bd11 --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessible.java @@ -0,0 +1,50 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyAccessible.java 23 2006-02-01 17:17:31Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+
+/**
+ * A generic accessor interface. By this means any attribute should be
+ * retrievable by using the provided methods, as well as the existence of
+ * an accessor method can be detected.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface DynamicallyAccessible extends Dynamic{
+
+ public boolean hasAttribute(String attributeName);
+ public Object get(String attributeName);
+ public abstract boolean hasAccessor(String attributeName);
+
+}
\ No newline at end of file diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java new file mode 100644 index 0000000..fd376a7 --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyAccessibleObject.java @@ -0,0 +1,144 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyAccessibleObject.java 76 2006-08-03 15:37:05Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.core.Strings;
+
+/**
+ * An implementation of the DynamicallyAccessible interface with the
+ * appropriate infrastructure for retrieving field data, via accessors if
+ * such are implemented, or directly from the field where not.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 76 $
+ */
+public abstract class DynamicallyAccessibleObject extends DynamicObject implements DynamicallyAccessible {
+ private static Logger logger = Logger.getLogger(DynamicallyAccessibleObject.class.getName());
+
+ public Object get(String attributeName) {
+ return get(this,attributeName);
+ }
+
+ public static Object get(Object receiver, String attributeName) {
+ try {
+ return _get(receiver, attributeName);
+ } catch (NoSuchFieldException e) {
+ logger.log(Level.FINE,"Object attempted to dynamically access a non-existant or unreadable field.",e);
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ logger.log(Level.FINE,"Object attempted to dynamically access a inaccessible field.",e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** @deprecated This method is deprecated in favour of the static _get(receiver, attributeName) */
+ Object _get(String attributeName) throws NoSuchFieldException, IllegalAccessException {
+ return _get(this,attributeName);
+ }
+
+ /**
+ * Internal _get method that throws all the exceptions, to be wrapped by public methods
+ * so that the various exceptions can be given meaning in different contexts (such
+ * as fetching data, vs. testing for the existance of something.
+ *
+ * @param attributeName
+ * @return
+ * @throws NoSuchFieldException
+ * @throws IllegalAccessException
+ */
+ static Object _get(Object receiver, String attributeName) throws NoSuchFieldException, IllegalAccessException {
+ if (hasAccessor(receiver,attributeName)) return DynamicUtil.performOn(receiver,_getAccessorSelector(receiver,attributeName), new Object[]{});
+ return receiver.getClass().getField(attributeName).get(receiver);
+ }
+
+ /**
+ * Determines whether an attribute of the given name exists on this object's
+ * definition, or if not, if there is a javabeans-style accessor named
+ * appropriately for that attribute. Put another way, determines whether
+ * a get() call would work against this attribute name.
+ *
+ * The existing implementation is inefficient, but simple to maintain.
+ */
+ public boolean hasAttribute(String attributeName) {
+ return hasAttribute(this,attributeName);
+ }
+
+ public static boolean hasAttribute(Object receiver, String attributeName) {
+ try {
+ _get(receiver,attributeName);
+ return true;
+ } catch (NoSuchFieldException e) {
+ logger.log(Level.FINEST,"Object attempted to dynamically access a non-existant or unreadable field.",e);
+ return false;
+ } catch (IllegalAccessException e) {
+ logger.log(Level.FINEST,"Object attempted to dynamically access a inaccessible field.",e);
+ return false;
+ }
+ }
+
+ protected static final String[] accessPrefixes = new String[] { "get","is" };
+
+ /** @deprecated This method is deprecated in favour of the static _getAccessorSelector(receiver,attribute) */
+ protected String getAccessorSelector(String attributeName) { return _getAccessorSelector(this,attributeName); }
+
+ protected static String _getAccessorSelector(Object receiver, String attributeName) {
+ if (attributeName == null || attributeName.equals("")) return null;
+ String camelAttr = camel(attributeName);
+ for (String prefix : accessPrefixes) {
+ String selector = prefix+camelAttr;
+ if (DynamicUtil.respondsTo(receiver,selector)) return selector;
+ }
+ // No accessor, try a NeXTSTEP-style accessor, named the same as the property.
+ if (DynamicUtil.respondsTo(receiver,attributeName)) return attributeName;
+ return null;
+ }
+
+ public boolean hasAccessor(String attributeName) {
+ return hasAccessor(this,attributeName);
+ }
+
+ public static boolean hasAccessor(Object receiver, String attributeName) {
+ return _getAccessorSelector(receiver,attributeName) != null;
+ }
+
+ /** @deprecated This method has been moved to net.israfil.foundation.core.Strings.camel(String) */
+ public static String camel(String string) {
+ return Strings.camel(string);
+ }
+
+}
diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java new file mode 100644 index 0000000..49b2a5d --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutable.java @@ -0,0 +1,54 @@ +/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyMutable.java 39 2006-02-23 00:01:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+
+/**
+ * A generic mutator interface. By this means any attribute should be
+ * mutable by using the provided methods. Additionally, the existence of
+ * a mutator method can be detected.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public interface DynamicallyMutable extends DynamicallyAccessible{
+
+ public void set(String attributeName, Object attributeValue);
+
+ public void set(String attributeName, Object attributeValue, Class<?> type);
+
+ public void setNull(String attributeName, Class<?> type);
+
+ public abstract boolean hasMutator(String attributeName, Class<?> type);
+
+}
\ No newline at end of file diff --git a/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java new file mode 100644 index 0000000..63b301d --- /dev/null +++ b/israfil-foundation-dynamic/src/main/java/net/israfil/foundation/dynamic/DynamicallyMutableObject.java @@ -0,0 +1,197 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyMutableObject.java 127 2006-11-09 18:04:43Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.israfil.foundation.core.Strings;
+import net.israfil.foundation.core.Types;
+
+/**
+ * An abstract class which implements the DynamicallyMutableObject
+ * infrastructure. It sets a field's value, by mutator method if such
+ * exists, or directly if none such exists.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ *
+ */
+public abstract class DynamicallyMutableObject extends DynamicallyAccessibleObject implements DynamicallyMutable {
+ private static Logger logger = Logger.getLogger(DynamicallyMutableObject.class.getName());
+
+
+ public void setNull(String attributeName, Class<?> valueType) {
+ setNull(this,attributeName,valueType);
+ }
+ public void setNull(Object target, String attributeName, Class<?> valueType) {
+ if (valueType == null)
+ throw new IllegalArgumentException("Cannot give a valueType of null for setNull(String,Class) method.");
+ set(target,attributeName, null, valueType);
+ }
+
+ public void set(String attributeName,Object value) {
+ set(this,attributeName,value);
+ }
+ public static void set(Object target, String attributeName,Object value) {
+ if (value == null) set(target,attributeName, value, null);
+ else set(target,attributeName, value, value.getClass());
+ }
+
+ public void set(String attributeName, Object value, Class<?> valueType) {
+ set(this,attributeName,value,valueType);
+ }
+ public static void set(Object target, String attributeName, Object value,
+ Class<?> valueType) {
+ if (value == null) {
+ if (valueType != null && valueType.isPrimitive()) throw new IllegalArgumentException("Attempted to set null on a variable or accessor for attribute '"+attributeName+"' of primitive type: " + valueType);
+ String selector = getMutatorSelector(target,attributeName,valueType);
+ if (selector != null) {
+ Method m = DynamicUtil.getMethodForSelector(target,selector);
+ Class<?>[] parmTypes = m.getParameterTypes();
+ if (parmTypes[0].isPrimitive())
+ throw new IllegalArgumentException("Attempted to set null using an accessor for attribute '"+attributeName+"' of primitive type: " + parmTypes[0]);
+ DynamicUtil.performOn(target,selector,new Object[]{value});
+ } else {
+ Field f = DynamicUtil.getField(target,attributeName);
+ if (f == null || f.getType().isPrimitive())
+ throw new IllegalArgumentException("Attempted to set null but could not find a set"+Strings.camel(attributeName)+" method with a single non-primitive type.");
+ else
+ _setField(target,attributeName,valueType);
+ }
+ } else /* value != null */ {
+ if (valueType == null) valueType = value.getClass();
+ if (hasMutator(target,attributeName,valueType)) {
+ DynamicUtil.performOn(target,getMutatorSelector(target,attributeName,valueType),new Object[]{value});
+ return;
+ } else if(hasMutator(target,attributeName,DynamicUtil.getPrimitiveTypeEquivalent(valueType))) {
+ DynamicUtil.performOn(target,getMutatorSelector(target,attributeName,DynamicUtil.getPrimitiveTypeEquivalent(valueType)),new Object[]{value});
+ return;
+ } else {
+ _setField(target,attributeName,value);
+ }
+ }
+ }
+
+ protected void _setField(String attributeName,Object value) {
+ _setField(this,attributeName,value);
+ }
+
+ protected static void _setField(Object target, String attributeName,Object value) {
+ Field f = DynamicUtil.getField(target,attributeName);
+ try {
+ if (f == null) {
+ RuntimeException rte = new RuntimeException("Could not find field named " + attributeName,
+ new NoSuchFieldException(target + " has no property " + attributeName));
+ logger.log(Level.FINEST,"Failed to set field.",rte);
+ throw rte;
+ }
+ f.set(target,Types.convert(value,f.getType()));
+ } catch (IllegalAccessException e) {
+ logger.log(Level.FINEST,"Object attempted to dynamically access a inaccessible field.",e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected static final String mutatePrefix = "set";
+ protected String getMutatorSelector(String attributeName, Class<?> type) {
+ return getMutatorSelector(this,attributeName,type);
+ }
+ protected static String getMutatorSelector(Object target,
+ String attributeName, Class<?> type) {
+ if (attributeName == null || attributeName.equals("")) return null;
+ String camelAttr = Strings.camel(attributeName);
+ String selector = null;
+ if (type == null) {
+ Method method = _tryToFindMutator(target,attributeName);
+ if (method == null) {
+ return null;
+ } else /* method != null */ {
+ if (method.getParameterTypes().length != 1) return null;
+ else return "set"+Strings.camel(attributeName)+":"+method.getParameterTypes()[0].getName();
+ }
+ } else /* type != null */ {
+
+ String tmp = mutatePrefix+camelAttr+":"+type.getName();
+ if (DynamicUtil.respondsTo(target,tmp)) selector = tmp;
+ for (Class<?> c : DynamicUtil.getAllParentTypes(type)) {
+ tmp = mutatePrefix + camelAttr + ":" + c.getName();
+ if (DynamicUtil.respondsTo(target, tmp))
+ selector = tmp;
+ }
+ }
+ return selector;
+ }
+
+ protected static Method _tryToFindMutator(Object target, String attributeName) {
+ Method method = null;
+ Method[] methods = target.getClass().getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ if (methods[i].getName().equals("set"+Strings.camel(attributeName))) {
+ if (method == null) method = methods[i];
+ else throw new IllegalArgumentException("Attempted to find "+mutatePrefix+Strings.camel(attributeName) + " without a given type, but more than one such method exists. Should use set(String,Object,Class)");
+ }
+ }
+ return method;
+ }
+
+ protected static Method _tryToFindMutator(Object target,
+ String attributeName, Class<?> type) {
+ if (type == null) throw new IllegalArgumentException("Must set a type, or use _tryToFindMutator(Object,String).");
+ String methodName = mutatePrefix+Strings.camel(attributeName);
+ Method m = DynamicUtil.getMethodForSelector(target,methodName+":"+type.getName());
+ for (Class<?> c : DynamicUtil.getAllParentTypes(type)) {
+ m = DynamicUtil.getMethodForSelector(target,methodName+":"+c.getName());
+ }
+ return m;
+ }
+
+ public static Method getMutator(Object target, String attributeName,
+ Class<?> type) {
+ if (type == null) {
+ return _tryToFindMutator(target,attributeName);
+ } else {
+ return _tryToFindMutator(target,attributeName,type);
+ }
+ }
+
+ public boolean hasMutator(String attributeName, Class<?> type) {
+ return hasMutator(this,attributeName,type);
+ }
+ public static boolean hasMutator(Object target, String attributeName,
+ Class<?> type) {
+ return getMutatorSelector(target,attributeName,type) != null;
+ }
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java new file mode 100644 index 0000000..a5b7a90 --- /dev/null +++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicObjectTest.java @@ -0,0 +1,120 @@ +/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicObjectTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+@Test
+public class DynamicObjectTest {
+
+ private static final String TEST_STRING1 = "String1";
+ private static final String TEST_STRING2 = "String2";
+
+ DynamicTestObject testDO;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ testDO = new DynamicTestObject();
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ testDO = null;
+ }
+
+ public void testPerformMethods() {
+ Assert.assertTrue((Boolean)testDO.perform("action"));
+ Assert.assertEquals(TEST_STRING1,testDO.perform("action:java.lang.String",TEST_STRING1));
+ Assert.assertEquals(TEST_STRING2,testDO.perform("action:java.lang.String:boolean",
+ new Object[] {TEST_STRING2,Boolean.TRUE}));
+ Assert.assertEquals(TEST_STRING2+TEST_STRING2,testDO.perform("action:java.lang.String:boolean",new Object[] {TEST_STRING2,Boolean.FALSE}));
+ Assert.assertNull(testDO.perform("action:java.util.Date",new Object[] {new Date()}));
+ }
+
+ @Test(expectedExceptions={NoSuchMethodError.class})
+ public void testPerformAgainstProtectedMethod() {
+ testDO.perform("action:boolean",new Object[] {Boolean.TRUE});
+ }
+
+ @Test(expectedExceptions={NoSuchMethodError.class})
+ public void testPerformAgainstPackageFriendlyMethod() {
+ testDO.perform("action:java.lang.Float",new Object[] {1.5f});
+ }
+
+ @Test(expectedExceptions={NoSuchMethodError.class})
+ public void testPerformAgainstPrivateMethod() {
+ testDO.perform("privateAction");
+ }
+
+ public void testRespondsTo() {
+ Assert.assertTrue(testDO.respondsTo("action"));
+ Assert.assertFalse(testDO.respondsTo("noAction"));
+ Assert.assertTrue(testDO.respondsTo("action:java.lang.String"));
+ Assert.assertFalse(testDO.respondsTo("action:java.lang.Integer"));
+ Assert.assertTrue(testDO.respondsTo("action:java.lang.String:"+boolean.class.getName()));
+ Assert.assertFalse(testDO.respondsTo("action:java.lang.Integer:java.lang.String"));
+ Assert.assertFalse(testDO.respondsTo("action:boolean"));
+ Assert.assertFalse(testDO.respondsTo("action:java.lang.Float"));
+ Assert.assertTrue(testDO.respondsTo("action:int"));
+ }
+
+ public void testGetMethodForSelector() {
+ Method m = testDO.getMethodForSelector("action:java.lang.String");
+ Assert.assertNotNull(m);
+ Assert.assertEquals("action",m.getName());
+ Assert.assertEquals(String.class,m.getParameterTypes()[0]);
+ }
+
+ public class DynamicTestObject extends DynamicObject {
+ public boolean action() { return !privateAction(); /* false */ }
+ public String action(String foo) { return foo; }
+ public String action(String foo, boolean bool) {
+ if (bool) return foo;
+ else return foo+foo;
+ }
+ public void action(Date foo) { if (foo==null);return; }
+ protected boolean action(boolean b) { return b; }
+ Float action(Float f) { return f; }
+ public int action(int i) { return i; }
+ private boolean privateAction() { return false; }
+ }
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java new file mode 100644 index 0000000..31d11a7 --- /dev/null +++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicUtilTest.java @@ -0,0 +1,160 @@ +/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicUtilTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class DynamicUtilTest {
+
+ public void testAddSuperinterfaces1() {
+ Class<?> clz = IA.class;
+ Set<Class<?>> cSet = new HashSet<Class<?>>();
+ DynamicUtil.addSuperInterfaces(cSet,clz);
+ Assert.assertEquals(0,cSet.size());
+ }
+ public void testAddSuperinterfaces2() {
+ Class<?> clz = IC.class;
+ Set<Class<?>> cSet = new HashSet<Class<?>>();
+ DynamicUtil.addSuperInterfaces(cSet,clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertEquals(1,cSet.size());
+ }
+ public void testClassLookupForA() {
+ Class<?> clz = A.class;
+ Set<Class<?>> cSet = DynamicUtil.getAllParentTypes(clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertTrue(cSet.contains(Object.class),"Should have type Object");
+ Assert.assertEquals(2,cSet.size());
+ }
+ public void testClassLookupForB() {
+ Class<?> clz = B.class;
+ Set<Class<?>> cSet = DynamicUtil.getAllParentTypes(clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertTrue(cSet.contains(A.class),"Should have type A");
+ Assert.assertTrue(cSet.contains(IB.class),"Should have type IB");
+ Assert.assertTrue(cSet.contains(Object.class),"Should have type Object");
+ Assert.assertEquals(4,cSet.size());
+ }
+ public void testClassLookupForC() {
+ Class<?> clz = C.class;
+ Set<Class<?>> cSet = DynamicUtil.getAllParentTypes(clz);
+ Assert.assertTrue(cSet.contains(IA.class),"Should have type IA");
+ Assert.assertTrue(cSet.contains(IC.class),"Should have type IC");
+ Assert.assertTrue(cSet.contains(Object.class),"Should have type Object");
+ Assert.assertFalse(cSet.contains(A.class),"Should not have type A");
+ Assert.assertEquals(3,cSet.size());
+ }
+
+ public void testRespondsTo() {
+ Object obj = new TestObject();
+ Assert.assertTrue(DynamicUtil.respondsTo(obj,"action:java.lang.String"));
+ Assert.assertFalse(DynamicUtil.respondsTo(obj,"action"));
+ Assert.assertFalse(DynamicUtil.respondsTo(obj,"action:boolean"));
+ Assert.assertTrue(DynamicUtil.respondsTo(obj,"equals:java.lang.Object"));
+ }
+
+ public void testHasPrimitiveTypeEquivalent() {
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Boolean.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Integer.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Long.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Short.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Byte.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Double.class));
+ Assert.assertTrue(DynamicUtil.hasPrimitiveTypeEquivalent(Character.class));
+ Assert.assertFalse(DynamicUtil.hasPrimitiveTypeEquivalent(String.class));
+ }
+
+ public void testGetMethodForSelectorObjectString() {
+ Method m = null;
+ Object obj = new TestObject();
+
+ m = DynamicUtil.getMethodForSelector(obj,"action:java.lang.String");
+ Assert.assertNotNull(m);
+
+ m = DynamicUtil.getMethodForSelector(obj,"action:boolean");
+ Assert.assertNull(m);
+
+ // force a test of getMethodForSelector(Object,String) with a class
+ m = DynamicUtil.getMethodForSelector((Object)obj.getClass(),"action:java.lang.String");
+ // force a test of getMethodForSelector(Class<?>,String)
+ m = DynamicUtil.getMethodForSelector((Class<?>) obj.getClass(),
+ "action:java.lang.String");
+ Assert.assertNotNull(m);
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testConstructWithClass() {
+ ArrayList<String> al = DynamicUtil.construct(ArrayList.class);
+ Assert.assertNotNull(al);
+ Assert.assertEquals(ArrayList.class,al.getClass());
+ }
+ @SuppressWarnings("unchecked")
+ public void testConstructWithString() {
+ ArrayList<String> al = (ArrayList<String>)DynamicUtil.construct("java.util.ArrayList");
+ Assert.assertNotNull(al);
+ Assert.assertEquals(ArrayList.class,al.getClass());
+ }
+
+ public void testGetMethodForSelectorClassString() {
+ Object obj = new TestObject();
+ Assert.assertNotNull(DynamicUtil.getMethodForSelector(obj.getClass(),"action:java.lang.String"));
+ }
+
+ public interface IA {}
+ public interface IB {}
+ public interface IC extends IA {}
+
+ public class A implements IA {}
+ public class B extends A implements IB {}
+ public class C implements IC {}
+
+ public class TestObject {
+ public void action(String s) {}
+ }
+
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java new file mode 100644 index 0000000..94c9edb --- /dev/null +++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyAccessibleTest.java @@ -0,0 +1,174 @@ +/*
+ * Copyright (c) 2003-2009 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyAccessibleTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class DynamicallyAccessibleTest {
+
+ TestAccessibleObject testDBO;
+ String var1 = "value1";
+ String var1Name = "publicVariable";
+ String var2 = "value2";
+ String var2Name = "publicVariableWithAccessor";
+ String var3 = "value3";
+ String var3Name = "privateVariable";
+ boolean var4 = false;
+ String var4Name = "booleanVariable";
+ int var5 = 5;
+ String var5Name = "intVariable";
+ boolean var6 = true;
+ String var6Name = "isTrue";
+
+ @BeforeMethod
+ protected void setUp() {
+ testDBO = new TestAccessibleObject(var1,var2,var3,var4,var5,var6);
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ testDBO = null;
+ }
+
+ public void testHasAccessor() {
+ Assert.assertFalse(testDBO.hasAccessor(var1Name));
+ Assert.assertTrue(testDBO.hasAccessor(var2Name));
+ Assert.assertTrue(testDBO.hasAccessor(var3Name));
+ Assert.assertTrue(testDBO.hasAccessor(var4Name));
+ Assert.assertTrue(testDBO.hasAccessor(var5Name));
+ }
+
+ public void testHasAttribute() {
+ Assert.assertTrue(testDBO.hasAttribute("publicVariable"));
+ Assert.assertTrue(testDBO.hasAttribute("publicVariableWithAccessor"));
+ Assert.assertTrue(testDBO.hasAttribute("privateVariable"));
+ Assert.assertTrue(testDBO.hasAttribute("booleanVariable"));
+ Assert.assertFalse(testDBO.hasAttribute("oddlyNamedIntVariable"));
+ Assert.assertTrue(testDBO.hasAttribute("aFinalStaticString"));
+ }
+
+ public void testGet() {
+ Assert.assertEquals(var1,testDBO.get(var1Name));
+ Assert.assertEquals(var2,testDBO.get(var2Name));
+ Assert.assertEquals(var3,testDBO.get(var3Name));
+ Assert.assertEquals(var4,testDBO.get(var4Name));
+ Assert.assertEquals(var5,testDBO.get(var5Name));
+ Assert.assertEquals(var6,testDBO.get(var6Name));
+ }
+
+ public void testHasAccessorStatic() {
+ Assert.assertFalse(DynamicallyAccessibleObject.hasAccessor(testDBO,var1Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var2Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var3Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var4Name));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAccessor(testDBO,var5Name));
+ }
+
+ public void testHasAttributeStatic() {
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"publicVariable"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"publicVariableWithAccessor"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"privateVariable"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"booleanVariable"));
+ Assert.assertFalse(DynamicallyAccessibleObject.hasAttribute(testDBO,"oddlyNamedIntVariable"));
+ Assert.assertTrue(DynamicallyAccessibleObject.hasAttribute(testDBO,"aFinalStaticString"));
+ }
+
+ public void testGetStatic() {
+ Assert.assertEquals(var1,DynamicallyAccessibleObject.get(testDBO,var1Name));
+ Assert.assertEquals(var2,DynamicallyAccessibleObject.get(testDBO,var2Name));
+ Assert.assertEquals(var3,DynamicallyAccessibleObject.get(testDBO,var3Name));
+ Assert.assertEquals(new Boolean(var4),DynamicallyAccessibleObject.get(testDBO,var4Name));
+ Assert.assertEquals(new Integer(var5),DynamicallyAccessibleObject.get(testDBO,var5Name));
+ }
+
+ @Test(expectedExceptions={RuntimeException.class})
+ public void testGetWithNoFieldOrAccessor() {
+ testDBO.get("nonExistantVariable");
+ }
+
+
+ public static class TestAccessibleObject extends DynamicallyAccessibleObject {
+
+ public String publicVariable;
+ public String publicVariableWithAccessor;
+ private String privateVariable;
+ private boolean booleanVariable;
+ private int oddlyNamedIntVariable;
+ public static final String aFinalStaticString = "foo";
+ private boolean isTrue;
+
+ public TestAccessibleObject() {}
+
+ public TestAccessibleObject(String publicVar,
+ String publicVarWithAcc,
+ String privateVar,
+ boolean booleanVar,
+ int intVar,
+ boolean isTrue) {
+ this.publicVariable = publicVar;
+ this.publicVariableWithAccessor = publicVarWithAcc;
+ this.privateVariable = privateVar;
+ this.booleanVariable = booleanVar;
+ this.oddlyNamedIntVariable = intVar;
+ this.isTrue = isTrue;
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ publicVariable = null;
+ publicVariableWithAccessor = null;
+ privateVariable = null;
+ super.finalize();
+ }
+ public String getPublicVariableWithAccessor()
+ { return publicVariableWithAccessor;}
+
+ public String getPrivateVariable() { return privateVariable; }
+ public boolean getBooleanVariable() { return booleanVariable; }
+ public int getIntVariable() { return oddlyNamedIntVariable; }
+ public boolean isTrue() { return isTrue; }
+ }
+}
diff --git a/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java new file mode 100644 index 0000000..9bc9103 --- /dev/null +++ b/israfil-foundation-dynamic/src/test/java/net/israfil/foundation/dynamic/DynamicallyMutableTest.java @@ -0,0 +1,210 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: DynamicallyMutableTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.dynamic;
+
+import net.israfil.foundation.core.Strings;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+@Test
+public class DynamicallyMutableTest {
+
+ MutableTestObject testMO;
+ String var1 = "value1";
+ String var1Name = "publicVariable";
+ String var2 = "value2";
+ String var2Name = "publicVariableWithAccessor";
+ String var3 = "value3";
+ String var3Name = "privateVariable";
+ Boolean var4 = false;
+ String var4Name = "booleanVariable";
+ Integer var5 = 5;
+ String var5Name = "intVariable";
+ boolean var6 = true;
+ String var6Name = "primitiveBoolean";
+ int var7 = 9;
+ String var7Name = "primitiveInt";
+
+ MutableTestObject2 mto2;
+
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ testMO = new MutableTestObject();
+ mto2 = new MutableTestObject2();
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ testMO = null;
+ mto2 = null;
+ }
+
+ public void testHasMutator() {
+ Assert.assertFalse(testMO.hasMutator(var1Name,var1.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var2Name,var2.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var3Name,var3.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var4Name,var4.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var5Name,var5.getClass()));
+ Assert.assertTrue(testMO.hasMutator(var6Name,boolean.class));
+ Assert.assertTrue(testMO.hasMutator(var7Name,int.class));
+
+ }
+
+ public void testSet() {
+ testMO.set(var1Name,var1);
+ testMO.set(var2Name,var2);
+ testMO.set(var3Name,var3);
+ testMO.set(var4Name,var4);
+ testMO.set(var5Name,var5);
+ testMO.set(var6Name,var6);
+ testMO.set(var7Name,var7);
+ Assert.assertEquals(var1,testMO.get(var1Name));
+ Assert.assertEquals(var2,testMO.get(var2Name));
+ Assert.assertEquals(var3,testMO.get(var3Name));
+ Assert.assertEquals(var4,testMO.get(var4Name));
+ Assert.assertEquals(var5,testMO.get(var5Name));
+ }
+
+ @Test(expectedExceptions={RuntimeException.class})
+ public void testSetWithNoFieldOrAccessor() {
+ testMO.set("nonExistantVariable","aString");
+ }
+
+ public void testCamel() {
+ Assert.assertEquals("BlahFoo",Strings.camel("blahFoo"));
+ Assert.assertEquals("FooBar",Strings.camel("FooBar"));
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetWithNullAndNoParameterSetMethod() {
+ mto2.set("a",null);
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetWithNullWithTooManySetMethods() {
+ mto2.set("b",null);
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetWithNullAndSolitarySinglePrimitiveParameter() {
+ mto2.set("c",null);
+ }
+
+ public void testSetWithNullAndSolitarySingleNonPrimitiveParameter() {
+ mto2.set("d",null);
+ Assert.assertTrue(mto2.d_String_WasTouched);
+ }
+
+ public void testSetNullWithTypeAndSolitarySingleNonPrimitiveParameter() {
+ mto2.setNull("b",Integer.class);
+ Assert.assertTrue(mto2.b_Integer_WasTouched);
+ mto2.setNull("b",String.class);
+ Assert.assertTrue(mto2.b_String_WasTouched);
+ }
+
+ @Test(expectedExceptions={IllegalArgumentException.class})
+ public void testSetNullWithTypeAndSolitarySinglePrimitiveParameter() {
+ mto2.setNull("b",boolean.class);
+ }
+
+ public class MutableTestObject2 extends DynamicallyMutableObject {
+
+ public boolean a_WasTouched = false;
+ public boolean b_Integer_WasTouched = false;
+ public boolean b_String_WasTouched = false;
+ public boolean b_boolean_WasTouched = false;
+ public boolean c_boolean_WasTouched = false;
+ public boolean d_String_WasTouched = false;
+
+ public boolean c;
+
+ public void setA() {a_WasTouched = true;}
+
+ public void setB(String s) {b_String_WasTouched = true;}
+ public void setB(Integer i) {b_Integer_WasTouched = true;}
+ public void setB(boolean b) {b_boolean_WasTouched = true;}
+
+ public void setC(boolean b) {c_boolean_WasTouched = true;}
+
+ public void setD(String s) {d_String_WasTouched = true;}
+
+ }
+
+ public class MutableTestObject extends DynamicallyMutableObject {
+
+ public String publicVariable;
+ public String publicVariableWithAccessor;
+ private String privateVariable;
+ private boolean booleanVariable;
+ private int oddlyNamedIntVariable;
+
+ public MutableTestObject() {
+ }
+
+ @Override
+ public void finalize() throws Throwable {
+ publicVariable = null;
+ publicVariableWithAccessor = null;
+ privateVariable = null;
+ super.finalize();
+ }
+
+ public void setPublicVariableWithAccessor(String s)
+ { publicVariableWithAccessor = s; }
+
+ public void setPrivateVariable(String s) { privateVariable = s; }
+ public String getPrivateVariable() { return privateVariable; }
+
+ public void setBooleanVariable(Boolean b) { booleanVariable = b; }
+ public boolean getBooleanVariable() { return booleanVariable; }
+
+ public void setIntVariable(Integer i) { oddlyNamedIntVariable = i; }
+ public Integer getIntVariable() { return oddlyNamedIntVariable; }
+
+ public void setPrimitiveInt(int i) {}
+ public void setPrimitiveBoolean(boolean b) {}
+ }
+}
diff --git a/israfil-foundation-lifecycle/pom.xml b/israfil-foundation-lifecycle/pom.xml new file mode 100644 index 0000000..7bed4a7 --- /dev/null +++ b/israfil-foundation-lifecycle/pom.xml @@ -0,0 +1,21 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-lifecycle</artifactId> + <name>Israfil Foundation Lifecycle Classes and Interfaces</name> + <version>1.0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2007</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> +</project>
\ No newline at end of file diff --git a/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java new file mode 100644 index 0000000..131e23e --- /dev/null +++ b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Consumer.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006-2009 Israfil Consulting Services Corporation + * Copyright (c) 2006-2009 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $ + */ +package net.israfil.foundation.lifecycle; + + +/** + * An object that is consumes objects of a given type. + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public interface Consumer<T> { + + /** + * Consumes an item of type T. + * + * @param item The item to be consumed. + */ + public void consume(T item); + +} diff --git a/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java new file mode 100644 index 0000000..9ae0035 --- /dev/null +++ b/israfil-foundation-lifecycle/src/main/java/net/israfil/foundation/lifecycle/Producer.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006-2009 Israfil Consulting Services Corporation + * Copyright (c) 2006-2009 Christian Edward Gruber + * All Rights Reserved + * + * This software is licensed under the Berkeley Standard Distribution license, + * (BSD license), as defined below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Israfil Consulting Services nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * $Id: Source.java 129 2006-12-31 23:20:02Z cgruber $ + */ +package net.israfil.foundation.lifecycle; + + +/** + * An object that is a source (producer) of objects + * + * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a> + */ +public interface Producer<T> { + + /** + * Produces an item of type T upon request. + */ + public T produce(); + +} diff --git a/israfil-foundation-notification/pom.xml b/israfil-foundation-notification/pom.xml new file mode 100644 index 0000000..344acda --- /dev/null +++ b/israfil-foundation-notification/pom.xml @@ -0,0 +1,28 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-notification</artifactId> + <name>Israfil Foundation Notification System</name> + <version>1.0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-dynamic</artifactId> + <version>1.0.1</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java new file mode 100644 index 0000000..acf60b8 --- /dev/null +++ b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/Notification.java @@ -0,0 +1,59 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Notification.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.notification;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * An encapsulated notification, used within a NotificationCentre
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class Notification {
+ private static Map<String,Object> EMPTY_INFO = Collections.unmodifiableMap(new HashMap<String,Object>());
+
+ public final Object sender;
+ public final String notification;
+ public final Map<String,Object> info;
+ public Notification(Object sender, String notification) {
+ this(sender,notification,EMPTY_INFO);
+ }
+ public Notification(Object sender, String notification, Map<String,Object> info) {
+ this.sender = sender;
+ this.notification = notification;
+ this.info = info;
+ }
+}
diff --git a/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java new file mode 100644 index 0000000..8261d12 --- /dev/null +++ b/israfil-foundation-notification/src/main/java/net/israfil/foundation/notification/NotificationCentre.java @@ -0,0 +1,200 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: NotificationCentre.java 125 2006-11-09 15:51:38Z cgruber $
+ */
+package net.israfil.foundation.notification;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import net.israfil.foundation.dynamic.DynamicUtil;
+
+/**
+ * A nextstep-like central notification system.
+ * @author cgruber
+ */
+public class NotificationCentre {
+
+ private static NotificationCentre _shared = new NotificationCentre();
+
+ private Set<ObservationSpec> observers = new HashSet<ObservationSpec>();
+
+ protected NotificationCentre() {
+ }
+
+ public static NotificationCentre defaultCentre() {
+ return _shared;
+ }
+
+ /**
+ * This registers an object as an observer of notifications. The object
+ * registers interest in either a particular named notification, or a
+ * particular object who may issue the notifications, or the union of the
+ * two. The following table lists the possible combinations:
+ * <table>
+ * <tr>
+ * <th>Notification Name</th>
+ * <th>Sender Object</th>
+ * <th>Effect</th>
+ * </tr>
+ * <tr>
+ * <td>null</td>
+ * <td>a sender</td>
+ * <th>Notifications (of any name) from this sender are observed</th>
+ * </tr>
+ * <tr>
+ * <td>notification string</td>
+ * <td>null</td>
+ * <th>Notifications with this name (from any sender) are observed.</th>
+ * </tr>
+ * <tr>
+ * <td>notification string</td>
+ * <td>a sender</td>
+ * <th>Only notifications with this name and originating from this sender are observed</th>
+ * </tr>
+ * <tr>
+ * <td>null</td>
+ * <td>null</td>
+ * <th>All Notifications from any source will be sent (big performance drag)</th>
+ * </tr>
+ * </table>
+ * @param observer The object instance that wants to be registered
+ * @param callbackSignature Must be a method that takes a single Object parameter which will be a Notification at run-time, or a single Notification parameter
+ * @param notification The name of the notification to watch for (if any)
+ * @param sender The name of the object to whose notifications should be paid attention. (if any)
+ */
+ public void addObserver(Object observer,
+ String callbackSignature,
+ String notification,
+ Object sender){
+ if (observer == null) return;
+ if (callbackSignature == null)
+ throw new IllegalArgumentException("Reciever did not pass in a callback method.");
+ if (!checkSignature(observer,callbackSignature))
+ throw new IllegalArgumentException("Reciever does not implement specified callback method.");
+ observers.add(new ObservationSpec(sender,notification, callbackSignature, observer));
+
+ }
+ /** Post a notification with the given nam and notifier. */
+ public void postNotification(Notification notification) {
+ for (ObservationSpec obs : this.observers) {
+ obs.postNotification(notification);
+ }
+ }
+ /** Post a notification with the given name, notifier, and with additional
+ * context information presented in a java.util.Map. */
+ public void postNotification(Object sender,String notification) {
+ postNotification(new Notification(sender,notification));
+ }
+ /** Post a notification with the given name, notifier, and with additional
+ * context information presented in a java.util.Map. */
+ public void postNotification(Object sender,String notification, Map<String,Object> info) {
+ postNotification(new Notification(sender,notification,info));
+ }
+ /** Removes an observer from any notofications with either or both a
+ * provided notification string, or notifier
+ */
+ public void removeObserver(Object observer, String notification, Object sender) {
+ for (ObservationSpec obs : observers) {
+ if (obs.observer == observer &&
+ obs.sender == sender &&
+ (obs.notification == null || obs.notification.equals(notification))){
+ observers.remove(obs);
+ }
+ }
+ }
+ public void clearObservers() {
+ observers.clear();
+ }
+
+ private boolean checkSignature(Object receiver,String selector) {
+ if (!DynamicUtil.respondsTo(receiver,selector)) return false;
+ StringTokenizer st = new StringTokenizer(selector,":");
+ if (st.countTokens() != 2) return false;
+ st.nextToken();
+ String parameter = st.nextToken();
+ if (Notification.class.getName().equals(parameter)) return true;
+ if (Object.class.getName().equals(parameter)) return true;
+ return false;
+ }
+
+ /**
+ * TODO Use WeakReferences
+ */
+ public class ObservationSpec {
+ public final Object sender;
+ public final String notification;
+ public final String callback;
+ public final Object observer;
+ private final int _hashCode;
+ public ObservationSpec(Object sender,String notification,String callback, Object observer) {
+ if (observer == null)
+ throw new IllegalArgumentException("Both sender and notification cannot be null");
+ this.sender = sender;
+ this.notification = notification;
+ this.callback = callback;
+ this.observer = observer;
+
+ // Pre-calculate hash
+ int code = 13;
+ if (sender != null) code *= sender.hashCode();
+ if (notification != null) code *= notification.hashCode();
+ code *= observer.hashCode();
+ this._hashCode = code;
+ }
+ public void postNotification(Notification notification) {
+ if (this.sender == null && this.notification == null) {
+ _post(notification);
+ } else if (this.sender == null) {
+ if (notification.notification.equals(this.notification))
+ _post(notification);
+ } else if (this.notification == null) {
+ if (notification.sender.equals(this.sender))
+ _post(notification);
+ } else {
+ if (notification.notification.equals(this.notification) && notification.sender.equals(this.sender))
+ _post(notification);
+ }
+ }
+ private void _post(Notification notification) {
+ DynamicUtil.performOn(this.observer,callback,new Object[]{notification} );
+ }
+
+ @Override
+ public int hashCode() {
+ return _hashCode;
+ }
+ }
+
+}
diff --git a/israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java b/israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java new file mode 100644 index 0000000..beb310e --- /dev/null +++ b/israfil-foundation-notification/src/test/java/net/israfil/foundation/notification/NotificationCentreTest.java @@ -0,0 +1,180 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: NotificationCentreTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.notification;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.israfil.foundation.core.Copyright;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * @author cgruber
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+@Copyright(years={"2003","2004","2005","2006"},owner="Israfil Consulting Services Corporation",license="BSD")
+@Test
+public class NotificationCentreTest{
+
+ private static String NOTIFICATION_1 = "notification1";
+ private static String NOTIFICATION_2 = "notification2";
+ private static String NOTIFICATION_3 = "notification3";
+
+ private static String INFO_KEY = "key";
+ private static String INFO_VALUE = "value";
+
+
+ public boolean didReceiveNotifyWithNotification = false;
+ public boolean didReceiveNotifyWithObject = false;
+ public boolean didReceiveNotifyOtherWithObject = false;
+
+ public Map<String,Object> info = null;
+
+ NotificationCentre centre = null;
+ ObserverFixture observer = null;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ centre = NotificationCentre.defaultCentre();
+ observer = new ObserverFixture();
+ didReceiveNotifyWithNotification = false;
+ didReceiveNotifyWithObject = false;
+ didReceiveNotifyOtherWithObject = false;
+ info = new HashMap<String,Object>();
+ info.put(INFO_KEY,INFO_VALUE);
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ centre.clearObservers();
+ centre = null;
+ observer = null;
+ info = null;
+ }
+
+ /*
+ * Test for void postNotification(Notification)
+ */
+ public void testPostNotificationNotification() {
+ Notification n1 = new Notification(this,NOTIFICATION_1);
+ Notification n2 = new Notification(this,NOTIFICATION_2);
+ Notification n3 = new Notification(this,NOTIFICATION_3);
+ centre.postNotification(n1);
+ Assert.assertFalse(didReceiveNotifyWithNotification);
+ Assert.assertFalse(observer.notification == n1);
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ centre.postNotification(n2);
+ Assert.assertTrue(didReceiveNotifyWithNotification);
+ Assert.assertTrue(observer.notification == n2);
+
+ // register as global
+ centre.removeObserver(observer,null,null);
+ centre.postNotification(n3);
+ Assert.assertFalse(observer.notification == n3);
+ }
+
+ /*
+ * Test for void postNotification(Object, String)
+ */
+ public void testPostNotificationObjectString() {
+ centre.postNotification(this,NOTIFICATION_1);
+ Assert.assertFalse(didReceiveNotifyWithNotification);
+ Assert.assertEquals(null,observer.notification);
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ centre.postNotification(this,NOTIFICATION_2);
+ Assert.assertTrue(didReceiveNotifyWithNotification);
+ Assert.assertEquals(NOTIFICATION_2,observer.notification.notification);
+ }
+
+ /*
+ * Test for void postNotification(Object, String, Map)
+ */
+ public void testPostNotificationObjectStringMap() {
+ centre.postNotification(this,NOTIFICATION_1,info);
+ Assert.assertFalse(didReceiveNotifyWithNotification);
+ Assert.assertEquals(null,observer.notification);
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ centre.postNotification(this,NOTIFICATION_2,info);
+ Assert.assertTrue(didReceiveNotifyWithNotification);
+ Assert.assertEquals(NOTIFICATION_2,observer.notification.notification);
+ Assert.assertEquals(INFO_VALUE,observer.notification.info.get(INFO_KEY));
+ }
+
+ /*
+ * Test for void removeObserver(Object, String, Object)
+ */
+ public void testRemoveObserverObjectStringObject() {
+ // register as global
+ centre.addObserver(observer,"notify:net.israfil.foundation.notification.Notification",null,null);
+ // remove right away (we know addObserver works from other tests.
+ centre.removeObserver(observer,null,null);
+ centre.postNotification(this,NOTIFICATION_1,info);
+ Assert.assertEquals(null,observer.notification);
+ }
+
+ public class ObserverFixture {
+ public Notification notification = null;
+ public void notify(Notification n) {
+ NotificationCentreTest sender = (NotificationCentreTest)n.sender;
+ sender.didReceiveNotifyWithNotification = true;
+ this.notification = n;
+ }
+ public void notify(Object o) {
+ Notification n = (Notification)o;
+ NotificationCentreTest sender = (NotificationCentreTest)n.sender;
+ sender.didReceiveNotifyWithObject = true;
+ this.notification = n;
+ }
+ public void notifyOther(Object o) {
+ Notification n = (Notification)o;
+ NotificationCentreTest sender = (NotificationCentreTest)n.sender;
+ sender.didReceiveNotifyWithObject = true;
+ this.notification = n;
+ }
+ public void finalize() throws Throwable {
+ notification = null;
+ super.finalize();
+ }
+ }
+
+}
diff --git a/israfil-foundation-nspace/pom.xml b/israfil-foundation-nspace/pom.xml new file mode 100644 index 0000000..969dae5 --- /dev/null +++ b/israfil-foundation-nspace/pom.xml @@ -0,0 +1,21 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-nspace</artifactId> + <name>Israfil Foundation N-Dimensional Array</name> + <version>0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> +</project>
\ No newline at end of file diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java new file mode 100755 index 0000000..620124a --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Coordinate.java @@ -0,0 +1,56 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: Coordinate.java 254 2003-02-10 16:01:01Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Logically an array of tuples
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 254 $
+ */
+public interface Coordinate {
+
+ /**
+ * A single empty Coordinate, which can be passed in to point-NSpaces, where
+ * no dimension constraint is required.
+ */
+ public final static Coordinate EMPTY =
+ new Coordinate() {
+ private final Set<String> dim = new HashSet<String>();
+
+ public Set<String> getDimensions() {
+ return dim;
+ }
+ public long getDimensionality() { return 0; }
+ public String getOrdinal(String dimensionName) {
+ if (false) dimensionName.hashCode(); //quiet compiler warning.
+ return null;
+ }
+ };
+
+ /**
+ * Returns a set of names of contained dimensions.
+ * @return Set
+ */
+ public Set<String> getDimensions();
+
+ /**
+ * Returns the number of dimensions
+ * @return long
+ */
+ public long getDimensionality();
+
+ /**
+ * Returns the ordinal of the given named dimension..
+ * @return Set
+ */
+ public String getOrdinal(String dimensionName);
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java new file mode 100755 index 0000000..f4e73bb --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/Dimension.java @@ -0,0 +1,36 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: Dimension.java 260 2005-05-15 13:08:53Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * A named set of positions within an nspace
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 260 $
+ */
+public interface Dimension extends Set<String> {
+
+ /**
+ * Returns the name of the position
+ * @return String
+ */
+ public String getName();
+
+
+ void getWithNSpace(NSpace space);
+ void abandonNSpace(NSpace space);
+ void getWithNSpaces(Collection<NSpace> spaces);
+ void abandonNSpaces(Collection<NSpace> spaces);
+
+ public Dimension addPosition(String s);
+ public Dimension deletePosition(String s);
+
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java new file mode 100755 index 0000000..e53397a --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/DimensionExistsException.java @@ -0,0 +1,38 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: DimensionExistsException.java 249 2003-02-02 03:33:46Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+/**
+ * Thrown if a dimension is added to an NSpace which already defines a
+ * Dimension with that name.
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 249 $
+ */
+public class DimensionExistsException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -801633377290441235L;
+
+ /**
+ * Constructor for DimensionExistsException.
+ */
+ public DimensionExistsException() {
+ super();
+ }
+
+ /**
+ * Constructor for DimensionExistsException.
+ * @param arg0
+ */
+ public DimensionExistsException(String arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java new file mode 100755 index 0000000..3a12d31 --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/InvalidDimensionalityException.java @@ -0,0 +1,39 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: InvalidDimensionalityException.java 249 2003-02-02 03:33:46Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+/**
+ * Thrown when the provided Coodinate inadequately specifies, or incorrectly
+ * specifies the dimensions relative to the NSpace. Primarily used with
+ * setters.
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 249 $
+ */
+public class InvalidDimensionalityException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5349982487272515716L;
+
+ /**
+ * Constructor for InvalidDimensionalityException.
+ */
+ public InvalidDimensionalityException() {
+ super();
+ }
+
+ /**
+ * Constructor for InvalidDimensionalityException.
+ * @param arg0
+ */
+ public InvalidDimensionalityException(String arg0) {
+ super(arg0);
+ }
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java new file mode 100755 index 0000000..196f4e9 --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/NSpace.java @@ -0,0 +1,98 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: NSpace.java 259 2004-08-23 21:30:01Z mberteig $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Set;
+
+/**
+ * An N-Dimensional Space representation, such that:
+ * <ol>
+ * <li>Each dimension is named</li>
+ * <li>Each co-ordinate is specified using names not numbers <subscript>IOW:
+ * Domain of each dim. is specified as an ordered set of names
+ * </subscript></li>
+ * <li>Number of dimensions can change throughout lifecycle</li>
+ * <li>Dimensions
+ * </ol>
+ * <p>
+ * A SparseNSpace represents a set of tuples of the form (D1,D2,D3,...,Dn;V)
+ * where Dx represents a location in dimension x and V represents a value in
+ * the n-dimensional space at a location specified by the dimensional locations
+ * D1..Dn. Dimensions can be added or removed at any time with well-defined
+ * results.</p>
+ * <p><strong>Note:</strong> Maybe have origin</p>
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 259 $
+ */
+public interface NSpace {
+
+ /*
+ * Content Management
+ */
+
+ /**
+ * Returns an NSpace such that each coordinate of the receiver that contains the values of the passed in
+ * coordinate becomes a part of the resulting NSpace. The dimensionality of the resulting NSpace is the difference
+ * of the dimensionality of the receiver and the coordinate. E.g. say we have 3-NSpace with dimensions (D1,D2,D3)
+ * and data [0,0,0;A], [0,1,0;B], [1,0,0;C], [1,1,0;D]. If we lookup a coordinate with dimensions (D2,D3) and values
+ * [0,0] we will get a resulting 1-NSpace with dimension (D1) and data [0;A], [1;C].
+ */
+ public NSpace lookup(Coordinate c);
+
+ /**
+ * Returns an NSpace such that each coordinate of the receiver that contains the values of the passed in
+ * coordinate is not a part of the resulting NSpace. The dimensionality of the resulting NSpace is the dimensionality
+ * of the receiver. E.g. say we have 3-NSpace with dimensions (D1,D2,D3)
+ * and data [0,0,0;A], [0,1,0;B], [1,0,0;C], [1,1,0;D]. If we slice with a coordinate with dimensions (D2,D3) and values
+ * [0,0] we will get a resulting 3-NSpace with dimension (D1,D2,D3) and data [0,1,0;B], [1,1,0;D].
+ */
+ public NSpace slice(Coordinate c);
+
+ /**
+ * Returns an array of NSpace instances such that for each ordinal in Dimension d, there is an NSpace in the array
+ * of dimensionality one less than the receiver that contains the data from the receiver that contains the ordinal.
+ * E.g. say we have 3-NSpace with dimensions (D1,D2,D3)
+ * and data [0,0,0;A], [0,1,0;B], [1,0,0;C], [1,1,0;D].
+ * then slicing on dimension D2 would give us two 2-NSpaces with dimensions (D1,D3):
+ * [0,0;A], [1,0;C] and
+ * [0,0;B], [1,0;D]
+ * @param d the dimension to use to make the cuts in the receiver
+ * @return all the sub-NSpaces, one for each ordinal of d
+ */
+ public NSpace[] slice(Dimension d);
+
+ /**
+ * Returns true if NSpace contains zero dimensions, or if the size of each
+ * dimension == 1.
+ * @return boolean
+ */
+ public boolean isPoint();
+ public Object getValue(Coordinate c);
+
+ public NSpace setValue(Coordinate c, Object value)
+ throws InvalidDimensionalityException;
+ public NSpace setValue(Coordinate c, NSpace value)
+ throws InvalidDimensionalityException;
+
+ /*
+ * Dimension Management
+ */
+ public Dimension createDimension(String name, String initialSlot)
+ throws DimensionExistsException;
+ public void deleteDimension(Dimension dimension);
+ public Set<Dimension> getDimensions();
+ public Dimension getDimension(String name);
+
+ /*
+ * Notifications
+ */
+
+ void dimensionAddedPosition(Dimension dimension,String position);
+ void dimensionRemovedPosition(Dimension dimension, String position);
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java new file mode 100755 index 0000000..52250fa --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SimpleDimension.java @@ -0,0 +1,225 @@ +package net.israfil.foundation.collections.nspace;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * @author cgruber
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+public class SimpleDimension implements Dimension {
+
+ private final String name;
+ private final Set<String> positions = new HashSet<String>();
+ private final Set<NSpace> spaces = new HashSet<NSpace>();
+
+ public SimpleDimension() {
+ name = null;
+ }
+
+ public SimpleDimension(String name, String ordinal) {
+ this.name = name;
+ positions.add(ordinal);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#getName()
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @see java.util.Collection#size()
+ */
+ public int size() {
+ return this.positions.size();
+ }
+
+ /**
+ * @see java.util.Collection#isEmpty()
+ */
+ public boolean isEmpty() {
+ throw new UnsupportedOperationException("Dimension cannot have no positions. Remove the dimension.");
+ }
+
+ /**
+ * @see java.util.Collection#contains(java.lang.Object)
+ */
+ public boolean contains(Object positions) {
+ return this.positions.contains(positions);
+ }
+
+ /**
+ * @see java.util.Collection#iterator()
+ */
+ public Iterator<String> iterator() {
+ return this.positions.iterator();
+ }
+
+ /**
+ * @see java.util.Collection#toArray()
+ */
+ public String[] toArray() {
+ return this.positions.toArray(new String[size()]);
+ }
+
+ /**
+ * @see java.util.Collection#toArray(java.lang.Object)
+ */
+ public <T> T[] toArray(T[] array) {
+ return this.positions.toArray(array);
+ }
+
+ /**
+ * @see java.util.Collection#add(java.lang.Object)
+ */
+ public boolean add(String
+ position) {
+ boolean result = this.positions.add(position);
+ notifyAddPosition((String)position);
+ return result;
+ }
+
+ /**
+ * @see java.util.Collection#remove(java.lang.Object)
+ */
+ public boolean remove(Object position) {
+ boolean result = this.positions.remove(position);
+ notifyRemovePosition((String)position);
+ return result;
+ }
+
+ /**
+ * @see java.util.Collection#containsAll(java.util.Collection)
+ */
+ public boolean containsAll(Collection<?> positions) {
+ return this.positions.containsAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#addAll(java.util.Collection)
+ */
+ public boolean addAll(Collection<? extends String> positions) {
+ return this.positions.addAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#retainAll(java.util.Collection)
+ */
+ public boolean retainAll(Collection<?> positions) {
+ return this.positions.retainAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#removeAll(java.util.Collection)
+ */
+ public boolean removeAll(Collection<?> positions) {
+ return this.positions.removeAll(positions);
+ }
+
+ /**
+ * @see java.util.Collection#clear()
+ */
+ public void clear() {
+ throw new UnsupportedOperationException("Dimensions must always have one ordinal");
+ }
+
+
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#abandonNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void abandonNSpace(NSpace n) {
+ this.spaces.remove(n);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#getWithNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void getWithNSpace(NSpace n) {
+ this.spaces.add(n);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#abandonNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void abandonNSpaces(Collection<NSpace> spaces) {
+ this.spaces.removeAll(spaces);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#getWithNSpace(org.frugenplat.framework.nspace.NSpace)
+ */
+ public void getWithNSpaces(Collection<NSpace> spaces) {
+ this.spaces.addAll(spaces);
+ }
+
+ private void notifyAddPosition(String position) {
+ for (NSpace space : spaces) {
+ space.dimensionAddedPosition(this,position);
+ }
+ }
+
+ private void notifyRemovePosition(String position) {
+ for (NSpace space : spaces) {
+ space.dimensionRemovedPosition(this,position);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ private void notifyAddPositions(Collection<String> positions) {
+
+ }
+
+ @SuppressWarnings("unused")
+ private void notifyRemovePositions(Collection<String> positions) {
+
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(super.toString());
+ sb.append(" [");
+ sb.append(name);
+ sb.append("] {");
+ for (String s : positions) sb.append(s);
+ sb.append("}");
+ return sb.toString();
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#addPosition(java.lang.String)
+ */
+ public Dimension addPosition(String s) {
+ add(s);
+ return this;
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.Dimension#deletePosition(java.lang.String)
+ */
+ public Dimension deletePosition(String s) {
+ remove(s);
+ return this;
+ }
+
+
+
+}
diff --git a/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java new file mode 100755 index 0000000..4c48842 --- /dev/null +++ b/israfil-foundation-nspace/src/main/java/net/israfil/foundation/collections/nspace/SparseNSpace.java @@ -0,0 +1,165 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: SparseNSpace.java 260 2005-05-15 13:08:53Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An implementatino of NSpace that is sparsely populated.
+ *
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 260 $
+ */
+public class SparseNSpace implements NSpace {
+
+ private final Set<Dimension> dimensions = new HashSet<Dimension>();
+
+ public SparseNSpace() {
+ super();
+ }
+
+ public SparseNSpace(Set<Dimension> initialDimensions) {
+ this();
+ for (Dimension d : dimensions) {
+ // This is temporary, until we have an internal protected mutator.
+ dimensions.add(d);
+ }
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#createDimension(java.lang.String, java.lang.String)
+ */
+ public Dimension createDimension(String name, String initialSlot)
+ throws DimensionExistsException {
+ Dimension d = new SimpleDimension(name,initialSlot);
+ dimensions.add(d);
+ return d;
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#deleteDimension(org.frugenplat.framework.nspace.Dimension)
+ */
+ public void deleteDimension(Dimension dimension) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#dimensionAddedPosition(org.frugenplat.framework.nspace.Dimension, java.lang.String)
+ */
+ public void dimensionAddedPosition(Dimension dimension, String position) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#dimensionRemovedPosition(org.frugenplat.framework.nspace.Dimension, java.lang.String)
+ */
+ public void dimensionRemovedPosition(
+ Dimension dimension,
+ String position) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#getDimension(java.lang.String)
+ */
+ public Dimension getDimension(String name) {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * Returns an immutable set of dimensions for inspection..
+ * @see org.frugenplat.framework.nspace.NSpace#getDimensions()
+ */
+ public Set<Dimension> getDimensions() {
+ return Collections.unmodifiableSet(dimensions);
+ }
+
+ /**
+ * Exposes the internal dimensions set to any children
+ * @return Set
+ */
+ protected Set<Dimension> getInternalDimensions() {
+ return dimensions;
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#getValue()
+ */
+ public Object getValue(Coordinate c) {
+ // SparseNSpace s = _slice(c);
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ Object _findValue() {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#isPoint()
+ */
+ public boolean isPoint() {
+ if (dimensions.size() == 0) return true;
+ else {
+ boolean hasThinDimensions = true;
+ for(Dimension d : dimensions){
+ hasThinDimensions = hasThinDimensions &&
+ (d.size() == 1);
+ }
+ return hasThinDimensions;
+ }
+
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#lookup(org.frugenplat.framework.nspace.Coordinate)
+ */
+ public NSpace lookup(Coordinate c) {
+ return _lookup(c);
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#setValue(org.frugenplat.framework.nspace.Coordinate, org.frugenplat.framework.nspace.NSpace)
+ */
+ public NSpace setValue(Coordinate c, NSpace value)
+ throws InvalidDimensionalityException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#setValue(org.frugenplat.framework.nspace.Coordinate, java.lang.Object)
+ */
+ public NSpace setValue(Coordinate c, Object value)
+ throws InvalidDimensionalityException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ /**
+ * @see org.frugenplat.framework.nspace.NSpace#slice(org.frugenplat.framework.nspace.Coordinate)
+ */
+ public NSpace slice(Coordinate c) {
+ return _slice(c);
+ }
+
+ private SparseNSpace _lookup(Coordinate c) {
+ if (c.equals(Coordinate.EMPTY)) return this;
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ private SparseNSpace _slice(Coordinate c) {
+ if (c.equals(Coordinate.EMPTY)) return this;
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+ /* (non-Javadoc)
+ * @see org.frugenplat.framework.nspace.NSpace#slice(org.frugenplat.framework.nspace.Dimension)
+ */
+ public NSpace[] slice(Dimension d) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/israfil-foundation-nspace/src/site/apt/Specification.apt b/israfil-foundation-nspace/src/site/apt/Specification.apt new file mode 100755 index 0000000..5da06ac --- /dev/null +++ b/israfil-foundation-nspace/src/site/apt/Specification.apt @@ -0,0 +1,63 @@ +This doc defines the theoretical nature of an NSpace and Sparse NSpace implementation.
+
+
+
+NSpace
+
+ Definition:
+ - N-Dimensional Space representation
+ - NSpace is set of Dimensions
+ - Dimension is a set of Positions
+ - Each dimension is named
+ - Each co-ordinate is specified using names not numbers
+ IOW: Domain of each dim. is specified as a set of names
+ - Number of dimensions can change throughout lifecycle
+ - Dimensions are not ordered in a Space.
+ - Positions are not ordered in a Dimension
+ - value at fully-qualified-coordinate is of type Object
+
+
+ Operations
+ - When looking up co-ordinate - specify dimension + position
+ - 2 kinds of search (lookup and extract)
+
+ Questions:
+ - can an NSpace hold an (NSpace)value
+
+
+Dimension
+
+ Definition
+
+SparseNSpace
+
+ Characteristics:
+
+
+
+ Questions
+
+Example:
+
+ lookup()
+ Given a 5Space
+ specify 3 ordinates in lookup
+ Get a 5Space (3 dims have size of 1)
+
+ extractSlice()
+ Given a 5Space
+ specify 3 ordinates in lookup
+ Get a 2Space
+
+ getDimensions()
+ returns a set of Dimensions
+
+ getDimension(String name)
+ returns a set of Positions
+
+ space.addDimension(Dimension dimension, String origin)
+ all the points in the current system have to know of new dim.
+
+
+
+
diff --git a/israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd b/israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd new file mode 100755 index 0000000..dae310b --- /dev/null +++ b/israfil-foundation-nspace/src/site/resources/org.frugenplat.framework.nspace.ucd @@ -0,0 +1,58 @@ +<editmodel:ClassDiagramEditModel xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:editmodel="editmodel.xmi" size="1088,378" id="fenestratedcgruberSparseNSpace0" metadata="nsuml-1.4" initialized="true"> + <children xsi:type="editmodel:InterfaceEditModel" location="73,103" size="184,265" id="fenestratedcgruberSparseNSpace2" runTimeClassModel="fenestratedcgruberSparseNSpace54;fenestratedcgruberSparseNSpace73;fenestratedcgruberSparseNSpace7;fenestratedcgruberSparseNSpace121;fenestratedcgruberSparseNSpace32;fenestratedcgruberSparseNSpace123;fenestratedcgruberSparseNSpace13;fenestratedcgruberSparseNSpace119;fenestratedcgruberSparseNSpace116;fenestratedcgruberSparseNSpace21;fenestratedcgruberSparseNSpace69;fenestratedcgruberSparseNSpace30"> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace54"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace116"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace69"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace73"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace32"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace30"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace121"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace21"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace119"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace7"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace13"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace123"/> + </children> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + </children> + <children xsi:type="editmodel:InterfaceEditModel" location="304,226" size="140,139" id="fenestratedcgruberSparseNSpace36" runTimeClassModel="fenestratedcgruberSparseNSpace161;fenestratedcgruberSparseNSpace156;fenestratedcgruberSparseNSpace427;fenestratedcgruberSparseNSpace164;fenestratedcgruberSparseNSpace158;fenestratedcgruberSparseNSpace167;fenestratedcgruberSparseNSpace430"> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + <children xsi:type="editmodel:CompartmentEditModel" size="121,94" viewSorter="Name"> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace161"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace167"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace427"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace430"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace156"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace158"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace164"/> + </children> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + </children> + <children xsi:type="editmodel:InterfaceEditModel" location="311,47" size="137,103" id="fenestratedcgruberSparseNSpace150" runTimeClassModel="fenestratedcgruberSparseNSpace171;fenestratedcgruberSparseNSpace175;fenestratedcgruberSparseNSpace173;fenestratedcgruberSparseNSpace177"> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + <children xsi:type="editmodel:CompartmentEditModel" size="118,58" viewSorter="Name"> + <children xsi:type="editmodel:MethodEditModel" location="299,84" id="fenestratedcgruberSparseNSpace175"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace173"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace177"/> + </children> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + </children> + <children xsi:type="editmodel:ClassEditModel" location="528,39" size="213,33" id="fenestratedcgruberSparseNSpace258" runTimeClassModel="fenestratedcgruberSparseNSpace419;fenestratedcgruberSparseNSpace417"> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace419"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace417"/> + </children> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + </children> + <children xsi:type="editmodel:ClassEditModel" location="487,158" size="247,33" id="fenestratedcgruberSparseNSpace261" runTimeClassModel="fenestratedcgruberSparseNSpace414;fenestratedcgruberSparseNSpace412"> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace414"/> + <children xsi:type="editmodel:MethodEditModel" id="fenestratedcgruberSparseNSpace412"/> + </children> + <children xsi:type="editmodel:CompartmentEditModel" size="4,4" viewSorter="Name"/> + </children> +</editmodel:ClassDiagramEditModel> diff --git a/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java new file mode 100755 index 0000000..cd2d4d4 --- /dev/null +++ b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SimpleDimensionTest.java @@ -0,0 +1,211 @@ +package net.israfil.foundation.collections.nspace;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ * @author cgruber
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+@Test
+public class SimpleDimensionTest {
+
+ Object o1 = "TestValue1";
+ String d1Name = "TestDimension1";
+ String ordinal1 = "TestOrdinal1";
+ String ordinal2 = "TestOrdinal2";
+ String ordinal3 = "TestOrdinal3";
+
+ /**
+ * test {@link Dimension.Dimension(String,String) Dimension(String,String)}
+ */
+ public void testConstructor_String_String() {
+ Dimension d = new SimpleDimension(d1Name, ordinal1);
+ Assert.assertEquals(d1Name,d.getName(),"Name doesn't equal provided string.");
+ Assert.assertTrue(d.size() == 1,"Size is not equal to 1");
+
+ }
+
+
+ /**
+ * test {@link Dimension.getName() getName()}
+ */
+ public void testGetName() {
+ Dimension d = new SimpleDimension(d1Name, ordinal1);
+ Assert.assertEquals(d1Name,d.getName());
+ }
+
+ /**
+ * test {@link Dimension.register(NSpace) register(NSpace)}
+ */
+ public void testRegister_NSpace() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.deregister(NSpace) deregister(NSpace)}
+ */
+ public void testDeregister_NSpace() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.register(NSpace[]) register(NSpace[])}
+ */
+ public void testRegister_NSpaceArray() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.deregister(NSpace[]) deregister(NSpace[])}
+ */
+ public void testDeregister_NSpaceArray() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /**
+ * test {@link Dimension.add(Object) add(Object)}
+ */
+ public void testAdd_Object() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ d.add(ordinal2);
+ Assert.assertTrue(d.contains(ordinal2),"Dimension doesn't contain added position.");
+ }
+
+ /**
+ * test {@link Dimension.addAll(Collection) addAll(Collection)}
+ */
+ public void testAddAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal2);
+ c.add(ordinal3);
+
+ d.addAll(c);
+ Assert.assertTrue(d.contains(ordinal2),"Dimension doesn't contain added position.");
+ Assert.assertTrue(d.contains(ordinal3),"Dimension doesn't contain added position.");
+ }
+
+ @Test(expectedExceptions={UnsupportedOperationException.class})
+ public void testClear() {
+ new SimpleDimension(d1Name,ordinal1).clear();
+ }
+
+ /**
+ * test {@link Dimension.containsAll(Collection) containsAll(Collection)}
+ */
+ public void testContainsAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ d.add(ordinal2);
+
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal1);
+ c.add(ordinal2);
+ Assert.assertTrue(d.containsAll(c),"Dimension doesn't contain added positions.");
+
+ d = new SimpleDimension(d1Name,ordinal1);
+ Assert.assertFalse(d.containsAll(c),"Dimension claims to contain positions it shouldn't.");
+ }
+
+ @Test(expectedExceptions={UnsupportedOperationException.class})
+ public void testIsEmpty() {
+ new SimpleDimension(d1Name,ordinal1).isEmpty();
+ }
+
+ /**
+ * test {@link Dimension.iterator() iterator()}
+ */
+ public void testIterator() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ Iterator<String> i = d.iterator();
+ Assert.assertEquals(ordinal1,i.next());
+ Assert.assertFalse(i.hasNext());
+ }
+
+ /**
+ * test (@link Dimension.remove(Object) remove(Object)}
+ */
+ public void testRemove_Object() {
+ String toBeRemoved = ordinal2;
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(toBeRemoved);
+ Assert.assertTrue(d.contains(toBeRemoved));
+ d.remove(toBeRemoved);
+ Assert.assertFalse(d.contains(toBeRemoved));
+ }
+
+ /**
+ * test {@link Dimension.removeAll(Collection) removeAll(Collection)}
+ * TODO: This should test removing every position
+ */
+ public void testRemoveAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(ordinal2)
+ .addPosition(ordinal3);
+
+ Assert.assertTrue(d.contains(ordinal2));
+ Assert.assertTrue(d.contains(ordinal3));
+
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal2);
+ c.add(ordinal3);
+ d.removeAll(c);
+ Assert.assertEquals(d.size(),1);
+ }
+
+ /**
+ * test {@link Dimension.retainAll(Collection) retainAll(Collection)}
+ */
+ public void testRetainAll_Collection() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(ordinal2)
+ .addPosition(ordinal3);
+
+ Assert.assertTrue(d.contains(ordinal2));
+ Assert.assertTrue(d.contains(ordinal3));
+
+ Collection<String> c = new HashSet<String>();
+ c.add(ordinal2);
+ c.add(ordinal3);
+ d.retainAll(c);
+ Assert.assertEquals(d.size(),2);
+ }
+
+ /**
+ * test {@link Dimensions.size() size()}
+ */
+ public void testSize() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1)
+ .addPosition(ordinal2)
+ .addPosition(ordinal3);
+ Assert.assertEquals(d.size(),3);
+ }
+
+ /**
+ * test {@link Dimensions.toArray() toArray()}
+ */
+ public void testToArray() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ String[] sa = (String[])d.toArray();
+ Assert.assertEquals(sa[0],ordinal1);
+ }
+
+ /**
+ * test {@link Dimension.toArray(Object[]) toArray(Object[])}
+ */
+ public void testToArray_ObjectArray() {
+ Dimension d = new SimpleDimension(d1Name,ordinal1);
+ String[] sa = (String[])d.toArray(new String[d.size()]);
+ Assert.assertEquals(sa[0],ordinal1);
+ }
+
+}
diff --git a/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java new file mode 100755 index 0000000..b291a23 --- /dev/null +++ b/israfil-foundation-nspace/src/test/java/net/israfil/foundation/collections/nspace/SparseNSpaceTest.java @@ -0,0 +1,87 @@ +/*
+ * Copyright (c) 2003, Mishkin Berteig and Christian Gruber
+ *
+ * $Id: SparseNSpaceTest.java 261 2005-05-15 13:36:26Z cgruber $
+ */
+package net.israfil.foundation.collections.nspace;
+
+import org.testng.Assert;
+import org.testng.SkipException;
+import org.testng.annotations.Test;
+
+/**
+ * @author <a href="mailto:mishkin@berteig.com">Mishkin Berteig</a>
+ * @author <a href="mailto:cgruber@israfil.net">Christian Gruber</a>
+ * @version $Revision: 261 $
+ */
+@Test
+public class SparseNSpaceTest {
+
+ public void testCreateDimension_String_String() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testDeleteDimension_Dimension() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testDimensionAddedPosition() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testDimensionRemovedPosition() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testGetDimension_String() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testGetDimensions() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testGetValue() throws InvalidDimensionalityException {
+ NSpace space = new SparseNSpace();
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testIsPoint() throws DimensionExistsException {
+ NSpace space = new SparseNSpace();
+ Assert.assertTrue(space.isPoint());
+
+ // Create two "thin" dimensions.
+ space.createDimension("TestDimension1","TestOrdinal");
+ space.createDimension("TestDimension2","TestOrdinal");
+
+ Assert.assertTrue(space.isPoint());
+ /*
+ space.createDimension("TestDimension3","TestOrdinal1")
+ .addPosition("TestOrdinal2");
+ Assert.assertFalse(space.isPoint());
+ */
+ }
+
+ public void testLookup_Coordinate() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /*
+ * Test for NSpace setValue(Coordinate, NSpace)
+ */
+ public void testSetValue_Coordinate_NSpace() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ /*
+ * Test for NSpace setValue(Coordinate, Object)
+ */
+ public void testSetValue_Coordinate_Object() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+ public void testSlice() {
+ throw new SkipException("Unimplemented Test");
+ }
+
+}
diff --git a/israfil-foundation-testing/pom.xml b/israfil-foundation-testing/pom.xml new file mode 100644 index 0000000..1eecf29 --- /dev/null +++ b/israfil-foundation-testing/pom.xml @@ -0,0 +1,21 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-testing</artifactId> + <name>Israfil Foundation Testing Helpers and Fakes</name> + <version>1.0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <inceptionYear>2003</inceptionYear> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> +</project>
\ No newline at end of file diff --git a/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java new file mode 100644 index 0000000..4de4a63 --- /dev/null +++ b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSet.java @@ -0,0 +1,1350 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSet.java 517M 2007-07-09 20:00:15Z (local) $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Map;
+
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.ColSpec;
+
+/**
+ * A Mock implementation of ResultSet that takes an array of column
+ * names and an array or rows, where rows are arrays of data. A Mock
+ * ResultSet can be used in unit testing where database access needs
+ * to be stubbed out.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class MockResultSet implements ResultSet {
+
+ public MockResultSetMetaData metadata;
+
+ protected List<Row> data;
+ public List<Row> getData() { return data; }
+ int cursorPosition = 0;
+ boolean insertRow = false;
+ private final static int BEFOREFIRST = 0;
+ private final int AFTERLAST;
+ protected int concurrency = CONCUR_READ_ONLY;
+ protected int fetchDirection = FETCH_UNKNOWN;
+ protected int fetchSize = 0;
+ protected Statement statement = null;
+ protected boolean wasNull = false;
+ boolean open = false;
+
+ private MockResultSet(int size) {
+ AFTERLAST = size+1;
+ }
+
+ /**
+ * The main constructor, which takes an array of strings representing
+ * the columns of the supposed DataReader, and an array of string arrays
+ * representing the row data. With this, one can simulate a call to the
+ * database.
+ *
+ * @param columns the columns to be simulated
+ * @param rows the rows to be simulated
+ *
+ */
+ public MockResultSet(String[] columns, Object[][] rows) {
+ this((rows==null)?0:rows.length);
+ metadata = new MockResultSetMetaData(columns);
+ primeRows(rows);
+ }
+
+ /**
+ * The main constructor, which takes an array of strings representing
+ * the columns of the supposed DataReader, and an array of string arrays
+ * representing the row data. With this, one can simulate a call to the
+ * database.
+ *
+ * @param columns the columns to be simulated
+ * @param rows the rows to be simulated
+ *
+ */
+ public MockResultSet(ColSpec[] columns, Object[][] rows) {
+ this((rows==null)?0:rows.length);
+ metadata = new MockResultSetMetaData(columns);
+ primeRows(rows);
+ }
+
+ /**
+ * Private method that takes given row data and populates the internal
+ * structures with said data.
+ * @param rows
+ */
+ private void primeRows(Object[][] rows) {
+ if (rows == null) rows = new String[][]{};
+ try {
+ data = new ArrayList<Row>(metadata.getColumnCount());
+ for (int rowNum = 0; rowNum < rows.length; rowNum++) {
+ data.add(new Row(metadata,new ArrayList<Object>(Arrays.asList(rows[rowNum]))));
+ }
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ cursorPosition = 0;
+ open = true;
+ }
+
+ public void finalize() throws Throwable {
+ data = null;
+ metadata = null;
+ super.finalize();
+ }
+
+ /**
+ * Moves the cursor to the given row number in this ResultSet object.
+ *
+ * If the row number is positive, the cursor moves to the given row number
+ * with respect to the beginning of the result set. The first row is row 1,
+ * the second is row 2, and so on.
+ *
+ * If the given row number is negative, the cursor moves to an absolute row
+ * position with respect to the end of the result set. For example, calling
+ * the method absolute(-1) positions the cursor on the last row; calling the
+ * method absolute(-2) moves the cursor to the next-to-last row, and so on.
+ *
+ * An attempt to position the cursor beyond the first/last row in the result
+ * set leaves the cursor before the first row or after the last row.
+ *
+ * Note: Calling absolute(1) is the same as calling first(). Calling
+ * absolute(-1) is the same as calling last().
+ *
+ * @param row - the number of the row to which the cursor should move. A positive number indicates the row number counting from the beginning of the result set; a negative number indicates the row number counting from the end of the result set
+ * @return true if the cursor is on the result set; false otherwise
+ */
+ public boolean absolute(int row) throws SQLException {
+ // the number of the row to which the cursor should move.
+ // A positive number indicates the row number counting from
+ // the beginning of the result set; a negative number indicates
+ // the row number counting from the end of the result set.
+ if (row > 0) {
+ if (BEFOREFIRST + row < AFTERLAST) {
+ cursorPosition = BEFOREFIRST + row;
+ return true;
+ } else {
+ cursorPosition = AFTERLAST;
+ return false;
+ }
+ } else if (row < 0) {
+ if (AFTERLAST + row > BEFOREFIRST) {
+ cursorPosition = AFTERLAST + row;
+ return true;
+ } else {
+ cursorPosition = BEFOREFIRST;
+ return false;
+ }
+ } else /* offset == 0 */ {
+ // This is essentially beforeFirst();
+ cursorPosition = 0;
+ return false;
+ }
+ }
+
+ public void afterLast() throws SQLException {
+ absolute(data.size()+1);
+ }
+
+ public void beforeFirst() throws SQLException {
+ absolute(0);
+ }
+
+ public void cancelRowUpdates() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void clearWarnings() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public void close() throws SQLException {
+ open = false;
+ }
+
+ public void deleteRow() throws SQLException {
+ if (insertRow) throw new SQLException("Cannot delete the insert row.");
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int findColumn(String column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public boolean first() throws SQLException {
+ return absolute(1);
+ }
+
+ public Object getInternalValue(int rowNumber, int column) {
+ try {
+ return processAccessedObject(data.get(rowNumber-1).get(column));
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+
+ public Object getInternalValue(int rowNumber, String column) {
+ try {
+ return processAccessedObject(data.get(rowNumber-1).get(column));
+ } catch (SQLException e) { throw new RuntimeException(e); }
+ }
+
+ public Object processAccessedObject(Object o) {
+ if (o == null) wasNull = true;
+ return o;
+ }
+
+ public Array getArray(int column) throws SQLException {
+ return (Array)getInternalValue(cursorPosition,column);
+ }
+
+ public Array getArray(String column) throws SQLException {
+ return (Array)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getAsciiStream(int column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getAsciiStream(String column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public BigDecimal getBigDecimal(int column, int scale) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ bd.setScale(scale);
+ return bd;
+ }
+
+ public BigDecimal getBigDecimal(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ return bd;
+ }
+
+ public BigDecimal getBigDecimal(String column, int scale) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ bd.setScale(scale);
+ return bd;
+ }
+
+ public BigDecimal getBigDecimal(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ BigDecimal bd;
+ if (o instanceof String) bd = new BigDecimal((String)o);
+ else if (o instanceof Number) bd = new BigDecimal(((Number)o).doubleValue());
+ else if (o instanceof java.util.Date) bd = new BigDecimal(((java.util.Date)o).getTime());
+ else if (o instanceof Calendar) bd = new BigDecimal(((Calendar)o).getTimeInMillis());
+ else if (o instanceof char[]) bd = new BigDecimal(((char[])o));
+ else if (o instanceof Boolean) return new BigDecimal(((Boolean)o).booleanValue() ? 1 : 0);
+ else bd = new BigDecimal(String.valueOf(o));
+ return bd;
+ }
+
+ public InputStream getBinaryStream(int column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getBinaryStream(String column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public Blob getBlob(int column) throws SQLException {
+ return new MockBlob(getBytes(column));
+ }
+
+ public Blob getBlob(String column) throws SQLException {
+ return new MockBlob(getBytes(column));
+ }
+
+ public boolean getBoolean(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return false;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) return ((Number)o).byteValue() != 0;
+ else return Boolean.valueOf(String.valueOf(o));
+ }
+
+ public boolean getBoolean(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return false;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) return ((Number)o).byteValue() != 0;
+ else return Boolean.valueOf(String.valueOf(o));
+ }
+
+ public byte getByte(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).byteValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (byte)1 : (byte)0 ;
+ } else return Byte.valueOf(String.valueOf(o));
+ }
+
+ public byte getByte(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).byteValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (byte)1 : (byte)0 ;
+ } else return Byte.valueOf(String.valueOf(o));
+ }
+
+ public byte[] getBytes(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public byte[] getBytes(String column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Reader getCharacterStream(int column) throws SQLException {
+ return (Reader)getInternalValue(cursorPosition,column);
+ }
+
+ public Reader getCharacterStream(String column) throws SQLException {
+ return (Reader)getInternalValue(cursorPosition,column);
+ }
+
+ public Clob getClob(int column) throws SQLException {
+ return (Clob)getInternalValue(cursorPosition,column);
+ }
+
+ public Clob getClob(String column) throws SQLException {
+ return (Clob)getInternalValue(cursorPosition,column);
+ }
+
+ public int getConcurrency() throws SQLException {
+ return concurrency;
+ }
+
+ public void setConcurrency(int concurrency) {
+ this.concurrency = concurrency;
+ }
+ public String getCursorName() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Date getDate(int column, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Date getDate(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Date) return (Date)o;
+ if (o instanceof java.util.Date)
+ return new Date(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Date(((Calendar)o).getTimeInMillis());
+ return Date.valueOf(String.valueOf(o));
+ }
+
+ public Date getDate(String column, Calendar cal) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public Date getDate(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Date) return (Date)o;
+ if (o instanceof java.util.Date)
+ return new Date(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Date(((Calendar)o).getTimeInMillis());
+ return Date.valueOf(String.valueOf(o));
+ }
+
+ public double getDouble(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).doubleValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 : 0 ;
+ } else return Double.valueOf(String.valueOf(o));
+ }
+
+ public double getDouble(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).doubleValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 : 0 ;
+ } else return Double.valueOf(String.valueOf(o));
+ }
+
+ public int getFetchDirection() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getFetchSize() throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public float getFloat(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).floatValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Float.valueOf(String.valueOf(o));
+ }
+
+ public float getFloat(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).floatValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Float.valueOf(String.valueOf(o));
+ }
+
+ public int getInt(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).intValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Integer.valueOf(String.valueOf(o));
+ }
+
+ public int getInt(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).intValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Integer.valueOf(String.valueOf(o));
+ }
+
+ public long getLong(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).longValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Long.valueOf(String.valueOf(o));
+ }
+
+ public long getLong(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).longValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? 1 :0 ;
+ } else return Long.valueOf(String.valueOf(o));
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return metadata;
+ }
+
+ public Object getObject(int column, Map<String, Class<?>> mapping) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public Object getObject(int column) throws SQLException {
+ return (Object)getInternalValue(cursorPosition,column);
+ }
+
+ public Object getObject(String column, Map<String, Class<?>> mapping) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public Object getObject(String column) throws SQLException {
+ return (Object)getInternalValue(cursorPosition,column);
+ }
+
+ public Ref getRef(int column) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public Ref getRef(String column) throws SQLException {
+ throw new UnsupportedOperationException("Unimplented feature.");
+ }
+
+ public int getRow() throws SQLException {
+ return (cursorPosition > BEFOREFIRST && cursorPosition < AFTERLAST) ? cursorPosition : 0;
+ }
+
+ public short getShort(int column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).shortValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (short)1 : (short)0 ;
+ } else return Short.valueOf(String.valueOf(o));
+ }
+
+ public short getShort(String column) throws SQLException {
+ if (getInternalValue(cursorPosition,column) == null) return 0;
+ Object o = getInternalValue(cursorPosition,column);
+ if (o instanceof Number) {
+ return ((Number)o).shortValue();
+ } else if (o instanceof Boolean) {
+ return ((Boolean)o).booleanValue() ? (short)1 : (short)0 ;
+ } else return Short.valueOf(String.valueOf(o));
+ }
+
+ public Statement getStatement() throws SQLException {
+ return null;
+ }
+
+ public String getString(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ return (o == null) ? null : String.valueOf(o);
+ }
+
+ public String getString(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ return (o == null) ? null : String.valueOf(o);
+ }
+
+ public Time getTime(int column, Calendar cal) throws SQLException {
+ return (Time)getInternalValue(cursorPosition,column);
+ }
+
+ public Time getTime(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Time) return (Time)o;
+ if (o instanceof java.util.Date)
+ return new Time(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Time(((Calendar)o).getTimeInMillis());
+ return Time.valueOf(String.valueOf(o));
+ }
+
+ public Time getTime(String column, Calendar cal) throws SQLException {
+ return (Time)getInternalValue(cursorPosition,column);
+ }
+
+ public Time getTime(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Time) return (Time)o;
+ if (o instanceof java.util.Date)
+ return new Time(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Time(((Calendar)o).getTimeInMillis());
+ return Time.valueOf(String.valueOf(o));
+ }
+
+ public Timestamp getTimestamp(int column, Calendar cal) throws SQLException {
+ return (Timestamp)getInternalValue(cursorPosition,column);
+ }
+
+ public Timestamp getTimestamp(int column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Timestamp) return (Timestamp)o;
+ if (o instanceof java.util.Date)
+ return new Timestamp(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Timestamp(((Calendar)o).getTimeInMillis());
+ return Timestamp.valueOf(String.valueOf(o));
+ }
+
+ public Timestamp getTimestamp(String column, Calendar cal) throws SQLException {
+ return (Timestamp)getInternalValue(cursorPosition,column);
+ }
+
+ public Timestamp getTimestamp(String column) throws SQLException {
+ Object o = getInternalValue(cursorPosition,column);
+ if (o == null) return null;
+ if (o instanceof Timestamp) return (Timestamp)o;
+ if (o instanceof java.util.Date)
+ return new Timestamp(((java.util.Date)o).getTime());
+ if (o instanceof Calendar)
+ return new Timestamp(((Calendar)o).getTimeInMillis());
+ return Timestamp.valueOf(String.valueOf(o));
+ }
+
+ public int getType() throws SQLException {
+ return TYPE_SCROLL_INSENSITIVE;
+ }
+
+ public InputStream getUnicodeStream(int column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public InputStream getUnicodeStream(String column) throws SQLException {
+ return (InputStream)getInternalValue(cursorPosition,column);
+ }
+
+ public URL getURL(int column) throws SQLException {
+ return (URL)getInternalValue(cursorPosition,column);
+ }
+
+ public URL getURL(String column) throws SQLException {
+ return (URL)getInternalValue(cursorPosition,column);
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void insertRow() throws SQLException {
+ if (!insertRow) throw new SQLException("Cannot insert any row except the insert row.");
+ // TODO: Add logic to check nullability.
+
+ }
+
+ public boolean isAfterLast() throws SQLException {
+ return cursorPosition >= AFTERLAST;
+ }
+
+ public boolean isBeforeFirst() throws SQLException {
+ return cursorPosition <= BEFOREFIRST;
+ }
+
+ public boolean isFirst() throws SQLException {
+ return data.size() > 0 && !insertRow && cursorPosition == BEFOREFIRST + 1;
+ }
+
+ public boolean isLast() throws SQLException {
+ return data.size() > 0 && !insertRow && cursorPosition == AFTERLAST - 1;
+ }
+
+ public boolean last() throws SQLException {
+ return absolute(-1);
+ }
+
+ public void moveToCurrentRow() throws SQLException {
+ insertRow = false;
+ }
+
+ public void moveToInsertRow() throws SQLException {
+ insertRow = true;
+ }
+
+ public boolean next() throws SQLException {
+ return relative(1);
+ }
+
+ public boolean previous() throws SQLException {
+ return relative(-1);
+ }
+
+ public void refreshRow() throws SQLException {
+ // TODO: blow away update row
+
+ }
+
+ public boolean relative(int offset) throws SQLException {
+ return absolute(cursorPosition+offset);
+ }
+
+ public boolean rowDeleted() throws SQLException {
+ // TODO: Possibly implement deletion detection
+ return false;
+ }
+
+ public boolean rowInserted() throws SQLException {
+ // TODO: Possibly implement insertion detection
+ return false;
+ }
+
+ public boolean rowUpdated() throws SQLException {
+ // TODO: Possibly implement update detection.
+ return false;
+ }
+
+ public void setFetchDirection(int direction) throws SQLException {
+ this.fetchDirection = direction;
+ }
+
+ public void setFetchSize(int rows) throws SQLException {
+ if (rows < 0 || (this.statement != null && rows > statement.getMaxRows()))
+ throw new SQLException("Fetch size less than zero or greater than statement's maximum rows.");
+ else this.fetchSize = rows;
+ }
+
+ public void updateArray(int column, Array x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateArray(String column, Array x) throws SQLException {
+ updateArray(findColumn(column),x);
+ }
+
+ public void updateAsciiStream(int column, InputStream x, int length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateAsciiStream(String column, InputStream x, int length) throws SQLException {
+ updateAsciiStream(findColumn(column),x,length);
+ }
+
+ public void updateBigDecimal(int column, BigDecimal x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBigDecimal(String column, BigDecimal x) throws SQLException {
+ updateBigDecimal(findColumn(column),x);
+ }
+
+ public void updateBinaryStream(int column, InputStream x, int length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBinaryStream(String column, InputStream x, int length) throws SQLException {
+ updateBinaryStream(findColumn(column),x,length);
+ }
+
+ public void updateBlob(int column, Blob x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBlob(String column, Blob x) throws SQLException {
+ updateBlob(findColumn(column),x);
+ }
+
+ public void updateBoolean(int column, boolean x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBoolean(String column, boolean x) throws SQLException {
+ updateBoolean(findColumn(column),x);
+ }
+
+ public void updateByte(int column, byte x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateByte(String column, byte x) throws SQLException {
+ updateByte(findColumn(column),x);
+ }
+
+ public void updateBytes(int column, byte[] x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateBytes(String column, byte[] x) throws SQLException {
+ updateBytes(findColumn(column),x);
+ }
+
+ public void updateCharacterStream(int column, Reader x, int length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateCharacterStream(String column, Reader reader, int length) throws SQLException {
+ updateCharacterStream(findColumn(column),reader,length);
+ }
+
+ public void updateClob(int column, Clob x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateClob(String column, Clob x) throws SQLException {
+ updateClob(findColumn(column),x);
+ }
+
+ public void updateDate(int column, Date x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateDate(String column, Date x) throws SQLException {
+ updateDate(findColumn(column),x);
+ }
+
+ public void updateDouble(int column, double x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateDouble(String column, double x) throws SQLException {
+ updateDouble(findColumn(column),x);
+ }
+
+ public void updateFloat(int column, float x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateFloat(String column, float x) throws SQLException {
+ updateFloat(findColumn(column),x);
+ }
+
+ public void updateInt(int column, int x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateInt(String column, int x) throws SQLException {
+ updateInt(findColumn(column),x);
+ }
+
+ public void updateLong(int column, long x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateLong(String column, long x) throws SQLException {
+ updateLong(findColumn(column),x);
+ }
+
+ public void updateNull(int column) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateNull(String column) throws SQLException {
+ updateNull(findColumn(column));
+ }
+
+ public void updateObject(int column, Object x, int scale) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateObject(int column, Object x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateObject(String column, Object x, int scale) throws SQLException {
+ updateObject(findColumn(column),x,scale);
+ }
+
+ public void updateObject(String column, Object x) throws SQLException {
+ updateObject(findColumn(column),x);
+ }
+
+ public void updateRef(int column, Ref x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateRef(String column, Ref x) throws SQLException {
+ updateRef(findColumn(column),x);
+ }
+
+ public void updateRow() throws SQLException {
+ // TODO: Implement update call.
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ public void updateShort(int column, short x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateShort(String column, short x) throws SQLException {
+ updateShort(findColumn(column),x);
+ }
+
+ public void updateString(int column, String x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateString(String column, String x) throws SQLException {
+ updateString(findColumn(column),x);
+ }
+
+ public void updateTime(int column, Time x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateTime(String column, Time x) throws SQLException {
+ updateTime(findColumn(column),x);
+ }
+
+ public void updateTimestamp(int column, Timestamp x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void updateTimestamp(String column, Timestamp x) throws SQLException {
+ updateTimestamp(findColumn(column),x);
+ }
+
+ public boolean wasNull() throws SQLException {
+ // TODO: Implement very awkward wasNull() method.
+ return false;
+ }
+
+
+ class MockBlob implements Blob {
+
+ private byte[] bytes;
+
+ public MockBlob(byte[] bytes) {
+ this.bytes=bytes;
+ }
+
+ public InputStream getBinaryStream() throws SQLException {
+ // TODO Implement getBinaryStream()
+ return null;
+ }
+
+ public byte[] getBytes(long pos, int length) throws SQLException {
+ // TODO Implement getBinaryStream()
+ if (false) bytes.hashCode();
+ return null;
+ }
+
+ public long length() throws SQLException {
+ // TODO Implement length()
+ return 0;
+ }
+
+ public long position(Blob pattern, long start) throws SQLException {
+ // TODO Implement position(Blob,long)
+ return 0;
+ }
+
+ public long position(byte[] pattern, long start) throws SQLException {
+ // TODO Implement position(byte[],long)
+ return 0;
+ }
+
+ public OutputStream setBinaryStream(long pos) throws SQLException {
+ // TODO Implement setBinaryStream(long)
+ return null;
+ }
+
+ public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {
+ // TODO Implement setBytes(long,byte[],int,int)
+ return 0;
+ }
+
+ public int setBytes(long pos, byte[] bytes) throws SQLException {
+ // TODO Implement setBytes(long,byte[])
+ return 0;
+ }
+
+ public void truncate(long len) throws SQLException {
+ // TODO Implement truncate(long)
+ }
+
+ @Override
+ public void free() throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public InputStream getBinaryStream(long pos, long length) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ }
+
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public RowId getRowId(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public RowId getRowId(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void updateRowId(int columnIndex, RowId x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateRowId(String columnLabel, RowId x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void updateNString(int columnIndex, String nString) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNString(String columnLabel, String nString) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, NClob nClob) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public NClob getNClob(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public NClob getNClob(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public SQLXML getSQLXML(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public SQLXML getSQLXML(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public String getNString(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public String getNString(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Reader getNCharacterStream(int columnIndex) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Reader getNCharacterStream(String columnLabel) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(int columnIndex, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateClob(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(int columnIndex, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void updateNClob(String columnLabel, Reader reader) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ };
+
+}
diff --git a/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java new file mode 100644 index 0000000..2a6b67c --- /dev/null +++ b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/MockResultSetMetaData.java @@ -0,0 +1,342 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSetMetaData.java 13 2006-01-27 23:45:36Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.math.BigDecimal;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * An implementation of DatabaseMetaData that partners with ResultSet to
+ * provide database-disconnected fixed results for testing via the JDBC
+ * APIs.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class MockResultSetMetaData implements ResultSetMetaData {
+
+ public static int ZERO_ORDER_LIST_OFFSET = 1;
+ List<ColSpec> columns;
+
+ MockResultSetMetaData(String ... columns) {
+ if (columns == null) throw new IllegalArgumentException("Cannot construct a MockResultSet with no columns.");
+ ColSpec[] colspecs = new ColSpec[columns.length];
+ for (int i = 0 ; i < columns.length ; i++) {
+ colspecs[i] = new ColSpec(columns[i]);
+ }
+ prepColumns(colspecs);
+ }
+
+ MockResultSetMetaData(ColSpec ... columns) {
+ prepColumns(columns);
+ }
+
+ private void prepColumns(ColSpec ... columns) {
+ if (columns == null || columns.length <= 0)
+ throw new IllegalArgumentException("Cannot construct a MockResultSet with no columns.");
+ this.columns = new ArrayList<ColSpec>(Arrays.asList(columns));
+ }
+
+ public void finalize() throws Throwable {
+ columns = null;
+ }
+
+ /**
+ * Given a column name, this method returns the number of the column, or 0 if
+ * no such column exists.
+ *
+ * @param name
+ * @return
+ */
+ public int getColumnNumber(String name) {
+ for (int i = 1; i <= columns.size(); i++)
+ if (columns.get(i-ZERO_ORDER_LIST_OFFSET).name.equalsIgnoreCase(name)) return i;
+ return 0;
+ }
+
+ public String getCatalogName(int column) throws SQLException {
+ return "";
+ }
+
+ public String getColumnClassName(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int getColumnCount() throws SQLException {
+ return columns.size();
+ }
+
+ public int getColumnDisplaySize(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).width;
+ }
+
+ public String getColumnLabel(int column) throws SQLException {
+ if (column < 1) throw new IllegalArgumentException("Column number must be greater than 0.");
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).name;
+ }
+
+ public String getColumnName(int column) throws SQLException {
+ if (column < 1) throw new IllegalArgumentException("Column number must be greater than 0.");
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).name;
+ }
+
+ public int getColumnType(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).type.sqltype;
+ }
+
+ public String getColumnTypeName(int column) throws SQLException {
+ return columns.get(column).type.name();
+ }
+
+ public int getPrecision(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).precision;
+ }
+
+ public int getScale(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).scale;
+ }
+
+ public String getSchemaName(int column) throws SQLException {
+ return "";
+ }
+
+ public String getTableName(int column) throws SQLException {
+ return "";
+ }
+
+ public boolean isAutoIncrement(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isCaseSensitive(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isCurrency(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isDefinitelyWritable(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public int isNullable(int column) throws SQLException {
+ return columns.get(column-ZERO_ORDER_LIST_OFFSET).nullable ? ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls;
+ }
+
+ public boolean isReadOnly(int column) throws SQLException {
+ return true;
+ }
+
+ public boolean isSearchable(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public boolean isSigned(int column) throws SQLException {
+ return false;
+ }
+
+ public boolean isWritable(int column) throws SQLException {
+ throw new UnsupportedOperationException("Not yet implemented.");
+ }
+
+ public static class ColSpec {
+ public final String name;
+ public final DBType type;
+ public final int width;
+ public final int precision;
+ public final int scale;
+ public final boolean nullable;
+
+ public ColSpec(String name) {
+ this.name = name;
+ this.type = DBType.OBJECT;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, boolean nullable) {
+ this.name = name;
+ this.type = DBType.OBJECT;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = nullable;
+ }
+ public ColSpec(String name, DBType type) {
+ this.name = name;
+ this.type = type;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, DBType type, boolean nullable) {
+ this.name = name;
+ this.type = type;
+ this.width = 0;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = nullable;
+ }
+ public ColSpec(String name, DBType type, int width) {
+ this.name = name;
+ this.type = type;
+ this.width = width;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, DBType type, int precision, int scale) {
+ this.name = name;
+ this.type = type;
+ this.precision = precision;
+ this.scale = scale;
+ this.width = 0;
+ this.nullable = true;
+ }
+ public ColSpec(String name, DBType type, int width, boolean nullable) {
+ this.name = name;
+ this.type = type;
+ this.width = width;
+ this.precision = 0;
+ this.scale = 0;
+ this.nullable = nullable;
+ }
+ public ColSpec(String name, DBType type, int precision, int scale, boolean nullable) {
+ this.name = name;
+ this.type = type;
+ this.precision = precision;
+ this.scale = scale;
+ this.width = 0;
+ this.nullable = nullable;
+ }
+ }
+
+ public enum DBTypeGroup {
+ Time(0), Number(1), String(2), Complex(3), Other(4);
+ public int value;
+ private DBTypeGroup(int i) {
+ value = i;
+ }
+ }
+
+ public enum DBType {
+ BLOB(byte[].class,Types.BLOB,DBTypeGroup.Other),
+ BIT(boolean.class,Types.BIT,DBTypeGroup.Number),
+ CHAR(char.class,Types.CHAR,DBTypeGroup.Number),
+ DECIMAL(BigDecimal.class,Types.DECIMAL,DBTypeGroup.Number),
+ FLOAT(float.class,Types.FLOAT,DBTypeGroup.Number),
+ DOUBLE(double.class,Types.DOUBLE,DBTypeGroup.Number),
+ SHORT(short.class,Types.SMALLINT,DBTypeGroup.Number),
+ INTEGER(int.class,Types.INTEGER,DBTypeGroup.Number),
+ LONG(long.class,Types.BIGINT,DBTypeGroup.Number),
+ BYTE(byte.class,Types.TINYINT,DBTypeGroup.Number),
+ STRING(String.class,Types.VARCHAR,DBTypeGroup.String),
+ TIMESTAMP(Timestamp.class,Types.TIMESTAMP,DBTypeGroup.Time),
+ OBJECT(Object.class,Types.JAVA_OBJECT,DBTypeGroup.Complex);
+
+ public final Class<?> javaClass;
+ public final int sqltype;
+ public final DBTypeGroup group;
+ private DBType(Class<?> javaClass, int sqltype, DBTypeGroup group) {
+ this.javaClass = javaClass;
+ this.sqltype = sqltype;
+ this.group = group;
+ }
+ public static DBType valueOf(int sqlType) {
+ switch (sqlType) {
+ case Types.BLOB:
+ case Types.CLOB:
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY: return DBType.BLOB;
+
+ case Types.BIGINT: return DBType.LONG;
+
+ case Types.BOOLEAN:
+ case Types.BIT: return DBType.BIT;
+
+ case Types.CHAR: return DBType.CHAR;
+ case Types.DOUBLE: return DBType.DOUBLE;
+ case Types.FLOAT: return DBType.FLOAT;
+ case Types.INTEGER: return DBType.INTEGER;
+ case Types.SMALLINT: return DBType.SHORT;
+ case Types.TINYINT: return DBType.BYTE;
+
+ case Types.NUMERIC:
+ case Types.REAL:
+ case Types.DECIMAL: return DBType.DECIMAL;
+
+ case Types.VARCHAR:
+ case Types.LONGVARCHAR: return DBType.STRING;
+
+ case Types.DATE:
+ case Types.TIME:
+ case Types.TIMESTAMP: return DBType.TIMESTAMP;
+
+ case Types.JAVA_OBJECT:
+ case Types.ARRAY:
+ case Types.STRUCT: return DBType.OBJECT;
+
+ case Types.REF:
+ case Types.DISTINCT:
+ case Types.NULL:
+ case Types.OTHER:
+ case Types.DATALINK:
+ default:
+ throw new IllegalArgumentException("Unsupported JDBC type");
+ }
+
+ }
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+}
diff --git a/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java new file mode 100644 index 0000000..e48e342 --- /dev/null +++ b/israfil-foundation-testing/src/main/java/net/israfil/foundation/mock/sql/Row.java @@ -0,0 +1,98 @@ +/*
+ * Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation
+ * Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: Row.java 27 2006-02-13 19:40:43Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.sql.SQLException;
+import java.util.List;
+
+/**
+ * An object representing row data in a MockResultSet.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ */
+public class Row {
+
+ MockResultSetMetaData metadata = null;
+ List<Object> data;
+
+ int cursorPosition;
+ final boolean insertRow;
+ public boolean dirty = true;
+
+ public Row(MockResultSetMetaData metadata, List<Object> rowData) {
+ this(metadata,rowData,false);
+ }
+
+ public Row(MockResultSetMetaData metadata, List<Object> rowData, boolean isInsertRow) {
+ this.metadata = metadata;
+ this.data = rowData;
+ this.insertRow = isInsertRow;
+ this.dirty = false;
+ }
+
+ public void finalize() throws Throwable {
+ data = null;
+ metadata = null;
+ super.finalize();
+ }
+
+ public void validateColumn(int i) throws SQLException {
+ if (i <= 0 || i > metadata.columns.size()) throw new SQLException("No such column #" + i);
+ }
+
+ public List<Object> getData() { return data; }
+
+ public Object get(int i) throws SQLException {
+ validateColumn(i);
+ return data.get(i-1);
+ }
+
+ public Object get(String columnName) throws SQLException {
+ return get(metadata.getColumnNumber(columnName));
+ }
+
+ public void set(int i,Object o) throws SQLException {
+ validateColumn(i);
+ data.set(i-1,o);
+ dirty = true;
+ }
+
+ public void set(String columnName,Object o) throws SQLException {
+ set(metadata.getColumnNumber(columnName),o);
+ }
+
+ public boolean isDirty() {
+ return dirty;
+ }
+}
diff --git a/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java new file mode 100644 index 0000000..8a2d7c8 --- /dev/null +++ b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetMetaDataTest.java @@ -0,0 +1,113 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSetMetaDataTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.sql.SQLException;
+
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.ColSpec;
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.DBType;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+public class MockResultSetMetaDataTest {
+
+
+ public MockResultSetMetaDataTest() {
+ super();
+ }
+
+ @Test
+ public void testResultSetMetaDataCreation() throws SQLException {
+ String colA = "colA", colB = "colB", colC = "colC";
+ String[] cols = { colA, colB, colC };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(cols);
+ Assert.assertEquals(3,rsmd.getColumnCount());
+ Assert.assertEquals(colA,rsmd.getColumnName(1));
+ Assert.assertEquals(colB,rsmd.getColumnName(2));
+ Assert.assertEquals(colC,rsmd.getColumnName(3));
+ }
+
+ @Test
+ public void testResultSetMetaDataColumnReferencing() throws SQLException {
+ String colA = "colA", colB = "colB", colC = "colC";
+ String[] cols = { colA, colB, colC };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(cols);
+
+ Assert.assertEquals(3,rsmd.getColumnCount());
+
+ Assert.assertEquals(colA,rsmd.getColumnName(1));
+ Assert.assertEquals(colB,rsmd.getColumnName(2));
+ Assert.assertEquals(colC,rsmd.getColumnName(3));
+
+ Assert.assertEquals(1,rsmd.getColumnNumber(colA));
+ Assert.assertEquals(2,rsmd.getColumnNumber(colB));
+ Assert.assertEquals(3,rsmd.getColumnNumber(colC));
+ }
+
+ @Test
+ public void testResultSetMetaDataCreationWithColDefs() throws SQLException {
+ ColSpec colA = new ColSpec("colA", DBType.STRING, 12 );
+ ColSpec colB = new ColSpec("colB", DBType.INTEGER, 5, 0 );
+ ColSpec colC = new ColSpec("colC", DBType.DECIMAL, 3, 5, false);
+ ColSpec colD = new ColSpec("colD", DBType.STRING, 4, false);
+ ColSpec[] cols = { colA, colB, colC, colD };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(cols);
+ Assert.assertEquals(4,rsmd.getColumnCount());
+
+ Assert.assertEquals(colA.name,rsmd.getColumnName(1));
+ Assert.assertEquals(colB.name,rsmd.getColumnName(2));
+ Assert.assertEquals(colC.name,rsmd.getColumnName(3));
+ Assert.assertEquals(colD.name,rsmd.getColumnName(4));
+
+ Assert.assertEquals(colA.type.sqltype,rsmd.getColumnType(1));
+ Assert.assertEquals(colB.type.sqltype,rsmd.getColumnType(2));
+ Assert.assertEquals(colC.type.sqltype,rsmd.getColumnType(3));
+ Assert.assertEquals(colD.type.sqltype,rsmd.getColumnType(4));
+
+ Assert.assertEquals(colA.width,rsmd.getColumnDisplaySize(1));
+ Assert.assertEquals(colB.precision,rsmd.getPrecision(2));
+ Assert.assertEquals(colB.scale,rsmd.getScale(2));
+ Assert.assertEquals(colC.precision,rsmd.getPrecision(3));
+ Assert.assertEquals(colC.scale,rsmd.getScale(3));
+ Assert.assertEquals(colD.width,rsmd.getColumnDisplaySize(4));
+ }
+
+}
diff --git a/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java new file mode 100644 index 0000000..7dfcbcb --- /dev/null +++ b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/MockResultSetTest.java @@ -0,0 +1,263 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: MockResultSetTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Ref;
+import java.sql.SQLException;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.ColSpec;
+import net.israfil.foundation.mock.sql.MockResultSetMetaData.DBType;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+public class MockResultSetTest {
+
+ ColSpec colA, colB, colC, colD, colE,
+ colF, colG, colH, colI, colJ,
+ colK;
+ ColSpec[] cols;
+ Object[][] data;
+ MockResultSet mrs;
+
+ public MockResultSetTest() {
+ super();
+ }
+
+ @SuppressWarnings("deprecation")
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ colA = new ColSpec("colA", DBType.STRING, 12 );
+ colB = new ColSpec("colB", DBType.INTEGER);
+ colC = new ColSpec("colC", DBType.SHORT);
+ colD = new ColSpec("colD", DBType.LONG);
+ colE = new ColSpec("colE", DBType.BIT);
+ colF = new ColSpec("colF", DBType.BYTE);
+ colG = new ColSpec("colG", DBType.FLOAT);
+ colH = new ColSpec("colH", DBType.DOUBLE);
+ colI = new ColSpec("colI", DBType.DECIMAL, 3, 5, false);
+ colJ = new ColSpec("colJ", DBType.TIMESTAMP,true);
+ colK = new ColSpec("colK", DBType.OBJECT);
+ cols = new ColSpec[]{ colA, colB, colC, colD, colE};
+
+ data = new Object[][] {
+ { "str1", 254, (short)355, 921124432352L,
+ true, 0x44, 3.1415f, 9.994d,
+ new BigDecimal(4.45), Calendar.getInstance(), null },
+ { "str2", -922, (short)9283, 1910382394511L,
+ true, 0x94, null, -0.994d,
+ new BigDecimal(-229444.452322), new Date(2005,04,02), colE },
+ { null, 011, (short)4242, 4992830402903L,
+ false, 0x4a, 9.95d, 0.0d,
+ new BigDecimal(0.0), null, null },
+ };
+
+ mrs = new MockResultSet(cols,data);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ colA = colB = colC = colD = colE = null;
+ data = null;
+ mrs = null;
+ }
+
+ /** Should simply not throw an exception */
+ @Test
+ public void testResultSetCreationWithStrings() throws SQLException {
+ String[] cols2 = { "colA", "colB", "colC" };
+ mrs = new MockResultSet(cols2,data);
+ List<Row> dataMap = mrs.getData();
+ for (int i = 0; i < data.length ; i++) {
+ Row row = dataMap.get(i);
+ Assert.assertEquals(data[i][0], row.get("colA"));
+ Assert.assertEquals(data[i][1], row.get("colB"));
+ Assert.assertEquals(data[i][2], row.get("colC"));
+ }
+ }
+
+ @Test
+ public void testResultSetCreationWithNull() throws SQLException {
+ mrs = new MockResultSet(cols,null);
+ Assert.assertEquals(0,mrs.getData().size());
+ }
+
+ @Test
+ public void testResultSetAbsoluteNavigation() throws SQLException {
+ Assert.assertFalse(mrs.absolute(0));
+ Assert.assertTrue(mrs.absolute(1));
+ Assert.assertTrue(mrs.absolute(2));
+ Assert.assertTrue(mrs.absolute(3));
+ Assert.assertFalse(mrs.absolute(4));
+ Assert.assertFalse(mrs.absolute(5));
+
+ Assert.assertTrue(mrs.absolute(-1));
+ Assert.assertEquals(3,mrs.getRow());
+ Assert.assertTrue(mrs.absolute(-2));
+ Assert.assertEquals(2,mrs.getRow());
+ Assert.assertTrue(mrs.absolute(-3));
+ Assert.assertEquals(1,mrs.getRow());
+ Assert.assertFalse(mrs.absolute(-4));
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertFalse(mrs.absolute(-5));
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertTrue(mrs.isBeforeFirst());
+
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertFalse(mrs.isAfterLast());
+ mrs.first();
+ Assert.assertEquals(1,mrs.getRow());
+ Assert.assertFalse(mrs.isBeforeFirst());
+ Assert.assertFalse(mrs.isAfterLast());
+ mrs.last();
+ Assert.assertEquals(3,mrs.getRow());
+ Assert.assertFalse(mrs.isBeforeFirst());
+ Assert.assertFalse(mrs.isAfterLast());
+ mrs.afterLast();
+ Assert.assertEquals(0,mrs.getRow());
+ Assert.assertFalse(mrs.isBeforeFirst());
+ Assert.assertTrue(mrs.isAfterLast());
+ }
+
+ @Test
+ public void testResultSetRelativeNavigation() throws SQLException {
+ mrs.beforeFirst();
+ Assert.assertTrue(mrs.isBeforeFirst());
+ Assert.assertTrue(mrs.next());
+ Assert.assertTrue(mrs.next());
+ Assert.assertTrue(mrs.next());
+ Assert.assertFalse(mrs.next());
+ Assert.assertTrue(mrs.isAfterLast());
+ Assert.assertTrue(mrs.previous());
+ Assert.assertTrue(mrs.previous());
+ Assert.assertTrue(mrs.previous());
+ Assert.assertFalse(mrs.previous());
+ Assert.assertTrue(mrs.isBeforeFirst());
+ }
+
+
+
+ /**
+ * Test each group of accessors depending on the type.
+ */
+ @Test
+ public void testResultSetGetOperations() throws Throwable {
+ String[] ptypes = { "java.lang.String", "int" };
+ Class<?>[][] classes = {
+ { Timestamp.class, Time.class, Date.class },
+ { short.class, long.class, int.class, float.class,
+ double.class, BigDecimal.class, boolean.class, byte.class },
+ { String.class },
+ { Object.class },
+ { byte[].class, Reader.class, Clob.class, Ref.class,
+ InputStream.class, InputStream.class, Array.class, Blob.class }
+ };
+ String[][] props = { { "Timestamp", "Time", "Date" },
+ { "Short", "Long", "Int", "Float",
+ "Double", "BigDecimal", "Boolean", "Byte" },
+ { "String" },
+ { "Object" },
+ { "Bytes", "CharacterStream", "Clob", "Ref",
+ "BinaryStream", "AsciiStream", "Array", "Blob" } };
+ mrs.beforeFirst();
+ System.out.println("Count:"+props.length);
+ while(mrs.next()) {
+ for (int colNo = 0 ; colNo < cols.length ; colNo++) {
+ ColSpec col = cols[colNo];
+ for (int i = 0; i < props[col.type.group.value].length ; i++) {
+ for (String ptype : ptypes) { // try both int and string column access
+ //System.out.println(col.name + ":col.type.group=" + col.type.group + "(" + col.type.group.value + ")" + ":method=get" + props[col.type.group.value][i] + "(" + ptype + "):data=" + data[mrs.getRow()-1][colNo] );
+ try {
+ // Do this the unsafe way so we don't use DynamicUtil and can avoid the dependency.
+ Method m = mrs.getClass().getMethod("get"+props[col.type.group.value][i],new Class[] { String.class });
+ Object obj = m.invoke(mrs, col.name );
+
+ Class<?> expectedClass = _boxedTypeEquivalents
+ .containsKey(classes[col.type.group.value][i]) ?
+ _boxedTypeEquivalents.get(classes[col.type.group.value][i]) :
+ classes[col.type.group.value][i];
+ Assert.assertEquals(expectedClass,obj.getClass());
+ Assert.assertTrue(expectedClass.isAssignableFrom(obj.getClass()));
+ } catch (ClassCastException e) {
+ //e.printStackTrace();
+ } catch (RuntimeException e) {
+ if (e.getCause() != null && !e.getCause().getClass().equals(ClassCastException.class)) throw e;
+ }
+
+ }
+ }
+ }
+ }
+ }
+ static Map<Class<?>, Class<?>> _boxedTypeEquivalents = new HashMap<Class<?>, Class<?>>();
+ static {
+ _boxedTypeEquivalents.put(boolean.class,Boolean.class);
+ _boxedTypeEquivalents.put(int.class,Integer.class);
+ _boxedTypeEquivalents.put(long.class,Long.class);
+ _boxedTypeEquivalents.put(short.class,Short.class);
+ _boxedTypeEquivalents.put(byte.class,Byte.class);
+ _boxedTypeEquivalents.put(char.class,Character.class);
+ _boxedTypeEquivalents.put(double.class,Double.class);
+ _boxedTypeEquivalents.put(float.class,Float.class);
+ }
+
+
+}
+
+
+
+
+
diff --git a/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java new file mode 100644 index 0000000..215a282 --- /dev/null +++ b/israfil-foundation-testing/src/test/java/net/israfil/foundation/mock/sql/RowTest.java @@ -0,0 +1,86 @@ +/*
+ * Copyright © 2003-2009 Israfil Consulting Services Corporation
+ * Copyright © 2003-2009 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * This software is licensed under the Berkeley Standard Distribution license,
+ * (BSD license), as defined below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. Neither the name of Israfil Consulting Services nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * $Id: RowTest.java 130 2006-12-31 23:22:17Z cgruber $
+ */
+package net.israfil.foundation.mock.sql;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber </a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 130 $
+ */
+public class RowTest {
+
+ Row row;
+ String[] columns = { "ColumnA", "ColumnB", "ColumnC" };
+ MockResultSetMetaData rsmd = new MockResultSetMetaData(columns);
+ String valc = "Value C";
+ List<Object> data = Arrays.asList(new Object[] {"Value A", "Value B", null});
+
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ row = new Row(rsmd, data);
+ }
+
+ @AfterMethod(alwaysRun=true)
+ public void tearDown() throws Exception {
+ row = null;
+ }
+
+ /* Should simply not throw an exception */
+ public void testSetWithInt() throws SQLException {
+ Assert.assertEquals(null,row.get(3));
+ row.set(3,valc);
+ Assert.assertEquals(valc,row.get(3));
+ }
+
+ /* Should simply not throw an exception */
+ public void testSetWithString() throws SQLException {
+ Assert.assertEquals(null,row.get("ColumnC"));
+ row.set("ColumnC",valc);
+ Assert.assertEquals(valc,row.get("ColumnC"));
+ }
+}
+
+
+
+
+
diff --git a/israfil-foundation-valuemodel/pom.xml b/israfil-foundation-valuemodel/pom.xml new file mode 100644 index 0000000..13aed6c --- /dev/null +++ b/israfil-foundation-valuemodel/pom.xml @@ -0,0 +1,30 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + </parent> + <artifactId>israfil-foundation-valuemodel</artifactId> + <name>Israfil Foundation Value Model Classes</name> + <description> + Classes which implement and support a SmallTalk-style valuemodel architecture. + </description> + <version>1.0.1-SNAPSHOT</version> + <url>http://www.israfil.net/projects/foundation/${artifactId}</url> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <dependencies> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>israfil-foundation-dynamic</artifactId> + <version>1.0.1</version> + </dependency> + </dependencies> +</project>
\ No newline at end of file diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java new file mode 100644 index 0000000..74d4dd1 --- /dev/null +++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/MutableValue.java @@ -0,0 +1,23 @@ +/*
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * $Id$
+ * $Revision$
+ *
+ */
+package net.israfil.foundation.valuemodel;
+
+
+/**
+ * A smalltalk-style generic value accessor/mutator system, where individual
+ * items are accessed through a single value
+ *
+ * @author Original: <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Recent: $Author$
+ *
+ */
+public interface MutableValue<E> extends Value<E>, Vetoable {
+
+ public void set(E value);
+
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java new file mode 100644 index 0000000..574c8cf --- /dev/null +++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Observable.java @@ -0,0 +1,37 @@ +/*
+ * Copyright (c) 2003-2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.valuemodel;
+
+/**
+ * An interface for objects that can notify observers of changes to itself. The
+ * changing object should call the provided callback signature, with the
+ * parameter being the object that was changed in its new state.
+ *
+ * Using a dynamic selector rather than a strong interface allows code
+ * to be notified of the change even if it was not constructed with the
+ * notification interface, though it does need to match the signature.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 129 $
+ */
+public interface Observable {
+
+ /** Add an observer to this object, with a callback method spec that will
+ * be invoked upon a data change. The callback method should contain three
+ * object parameters, one for the sender, one for the old value, and one for
+ * the new value. The meaning of the value (same object, copy, values, etc.)
+ * is left to the implementation object and the observers.
+ */
+ public void addObservers(String callback, Object ... observers);
+ /**
+ * Remove observer from observable object.
+ */
+ public void removeObservers(Object ... observers);
+
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java new file mode 100644 index 0000000..8c545bd --- /dev/null +++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Value.java @@ -0,0 +1,22 @@ +/*
+ * Copyright (c) 2003, Israfil Consulting Services Corporation
+ *
+ * $Id$
+ * $Revision$
+ *
+ */
+package net.israfil.foundation.valuemodel;
+
+/**
+ * A smalltalk-style generic value accessor/mutator system, where individual
+ * items are accessed through a single value
+ *
+ * @author Original: <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Recent: $Author$
+ *
+ */
+public interface Value<E> extends Observable {
+
+ public E get();
+
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java new file mode 100644 index 0000000..55f23c3 --- /dev/null +++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/ValueHolder.java @@ -0,0 +1,108 @@ +/*
+ * Created on Dec 8, 2003
+ *
+ * To change the template for this generated file go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+package net.israfil.foundation.valuemodel;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import net.israfil.foundation.dynamic.DynamicUtil;
+
+
+/**
+ * @author cgruber
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class ValueHolder<E> implements MutableValue<E> {
+
+ private E _value = null;
+ private Map<Integer, ObserverHolder> _observers = new HashMap<Integer, ObserverHolder>();
+ private Map<Integer, VetoerHolder> _vetoers = new HashMap<Integer, VetoerHolder>();
+
+ public ValueHolder(E o) {
+ set(o);
+ }
+
+ protected ValueHolder() { }
+
+ public E get() {
+ return _value;
+ }
+
+ public void set(E newValue) {
+ boolean approved = true;
+ E oldValue = _value;
+ for (VetoerHolder vetoer : _vetoers.values()) {
+ approved &= vetoer.evaluate(this, oldValue, newValue);
+ }
+
+ if (!approved) return;
+ else _value = newValue;
+ for (ObserverHolder observer : _observers.values()) {
+ observer.notify(this, oldValue, newValue);
+ }
+
+ }
+
+ /**
+ * @see org.israfil.maveric.Observable#addObserver(java.lang.Object, java.lang.String)
+ */
+ public void addObservers(String callback, Object ... observers) {
+ for (Object observer : observers) {
+ _observers.put(observer.hashCode(),new ObserverHolder(observer,callback));
+ }
+ }
+
+ /**
+ * @see org.israfil.maveric.Observable#removeObserver(java.lang.Object)
+ */
+ public void removeObservers(Object ... observers) {
+ for (Object observer : observers) {
+ _observers.remove(observer.hashCode());
+ }
+ }
+ /**
+ * @see org.israfil.maveric.Vetoable#addVetoer(java.lang.Object, java.lang.String)
+ */
+ public void addVetoers(String callback, Object ... vetoers) {
+ for (Object vetoer : vetoers) {
+ _vetoers.put(vetoer.hashCode(),new VetoerHolder(vetoer,callback));
+ }
+ }
+
+ /**
+ * @see org.israfil.maveric.Vetoable#removeVetoer(java.lang.Object)
+ */
+ public void removeVetoers(Object ... vetoers) {
+ for (Object vetoer : vetoers) {
+ _vetoers.remove(vetoer.hashCode());
+ }
+ }
+
+ protected class CallbackObjectHolder {
+ public final Object receiver;
+ protected final String callback;
+ public CallbackObjectHolder(Object receiver, String callback) {
+ this.receiver = receiver;
+ this.callback = callback;
+ }
+ }
+ protected class ObserverHolder extends CallbackObjectHolder {
+ public ObserverHolder(Object observer, String callback) { super(observer, callback); }
+ public void notify(Object notifier, Object oldValue, Object newValue) {
+ DynamicUtil.performOn(receiver,callback,new Object[]{notifier, oldValue , newValue});
+ }
+ }
+ protected class VetoerHolder extends CallbackObjectHolder {
+ public VetoerHolder(Object vetoer, String callback) { super(vetoer, callback); }
+ public Boolean evaluate(Object notifier, Object oldValue, Object newValue) {
+ Boolean result = (Boolean)DynamicUtil.performOn(receiver,callback,new Object[]{notifier,oldValue,newValue});
+ return (result == null) ? true : result.booleanValue();
+ }
+ }
+}
diff --git a/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java new file mode 100644 index 0000000..5369287 --- /dev/null +++ b/israfil-foundation-valuemodel/src/main/java/net/israfil/foundation/valuemodel/Vetoable.java @@ -0,0 +1,44 @@ +/*
+ * Copyright (c) 2003-2007 Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2007 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.valuemodel;
+
+/**
+ * An interface for objects that can notify observers of changes to itself
+ * before the change. The objects thus notified can veto the change. The
+ * specific behaviour for vetoing is undefined and is dependent upon the
+ * particular implementation of the vetoable object and its vetoers.
+ * The changing object should call the provided callback signature, with the
+ * parameter being the object that was changed in its new state. The vetoer
+ * is responsible for knowing what it needs to know in order to validate or
+ * veto the change.
+ *
+ * Using a dynamic selector rather than a strong interface allows code
+ * to be notified of the change even if it was not constructed with the
+ * notification interface, though it does need to match the signature.
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 129 $
+ */
+public interface Vetoable {
+
+ /** Add one or more vetoers to this object, with a callback method spec
+ * that will be invoked upon a data change. The callback method should
+ * contain three parameters. The first is the notification source (the
+ * holder or whatever), the second the old value, and the third the new
+ * value. It also should return a boolean approving the change (or
+ * returning false to veto it)
+ */
+ public void addVetoers(String callback, Object ... approvers);
+
+ /**
+ * Remove one or more vetoers from vetoable object.
+ */
+ public void removeVetoers(Object ... approvers);
+
+}
diff --git a/israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java b/israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java new file mode 100644 index 0000000..271c4a0 --- /dev/null +++ b/israfil-foundation-valuemodel/src/test/java/net/israfil/foundation/valuemodel/ValueHolderTest.java @@ -0,0 +1,143 @@ +/*
+ * Copyright (c) 2003-2008Israfil Consulting Services Corporation
+ * Copyright (c) 2003-2008 Christian Edward Gruber
+ * All Rights Reserved
+ *
+ * $Id: Types.java 129 2006-12-31 23:20:02Z cgruber $
+ */
+package net.israfil.foundation.valuemodel;
+
+import net.israfil.foundation.core.Copyright;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests for ValueHolder
+ *
+ * @author <a href="mailto:cgruber@israfil.net">Christian Edward Gruber</a>
+ * @author Latest: $Author: cgruber $
+ * @version $Revision: 129 $
+ */
+@Copyright(years={"2003","2004","2005","2006","2007","2008"},owner="Israfil Consulting Services Corporation",license="BSD")
+@Test
+public class ValueHolderTest {
+
+ private String stringValue = null;
+ private Integer integerValue = null;
+ private ValueHolder<String> stringValueHolder = null;
+ private ValueHolder<Integer> integerValueHolder = null;
+
+ @BeforeMethod
+ protected void setUp() throws Exception {
+ stringValue = "String Value";
+ integerValue = new Integer(5);
+ stringValueHolder = new ValueHolder<String>(stringValue);
+ integerValueHolder = new ValueHolder<Integer>(integerValue);
+ }
+
+ @AfterMethod
+ protected void tearDown() throws Exception {
+ stringValue = null;
+ integerValue = null;
+ stringValueHolder = null;
+ integerValueHolder = null;
+ }
+
+ /*
+ * Test for void ValueHolder(Object)
+ */
+ public void testValueHolderObject() {
+ String valueString = "Value";
+ ValueHolder<String>valueHolder = new ValueHolder<String>(valueString);
+ Assert.assertEquals(valueString,valueHolder.get());
+ }
+
+ public void testGetValue() {
+ Assert.assertEquals(stringValue,stringValueHolder.get());
+ Assert.assertEquals(integerValue,integerValueHolder.get());
+ }
+
+ public void testSetValueObject() {
+ String stringValue2 = "String Value 2";
+ stringValueHolder.set(stringValue2);
+ Assert.assertEquals(stringValue2,stringValueHolder.get());
+ }
+
+ public void testAddObserverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addObservers("notifyMe:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.set(stringValue2);
+ Assert.assertTrue(callback.notified);
+ }
+ public void testRemoveObserverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addObservers("notifyMe:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.removeObservers(callback);
+ stringValueHolder.set(stringValue2);
+ Assert.assertFalse(callback.notified);
+ }
+ public void testAddApproverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addVetoers("approve:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.set(stringValue2);
+ Assert.assertEquals(stringValue2,stringValueHolder.get());
+
+ callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addVetoers("approve:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.set(stringValue2);
+ stringValueHolder.set(stringValue);
+ Assert.assertEquals(stringValue2,stringValueHolder.get());
+ Assert.assertFalse(stringValue.equals(stringValueHolder.get()));
+ }
+ public void testRemoveApproverObjectString() {
+ String stringValue2 = "String Value 2";
+ CallbackObject<String> callback = new CallbackObject<String>(stringValueHolder);
+ stringValueHolder.addVetoers("approve:java.lang.Object:java.lang.Object:java.lang.Object",callback);
+ stringValueHolder.removeVetoers(callback);
+ stringValueHolder.set(stringValue2);
+ stringValueHolder.set(stringValue);
+ Assert.assertEquals(stringValue,stringValueHolder.get());
+ Assert.assertFalse(stringValue2.equals(stringValueHolder.get()));
+ }
+ public void finalize() throws Throwable {
+ stringValue = null;
+ integerValue = null;
+ stringValueHolder = null;
+ integerValueHolder = null;
+ super.finalize();
+ }
+
+ public class CallbackObject<E> {
+ private final MutableValue<E> valueModel;
+ public boolean notified = false;
+ public Object oldValue = null;
+ public Object newValue = null;
+ public CallbackObject(MutableValue<E> valueModel) {
+ this.valueModel = valueModel;
+ }
+ public void notifyMe(Object sender, Object oldValue, Object newValue) {
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ Assert.assertEquals(this.valueModel,sender);
+ notified = true;
+ }
+ public boolean approve(Object sender, Object oldValue, Object newValue) {
+ this.oldValue = oldValue;
+ this.newValue = newValue;
+ Assert.assertEquals(this.valueModel,sender);
+ if (!newValue.equals(stringValue)) return true;
+ return false;
+ }
+ public void finalize() throws Throwable {
+ this.oldValue = null;
+ this.newValue = null;
+ super.finalize();
+ }
+ }
+}
@@ -0,0 +1,151 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>net.israfil.foundation</groupId> + <artifactId>israfil-foundation-all</artifactId> + <version>5-SNAPSHOT</version> + <packaging>pom</packaging> + <name>Israfil Foundation: All</name> + <description>Foundation Frameworks from Israfil Consulting Services</description> + <inceptionYear>2006</inceptionYear> + <url>http://www.israfil.net/projects/foundation</url> + <modules> + <module>israfil-foundation-core</module> + <module>israfil-foundation-dynamic</module> + <module>israfil-foundation-cache</module> + <module>israfil-foundation-collections</module> + <module>israfil-foundation-container</module> + <module>israfil-foundation-concurrent</module> + <module>israfil-foundation-lifecycle</module> + <module>israfil-foundation-notification</module> + <module>israfil-foundation-testing</module> + <module>israfil-foundation-nspace</module> + <module>israfil-foundation-valuemodel</module> + </modules> + <licenses> + <license> + <name>BSD</name> + <distribution>repo</distribution> + <url>http://www.israfil.net/israfil-license-bsd.txt</url> + <comments>A simple open-source license with minimal restrictions</comments> + </license> + </licenses> + <build> + <plugins> + <plugin> + <artifactId>maven-release-plugin</artifactId> + <configuration> + <tagBase>https://israfil-foundation.googlecode.com/svn/tags/RELEASE</tagBase> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>cobertura-maven-plugin</artifactId> + <executions> + <execution><goals><goal>clean</goal></goals></execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>11</source> + <target>11</target> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>5.7</version> + <classifier>jdk15</classifier> + <exclusions> + <exclusion> + <artifactId>junit</artifactId> + <groupId>junit</groupId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.jmock</groupId> + <artifactId>jmock</artifactId> + <version>2.4.0</version> + </dependency> + </dependencies> + <distributionManagement> + <!-- use the following if you're not using a snapshot version. --> + <repository> + <id>israfil</id> + <name>Israfil Deploy</name> + <url>scp://repo.israfil.net/var/www/vhosts/repo.israfil.net/htdocs/maven2</url> + </repository> + <!-- use the following if you ARE using a snapshot version. --> + <snapshotRepository> + <id>israfil</id> + <name>Israfil Snapshot</name> + <url>scp://repo.israfil.net/var/www/vhosts/repo.israfil.net/htdocs/maven2-snapshots</url> + </snapshotRepository> + <site> + <id>website</id> + <url>scp://projects.israfil.net/var/www/vhosts/projects.israfil.net/htdocs/foundation</url> + </site> + </distributionManagement> + <reporting> + <plugins> + <plugin> + <artifactId>maven-javadoc-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>jxr-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>surefire-report-maven-plugin</artifactId> + <configuration> + <forkMode>always</forkMode> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>cobertura-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>taglist-maven-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>jdepend-maven-plugin</artifactId> + </plugin> + <plugin> + <artifactId>maven-checkstyle-plugin</artifactId> + </plugin> + <plugin> + <groupId>com.google.testability-explorer</groupId> + <artifactId>maven2-testability-plugin</artifactId> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>findbugs-maven-plugin</artifactId> + <configuration> + <xmlOutput>false</xmlOutput> + <threshold>Normal</threshold> + <effort>Default</effort> + <!-- + <excludeFilterFile>findbugs-exclude.xml</excludeFilterFile> + <includeFilterFile>findbugs-include.xml</includeFilterFile> + --> + <visitors>FindDeadLocalStores,UnreadFields</visitors> + <omitVisitors>FindDeadLocalStores,UnreadFields</omitVisitors> + <!-- <pluginList>/libs/fb-contrib/fb-contrib-2.8.0.jar</pluginList> --> + </configuration> + </plugin> + </plugins> + </reporting> + <scm> + <connection>scm:svn:http://israfil-foundation.googlecode.com/svn/trunk</connection> + <developerConnection>scm:svn:https://israfil-foundation.googlecode.com/svn/trunk</developerConnection> + <url>http://israfil-foundation.googlecode.com/svn</url> + </scm> +</project> diff --git a/tools/scripts/mvn-deploy-files b/tools/scripts/mvn-deploy-files new file mode 100755 index 0000000..a972753 --- /dev/null +++ b/tools/scripts/mvn-deploy-files @@ -0,0 +1,185 @@ +#!/bin/sh +# +# Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation +# Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber +# All Rights Reserved +# +# This software is licensed under a Berkeley Standard Distribution license +# equivalent (BSD license) as defined below: +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of Israfil Consulting Services nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +# +# $Id$ +# + +command=`basename $0` + +original_command_line="${@}" + +#set -x + +function usage () { + + echo "usage: ${command} [-t <type>] [-e <ext>] [--test] -u <repo_url> -g <group_id> -v <version> <file> [<file>...] " + echo "Options: -t --type <type> sets the maven 2 packaging type " + echo " -e --ext <extension> the file extension (defaults to type) " + echo " -u --url <repo_url> the url to the deployment repository " + echo " -g --group <group_id> the groupId to which the artifacts will be deployed " + echo " -v --version <version> the version to which the artifacts will be deployed " + echo " -e --ext <extension> the file extension (defaults to type) " + echo " -p --poms <pomsfolder> a folder with poms, structured \${groupId}/\${artifactId}/\${version} " + echo " -o --pom-overrides determines whether a discovered pom file will override group/artifact/version " + echo " --test run the app without invoking maven, for testing " + +} + +function validate () { + valid="true" + echo "" + + if [ ! -n "${files}" ]; then + echo "[${command}] No files to deploy." ; valid="false" + fi + + if [ "${repository_url}" = "" ]; then + echo "[${command}] Missing repository url." ; valid="false" + fi + if [ "${group_id}" = "" ]; then + echo "[${command}] Missing group id." ; valid="false" + fi + if [ "${version}" = "" ]; then + echo "[${command}] Missing version." ; valid="false" + fi + if [ "${poms_dir}" != "" -a ! -d "${poms_dir}" ]; then + echo "[${command}] ${poms_dir} is not a valid directory" ; valid="false" + fi + if [ "${valid}" = "false" ]; then + echo "" ; usage ; exit 1 + fi +} + +# set initial defaults +type="jar" +test="false" +extension=__DEFAULT__ +repository_url="" +group_id="" +version="" +poms_dir="" +pom_overrides="false" +done="false" +export repository group_id version + +# loop through possible commands. +until [ "${done}" = "true" ]; do + + if [ "${1}" = "-t" -o "${1}" = "--type" ]; then + shift + type="${1}" + shift + elif [ "${1}" = "-e" -o "${1}" = "--ext" ]; then + shift + extension="${1}" + shift + elif [ "${1}" = "--test" ]; then + shift + test=true + elif [ "${1}" = "-u" -o "${1}" = "--url" ]; then + shift + repository_url="${1}" + shift + elif [ "${1}" = "-g" -o "${1}" = "--group" ]; then + shift + group_id="${1}" + shift + elif [ "${1}" = "-v" -o "${1}" = "--version" ]; then + shift + version="${1}" + shift + elif [ "${1}" = "-p" -o "${1}" = "--poms" ]; then + shift + poms_dir="${1}" + shift + elif [ "${1}" = "-o" -o "${1}" = "--pom-overrides" ]; then + shift + pom_overrides=true + else + # assume we're into files now. + done="true" + fi + +done +files=${@} + +# Validate whether key variables are set +validate + +# Given validated parameters, attend to any dynamic default settings. +if [ "${extension}" = "__DEFAULT__" ]; then + extension=${type} +fi +if [ "${poms_dir}" = "" ]; then + poms_dir=. +fi + + +echo "" +echo "Deploying ${type} artifacts into repository ${repository_url} with group ${group_id}." +echo "Deploying files: ${files}" +echo "" + +for file in ${files} ; do + + if [ ! -f "${file}" ]; then + echo "" && echo "[${command}] Cannot find file ${file}. Skipping..." && echo "" + break; + fi + + artifact_id=`basename ${file} .${extension}` + + # two ways to spec, or both. + pom_file=${poms_dir}/${group_id}/${artifact_id}/${version}/${artifact_id}-${version}.pom + artifact_spec="-DgroupId=${group_id} -DartifactId=${artifact_id} -Dversion=${version} -Dpackaging=${type}" + + echo -n "Deploying artifact: ${group_id}:${artifact_id}:${type}:${version} to ${repository_url}" + if [ -f ${pom_file} ]; then + echo " with ${pom_file}" + pom_arg="-DpomFile=${pom_file}" + if [ "${pom_overrides}" = "true" ]; then + artifact_spec="" + fi + fi + + + cmd="mvn --batch-mode deploy:deploy-file -Durl=${repository_url} ${artifact_spec} -Dfile=${file} ${pom_arg}" + + if [ "${test}" = "true" ]; then + echo "cmd: ${cmd}" + else + ${cmd} + fi + +done + + diff --git a/tools/scripts/mvn-deploy-wlp92-jars b/tools/scripts/mvn-deploy-wlp92-jars new file mode 100755 index 0000000..415d825 --- /dev/null +++ b/tools/scripts/mvn-deploy-wlp92-jars @@ -0,0 +1,158 @@ +#!/bin/sh +# +# Copyright (c) 2003, 2004, 2005, 2006 Israfil Consulting Services Corporation +# Copyright (c) 2003, 2004, 2005, 2006 Christian Edward Gruber +# All Rights Reserved +# +# This software is licensed under a Berkeley Standard Distribution license +# equivalent (BSD license) as defined below: +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of Israfil Consulting Services nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +# OF SUCH DAMAGE. +# +# $Id$ +# + +command=`basename $0` +cmd_dir=`dirname $0` + +#set -x + +function usage () { + + echo "usage: ${command} [--test]-u <repo_url> -b <bea_home> [-p <poms_folder>] " + echo "Options: -u --url <repo_url> the url to the deployment repository " + echo " -b --bea-home <bea_home> the BEA_HOME folder " + echo " -p --poms <pomsfolder> a folder with poms, structured \${groupId}/\${artifactId}/\${version} " + Echo " --test run the app without invoking maven, for testing " + +} + +function validate () { + valid="true" + echo "" + if [ "${bea_home}" = "" ]; then + echo "${command} requires that a bea home folder be given" ; valid="false" + elif [ ! -d "${bea_home}" ]; then + echo "BEA home folder ${bea_home} is not a valid directory." ; valid="false" + fi + if [ "${repository_url}" = "" ]; then + echo "${command} requires a repository URL" ; valid="false" + fi + if [ "${poms_dir}" != "" -a ! -d ${poms_dir} ]; then + echo "${poms_dir} is not a valid directory" ; valid="false" + fi + if [ "${valid}" = "false" ]; then + echo "" ; usage ; exit 1 + fi +} + +# loop through possible commands. +until [ "${done}" = "true" ]; do + + if [ "${1}" = "-b" -o "${1}" = "--bea-home" ]; then + shift + bea_home="${1}" + shift + elif [ "${1}" = "-u" -o "${1}" = "--url" ]; then + shift + repository_url="${1}" + shift + elif [ "${1}" = "--test" ]; then + shift + test="true" + else + # assume we're into files now. + done="true" + fi + +done + + +validate + +echo "Installing BEA weblogic portal 9.2 folders from ${bea_home} to ${repository_url}" +echo "" + +function install () { + group_id=$1 + shift + if [ "${test}" = "true" ]; then do_test="--test" ; fi + ${cmd_dir}/mvn-deploy-files -u ${repository_url} -g ${group_id} -v 9.2 ${do_test} $@ +} + +function installFromJ2EELibrary () { + j2eeLibrary=$1 + shift + group_id=$1 + shift + if [ "${test}" = "true" ]; then do_test="--test" ; fi + curdir=`pwd` + tmpdir=`mktemp.exe -d -p ${curdir}` + cd ${tmpdir} + jar -xf ${curdir}/${j2eeLibrary} + ${cmd_dir}/mvn-deploy-files -u ${repository_url} -g ${group_id} -v 9.2 ${do_test} $@ + cd ${curdir} + rm -r ${tmpdir} +} + + +# Visitor Tools +cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-tools-visitor-web-lib.war com.bea.weblogic.portal.visitor WEB-INF/lib/*.jar + +# The big one. +cd ${bea_home}/weblogic92/server/lib && install com.bea.weblogic.server weblogic*.jar +cd ${bea_home}/weblogic92/server/lib && install com.bea.weblogic.server *api.jar + +# The workshop stuff - important for ant support. +cd ${bea_home}/weblogic92/workshop/lib && install com.bea.weblogic.workshop *.jar + +# Critical beehive/netui stuff +cd ${bea_home}/weblogic92/beehive/weblogic-beehive/lib/netui && install com.bea.weblogic.beehive.netui *.jar +cd ${bea_home}/weblogic92/beehive/weblogic-beehive/lib/controls && install com.bea.weblogic.beehive.controls *.jar +cd ${bea_home}/weblogic92/beehive/weblogic-beehive/lib/controls/runtime && install com.bea.weblogic.beehive.controls.runtime *.jar + +# The portal platform +cd ${bea_home}/weblogic92/platform/lib/wlp && install com.bea.weblogic.portal.core *.jar +cd ${bea_home}/weblogic92/platform/lib/p13n && install com.bea.weblogic.portal.p13n *.jar +cd ${bea_home}/weblogic92/common/deployable-libraries/ && installFromJ2EELibrary p13n-app-lib.ear com.bea.weblogic.portal.p13n APP-INF/lib/*.jar *.jar + +# Console and netuix stuff. +cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.portal.core netuix_servlet.jar +cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-framework-full-web-lib.war com.bea.weblogic.portal.core WEB-INF/lib/netuix_servlet-full.jar +cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.portal.core struts-adapter.jar +cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-framework-full-app-lib.ear com.bea.weblogic.portal.core netuix.jar +cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.server console.jar + +cd ${bea_home}/weblogic92/portal/lib/modules/ && installFromJ2EELibrary wlp-tools-app-lib.ear com.bea.weblogic.portal.core APP-INF/lib/tools-framework.jar APP-INF/lib/wlptools_en.jar + +# Taglibs +cd ${bea_home}/weblogic92/server/lib/consoleapp/webapp/WEB-INF/lib && install com.bea.weblogic.server *_taglib.jar +cd ${bea_home}/weblogic92/portal/lib/netuix/web && install com.bea.weblogic.portal *_taglib.jar +cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.common.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar +cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.im.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar +cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.p13n.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar +cd ${bea_home}/weblogic92/portal/eclipse/plugins/com.bea.wlp.eclipse.wsrp.taglib_9.2.0 && install com.bea.weblogic.portal *_taglib.jar + + + |
