Pojo Container

I wrote a Pojo container “wrapper” that I would like to release/post here for others to use. What is the best way to do this?

The container is very easy to use, it parses a pojo and uses the public getters [get(), is(), has()]
as the ID’s. For for example if you passed it “java.io.File” in the TableDemo, the column names would be all of the public getters for File [isDirectory, UseableSpace, Name, Parent …]
.

  PojoContainer pc = new PojoContainer("java.io.File");

  pc.populatePojoItem( new File("/") );

  table.setContainerDataSource(pc);

or anywhere else that you would use a datasource.

I used reflection to get the method names, by default I sort the names, however there is a constructor to disable this. Code is easy to change. I did incorporate the setter()-side too, so if you wanted to update a field. The latter was not tested, just wrote the reflection code to call the pojo setter method as an example/template for others.

The original intentions was: a) to allow me to use any pojo with the toolkit, and avoid having to “hardcode” each container for a particular pojo. b) use it as a start to replace the “tree” functionality with dynamic row where I could use any Java object and it’s representation as the “row” content.

Code is in four small sections:

container.pojo
PojoClassMap.java
PojoClassProperty.java
PojoContainer.java
PojoContainerMap.java

All of the above could be incorporated into a single class, I kept them separate because I re-use them in other classes. It also makes it easier to read the code without it being cluttered.

So, where or how to post this? Paste it here? Zip it and place it somewhere? Thought I would ask before attempting to just post it.

Andy

Here is a demo using the TableDemo in the toolkit. I modifed the TableCode to use the newer HorizontalLayout scheme. If this does not work for you, simply replace the layout line with the original one from the toolkit.

TableDemo.java


/* @ITMillApache2LicenseForJavaFiles@
 */

package container.pojo;

import com.itmill.toolkit.event.Action;
import com.itmill.toolkit.ui.Button;
import com.itmill.toolkit.ui.HorizontalLayout;
import com.itmill.toolkit.ui.Label;
import com.itmill.toolkit.ui.Table;
import com.itmill.toolkit.ui.Window;
import java.io.File;

/**
 * Similar to QueryContainerDemo
 * 
 * @author IT Mill Ltd.
 * @since 4.0.0
 * 
 */
