I'm working on a Graph based Image editor. My current plan is to have Nodes of the graph be operations on the image, an operation will take a number of input buffers and manipulate them in some way (be it invert a single input, composite two inputs, draw a rectangle on an input, etc. ). a buffer could be an RGBA image (represented by a buffer class I'm working on as well) or a Buffer of simply doubles (represented by the same buffer class which is generic) which would be the output of something like a noise operation. each output from a node can go to any number of inputs but each input can only have one connection to it, an example might look something like this:
graph_example

My Current code is changing rapidly and drastically, so I don't want to post the whole so I'm going to just do the interfaces i have in mind, they won't compile I just want to get the idea across

interface BufferValue<T>{
    BufferValue<T> add(BufferValue<T> t);
    //various other math stuff for values

    //standard setters and getters
}

class Buffer<T extends BufferValue & Comparable<T>>{
   T[] data = new T[width*height]; //DOES NOT COMPILE, but demonstrates idea
   T getPixel(int x, int y);//these two used inside the operations
   void setPixel(int x, int y, T t);
}

class Connection{
    String sourceOp;
    String sourceOut;
    String destOp;
    String destIn;
}

abstract class Operation{
    List<String> inputNames;//names of inputs
    Map<String, Connection> inputs;//name to connection for input

    //WAY TO STORE WHAT TYPE OF BUFFER INPUTS NEED TO BE

    List<String> outputNames;
    Map<String, List<Connections> outputs;//output connections

    //WAY TO STORE WHAT TYPE OF BUFFER OUTPUTS ARE

    abstract Buffer getOutput(String out);// will use inputs to create output
    //TEST IF INPUT TYPES ARE CORRECT
}

The above assumes that the graph stores the nodes as names but that shouldn't matter for this question.

I'm looking for the best way to store and test what types of buffers are being passed around. My assumption is that storing a list of Classes is the way I should go, but the problem of type erasure has me confused. What would the proper way be to test that the buffer is the right type for the needed operation?

If you need clarification please ask. Thanks for the help

Unfortunately, not enough information. For e.g. you missed out the most important part as to how do you plan on using it? How does the code which interacts with Operation and the other classes posted above look like or is supposed to look like?

Also, the usage of Buffer class in the above code doesn't look right, mainly because it completely ignores the type parameters required. Try to move the Comparable part of the interface inside the BufferValue instead of placing it on Buffer assuming you want to compare the values and not the actual buffer.

Generally speaking, when you throw in generics in the mix of class/application design, you need to make sure you see it through till the end otherwise you are in for a world of pain. If you are using generics, restrictions can be easily applied by using type parameters but then again, it all depends on what you mean by "the buffer is the right type for the needed operation".

Thanks for the reply, by "the buffer is the right type" is that an operation may need three inputs, 2 color buffers and a float buffer for compositing. The BufferValue<T>'s T type being the thing needing check, I'm beginning to think this would work better by just parameterizing the buffer for a type and checking it's type parameter, or implementing seperate buffer classes for the tree or four types I need.

As for using the buffers the Operation classes getOutput(String) method would probably look a bit like this:

public Buffer getOutput(String output){
    if(output.equals("OUT")){
        Connection floatCon = inputs.get("AlphaBuffer");
        Connection col1Con = inputs.get("src1Buffer");
        Connection col2Con = inputs.get("src2Buffer");
        Graph g = GET CURRENT GRAPH, probably should be a parameter to this function;
        Buffer floatBuf = 
            g.getNodeByName(floatCon.sourceOp).getOutput(floatCon.sourceOut);
        //same for 2 color buffers

        ENSURE floatBuf IS A BUFFER FOR FLOATS and similar for the color buffers
        ALSO CHECK SIZES

        Buffer<ColorValue> output = new Buffer<ColorValue>(width, height);

        for(int x=0;x<width;x++){
            for(int y=0;y<height;y++){
                ColorValue c1 = col1Buf.getPixel(x,y);
                ColorValue c2 = col2Buf.getPixel(x,y);
                FloatValue a = floatBuf.getPixel(x,y);
                ColorValue v = c1.mul(a.floatValue()).add(c2.mul(1-a.floatValue()));
                output.setValue(x,y,v);
            }
        }
        return output;
    } else {
        throw new IllegalArgumentException("Composite only has one "+ 
            "output called OUT found: " + output);
    }
}

checking sizes is simple, checking what type it is is what i'm wondering about, I think it may be best if I just implement each as a subclass rather than using generics

The code is turning out to be confusing for me given that I'm completely out of context but I'll try.

The code you posted requires you to have special knowledge about the types is the code inside the for loop. If using some way you can make sure that all BufferValue objects implement a getFloat method and also make sure that the type parameter for the Buffer to be returned is passed in the method, you can achieve a good enough level of generic nature. Something like:

public Buffer<T> getOutput(String output, Class<T> outclass) {
   // something here
}

Also, make sure that the Operation class also has a type to represent the type of the output buffer. Something like:

 abstract class Operation<R> { 
     public abstract Buffer<R> getOutput(String s);   
 }

Also, make sure that the Operation class also has a type to represent the type of the output buffer.
Somethng like:

I like the idea here, the problem is that an Operation may have multiple outputs which can be of different types so this interface would not work. How could I add that to this scheme?

I have attached my entire NetBeans project, note that running it does nothing to do with the question and will display a simple gradient editor, but it does have the full implementations of the classes I'm working with. They aren't organized anywhere into the actual graph yet though.

I like the idea here, the problem is that an Operation may have multiple outputs which can be of different types so this interface would not work

I'm not sure I understand. How can a single operation have multiple outputs? Aren't those lines in the diagram just sending across the same output to multiple other operations?

I have attached my entire NetBeans project

I don't see any attachment. Plus I'm not sure if I would have the time to look at the entire project in depth though attaching it won't hurt; I'll have a look if I get some time.

I think your right actually, I don't think I need multiple outputs, I was just hoping for a more general solution, I thought i attached it and this time I uploaded it to my site: click here

Edited 4 Years Ago by sciwizeh: mroe info

I think your right actually, I don't think I need multiple outputs

Given that this query is out of the way, I'd recommend you give the new design a go and post back if you still have problems after modifying the getOutput method and the Operation interface.

This article has been dead for over six months. Start a new discussion instead.