View Javadoc

1   /*
2    *  XNap - A P2P framework and client.
3    *
4    *  See the file AUTHORS for copyright information.
5    *
6    *  This program is free software; you can redistribute it and/or modify
7    *  it under the terms of the GNU General Public License as published by
8    *  the Free Software Foundation.
9    *
10   *  This program is distributed in the hope that it will be useful,
11   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   *  GNU General Public License for more details.
14   *
15   *  You should have received a copy of the GNU General Public License
16   *  along with this program; if not, write to the Free Software
17   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  
20  package org.xnap.plugin.gift.net.lexer;
21  
22  import java.text.CharacterIterator;
23  import java.text.StringCharacterIterator;
24  import java.util.Enumeration;
25  import java.util.Hashtable;
26  import java.util.Vector;
27  
28  
29  /***
30   * Command  Represents a GiFT-Command
31   *
32   * @author <a href="mailto:tvanlessen@taval.de">Tammo van Lessen</a>
33   * @version CVS $Id: Command.java,v 1.2 2003/10/06 10:17:37 squig Exp $
34   */
35  public class Command
36  {
37      //~ Instance fields --------------------------------------------------------
38  
39      private Hashtable keys;
40      private Hashtable modifiers;
41      private Vector subCommands;
42      private String cmdArgument;
43      private String cmdModifier;
44      private String command;
45  
46      //~ Constructors -----------------------------------------------------------
47  
48      /***
49       * Creates a new <code>cmd</code>-Command object.
50       *
51       * @param cmd the command's name
52       */
53      public Command(String cmd)
54      {
55          modifiers = new Hashtable();
56          keys = new Hashtable();
57          subCommands = new Vector();
58          command = cmd;
59          cmdModifier = null;
60          cmdArgument = null;
61      }
62  
63      /***
64       * Creates an empty Command object.
65       */
66      public Command()
67      {
68  		this(null);
69      }
70  
71      //~ Methods ----------------------------------------------------------------
72  
73      /***
74       * Method getAllSubCommandsByName.
75       */
76      public Vector getAllSubCommandsByName(String key)
77      {
78  		Command cmd;
79  		Vector cmdList = new Vector();
80  		for (int i = 0; i < subCommands.size(); i++) {
81  			cmd =(Command)subCommands.get(i); 
82  			if (cmd.getCommand().equalsIgnoreCase(key)) {
83  				cmdList.add(cmd);
84  			}
85  		}
86  		return cmdList;
87      }
88  
89      /***
90       * returns the command
91       *
92       * @return the command's name
93       */
94      public String getCommand()
95      {
96          return command;
97      }
98  
99      /***
100      * Sets the commands argument
101      *
102      * @param arg the argument
103      */
104     public void setCommandArgument(String arg)
105     {
106         cmdArgument = arg;
107     }
108 
109     /***
110      * Returns the commands argument
111      *
112      * @return the argument
113      */
114     public String getCommandArgument()
115     {
116         return cmdArgument;
117     }
118 
119     /***
120      * Sets the modifier for the command
121      *
122      * @param arg the modifier
123      */
124     public void setCommandModifier(String arg)
125     {
126         cmdModifier = arg;
127     }
128 
129     /***
130      * Returns the commands modifier
131      *
132      * @return the modifier
133      */
134     public String getCommandModifier()
135     {
136         return cmdModifier;
137     }
138 
139     /***
140      * Returns the argument corresponding to the given key
141      *
142      * @param key the key
143      *
144      * @return the key's argument
145      */
146     public String getKey(String key)
147     {
148         return (String) keys.get(key);
149     }
150 
151     /***
152      * Sets the argument for the given key
153      *
154      * @param key the key
155      * @param arg the argument
156      */
157     public void setKeyArgument(String key, String arg)
158     {
159         keys.put(key, arg);
160     }
161 
162     /***
163      * Sets the modifier for the specified key.
164      *
165      * @param key the key
166      * @param mod the modifier
167      */
168     public void setKeyModifier(String key, String mod)
169     {
170         modifiers.put(key, mod);
171     }
172 
173     /***
174      * Returns the modifier for the given key.
175      *
176      * @param key the key
177      *
178      * @return the modifier
179      */
180     public String getKeyModifier(String key)
181     {
182         return (String) modifiers.get(key);
183     }
184 
185     /***
186      * Returns all keys
187      *
188      * @return all keys
189      */
190     public Enumeration getKeys()
191     {
192         return keys.keys();
193     }
194 
195     /***
196      * Returns the subcommand by its name
197      * If more subcommands with the same name exists, the first will be returned
198      *
199      * @param key the subcommands name
200      *
201      * @return the subcommand
202      */
203     public Command getSubCommandByName(String key)
204     {
205         Command cmd;
206         for (int i = 0; i < subCommands.size(); i++) {
207         	cmd =(Command)subCommands.get(i); 
208         	if (cmd.getCommand().equalsIgnoreCase(key)) {
209         		return cmd;
210         	}
211         }
212         return null;
213     }
214 
215     /***
216      * Returns all subcommands (its names)
217      *
218      * @return the subcommands
219      */
220     public Vector getSubCommands()
221     {
222         return subCommands;
223     }
224 
225     /***
226      * Adds a key with its argument
227      *
228      * @param key the key
229      * @param arg the argument
230      */
231     public void addKey(String key, String arg)
232     {
233         keys.put(key, arg);
234     }
235 
236     /***
237      * Adds a key without its argument
238      *
239      * @param key the key
240      */
241     public void addKey(String key)
242     {
243         keys.put(key, "empty");
244     }
245 
246     /***
247      * Adds a subcommand
248      *
249      * @param command the subcommand
250      */
251     public void addSubCommand(Command command)
252     {
253         subCommands.add(command);
254     }
255 
256     /***
257      * Returns if command has keys
258      *
259      * @return hasKeys
260      */
261     public boolean hasKeys()
262     {
263         return !((keys.size() == 0) ||
264         ((keys.size() == 1) && (keys.get("COMMAND") != null)));
265     }
266 
267     /***
268      * Parses the command from a String (GiFT-UI-protocol)
269      *
270      * @param cmd the String
271      */
272     public boolean parse(String cmd)
273     {
274         return parseRecursive(this, new StringCharacterIterator(cmd));
275     }
276 
277     /***
278      * Returns the command as String (GiFT-UI-protocol)
279      *
280      * @return the commandstr
281      */
282     public String print()
283     {
284         return print(true);
285     }
286 
287     /***
288      * Debugdump
289      *
290      * @return String
291      */
292     public String toString()
293     {
294         String str = "GiFTCommand " + command + "\n";
295         Enumeration en = keys.keys();
296         String key;
297 
298         while (en.hasMoreElements()) {
299             key = (String) en.nextElement();
300             str += ("  + " + key + " = " + keys.get(key) + "\n");
301         }
302 
303 		for (int i = 0; i < subCommands.size(); i++) {
304             str += "--- sub ---\n";
305             str += subCommands.get(i);
306             str += "--- /sub ---\n";
307 		}
308 
309         return str;
310     }
311 
312     private String escape(String s)
313     {
314         StringBuffer buffer = new StringBuffer(s.length());
315 
316         for (int i = 0; i < s.length(); i++) {
317             char ch = s.charAt(i);
318 
319             switch (ch) {
320             case '(':
321                 buffer.append('//');
322                 buffer.append(ch);
323 
324                 break;
325 
326             case ')':
327                 buffer.append('//');
328                 buffer.append(ch);
329 
330                 break;
331 
332             case '{':
333                 buffer.append('//');
334                 buffer.append(ch);
335 
336                 break;
337 
338             case '}':
339                 buffer.append('//');
340                 buffer.append(ch);
341 
342                 break;
343 
344             case '[':
345                 buffer.append('//');
346                 buffer.append(ch);
347 
348                 break;
349 
350             case ']':
351                 buffer.append('//');
352                 buffer.append(ch);
353 
354                 break;
355 
356             case ';':
357                 buffer.append('//');
358                 buffer.append(ch);
359 
360                 break;
361 
362             case '//':
363                 buffer.append('//');
364                 buffer.append(ch);
365 
366                 break;
367 
368             default:
369                 buffer.append(ch);
370             }
371         }
372 
373         return buffer.toString();
374     }
375 
376     private boolean parseRecursive(Command cmd, StringCharacterIterator sci)
377     {
378         String currKey = null;
379         char curr;
380 
381         while (sci.getIndex() < sci.getEndIndex()) {
382             switch (curr = sci.current()) {
383             case ' ':
384             case '\t':
385             case '\r':
386             case '\n':
387                 sci.next();
388 
389                 continue;
390 
391             case '(':
392 
393                 StringBuffer argBuf = new StringBuffer();
394 
395                 for (char ch = sci.next();
396                         (ch != ')') && (ch != CharacterIterator.DONE);
397                         ch = sci.next()) {
398                     if (ch == '//') {
399                         sci.next();
400                     }
401 
402                     argBuf.append(ch);
403                 }
404 
405                 if (currKey == null) {
406                     cmd.setCommandArgument(argBuf.toString());
407                 } else {
408                     cmd.addKey(currKey, argBuf.toString());
409                     currKey = null;
410                 }
411 
412                 sci.next(); // skip ')'
413 
414                 continue;
415 
416             case '{':
417                 sci.next(); // skip '{'
418 
419                 Command subCommand = new Command(currKey);
420 
421                 if (this.parseRecursive(subCommand, sci) == false) {
422                     return false;
423                 }
424 
425                 sci.next(); // skip '}'
426                 cmd.addSubCommand(subCommand);
427 
428                 continue;
429 
430             case '}':
431             case ';':
432                 return true;
433 
434             default:
435 
436                 StringBuffer buf = new StringBuffer();
437 
438                 for (char ch = sci.current(); ch != CharacterIterator.DONE;
439                         ch = sci.next()) {
440                     if (ch == ';') {
441                         break;
442                     }
443 
444                     if (ch == '(') {
445                         break;
446                     }
447 
448                     if (ch == '{') {
449                         break;
450                     }
451 
452                     if (Character.isWhitespace(ch)) {
453                         break;
454                     }
455 
456                     if (ch == '//') {
457                         sci.next();
458                     }
459 
460                     buf.append(ch);
461                 }
462 
463                 if (cmd.command == null) {
464                     cmd.command = buf.toString();
465                 } else {
466                     currKey = buf.toString();
467                 }
468 
469                 continue;
470             }
471         }
472 
473         return false;
474     }
475 
476     private String print(boolean root)
477     {
478         String str = "\n";
479 
480         if (root) {
481             str += escape(command.toUpperCase());
482         } else {
483             str += escape(command);
484         }
485 
486         if (getCommandArgument() != null) {
487             str += ("(" + escape(getCommandArgument()) + ")");
488         }
489 
490         if (!root && keys.isEmpty()) {
491             return str;
492         }
493 
494         if (!root) {
495             str += "{\n";
496         }
497 
498         Enumeration en = keys.keys();
499 
500         while (en.hasMoreElements()) {
501             String key = (String) en.nextElement();
502             String keymod = (getKeyModifier(key) == null) ? ""
503                                                           : (" [" +
504                 getKeyModifier(key) + "] ");
505             str += (" " + escape(key) + escape(keymod) + "(" +
506             escape((String) keys.get(key)) + ")\n");
507         }
508 
509 		for (int i = 0; i < subCommands.size(); i++) {
510             str += ((Command) subCommands.get(i)).print(false);
511 		}
512 
513         str += (root ? ";\n" : "}");
514 
515         return str;
516     }
517 }