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-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 }