All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xceptance.common.util.ConsoleUiUtils Maven / Gradle / Ivy

Go to download

XLT (Xceptance LoadTest) is an extensive load and performance test tool developed and maintained by Xceptance.

There is a newer version: 8.4.0
Show newest version
/*
 * Copyright (c) 2005-2022 Xceptance Software Technologies GmbH
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.xceptance.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.xceptance.common.lang.ThreadUtils;

/**
 * The {@link ConsoleUiUtils} class provides utility methods to ease building console-based UIs.
 * 
 * @author Jörg Werner (Xceptance Software Technologies GmbH)
 */
public final class ConsoleUiUtils
{
    /**
     * An {@link EofHandler} is called if EOF was detected while reading input from stdin.
     */
    public interface EofHandler
    {
        /**
         * Called if EOF was detected.
         */
        public void onEof();
    }

    /**
     * The list of registered {@link EofHandler} instances.
     */
    private static final Set EOF_HANDLERS = new LinkedHashSet();

    /**
     * A reader on top of {@link System#in}.
     */
    private static final BufferedReader STDIN_READER = new BufferedReader(new InputStreamReader(System.in));

    /**
     * Adds the passed {@link EofHandler} instance to the internal list of handlers.
     * 
     * @param eofHandler
     *            the handler
     */
    public static void addEofHandler(final EofHandler eofHandler)
    {
        ParameterCheckUtils.isNotNull(eofHandler, "eofHandler");
        EOF_HANDLERS.add(eofHandler);
    }

    /**
     * Asks the user for confirmation.
     * 
     * @param message
     *            the message text presented to the user
     * @return true if the user confirmed, false otherwise
     */
    public static boolean confirm(String message)
    {
        message = message + " [y/n]";

        while (true)
        {
            final String s = readLine(message);

            if ("n".equalsIgnoreCase(s))
            {
                return false;
            }
            else if ("y".equalsIgnoreCase(s))
            {
                return true;
            }
        }
    }

    /**
     * Presents the user a list of items from which the user might select one or more. The selected items will be
     * returned. If so specified, an "All" item is added to the list, which - when chosen - selects all items at once.
     * 
     * @param 
     * @param header
     *            the header text
     * @param displayNames
     *            the display names of the items
     * @param items
     *            the corresponding items
     * @param allInsteadOfNone
     *            whether an "all" item is to be shown instead of the default "none" item
     * @return the selected items (never null)
     */
    public static  List multiSelectItems(final String header, final List displayNames, final List items,
                                               final boolean allInsteadOfNone)
    {
        return multiSelectItems(header, displayNames, items, allInsteadOfNone, null);
    }

    /**
     * Presents the user a list of items from which the user might select one or more. The selected items will be
     * returned. If so specified, an "All" item is added to the list, which - when chosen - selects all items at once.
     * 
     * @param 
     * @param header
     *            the header text
     * @param displayNames
     *            the display names of the items
     * @param items
     *            the corresponding items
     * @param allInsteadOfNone
     *            whether an "all" item is to be shown instead of the default "none" item
     * @param allInsteadOfNothingLabel
     *            all/nothing label text. If blank there will be default labels.
     * @return the selected items (never null)
     */
    public static  List multiSelectItems(final String header, List displayNames, final List items,
                                               final boolean allInsteadOfNone, final String allInsteadOfNothingLabel)
    {
        // copy the list of display names as we will extend the list
        displayNames = new ArrayList<>(displayNames);
        
        // add the "all"/"none" item as the first item
        if (StringUtils.isNotBlank(allInsteadOfNothingLabel))
        {
            displayNames.add(0, allInsteadOfNothingLabel);
        }
        else
        {
            displayNames.add(0, allInsteadOfNone ? "" : "");
        }

        // determine longest key
        int maxKeyLength = String.valueOf(displayNames.size()).length();

        // print the menu
        System.out.println(header);
        for (int i = 0; i < displayNames.size(); i++)
        {
            System.out.printf(" %s %s\n", StringUtils.leftPad("(" + i + ")", maxKeyLength + 2), displayNames.get(i));
        }

        // get the user's selection
        while (true)
        {
            final String s = readLine();
            if (StringUtils.isNotBlank(s))
            {
                try
                {
                    final String[] parts = StringUtils.split(s, " ,;");
                    final Set result = new LinkedHashSet();

                    for (int i = 0; i < parts.length; i++)
                    {
                        final int n = Integer.parseInt(parts[i]);

                        if (n == 0)
                        {
                            // all/none item
                            if (allInsteadOfNone)
                            {
                                result.addAll(items);
                                break;
                            }
                        }
                        else
                        {
                            result.add(items.get(n - 1));
                        }
                    }

                    return new ArrayList(result);
                }
                catch (final IndexOutOfBoundsException e)
                {
                    // simply retry
                }
                catch (final NumberFormatException e)
                {
                    // simply retry
                }
            }
        }
    }

