001/*
002 * Stallion Core: A Modern Web Framework
003 *
004 * Copyright (C) 2015 - 2016 Stallion Software LLC.
005 *
006 * This program is free software: you can redistribute it and/or modify it under the terms of the
007 * GNU General Public License as published by the Free Software Foundation, either version 2 of
008 * the License, or (at your option) any later version. This program is distributed in the hope that
009 * it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
011 * License for more details. You should have received a copy of the GNU General Public License
012 * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
013 *
014 *
015 *
016 */
017
018package io.stallion.utils;
019
020import org.apache.commons.lang3.StringUtils;
021
022import java.util.Arrays;
023import java.util.List;
024import java.util.Scanner;
025import java.util.regex.Pattern;
026
027import static io.stallion.utils.Literals.*;
028
029/**
030 * A helper class for building interactive, command-line prompts.
031 */
032public class Prompter {
033    protected Scanner scanner;
034    protected String message;
035    protected List<String> choices;
036    protected Pattern validPattern;
037    protected boolean isPassword = false;
038
039    protected String lastErrorMessage = "";
040    protected int minLength = 1;
041
042    public Prompter(String message) {
043        this.scanner = new Scanner(System.in);
044        this.message = message;
045    }
046
047    public Prompter(Scanner scanner, String message) {
048        this.scanner = scanner;
049        this.message = message;
050    }
051
052    public static String prompt(String msg) {
053        return new Prompter(msg).prompt();
054    }
055
056    public boolean validate(String line) {
057        return true;
058    }
059
060    public String failAndPromptAgain() {
061
062
063        if (!empty(lastErrorMessage)) {
064            System.out.println(lastErrorMessage);
065            lastErrorMessage = "";
066        } else {
067            System.out.println("Sorry, that was not a valid response.");
068        }
069        return prompt();
070    }
071
072    public boolean yesNo() {
073        setChoices("Y", "yes", "y", "n", "N", "no");
074        String line = prompt();
075        if (line.equals("Y") || line.equals("yes") || line.equals("y")) {
076            return true;
077        } else {
078            return false;
079        }
080    }
081
082    public String prompt() {
083        System.out.print(message);
084        String line = "";
085        if (isPassword && System.console() != null) {
086            line = new String(System.console().readPassword());
087        } else {
088            line = this.scanner.nextLine();
089        }
090        line = line.trim();
091        if (line.length() < minLength && line.length() == 0) {
092            lastErrorMessage = "Sorry, your response must be at least " + minLength + " character(s) long. Please make a choice.";
093            return failAndPromptAgain();
094        }
095        if (!empty(choices)) {
096            if (!choices.contains(line)) {
097                lastErrorMessage = "Sorry, that was not one of the allowed choices.\n" +
098                        "The allowed choices are: " + StringUtils.join(choices, ", ");
099
100                return failAndPromptAgain();
101            }
102        }
103        if (validPattern != null) {
104            if (!validPattern.matcher(line).matches()) {
105                lastErrorMessage = "Sorry, that was not a valid entry.";
106                return failAndPromptAgain();
107            }
108        }
109        return line;
110    }
111
112    public Prompter setValidPattern(String patternString) {
113        this.validPattern = Pattern.compile(patternString);
114        return this;
115    }
116
117    public Prompter setChoices(String...choices) {
118        this.choices = Arrays.asList(choices);
119        return this;
120    }
121
122    public Prompter setChoices(List<String> choices) {
123        this.choices = choices;
124        return this;
125    }
126
127
128    public Prompter setAllowEmpty(boolean allow) {
129        if (allow) {
130            this.minLength = 0;
131        } else {
132            this.minLength = 1;
133        }
134        return this;
135    }
136
137    public Prompter setMinLength(int minLength) {
138        this.minLength = minLength;
139        return this;
140    }
141
142
143    public Prompter setIsPassword(boolean isPassword) {
144        this.isPassword = isPassword;
145        return this;
146    }
147
148
149    public String getLastErrorMessage() {
150        return lastErrorMessage;
151    }
152
153    public Prompter setLastErrorMessage(String lastErrorMessage) {
154        this.lastErrorMessage = lastErrorMessage;
155        return this;
156    }
157
158
159}