class QueryExplorer extends BeanTreeView implements PropertyChangeListener, ChangeListener {

    private ExplorerManager manager;
    private FilterModel model;
    private FilterUIModel uiModel;
    private FilterController filterController;
    //state
    private boolean listenSelectedNodes = false;

    public QueryExplorer() {
        setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    }

    public void unsetup() {
        if (model != null) {
            model.removeChangeListener(this);
            model = null;
        }
    }

    public void setup(final ExplorerManager manager, final FilterModel model, FilterUIModel uiModel) {
        this.manager = manager;
        this.model = model;
        this.uiModel = uiModel;
        this.filterController = Lookup.getDefault().lookup(FilterController.class);

        if (model != null) {
            model.addChangeListener(this);
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    manager.setRootContext(new RootNode(new QueryChildren(model.getQueries())));
                }
            });
        } else {
            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {
                    manager.setRootContext(new AbstractNode(Children.LEAF) {

                        @Override
                        public Action[] getActions(boolean context) {
                            return new Action[0];
                        }
                    });
                }
            });
        }
        updateEnabled(model != null);

        if (!listenSelectedNodes) {
            manager.addPropertyChangeListener(this);
            listenSelectedNodes = true;
        }
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {<FILL_FUNCTION_BODY>}

    @Override
    public void stateChanged(ChangeEvent e) {
        //System.out.println("model updated");
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                //uiModel.setSelectedQuery(model.getCurrentQuery());
                saveExpandStatus(QueryExplorer.this.manager.getRootContext());
                QueryExplorer.this.manager
                    .setRootContext(new RootNode(new QueryChildren(QueryExplorer.this.model.getQueries())));
                loadExpandStatus(QueryExplorer.this.manager.getRootContext());
            }
        });
    }

    private void updateEnabled(final boolean enabled) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                setRootVisible(enabled);
                setEnabled(enabled);
            }
        });
    }

    private void loadExpandStatus(Node node) {
        if (node instanceof RootNode) {
            RootNode rootNode = (RootNode) node;
            for (Node n : rootNode.getChildren().getNodes()) {
                loadExpandStatus(n);
            }
        } else if (node instanceof QueryNode) {
            QueryNode queryNode = (QueryNode) node;
            if (uiModel.isExpanded(queryNode.getQuery())) {
                expandNode(queryNode);
            }
            Node firstChild = queryNode.getChildren().getNodeAt(0);
            if (firstChild != null && firstChild instanceof ParameterNode) {
                if (uiModel.isParametersExpanded(queryNode.getQuery())) {
                    expandNode(firstChild);
                }
            }
            for (Node n : queryNode.getChildren().getNodes()) {
                loadExpandStatus(n);
            }
        }
    }

    private void saveExpandStatus(Node node) {
        if (node instanceof RootNode) {
            RootNode rootNode = (RootNode) node;
            for (Node n : rootNode.getChildren().getNodes()) {
                saveExpandStatus(n);
            }
        } else if (node instanceof QueryNode) {
            QueryNode queryNode = (QueryNode) node;
            Node firstChild = queryNode.getChildren().getNodeAt(0);
            boolean parameterExpanded = false;
            if (firstChild != null && firstChild instanceof ParameterNode) {
                parameterExpanded = isExpanded(firstChild);
            }
            uiModel.setExpand(queryNode.getQuery(), isExpanded(queryNode), parameterExpanded);
            for (Node n : queryNode.getChildren().getNodes()) {
                saveExpandStatus(n);
            }
        }
    }
}

        if (evt.getPropertyName().equals(ExplorerManager.PROP_SELECTED_NODES)) {
            if (uiModel == null) {
                return;
            }
            Node[] nodeArray = (Node[]) evt.getNewValue();
            if (nodeArray.length > 0) {
                Node node = ((Node[]) evt.getNewValue())[0];
                if (node instanceof RootNode) {
                    uiModel.setSelectedQuery(null);
                    filterController.setCurrentQuery(null);
                    return;
                }
                while (!(node instanceof QueryNode)) {
                    node = node.getParentNode();
                    if (node.getParentNode() == null) {
                        uiModel.setSelectedQuery(null);
                        filterController.setCurrentQuery(null);
                        return;
                    }
                }
                QueryNode queryNode = (QueryNode) node;
                final Query query = queryNode.getQuery();
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        uiModel.setSelectedQuery(query);
                        model.removeChangeListener(QueryExplorer.this);
                        filterController.setCurrentQuery(uiModel.getSelectedRoot());
                        model.addChangeListener(QueryExplorer.this);
                    }
                }).start();
            }
        }
    
<no_super_class>