class DuplicateAction extends AbstractAction {

        public DuplicateAction() {
            super(NbBundle.getMessage(QueryNode.class, "QueryNode.actions.duplicate"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            FilterController filterController = Lookup.getDefault().lookup(FilterController.class);
            Query ancestor = query;
            while (ancestor.getParent() != null) {
                ancestor = ancestor.getParent();
            }
            duplicateQuery(filterController, null, ancestor);
        }

        private void duplicateQuery(FilterController filterController, Query parent, Query child) {<FILL_FUNCTION_BODY>}
    }

            Filter filter = child.getFilter();
            FilterBuilder builder = filterController.getModel().getLibrary().getBuilder(filter);

            Query childQuery = filterController.createQuery(builder);
            childQuery.setName(child.getName());

            Filter filterCopy = childQuery.getFilter();
            FilterProperty[] filterProperties = filter.getProperties();
            FilterProperty[] filterCopyProperties = filterCopy.getProperties();
            if (filterProperties != null && filterCopyProperties != null) {
                for (int i = 0; i < filterProperties.length; i++) {
                    filterCopyProperties[i].setValue(filterProperties[i].getValue());
                }
            }

            if (parent == null) {
                filterController.add(childQuery);
            } else {
                filterController.setSubQuery(parent, childQuery);
            }
            if (child.getChildrenSlotsCount() > 0) {
                for (Query grandChild : child.getChildren()) {
                    duplicateQuery(filterController, childQuery, grandChild);
                }
            }
        
<no_super_class>