Fork me on GitHub

Tutorial 7

E07: Using mixins to sort SVG elements

Demonstation of the concept of "projection mixins". While its not possible to let your own classes implements projection interfaces without losing the projection functionality, it is possible to define methods in a second interface called a mixin interface. If you let a projection extend a mixin interface, any object implementing the mixin interface can be registered to handle the method calls of the mixin interface. In this example the interface Comparable will be our mixin interface. (Of course you may choose your own interfaces.) Its possible to have a projection extending multiple mixin interfaces. Notice: Because the method call of a mixin method on a projection will not be executed by the projection instance itself but by your specified mixin implementation, we need a field to inject the current projection instance into. By convention this field must me named "me" (to resemble the keyword "this") and have the type of the projection. It may be private. (Yes, the result of this example could have been archived by specifying a Comparator when calling Collections.sort().)

  • Add behavior to projections by adding a Mixin.

Projection API

public interface SVGDocument {
     
    /**
     * We define a sub projection here to reflect the XML {@code <rect>} element
     * behind it. Notice: Although we only define a getter to one attribute, we
     * will work with the complete element when changing the order of the
     * rectangles.
     */
    public interface GraphicElement extends Comparable<GraphicElement> {
        @XBRead("@y")
        Integer getYPosition();
    }
     
    @XBRead("/svg/rect")
    List<GraphicElement> getGraphicElements();
 
    @XBWrite("/svg/rect")
    SVGDocument setGraphicElements(List<GraphicElement> elements);
 
}

Example Code

XBProjector xmlProjector = new XBProjector();
SVGDocument svgDocument = xmlProjector.io().fromURLAnnotation(SVGDocument.class);
xmlProjector.mixins().addProjectionMixin(GraphicElement.class, new Comparable<GraphicElement>() {
 
    private GraphicElement me;
 
    @Override
    public int compareTo(GraphicElement o) {
        return me.getYPosition().compareTo(o.getYPosition());
    }
 
});
List<GraphicElement> list = svgDocument.getGraphicElements();
Collections.sort(list);
svgDocument.setGraphicElements(list);