View Javadoc

1   /*
2    * Zemucan: A Syntax Assistant for DB2
3    * Copyright (C) 2009, 2010 Andres Gomez Casanova
4    *
5    * This file is part of Zemucan.
6    *
7    * Zemucan is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as published by
9    * the Free Software Foundation; either version 3 of the License, or
10   * (at your option) any later version.
11   *
12   * Zemucan is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public License
18   * along with this library; if not, see <http://www.gnu.org/licenses/>.
19   *
20   * Contact:
21   * a n g o c a  at  y a h o o  dot  c o m
22   * Cra. 45 No 61 - 31, Bogota, Colombia.
23   *
24   * Author:   $LastChangedBy: angoca $:
25   * Date:     $LastChangedDate: 2011-03-06 23:10:20 -0500 (dom, 06 mar 2011) $:
26   * Revision: $LastChangedRevision: 1917 $:
27   * URL:      $HeadURL: https://zemucan.svn.sourceforge.net/svnroot/zemucan/branches/zemucan_v1/source-code/uiImplJLine/src/main/java/name/angoca/zemucan/ui/impl/jline/JlineInputReader.java $:
28   */
29  package name.angoca.zemucan.ui.impl.jline;
30  
31  import java.awt.event.ActionEvent;
32  import java.awt.event.ActionListener;
33  import java.io.IOException;
34  
35  import jline.ConsoleReader;
36  import name.angoca.zemucan.tools.configurator.Configurator;
37  import name.angoca.zemucan.tools.messages.jline.Messages;
38  import name.angoca.zemucan.ui.api.AbstractUIException;
39  import name.angoca.zemucan.ui.api.InputReader;
40  import name.angoca.zemucan.ui.api.InputReaderException;
41  
42  import org.slf4j.Logger;
43  import org.slf4j.LoggerFactory;
44  
45  /**
46   * Implementation of the input reader using JLine.
47   * <p>
48   * <b>Control Version</b>
49   * <p>
50   * <ul>
51   * <li>0.0.1 Class creation.</li>
52   * <li>0.0.2 'this' to access attributes.</li>
53   * <li>0.0.3 No override.</li>
54   * <li>0.0.4 final.</li>
55   * <li>1.0.0 Moved to version 1.</li>
56   * <li>1.0.1 Validate console.</li>
57   * <li>1.1.0 Exception hierarchy changed.</li>
58   * <li>1.1.1 try catch modified.</li>
59   * <li>1.1.2 Asserts.</li>
60   * <li>1.1.3 Extra line deleted.</li>
61   * <li>1.1.4 Completor renamed.</li>
62   * <li>1.1.5 Completion Handler.</li>
63   * <li>1.1.6 Key binding.</li>
64   * </ul>
65   *
66   * @author Andres Gomez Casanova <a
67   *         href="mailto:a n g o c a at y a h o o dot c o m" >(AngocA)</a>
68   * @version 1.1.6 2010-05-24
69   */
70  public final class JlineInputReader implements InputReader {
71      /**
72       * Logger.
73       */
74      private static final Logger LOGGER = LoggerFactory
75              .getLogger(JlineInputReader.class);
76  
77      /**
78       * Prompt to show in the console.
79       */
80      private final transient String prompt;
81      /**
82       * JLine console reader.
83       */
84      private final transient ConsoleReader reader;
85  
86      /**
87       * Constructor that flushes the stream.
88       *
89       * @param consolePrompt
90       *            Prompt to show in each line of the console.
91       * @throws InputReaderException
92       *             If there is a problem flushing the stream.
93       */
94      public JlineInputReader(final String/* ! */consolePrompt)
95              throws InputReaderException {
96          assert consolePrompt != null;
97  
98          this.prompt = consolePrompt;
99          try {
100             this.reader = new ConsoleReader();
101         } catch (final IOException exception) {
102             throw new InputReaderException(exception);
103         }
104 
105         if (this.reader != null) {
106             this.configureConsoleReader();
107         }
108     }
109 
110     /**
111      * Configures the console reader.
112      */
113     private void configureConsoleReader() {
114         // Normally, each time a tab is pressed, a beep sounds. It
115         // blocks that.
116         this.reader.setBellEnabled(false);
117 
118         // Adds the completor that calls the application's core.
119         this.reader.addCompletor(new ZemucanCompletor());
120 
121         // Sets a handler that does not analyzes the candidates, it just
122         // prints them.
123         this.reader.setCompletionHandler(new ZemucanCompletionHandler());
124 
125         // Maximum quantity of candidates to show in an assistance.
126         int threshold = -1;
127         try {
128             threshold = Integer
129                     .parseInt(Configurator
130                             .getInstance()
131                             .getProperty(
132                                     ImplementationJlineInterfaceController.AUTO_PRINT_THRESHOLD_KEY));
133 
134         } catch (final NumberFormatException exception) {
135             threshold = ImplementationJlineInterfaceController.AUTO_PRINT_THRESHOLD_VALUE;
136             JlineInputReader.LOGGER.info(Messages.getString("JlineInputReader"
137                     + ".InvalidThresholdNumber"), threshold);
138         }
139         this.reader.setAutoprintThreshhold(threshold);
140 
141         // Configures the Ctrl + c key to exit from the application.
142         this.reader.addTriggeredAction((char) 3,
143         /**
144          * This class is the listener to exit from the application when the Ctrl
145          * + c keys are pressed.
146          * <p>
147          * This only works for Windows systems. In Linux, it already exists.
148          *
149          * @author Andres Gomez Casanova <a
150          *         href="mailto:a n g o c a at y a h o o dot c o m"
151          *         >(AngocA)</a>
152          */
153         new ActionListener() {
154             /*
155              * (non-Javadoc)
156              *
157              * @see
158              * java.awt.event.ActionListener#actionPerformed(java.awt.event.
159              * ActionEvent)
160              */
161             @Override
162             public void actionPerformed(final ActionEvent e) {
163                 System.exit(0);
164             }
165         });
166     }
167 
168     /*
169      * (non-Javadoc)
170      *
171      * @see name.angoca.zemucan.ui.api.InputReader#readString()
172      */
173     @Override
174     public String/* ! */readString() throws AbstractUIException {
175 
176         String ret = ""; //$NON-NLS-1$
177         try {
178             ret = this.reader.readLine(this.prompt);
179         } catch (final IOException exception) {
180             throw new InputReaderException(exception);
181         }
182         if (ret == null) {
183             throw new ConsoleProblemException();
184         }
185         return ret;
186     }
187 }