    /**
     * Asks the user to enter an integer value. The number must be greater than 0.
     * 
     * @param message
     *            the message text
     * @return the value entered
     */
    public static int readInt(final String message)
    {
        while (true)
        {
            final String s = readLine(message);

            try
            {
                final int i = Integer.parseInt(s);

                if (i >= 1)
                {
                    return i;
                }
            }
            catch (final NumberFormatException e)
            {
                // simply retry
            }
        }
    }

    /**
     * Reads a line of text from the console.
     * 
     * @return the line just read (never null)
     */
    public static String readLine()
    {
        return readLine(null);
    }

    /**
     * Reads a line of text from the console.
     * 
     * @param message
     *            the message text to show
     * @return the line just read (never null)
     */
    public static String readLine(final String message)
    {
        final StringBuilder prompt = new StringBuilder();

        if (!StringUtils.isBlank(message))
        {
            prompt.append(message).append(' ');
        }

        prompt.append("=> ");

        System.out.print(prompt);

        try
        {
            final String s = STDIN_READER.readLine();

            // EOF handling
            if (s == null)
            {
                // give some visual feedback
                System.out.println();

                // execute any registered EOF handlers
                runEofHandlers();

                // block this thread until regular shutdown is complete
                ThreadUtils.sleep();
            }

            return s;
        }
        catch (final IOException e)
        {
            throw new RuntimeException("Failed to read input from stdin", e);
        }
    }

    /**
     * Removes the passed {@link EofHandler} instance from the internal list of handlers.
     * 
     * @param eofHandler
     *            the handler
     */
    public static void removeEofHandler(final EofHandler eofHandler)
    {
        ParameterCheckUtils.isNotNull(eofHandler, "eofHandler");
        EOF_HANDLERS.remove(eofHandler);
    }

    /**
     * Asks the user to select an item from a list of items.
     * 
     * @param 
     * @param header
     *            the header line
     * @param keys
     *            the keys used to select the respective items (maybe null, in which case numbers will be
     *            used)
     * @param displayNames
     *            the display names for the items
     * @param items
     *            the list of items
     * @return the selected item (never null)
     */
    public static  T selectItem(final String header, List keys, final List displayNames, final List items)
    {
        // build the list of keys if none was specified
        if (keys == null)
        {
            keys = new ArrayList();
            for (int i = 0; i < displayNames.size(); i++)
            {
                keys.add(String.valueOf(i + 1));
            }
        }

        // parameter check
        if (keys.size() != displayNames.size())
        {
            throw new IllegalArgumentException("The count of display names and keys has to be equal!");
        }
        if (keys.size() != items.size())
        {
            throw new IllegalArgumentException("The count of items and keys has to be equal!");
        }

        // determine longest key
        int maxKeyLength = 0;
        for (String key : keys)
        {
            maxKeyLength = Math.max(maxKeyLength, key.length());
        }

        // print the menu
        System.out.println(header);
        for (int i = 0; i < displayNames.size(); i++)
        {
            System.out.printf(" %s %s\n", StringUtils.leftPad("(" + keys.get(i) + ")", maxKeyLength + 2), displayNames.get(i));
        }

        // let the user choose an item
        while (true)
        {
            // read the key
            final String key = readLine();

            // search the key in the list of keys and return the corresponding item
            for (int i = 0; i < keys.size(); i++)
            {
                if (keys.get(i).equals(key))
                {
                    return items.get(i);
                }
            }
        }
    }

    /**
     * Asks the user to select an item from a list of items.
     * 
     * @param 
     * @param header
     *            the header line
     * @param displayNames
     *            the display names for the items
     * @param items
     *            the list of items
     * @return the selected item (never null)
     */
    public static  T selectItem(final String header, final List displayNames, final List items)
    {
        // parameter check
        if (displayNames.size() != items.size())
        {
            throw new IllegalArgumentException("The count of display names and items has to be equal!");
        }
        return selectItem(header, null, displayNames, items);
    }

    /**
     * Checks whether the ENTER key was pressed.
     * 
     * @return true if the ENTER key was pressed, false otherwise
     */
    public static boolean wasEnterKeyPressed()
    {
        try
        {
            if (STDIN_READER.ready())
            {
                // consume a line of input
                STDIN_READER.readLine();

                return true;
            }
            else
            {
                // no input available
                return false;
            }
        }
        catch (final IOException e)
        {
            // should never happen
            throw new RuntimeException("Failed to read input from stdin", e);
        }
    }

    /**
     * Runs the registered {@link EofHandler} instances in the order they were added.
     */
    private static void runEofHandlers()
    {
        for (final EofHandler eofHandler : EOF_HANDLERS)
        {
            eofHandler.onEof();
        }
    }

    /**
     * Constructor. Declared private to avoid instantiation.
     */
    private ConsoleUiUtils()
    {
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy