How I broadcast my output


I want to try to explain my latest idea without using the letters “X”, “M”, and “L”. (Crap! That’s the first sentence of my post and I already typed them. Oh well. You’ll just have to take my word that today’s topic has nothing to do with angle brackets. I promise I won’t stab you with one, really. Believe me…) In a very agile way I started with a unit test. The test demonstrated what I was trying to do. My test really didn’t make much sense because it involved some objects that I spun off of my head and these objects had nothing to do with the problem I was addressing. Let me explain. I wanted a way to broadcast method calls. In concept it would work like one of those”Y” splitters that you would use on the A/V cords in the back of your home theater setup. You know how when you have a single output jack and you want to feed two devices? Or kind of like what the cable company uses to split the cable signal coming in so it powers all of your TV sets. (I’m probably not being too clear here so just think of one input with multiple outputs.) Get the picture? Good! Well here’s how I started to model it.

What’s the best way to model some split output? I return to my home theater analogy except this time the models I choose for my test are not output cords. Instead I use something way more meaningful to the idea of splitting output. I choose players. That’s right, players. The best idea I could come up with while thinking of home theaters. (If you haven’t figured it out by now I got home theater on the brain cuz I really want a banging home theater but I’m not allowed to because we have to use the money to buy curtains and rugs first. I sincerely love my wife but boy what I wouldn’t do for a Sony surround sound powered by a media PC with a plasma HD TV display!) So now I make a Player interface.


    public interface Player
    {
        void play();
        void stop();
        int amountOfPlays();
    }


Pretty nifty right? I bet you can completely understand how I’d want to broadcast something to that right? Well let’s not stop there. I’ll add some concrete examples so it makes even more sense.


    public static class MusicPlayer implements Player
    {
        ArrayList songsPlayed = new ArrayList();
        String nowPlaying;
        public void play()
        {
            String music = "E.P.M.D. Crossovers";
            songsPlayed.add(music);
            nowPlaying = music;
        }

        public void stop()
        {
            nowPlaying = null;
        }

        public int amountOfPlays()
        {
            return songsPlayed.size();
        }
    }

    public static class MoviePlayer implements Player
    {
        ArrayList moviesPlayed = new ArrayList();
        String nowPlaying;
        public void play()
        {
            String movie = "Return Of the Dragon";
            moviesPlayed.add(movie);
            nowPlaying = movie;
        }

        public void stop()
        {
            nowPlaying = null;
        }

        public int amountOfPlays()
        {
            return moviesPlayed.size();
        }
    }


Ok now you can imagine pressing play on your remote and both the Movie and the audio start playing right? Well let’s now code the test so we can see how this all works.


package com.gbg.util.reflect;

/**
 * Created ccc on Jun 27, 2006 at 2:50:13 PM
 * Copywright Jun 27, 2006
 */

import com.gbg.junit.ext.GBGTestCase;

import java.util.ArrayList;

public class BroadcastProxyTest extends GBGTestCase
{
    BroadcastProxy broadcastProxy;
    public void testBroadCastMethodCalls() throws Exception
    {
        broadcastProxy = new ReflectionBroadCastProxy(Player.class);
        Player cdPlayer = new MusicPlayer(), tapePlayer = new MusicPlayer(), dvdPlayer = new MoviePlayer();
        broadcastProxy.register(cdPlayer).register(tapePlayer).register(dvdPlayer);
        Player generic = (Player) broadcastProxy.proxy();
        assertNotNull("Expecting a Player implementation from the proxy.", generic);
        assertIsOfType(Player.class, generic);
        generic.play();
        generic.stop();
        generic.play();
        assertEquals(2, cdPlayer.amountOfPlays());
        assertEquals(cdPlayer.amountOfPlays(), tapePlayer.amountOfPlays());
        assertEquals(tapePlayer.amountOfPlays(), dvdPlayer.amountOfPlays());
    }
}


Clear as day right? (Hey, I told you it was a dumb example but you kept reading anyway!) With that as my leaping pad I ran the test true TDD style. (No I didn’t that’s a lie because the broadcaster interface and implementation didn’t exist so it wouldn’t compile! A few Alt+Enter’s in Idea fixed those problems with stubs.) After seeing my red bar it was particularly easy for me to color it green. I whipped out my green highlighter and started scribbling on my monitor while cussing at the error messages that kept showing up. When I got tired of that approach I broke down and wrote the following code using a dynamic proxy to achieve the desired pigment of the growing status meter. (Yes my humor is getting more and more played out but it’s hard to come up with good material on every post.)


package com.gbg.util.reflect;

import java.util.Queue;
import java.util.LinkedList;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * Created ccc on Jun 27, 2006 at 3:18:36 PM
 * Copywright Jun 27, 2006
 */
public class ReflectionBroadCastProxy implements BroadcastProxy, InvocationHandler
{
    Queue clients = new LinkedList();
    private Class type;

    public ReflectionBroadCastProxy(Class aClass)
    {
        type = aClass;
    }

    public BroadcastProxy register(Object obj)
    {
        clients.add(obj);
        return this;
    }

    public Object proxy()
    {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{type}, this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        Object result = null;
        for(Object client : clients)
        {
            Method invokeMe = client.getClass().getMethod(method.getName(), method.getParameterTypes());
            result = invokeMe.invoke(client, args);
        }
        return result;
    }
}


Now why would you need something that dumb?
I plan on using the idea in … guess what? My XML conversion. We currently run reports that stream XML to disk and then immediate read the XML from disk into a transformer that generates the final result. I want to stream to disk and transform simultaneously. For that I need my input to feed two outputs. I step back and admire my latest creation. Nice, tested, and over cooked! Just how I like it. If you come here on the regular, hollaback, if not just holla…

(The author makes a distinction between holla and hollaback as those who visit often may want to holla again whereas all other need only holla. A return holla is typically supplied for all initial hollas…)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s