[jboss-remoting-commits] JBoss Remoting SVN: r5580 - remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Tue Nov 3 21:11:18 EST 2009


Author: david.lloyd at jboss.com
Date: 2009-11-03 21:11:18 -0500 (Tue, 03 Nov 2009)
New Revision: 5580

Added:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Pair.java
Modified:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Streams.java
Log:
Interlude: beef up streams convenience methods

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Pair.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Pair.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Pair.java	2009-11-04 02:11:18 UTC (rev 5580)
@@ -0,0 +1,68 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.stream;
+
+import java.io.Serializable;
+
+/**
+ * A serializable pair of values.
+ *
+ * @param <A> the type of the first value
+ * @param <B> the type of the second value
+ */
+public final class Pair<A, B> implements Serializable {
+
+    private static final long serialVersionUID = -1812076980977921946L;
+
+    private final A a;
+    private final B b;
+
+    /**
+     * Construct a new instance.
+     *
+     * @param a the first value
+     * @param b the second value
+     */
+    public Pair(final A a, final B b) {
+        this.a = a;
+        this.b = b;
+    }
+
+    /**
+     * Get the first value.
+     *
+     * @return the first value
+     */
+    public A getA() {
+        return a;
+    }
+
+    /**
+     * Get the second value.
+     *
+     * @return the second value
+     */
+    public B getB() {
+        return b;
+    }
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Streams.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Streams.java	2009-11-03 18:45:12 UTC (rev 5579)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/Streams.java	2009-11-04 02:11:18 UTC (rev 5580)
@@ -6,6 +6,12 @@
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import org.jboss.xnio.IoFuture;
+import org.jboss.xnio.FutureResult;
+import org.jboss.xnio.Cancellable;
+import org.jboss.xnio.IoUtils;
 
 /**
  * Handy utility methods for stream types.
@@ -37,6 +43,193 @@
     }
 
     /**
+     * Get an object source which reads from a collection.
+     *
+     * @param collection the collection to read from
+     * @param <T> the collection member type
+     * @return an object source
+     */
+    public static <T> ObjectSource<T> getCollectionObjectSource(Collection<T> collection) {
+        return getIteratorObjectSource(collection.iterator());
+    }
+
+    /**
+     * Get an object sink that appends to a map.
+     *
+     * @param target the target map
+     * @param <K> the key type
+     * @param <V> the value type
+     * @return an object sink
+     */
+    public static <K, V> ObjectSink<Pair<K, V>> getMapObjectSink(Map<K, V> target) {
+        return new MapObjectSink<K, V>(target);
+    }
+
+    /**
+     * Get an object source that reads from an iterator over map entries.
+     *
+     * @param iterator the iterator object type
+     * @param <K> the key type
+     * @param <V> the value type
+     * @return an object source
+     */
+    public static <K, V> ObjectSource<Pair<K, V>> getMapEntryIteratorObjectSource(Iterator<Map.Entry<K, V>> iterator) {
+        return new MapEntryIteratorObjectSource<K, V>(iterator);
+    }
+
+    /**
+     * Get an object source that reads from a map.
+     *
+     * @param map the map
+     * @param <K> the key type
+     * @param <V> the value type
+     * @return an object source
+     */
+    public static <K, V> ObjectSource<Pair<K, V>> getMapObjectSource(Map<K, V> map) {
+        return getMapEntryIteratorObjectSource(map.entrySet().iterator());
+    }
+
+    /**
+     * Populate a new collection from an object source.  Since the collection may be only partially populated on error,
+     * it is recommended that the instance be discarded if an exception is thrown.
+     * <p>
+     * An example usage which meets this requirement would be: <code><pre>
+     * final List&lt;Foo&gt; fooList = getCollection(new ArrayList&lt;Foo&gt;(), fooSource);
+     * </pre></code>
+     *
+     * @param newCollection the new collection to populate
+     * @param objectSource the object source to fill the collection from
+     * @param <C> the collection type
+     * @param <T> the collection value type
+     * @return the new collection, populated
+     * @throws IOException if an error occurs
+     */
+    public static <C extends Collection<T>, T> C getCollection(C newCollection, ObjectSource<T> objectSource) throws IOException {
+        while (objectSource.hasNext()) {
+            newCollection.add(objectSource.next());
+        }
+        return newCollection;
+    }
+
+    /**
+     * Populate a new map from an object source.  Since the map may be only partially populated on error,
+     * it is recommended that the instance be discarded if an exception is thrown.
+     * <p>
+     * An example usage which meets this requirement would be: <code><pre>
+     * final Map&lt;Foo, Bar&gt; fooBarMap = getMap(new HashMap&lt;Foo, Bar&gt;(), fooBarSource);
+     * </pre></code>
+     *
+     * @param newMap the new map to populate
+     * @param objectSource the object source to fill the map from
+     * @param <M> the map type
+     * @param <K> the map key type
+     * @param <V> the map value type
+     * @return the new map, populated
+     * @throws IOException if an error occurs
+     */
+    public static <M extends Map<K, V>, K, V> M getMap(M newMap, ObjectSource<Pair<K, V>> objectSource) throws IOException {
+        while (objectSource.hasNext()) {
+            final Pair<K, V> pair = objectSource.next();
+            newMap.put(pair.getA(), pair.getB());
+        }
+        return newMap;
+    }
+
+    /**
+     * Populate a new collection from an object source asynchronously.  Since the collection may be only partially populated on error,
+     * it is recommended that the instance be discarded if an exception is thrown.
+     * <p>
+     * An example usage which meets this requirement would be: <code><pre>
+     * final IoFuture&lt;List&lt;Foo&gt;&gt; futureFooList = getFutureCollection(executor, new ArrayList&lt;Foo&gt;(), fooSource);
+     * </pre></code>
+     *
+     * @param executor the executor in which to run asynchronous tasks
+     * @param newCollection the new collection to populate
+     * @param objectSource the object source to fill the collection from
+     * @param <C> the collection type
+     * @param <T> the collection value type
+     * @return the new future collection, populated
+     * @throws IOException if an error occurs
+     */
+    public static <C extends Collection<T>, T> IoFuture<C> getFutureCollection(Executor executor, final C newCollection, final ObjectSource<T> objectSource) {
+        final FutureResult<C> futureResult = new FutureResult<C>(executor);
+        futureResult.addCancelHandler(new Cancellable() {
+            public Cancellable cancel() {
+                if (futureResult.setCancelled()) {
+                    IoUtils.safeClose(objectSource);
+                }
+                return this;
+            }
+        });
+        try {
+            executor.execute(new Runnable() {
+                public void run() {
+                    try {
+                        while (objectSource.hasNext()) {
+                            newCollection.add(objectSource.next());
+                        }
+                        futureResult.setResult(newCollection);
+                    } catch (IOException e) {
+                        futureResult.setException(e);
+                    }
+                }
+            });
+        } catch (RuntimeException e) {
+            final IOException ioe = new IOException("Failed to initiate asynchronous population of a collection");
+            ioe.initCause(e);
+            futureResult.setException(ioe);
+        }
+        return futureResult.getIoFuture();
+    }
+
+    /**
+     * Populate a new map from an object source asynchronously.  Since the map may be only partially populated on error,
+     * it is recommended that the instance be discarded if an exception is thrown.
+     * <p>
+     * An example usage which meets this requirement would be: <code><pre>
+     * final IoFuture&lt;Map&lt;Foo, Bar&gt;&gt; futureFooBarMap = getFutureMap(executor, new HashMap&lt;Foo, Bar&gt;(), fooBarSource);
+     * </pre></code>
+     *
+     * @param newMap the new map to populate
+     * @param objectSource the object source to fill the map from
+     * @param <M> the map type
+     * @param <K> the map key type
+     * @param <V> the map value type
+     * @return the new map, populated
+     */
+    public static <M extends Map<K, V>, K, V> IoFuture<M> getFutureMap(Executor executor, final M newMap, final ObjectSource<Pair<K, V>> objectSource) {
+        final FutureResult<M> futureResult = new FutureResult<M>(executor);
+        futureResult.addCancelHandler(new Cancellable() {
+            public Cancellable cancel() {
+                if (futureResult.setCancelled()) {
+                    IoUtils.safeClose(objectSource);
+                }
+                return this;
+            }
+        });
+        try {
+            executor.execute(new Runnable() {
+                public void run() {
+                    try {
+                        while (objectSource.hasNext()) {
+                            final Pair<K, V> pair = objectSource.next();
+                            newMap.put(pair.getA(), pair.getB());
+                        }
+                        futureResult.setResult(newMap);
+                    } catch (IOException e) {
+                        futureResult.setException(e);
+                    }
+                }
+            });
+        } catch (RuntimeException e) {
+            final IOException ioe = new IOException("Failed to initiate asynchronous population of a collection");
+            ioe.initCause(e);
+            futureResult.setException(ioe);
+        }
+        return futureResult.getIoFuture();
+    }
+
+    /**
      * Get an object source that reads from an enumeration.
      *
      * @param <T> the enumeration object type
@@ -50,7 +243,7 @@
     private static final class CollectionObjectSink<T> implements ObjectSink<T> {
         private final Collection<T> target;
 
-        public CollectionObjectSink(final Collection<T> target) {
+        private CollectionObjectSink(final Collection<T> target) {
             this.target = target;
         }
 
@@ -68,7 +261,7 @@
     private static final class IteratorObjectSource<T> implements ObjectSource<T> {
         private final Iterator<T> src;
 
-        public IteratorObjectSource(final Iterator<T> src) {
+        private IteratorObjectSource(final Iterator<T> src) {
             this.src = src;
         }
 
@@ -94,7 +287,7 @@
     private static final class EnumerationObjectSource<T> implements ObjectSource<T> {
         private final Enumeration<T> src;
 
-        public EnumerationObjectSource(final Enumeration<T> src) {
+        private EnumerationObjectSource(final Enumeration<T> src) {
             this.src = src;
         }
 
@@ -116,4 +309,44 @@
             // empty
         }
     }
+
+    private static final class MapObjectSink<K, V> implements ObjectSink<Pair<K, V>> {
+
+        private final Map<K, V> target;
+
+        private MapObjectSink(final Map<K, V> target) {
+            this.target = target;
+        }
+
+        public void accept(final Pair<K, V> instance) throws IOException {
+            target.put(instance.getA(), instance.getB());
+        }
+
+        public void flush() throws IOException {
+            // empty
+        }
+
+        public void close() throws IOException {
+            // empty
+        }
+    }
+
+    private static final class MapEntryIteratorObjectSource<K, V> implements ObjectSource<Pair<K, V>> {
+        private final Iterator<Map.Entry<K, V>> source;
+
+        private MapEntryIteratorObjectSource(final Iterator<Map.Entry<K, V>> source) {
+            this.source = source;
+        }
+
+        public boolean hasNext() throws IOException {
+            return false;
+        }
+
+        public Pair<K, V> next() throws NoSuchElementException, IOException {
+            return null;
+        }
+
+        public void close() throws IOException {
+        }
+    }
 }



More information about the jboss-remoting-commits mailing list