Skip to main content

Bean Browsing with JXPath

Posted by richunger on June 14, 2005 at 2:03 PM PDT

Here's a little trick I've found useful for browsing the contents of my JAXB model, though it works just as well with any java beans. It's a GUI for testing JXPath expressions on a given Object. Try it out on any old object, and start with the XPath expression for the context node, which is just '.' (not quoted).

For example, if you create a new PathTestFrame(new java.util.Date()), and give it the expression '.', you'll see the bean properties of the Date object. Then, if you change the expression to, say 'time', you'll get the results of Date.getTime(). This is not very helpful, as the only bean property of a primitive type, as far as JXPath is concerned, is "class", but you get the idea.

It gets better. Let's say you've got an Object with a bean property called "dateList", a List of Dates. The first date in the list will be 'dateList[1]' (XPath is 1-indexed, not 0-indexed).

You can browse through a very large heirarchy of beans, and even edit the bean property values using the property sheet. Neat, eh?

import java.awt.BorderLayout;
import java.awt.event.ActionListener;
import java.beans.IntrospectionException;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.openide.DialogDisplayer;
import org.openide.ErrorManager;
import org.openide.NotifyDescriptor;
import org.openide.nodes.FilterNode;
import org.openide.nodes.Node;
import org.apache.commons.jxpath.JXPathContext;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import org.openide.nodes.BeanNode;
import org.openide.explorer.propertysheet.PropertySheet;

public class PathTestFrame extends JPanel
{
    private JXPathContext m_jxPathContext;
   
    private JTextField m_inputField;
    private JButton m_btn;
    private PropertySheet m_propsheet;
   
    public PathTestFrame(Object model)
    {
        super();
        setLayout(new BorderLayout());

        m_btn = new JButton("Test Path");
        m_inputField = new JTextField(50);
        m_propsheet = new PropertySheet();
        m_btn.addActionListener(new ActionListener(){
            public void actionPerformed(java.awt.event.ActionEvent e) {
                update();
            }
        });
       
        JPanel top = new JPanel();
        top.add(m_inputField);
        top.add(m_btn);
        add(top, BorderLayout.NORTH);
        add(m_propsheet, BorderLayout.CENTER);
       
        m_jxPathContext = JXPathContext.newContext(model);
    }
   
    private void update()
    {
        Iterator values = m_jxPathContext.iterate(m_inputField.getText());
        List l = new ArrayList();
        while (values.hasNext())
        {
            l.add(values.next());
        }
       
        Node[] nodes = new Node[l.size()];

        try
        {
            for (int i=0; i < nodes.length; i++)
            {
                nodes[i] = new BeanNode(l.get(i));
            }
            m_propsheet.setNodes(nodes);
        }
        catch (IntrospectionException ex)
        {
            ErrorManager.getDefault().notify(ex);
        }

    }
}

The class was written to be used in Netbeans, but can be used standalone as long as you have openide.jar in your classpath (and, of course, you need jxpath regardless).

Related Topics >>