<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>www.jugpadova.it: Tag proxy</title>
    <link>http://www.jugpadova.it/articles/tag/proxy</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Java User Group [Padova]</description>
    <item>
      <title>Iterating on non-iterable classes</title>
      <description>&lt;p&gt;(You&amp;#8217;ll find all the code of this post in &lt;a href="http://www.benfante.com/bensite/sourcecode.jsf"&gt;Benfante&amp;#8217;s Utilities&lt;/a&gt; mini-library)&lt;/p&gt;

&lt;p&gt;One of the futures I &amp;#8216;m reappraising is the JDK 5 enhanced for statement.&lt;/p&gt;

&lt;p&gt;I still consider it too limited, but it&amp;#8217;s very comfortable in the simplest (and maybe common) cases.&lt;/p&gt;

&lt;p&gt;But&amp;#8230;what if the elements on which you want to iterate are not managed by an Iterable class?&lt;/p&gt;

&lt;p&gt;For example, this happens with the &lt;a href="http://www.xom.nu/"&gt;XOM&lt;/a&gt; library, where the Element.getChildElements returns an instance of the Elements class, wich is neither a Collection, or an Iterable class. So, for iterating on children elements, you have to use the basic for statement:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;for (int i=0; i &amp;lt; elements.size(); i++) {
  Element element = elements.get(i);
  // etc...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I would like to write simply:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;for (Element element: elements) {
  // etc...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So I wrote an &lt;strong&gt;&lt;code&gt;Iterabletor&lt;/code&gt;&lt;/strong&gt; class that builds a proxy around a class, enhancing it with the Iterable interface.&lt;/p&gt;

&lt;p&gt;Now You can write:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;Iterable&amp;lt;Element&amp;gt; iterable =
  new Iterabletor&amp;lt;Element&amp;gt;(elements).getIterable();

for (Element element: iterable) {
  // etc...
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Take a look at how I realaized this.&lt;/p&gt;

&lt;p&gt;First, the &lt;code&gt;Iterabletor&lt;/code&gt; class:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;package com.benfante.utils.iterabletor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Iterator;

/**
 * A class for add iterability to another class
 * 
 * @author lucio
 */
public class Iterabletor&amp;lt;T&amp;gt; implements InvocationHandler {

    private final Object obj;
    private Class&amp;lt;? extends Iterator&amp;gt; iteratorClass;

    /**
     * Prepare for iterability the passed object using a XOMIterator.
     *
     * @param The object on which iterate.
     */
    @SuppressWarnings(value = &amp;quot;unchecked&amp;quot;)
    public Iterabletor(Object obj) {
        this.obj = obj;
        this.iteratorClass = XOMIterator.class;
    }

    /**
     * Prepare for iterability the passed object using the passed iterator class.
     *
     * @param The object on which iterate.
     */
    public Iterabletor(Object obj, Class&amp;lt;? extends Iterator&amp;gt; iteratorClass) {
        this.obj = obj;
        this.iteratorClass = iteratorClass;
    }

    @SuppressWarnings(value = &amp;quot;unchecked&amp;quot;)
    public synchronized Iterable&amp;lt;T&amp;gt; getIterable() {
        Class&amp;lt;?&amp;gt; objClass = obj.getClass();
        Class&amp;lt;?&amp;gt;[] oldInterfaces = objClass.getInterfaces();
        Class&amp;lt;?&amp;gt;[] newInterfaces = new Class&amp;lt;?&amp;gt;[oldInterfaces.length + 1];
        System.arraycopy(oldInterfaces, 0, newInterfaces, 0, oldInterfaces.length);
        newInterfaces[newInterfaces.length - 1] = Iterable.class;
        return (Iterable&amp;lt;T&amp;gt;) Proxy.newProxyInstance(objClass.getClassLoader(),
                newInterfaces,
                this);
    }

    @SuppressWarnings(value = &amp;quot;unchecked&amp;quot;)
    private Iterator&amp;lt;T&amp;gt; iterator() {
        try {
            return (Iterator&amp;lt;T&amp;gt;) iteratorClass
                .getConstructor(Object.class).newInstance(obj);
        } catch (Exception e) {
            throw new UnsupportedOperationException(&amp;quot;No contructor(object)&amp;quot;, e);
        }
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getName().equals(&amp;quot;iterator&amp;quot;)) {
            return this.iterator();
        } else {
            try {
                return method.invoke(obj, args);
            } catch (InvocationTargetException ite) {
                throw ite.getCause();
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The default Iterator is XOMIterator (you can imagine why this name :) ), which reflect on the &amp;#8220;collection&amp;#8221;, calling the get(int) and size() methods:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;package com.benfante.utils.iterabletor;

import java.util.Iterator;
import org.apache.log4j.Logger;

/**
 * An Iterator for XOM-like collection classes
 * ...i.e. classes with get(int) and size() methods.
 * 
 * @author lucio
 */
public class XOMIterator&amp;lt;T&amp;gt; implements Iterator&amp;lt;T&amp;gt; {

    private static final Logger logger = Logger.getLogger(XOMIterator.class);
    private Object obj;
    private int index;

    public XOMIterator(Object obj) {
        this.obj = obj;
    }

    public boolean hasNext() {
        try {
            int count = ((java.lang.Integer) obj.getClass()
                    .getMethod(&amp;quot;size&amp;quot;, new Class[0])
                    .invoke(obj)).intValue();
            return index &amp;lt; count;
        } catch (Exception ex) {
            logger.error(&amp;quot;No size() method in the target object (&amp;quot;
                    + obj.getClass().getName() + &amp;quot;)&amp;quot;, ex);
            throw
                    new UnsupportedOperationException(
                    &amp;quot;No size() method in the target object (&amp;quot;
                    + obj.getClass().getName() + &amp;quot;)&amp;quot;, ex);
        }
    }

    @SuppressWarnings(value = &amp;quot;unchecked&amp;quot;)
    public T next() {
        try {
            return (T) obj.getClass()
                    .getMethod(&amp;quot;get&amp;quot;, new Class&amp;lt;?&amp;gt;[]{int.class})
                    .invoke(obj, new Integer(index++));
        } catch (Exception ex) {
            logger.error(&amp;quot;No get(int) method in the target object (&amp;quot;
                    + obj.getClass().getName() + &amp;quot;)&amp;quot;, ex);
            throw
                    new UnsupportedOperationException(
                    &amp;quot;No get(int) method in the target object (&amp;quot;
                    + obj.getClass().getName() + &amp;quot;)&amp;quot;, ex);
        }
    }

    public void remove() {
        throw new UnsupportedOperationException(&amp;quot;Not supported.&amp;quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Of course, You can use a different Iterator:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_java "&gt;Iterator&amp;lt;MyElement&amp;gt; iterable =
    new Iterabletor&amp;lt;MyElement&amp;gt;(element, MyIterator.class)
        .getIterable();&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 27 Jul 2007 06:42:00 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:eef63133-72a4-4a79-8d9b-61c0efb7be20</guid>
      <author>Lucio Benfante</author>
      <link>http://www.jugpadova.it/articles/2007/07/27/iterating-on-non-iterable-classes</link>
      <category>Tips &amp; Tricks</category>
      <category>Software</category>
      <category>Iterable</category>
      <category>Iterator</category>
      <category>for</category>
      <category>reflection</category>
      <category>proxy</category>
    </item>
  </channel>
</rss>
