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-07 00:34:33 -0500 (lun, 07 mar 2011) $:
26 * Revision: $LastChangedRevision: 1924 $:
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/ZemucanCompletor.java $:
28 */
29 package name.angoca.zemucan.ui.impl.jline;
30
31 import java.util.ArrayList;
32 import java.util.Collection;
33 import java.util.List;
34
35 import jline.Completor;
36 import name.angoca.zemucan.AbstractZemucanException;
37 import name.angoca.zemucan.interfaze.InterfaceCore;
38 import name.angoca.zemucan.interfaze.model.ReturnOptions;
39 import name.angoca.zemucan.tools.messages.jline.Messages;
40 import name.angoca.zemucan.ui.api.InputReader;
41
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 /**
46 * This is the implementation of a JLine Completor. This class permits to search
47 * the options from the core and show them via Jline.
48 * <p>
49 * <b>Control Version</b>
50 * <p>
51 * <ul>
52 * <li>0.0.1 Class creation.</li>
53 * <li>0.0.2 Logger messages.</li>
54 * <li>0.0.3 No override, no supress warnings.</li>
55 * <li>0.0.4 finals.</li>
56 * <li>1.0.0 Moved to version 1.</li>
57 * <li>1.0.1 Strings externalized.</li>
58 * <li>1.0.2 Asserts.</li>
59 * <li>1.1.0 Renamed.</li>
60 * <li>1.1.1 Completion handler.</li>
61 * <li>1.1.2 Assistance fixed.</li>
62 * </ul>
63 *
64 * @author Andres Gomez Casanova <a
65 * href="mailto:a n g o c a at y a h o o dot c o m" >(AngocA)</a>
66 * @version 1.1.2 2010-06-04
67 */
68 public class ZemucanCompletor implements Completor {
69 /**
70 * Logger.
71 */
72 private static final Logger LOGGER = LoggerFactory
73 .getLogger(ZemucanCompletor.class);
74
75 /**
76 * Assertion activation.
77 */
78 private boolean assertsEnabled;
79
80 /**
81 * Default constructor.
82 */
83 ZemucanCompletor() {
84 this.assertsEnabled = false;
85 // Intentional side-effect!
86 assert this.assertsEnabled = true;
87 }
88
89 /*
90 * (non-Javadoc)
91 *
92 * @see jline.Completor#complete(java.lang.String, int, java.util.List)
93 */
94 // The interface is generic, so there is a warning here.
95 @Override
96 @SuppressWarnings("unchecked")
97 public final int complete(final String/* ! */buffer, final int cursor,
98 @SuppressWarnings("rawtypes") final List/* <!>! */candidateRaw) {
99 assert buffer != null;
100 assert candidateRaw != null;
101 if (this.assertsEnabled) {
102 for (final Object object : candidateRaw) {
103 assert object != null;
104 }
105 }
106
107 final List<String> candidates = candidateRaw;
108
109 ZemucanCompletor.LOGGER.debug(
110 "Completor before: buffer '{}', cursor: {}", //$NON-NLS-1$
111 buffer, Integer.valueOf(cursor));
112
113 final String phrase = buffer.substring(0, cursor);
114 try {
115 final ReturnOptions answer = InterfaceCore.analyzePhrase(phrase);
116
117 // The first candidate is the new phrase.
118 final String complete = answer.getPhrase().toLowerCase();
119
120 // borra los espacios
121 final String trim = phrase.trim().toLowerCase();
122
123 // Compara si son iguales
124 if (complete.startsWith(trim)) {
125 // Toma la diferencia
126 String diff = complete.substring(trim.length());
127 if (diff.startsWith(" ") && phrase.endsWith(" ")) {
128 diff = diff.substring(1, diff.length());
129 }
130 candidates.add(diff);
131 ZemucanCompletor.LOGGER.debug("Diff '" + diff + "'");
132 } else {
133 candidates.add("");
134 }
135
136 // There are options or phrases, then add them as
137 // candidate. There is not a predefined phrase.
138 candidates.addAll(this.fromArrayToColletion(answer.getPhrases()));
139 candidates.addAll(this.fromArrayToColletion(answer.getOptions()));
140 // Adds a dummy option, in order to prevent that
141 // jLine adds automatically the option as a phrase.
142 if ((candidates.size() == 2) && (answer.getOptions().length == 1)
143 && (answer.getPhrases().length == 0)) {
144 candidates.add("");
145 }
146 } catch (final AbstractZemucanException e) {
147 String cause = "";
148 if (e.getCause() != null) {
149 cause = e.getCause().toString();
150 }
151 ZemucanCompletor.LOGGER.error(
152 Messages.getString("ZemucanCompletor.JLINE1-Exception"), //$NON-NLS-1$
153 new String[] { e.getMessage(), cause });
154 if (e.getCause() != null) {
155 final Throwable ex = e.getCause();
156 ZemucanCompletor.LOGGER.error(Messages.getString("ZemucanCompletor" //$NON-NLS-1$
157 + ".JLINE2-SpecificProblem"), //$NON-NLS-1$
158 new String[] { e.getMessage(), cause, ex.getMessage(),
159 ex.getCause().toString() });
160 }
161 System.exit(InputReader.ASSISTING_ERROR);
162 }
163
164 ZemucanCompletor.LOGGER.debug("Completor after: buffer '{}', cursor: {}", //$NON-NLS-1$
165 buffer, Integer.valueOf(cursor));
166 return cursor;
167 }
168
169 /**
170 * Converts a array into a collection.
171 *
172 * @param array
173 * array to convert.
174 * @return Collection.
175 */
176 private Collection<String>/* <!>! */fromArrayToColletion(
177 final String[]/* [!]! */array) {
178 assert array != null;
179 if (this.assertsEnabled) {
180 for (final String string : array) {
181 assert string != null;
182 }
183 }
184
185 final List<String> collection = new ArrayList<String>();
186 for (final String string : array) {
187 collection.add(string);
188 }
189
190 assert collection != null;
191 if (this.assertsEnabled) {
192 for (final String string : collection) {
193 assert string != null;
194 }
195 }
196 return collection;
197 }
198 }