Joperties allows you to create custom Interpreters that you can register so that Joperties will handle additional classes, other than the supported classes. To do that you subclass the abstract class AbstractInterpreter and you simply register it with Joperties using the methods registerInterpreter(AbstractInterpreter) or the method registerInterpreter(AbstractInterpreter,boolean). The first method will register the Interpreter regardless of whether a previous Interpreter was registered for that specific class, while the second allows you to only register the Interpreter if none is already present.
We will demonstrate with an example. Instead of creating an Interpreter for a new class, we will create a new Interpreter for the class Color which is already handled by Joperties. As the description says, the color is encoded as 0xXXXXXX where XX is the reg,green and blue channels as hex.
We will create a new Interpreter to encode the Color as such: #H;S;B with the HSB values as floats ranging from 0.0-1.0.
▲ TopWe will name our class HSBColorInterpreter and it will subclass the AbstractInterpreter<Color> (since it will deal with the Color class). This is the first draft without any implementation:
We will explain every method starting with the easiest. The method getClassType() must return the Color.class. This is used internally when registering the interpreter. So the implementation will be:
The next method we will implement is getDescription(). As you may have guessed this is not a vital method but it can be useful when you iterate though all the available Interpreters and you need a description of how they encode and decode the Objects. Plus it's a handy way of documenting the Interpreter behavior. So:
Next comes the encode() method. This method will receive the Color to encode and it must return a String representation of it. Also it must throw an EncodingException if something goes wrong with the encoding process (in such a trivial example, if the Color passed is null) and also a NoApropriateInterpeterFoundException in case the method needs other existing Interpreters for the process but none were found (in our example we will try and get the Interpreter for floats, so if that is not present, we will throw that exception). So:
As you see we did not explicitly throw a NoApropriateInterpeterFoundException since the Interpreters.getInterpreter() method will throw one automatically if it didn't find an appropriate Interpreter. This demonstrates another practice that you must follow when writing your own interpreters. Even in trivial cases such as writing a float, you must rely on finding an existing Interpreter and letting it encode your value for you instead of simply writing it, because this is where the extensibility of Joperties comes in. All existing interpreters use this practice so if you decide for any reason to register a custom interpreter for the Float class, all existing interpreters that deal with floats will use your new encoding and not simply write out the float as a String. This will be demonstrated with this example when, after we register out new interpreter, we will encode a GradientPaint which uses the registered interpreter for Color to encode the object. More on this, later.
Lastly we need to implement the interpret() method. This method will receive a String and it must return a Color object. It must throw an InterpretationException if there was an error with the format of the incoming String or a NoApropriateInterpeterFoundException if an interpreter is needed that is not found (same as above). So:
Now we will try the new Interpreter. We will write a small program that first encodes a Color and a GradientPaint, then registers our new Interpreter and does the same:
The output is:
As you can see, the first time around, the objects were encoded using the default Interpreters. After we registered our own interpreter, both the color and the gradient (which uses the registered color interpreter internally) used our new encoding. In the same manner if we were to write a new Interpreter for Float objects, then our HSBColorInterpreter would encode a color differently since it looked up the registered Float Interpreter and used that in order to encode the floats of the HSB channels.
▲ Top