public class TableDemo extends com.itmill.toolkit.Application implements
        Action.Handler {

    private static final String ACTION_DESCRIPTION = "Use right mouse button to initiate "
            + "actions menu.<br />Note: on Opera use meta key "
            + "and left mouse button.";

    private static final String TABLE_CAPTION = "Pojo Container";

    // Table component where SQL rows are attached (using QueryContainer)
    private final Table table = new Table();

    // Label which displays last performed action against table row
    private final Label tableLastAction = new Label(
            "No action selected for table.");

    // Example Actions for table
    private final Action ACTION1 = new Action("Upload");

    private final Action ACTION2 = new Action("Download");

    private final Action ACTION3 = new Action("Show history");

    private final Action[] actions = new Action[]
 { ACTION1, ACTION2, ACTION3 };

    // Button which is used to disable or enable table
    // note: when button click event occurs, tableEnabler() method is called
    private final Button tableEnabler = new Button("Disable table", this,
            "tableEnabler");

    // Button which is used to hide or show table
    // note: when button click event occurs, tableVisibility() method is called
    private final Button tableVisibility = new Button("Hide table", this,
            "tableVisibility");

    // Button which is used to hide or show table
    // note: when button click event occurs, tableVisibility() method is called
    private final Button tableCaption = new Button("Hide caption", this,
            "tableCaption");

    /**
     * Initialize Application. Demo components are added to main window.
     */
    @Override
    public void init() {
        final Window main = new Window("Table demo");
        setMainWindow(main);

        // Main window contains heading, two buttons, table and label
        main
                .addComponent(new Label(
                        "<h1>Table demo</h1>"
                                + "<b>Rows are loaded from the server as they are needed.<br />"
                                + "Try scrolling the table to see it in action.</b><br />"
                                + ACTION_DESCRIPTION, Label.CONTENT_XHTML));

        final HorizontalLayout layout = new HorizontalLayout();

        layout.addComponent(tableVisibility);
        layout.addComponent(tableEnabler);
        layout.addComponent(tableCaption);
        main.addComponent(layout);
        main.addComponent(table);
        main.addComponent(tableLastAction);

        // initialize demo components
        initTable();
    }

    /**
     * Populates table component with all rows from employee table.
     * 
     */
    private void initTable() {
        // init table
        table.setCaption(TABLE_CAPTION);
        table.setPageLength(10);
        table.setSelectable(true);
        table.setRowHeaderMode(Table.ROW_HEADER_MODE_INDEX);
        table.setColumnCollapsingAllowed(true);
        table.setColumnReorderingAllowed(true);
        table.setSelectable(true);
        // this class handles table actions (see handleActions method below)
        table.addActionHandler(this);
        table.setDescription(ACTION_DESCRIPTION);

        /**
         * Pojo Container
         */
        // populate  with the Pojo Container
        final PojoContainer pc = new PojoContainer(File.class.getName(), false);

        File root = new File("/");

        pc.populatePojoItem(root);
        pc.populatePojoItem(new File("/etc"));
        pc.populatePojoItem(new File("/etc/hosts"));

        table.setContainerDataSource(pc);

        table.setCaption(TABLE_CAPTION);

        table.setWidth(600, Table.UNITS_PIXELS);

    }

    public void tableVisibility() {
        if (table.isVisible()) {
            tableVisibility.setCaption("Show table");
            table.setVisible(false);
            tableEnabler.setEnabled(false);
            tableCaption.setEnabled(false);
        } else {
            tableVisibility.setCaption("Hide table");
            table.setVisible(true);
            tableEnabler.setEnabled(true);
            tableCaption.setEnabled(true);
        }
    }

    public void tableEnabler() {
        if (table.isEnabled()) {
            tableEnabler.setCaption("Enable table");
            table.setEnabled(false);
        } else {
            tableEnabler.setCaption("Disable table");
            table.setEnabled(true);
        }
    }

    public void tableCaption() {
        if (table.getCaption().equals("")) {
            table.setCaption(TABLE_CAPTION);
            tableCaption.setCaption("Hide caption");
        } else {
            table.setCaption("");
            tableCaption.setCaption("Show caption");
        }
    }

    /**
     * URIHandler Return example actions
     */
    public Action[] getActions(Object target, Object sender) {
        return actions;
    }

    /**
     * Executed by right mouse button on table or tree component.
     */
    public void handleAction(Action action, Object sender, Object target) {
        if (sender == table) {
            tableLastAction.setValue("Last action clicked was '"
                    + action.getCaption() + "' on item " + target);
        }
    }

}

Here are the web.xml insertions:

    <servlet>
        <servlet-name>Table</servlet-name>
        <servlet-class>com.itmill.toolkit.terminal.gwt.server.ApplicationServlet</servlet-class>
        <init-param>
            <param-name>application</param-name>
            <param-value>container.pojo.TableDemo</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>Table</servlet-name>
        <url-pattern>/table/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>Table</servlet-name>
        <url-pattern>/ITMILL/*</url-pattern>
    </servlet-mapping>

url example: http://localhost/your-context/table/

I am very interested in your Pojo container. What happens if an attribute with (getter and setter) is not a primitive type but another POJO? Will your Pojo Container handle that? It is kind of recursive.

How does the PojoContainer differ from the built-in BeanItemContainer? I know the built-in BeanItemContainer doesn’t do recursive calls to get/set methods on any contained pojos, but it can certainly handle your get/set being another pojo so long as the value can be displayed with yourpojoinstance.toString() and you it can construct one using: new YourPojoClass(String) constructor.