class GetUserRoster extends AdHocCommand
{
    @Override
    public String getCode() {
        return "http://jabber.org/protocol/admin#get-user-roster";
    }

    @Override
    public String getDefaultLabel() {
        return LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.label");
    }

    @Override
    public int getMaxStages(@Nonnull final SessionData data) {
        return 1;
    }

    @Override
    public void execute(@Nonnull SessionData sessionData, Element command)
    {
        final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(sessionData.getOwner());

        Element note = command.addElement("note");

        // Check if rosters are enabled
        if (!RosterManager.isRosterServiceEnabled()) {
            note.addAttribute("type", "error");
            note.setText(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.note.rosterservice-disabled", preferredLocale));
            return;
        }

        Map<String, List<String>> data = sessionData.getData();

        boolean requestError = false;
        Map<JID, Roster> rosters = new HashMap<>();
        final RosterManager rosterManager = XMPPServer.getInstance().getRosterManager();
        for ( final String accountjid : data.get( "accountjids" ))
        {
            JID account;
            try
            {
                account = new JID( accountjid );

                if ( !XMPPServer.getInstance().isLocal( account ) )
                {
                    note.addAttribute( "type", "error" );
                    note.setText(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.note.jid-not-local", List.of(accountjid), preferredLocale));
                    requestError = true;
                }
                else
                {
                    rosters.put(account, rosterManager.getRoster(account.getNode()));
                }
            }
            catch ( NullPointerException npe )
            {
                note.addAttribute( "type", "error" );
                note.setText(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.note.jid-required", preferredLocale));
                requestError = true;
            }
            catch (IllegalArgumentException npe)
            {
                note.addAttribute( "type", "error" );
                note.setText(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.note.jid-invalid", preferredLocale));
                requestError = true;
            }
            catch ( UserNotFoundException e )
            {
                note.addAttribute( "type", "error" );
                note.setText(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.note.user-does-not-exist", List.of(accountjid), preferredLocale));
                requestError = true;
            }
        }

        if (rosters.size() > 1) {
            note.addAttribute( "type", "error" );
            note.setText(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.note.cannot-return-multiple", preferredLocale));
            requestError = true;
        }

        if ( requestError )
        {
            // We've collected all errors. Return without applying changes.
            return;
        }

        // No errors.
        for (final Map.Entry<JID, Roster> entry : rosters.entrySet()) {
            final JID owner = entry.getKey();
            final Roster roster = entry.getValue();

            DataForm form = new DataForm(DataForm.Type.result);

            FormField field = form.addField();
            field.setType(FormField.Type.hidden);
            field.setVariable("FORM_TYPE");
            field.addValue("http://jabber.org/protocol/admin");

            field = form.addField();
            field.setType(FormField.Type.jid_multi);
            field.setVariable("accountjids");
            field.addValue(owner);

            final Element rosterElement = roster.getReset().getElement()
                .element(QName.get("query", "jabber:iq:roster"));

            if (rosterElement != null) {
                form.getElement().add(rosterElement.createCopy());
            }

            command.add(form.getElement());
        }

        // Answer that the operation was successful
        note.addAttribute("type", "info");
        note.setText(LocaleUtils.getLocalizedString("commands.global.operation.finished.success", preferredLocale));
    }

    @Override
    protected void addStageInformation(@Nonnull final SessionData data, Element command) {<FILL_FUNCTION_BODY>}

    @Override
    protected List<Action> getActions(@Nonnull final SessionData data) {
        return Collections.singletonList(Action.complete);
    }

    @Override
    protected Action getExecuteAction(@Nonnull final SessionData data) {
        return Action.complete;
    }

    @Override
    public boolean hasPermission(JID requester) {
        return (super.hasPermission(requester) || InternalComponentManager.getInstance().hasComponent(requester))
                && RosterManager.isRosterServiceEnabled();
    }
}

        final Locale preferredLocale = SessionManager.getInstance().getLocaleForSession(data.getOwner());

        DataForm form = new DataForm(DataForm.Type.form);
        form.setTitle(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.form.title", preferredLocale));
        form.addInstruction(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.form.instruction", preferredLocale));

        FormField field = form.addField();
        field.setType(FormField.Type.hidden);
        field.setVariable("FORM_TYPE");
        field.addValue("http://jabber.org/protocol/admin");

        field = form.addField();
        field.setType(FormField.Type.jid_multi);
        field.setLabel(LocaleUtils.getLocalizedString("commands.admin.user.getuserroster.form.field.accountjid.label", preferredLocale));
        field.setVariable("accountjids");
        field.setRequired(true);

        // Add the form to the command
        command.add(form.getElement());
    
<methods>public void <init>() ,public void addNextStageInformation(org.jivesoftware.openfire.commands.SessionData, Element) ,public void addPreviousStageInformation(org.jivesoftware.openfire.commands.SessionData, Element) ,public abstract void execute(org.jivesoftware.openfire.commands.SessionData, Element) ,public abstract java.lang.String getCode() ,public abstract java.lang.String getDefaultLabel() ,public java.lang.String getLabel() ,public abstract int getMaxStages(org.jivesoftware.openfire.commands.SessionData) ,public boolean hasPermission(JID) ,public void setLabel(java.lang.String) <variables>private java.lang.String label