001    /**
002     * Copyright (c) 2012, SIB. All rights reserved.
003     * 
004     * SIB (Swiss Institute of Bioinformatics) - http://www.isb-sib.ch Host -
005     * https://sourceforge.net/projects/javaprotlib/
006     * 
007     * Redistribution and use in source and binary forms, with or without
008     * modification, are permitted provided that the following conditions are met:
009     * Redistributions of source code must retain the above copyright notice, this
010     * list of conditions and the following disclaimer. Redistributions in binary
011     * form must reproduce the above copyright notice, this list of conditions and
012     * the following disclaimer in the documentation and/or other materials provided
013     * with the distribution. Neither the name of the SIB/GENEBIO nor the names of
014     * its contributors may be used to endorse or promote products derived from this
015     * software without specific prior written permission.
016     * 
017     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
018     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
019     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
020     * ARE DISCLAIMED. IN NO EVENT SHALL SIB/GENEBIO BE LIABLE FOR ANY DIRECT,
021     * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022     * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023     * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
024     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026     * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     */
028    package org.expasy.jpl.commons.app;
029    
030    
031    import java.io.BufferedReader;
032    import java.io.BufferedWriter;
033    import java.io.IOException;
034    import java.io.InputStream;
035    import java.io.InputStreamReader;
036    import java.io.OutputStream;
037    import java.io.OutputStreamWriter;
038    import java.util.regex.Matcher;
039    import java.util.regex.Pattern;
040    import org.expasy.jpl.commons.base.builder.BuilderException;
041    import org.expasy.jpl.commons.base.builder.InstanceBuilder;
042    
043    
044    public final class InteractiveInputScannerImpl implements
045        InteractiveInputScanner {
046            
047            public static final Pattern YES_NO_PATTERN =
048                Pattern.compile("^[yn]$", Pattern.CASE_INSENSITIVE);
049            
050            private BufferedReader in;
051            private BufferedWriter out;
052            private String prompt;
053            private Pattern inputPattern;
054            private Pattern exitPattern;
055            private String defaultInput;
056            
057            private Matcher matcher;
058            
059            public InteractiveInputScannerImpl(Builder builder) {
060                    setInputStream(builder.is);
061                    setOutputStream(builder.os);
062                    
063                    this.prompt = builder.prompt;
064                    this.inputPattern = builder.inputPattern;
065                    this.exitPattern = builder.exitPattern;
066                    this.defaultInput = builder.defaultInput;
067            }
068            
069            public static class Builder implements
070                InstanceBuilder<InteractiveInputScannerImpl> {
071                    
072                    private InputStream is;
073                    private OutputStream os;
074                    private String prompt;
075                    private Pattern inputPattern;
076                    private Pattern exitPattern;
077                    private String defaultInput;
078                    
079                    public Builder() {
080                            is = System.in;
081                            os = System.out;
082                            prompt = "";
083                            inputPattern = Pattern.compile("^.+$");
084                    }
085                    
086                    public Builder prompt(String prompt) {
087                            this.prompt = prompt;
088                            return this;
089                    }
090                    
091                    public Builder inputStream(InputStream is) {
092                            this.is = is;
093                            return this;
094                    }
095                    
096                    public Builder outputStream(OutputStream os) {
097                            this.os = os;
098                            return this;
099                    }
100                    
101                    public Builder inputPattern(Pattern pat) {
102                            this.inputPattern = pat;
103                            return this;
104                    }
105                    
106                    public Builder defaultInput(String defaultInput) {
107                            this.defaultInput = defaultInput;
108                            return this;
109                    }
110                    
111                    public Builder exitPattern(Pattern pat) {
112                            this.exitPattern = pat;
113                            return this;
114                    }
115                    
116                    public InteractiveInputScannerImpl build() throws BuilderException {
117                            return new InteractiveInputScannerImpl(this);
118                    }
119                    
120            }
121            
122            // open up standard input
123            public void setInputStream(InputStream stream) {
124                    in = new BufferedReader(new InputStreamReader(stream));
125            }
126            
127            public void setOutputStream(OutputStream stream) {
128                    out = new BufferedWriter(new OutputStreamWriter(stream));
129            }
130            
131            public String waitInput() throws IOException {
132                    String input = null;
133                    
134                    while (true) {
135                            if (prompt != null && prompt.length() > 0) {
136                                    out.append(prompt);
137                                    out.append(": ");
138                                    out.flush();
139                            }
140                            
141                            // read user input
142                            input = in.readLine();
143                            
144                            matcher = inputPattern.matcher(input);
145                            
146                            // valid input format
147                            if (matcher.find()) {
148                                    break;
149                            }
150                            
151                            if (defaultInput != null) {
152                                    return defaultInput;
153                            }
154                            
155                            // exit interruption
156                            if (exitPattern != null) {
157                                    matcher = exitPattern.matcher(input);
158                                    if (matcher.find()) {
159                                            break;
160                                    }
161                            }
162                    }
163                    return input;
164            }
165            
166            @Override
167            public Pattern getInputPattern() {
168                    return inputPattern;
169            }
170            
171            @Override
172            public String getPrompt() {
173                    return prompt;
174            }
175            
176            @Override
177            public Pattern getExitPattern() {
178                    return exitPattern;
179            }
180            
181            @Override
182            public String getDefaultInput() {
183                    return defaultInput;
184            }
185            
186    }