source: trunk/src/org/expeditee/actions/Actions.java@ 306

Last change on this file since 306 was 306, checked in by ra33, 16 years ago

Added some HELP actions
More mail stuff... and networking stuff
Can now save frames and send messages to peers
Also version control prevent versions from being lost

File size: 26.2 KB
Line 
1package org.expeditee.actions;
2
3import java.awt.GraphicsEnvironment;
4import java.io.File;
5import java.lang.reflect.Constructor;
6import java.lang.reflect.Method;
7import java.lang.reflect.Modifier;
8import java.net.URL;
9import java.util.ArrayList;
10import java.util.Collection;
11import java.util.Enumeration;
12import java.util.HashMap;
13import java.util.LinkedList;
14import java.util.List;
15import java.util.Set;
16import java.util.jar.JarFile;
17import java.util.zip.ZipEntry;
18
19import org.expeditee.agents.Agent;
20import org.expeditee.gui.DisplayIO;
21import org.expeditee.gui.Frame;
22import org.expeditee.gui.FrameGraphics;
23import org.expeditee.gui.FrameIO;
24import org.expeditee.gui.FrameUtils;
25import org.expeditee.gui.FreeItems;
26import org.expeditee.gui.MessageBay;
27import org.expeditee.io.Conversion;
28import org.expeditee.io.Logger;
29import org.expeditee.items.Item;
30import org.expeditee.items.ItemUtils;
31import org.expeditee.items.Text;
32import org.expeditee.simple.SString;
33
34/**
35 * The Action class is used to launch Actions and Agents.
36 *
37 * This class checks all class files in the same directory, and reads in and
38 * adds all the methods from them. The methods are stored in a Hashtable so that
39 * the lowercase method names can be mapped to the correctly capatilized method
40 * names (to provide case-insensitivity)
41 *
42 * When adding an action to a class in the actions folder the following must be
43 * considered:
44 * <li> If the first parameter is of type Frame, the current frame will be
45 * passed as a parameter.
46 * <li> If the next param is of type Item the item on the end of the cursor will
47 * be passed or the item that was clicked to execute the action if nothing is on
48 * the end of the cursor. current frame or item.</li>
49 * <li> If there are multiple overloads for the same method they should be
50 * declared in order of the methods with the most parameteres to least
51 * parameters.</li>
52 */
53public class Actions {
54
55 private static final String INVALID_PARAMETERS_ERROR = "Invalid parameters for agent: "; //$NON-NLS-1$
56
57 // the currently running agent (if there is one)
58 private static Agent _Agent = null;
59
60 // maps lower case method names to the method
61 private static HashMap<String, Method> _Actions = new HashMap<String, Method>();
62
63 // map lower case fonts to capitalized fonts
64 private static HashMap<String, String> _Fonts = new HashMap<String, String>();
65
66 // maps lower case JAG class names to capitalized JAG full class names
67 private static HashMap<String, String> _JAGs = new HashMap<String, String>();
68
69 // maps lower case IW class names to capitalized IW names
70 private static HashMap<String, String> _IWs = new HashMap<String, String>();
71
72 public static final String ROOT_PACKAGE = "org.expeditee.";
73
74 // Package and class file locations
75 private static final String ACTIONS_PACKAGE = ROOT_PACKAGE + "actions.";
76
77 private static final String AGENTS_PACKAGE = ROOT_PACKAGE + "agents.";
78
79 private static final String WIDGET_PACKAGE = ROOT_PACKAGE
80 + "items.widgets.";
81
82 private static final String CHARTS_PACKAGE = ROOT_PACKAGE
83 + "items.widgets.charts.";
84
85 private static final String NAVIGATIONS_CLASS = ROOT_PACKAGE
86 + "actions.NavigationActions";
87
88 public static Class[] getClasses(String pckgname)
89 throws ClassNotFoundException {
90 ArrayList<Class> classes = new ArrayList<Class>();
91 // Get a File object for the package
92 File directory = null;
93 // Must be a forward slash for loading resources
94 String path = pckgname.replace('.', '/');
95 // System.out.println("Get classes: " + path);
96 try {
97 ClassLoader cld = Thread.currentThread().getContextClassLoader();
98 if (cld == null) {
99 throw new ClassNotFoundException("Can't get class loader.");
100 }
101 URL resource = null;
102 try {
103 Enumeration<URL> resources = cld.getResources(path);
104 while (resources.hasMoreElements()) {
105 URL url = resources.nextElement();
106 // Ingore the classes in the test folder when we are running
107 // the program from Eclipse
108 // This doesnt apply when running directly from the jar
109 // because the test classes are not compiled into the jar.
110 // TODO change this so it is only done when running from
111 // Eclipse... if it causes problems again!!
112 // if (!url.toString().toLowerCase().contains("/tests/")) {
113 resource = url;
114 // break;
115 // }
116 }
117 } catch (Exception e) {
118
119 }
120 if (resource == null) {
121 throw new ClassNotFoundException("No resource for " + path);
122 }
123 directory = new File(resource.getFile());
124 } catch (NullPointerException x) {
125 throw new ClassNotFoundException(pckgname + " (" + directory
126 + ") does not appear to be a valid package");
127 }
128 // System.out.println("Path:" + directory.getPath());
129 int splitPoint = directory.getPath().indexOf('!');
130 if (splitPoint > 0) {
131 try {
132 String jarName = directory.getPath().substring(
133 "file:".length(), splitPoint);
134 // Windows HACK
135 if (jarName.indexOf(":") >= 0)
136 jarName = jarName.substring(1);
137
138 if (jarName.indexOf("%20") > 0) {
139 jarName = jarName.replace("%20", " ");
140 }
141 // System.out.println("JarName:" + jarName);
142 JarFile jarFile = new JarFile(jarName);
143
144 Enumeration entries = jarFile.entries();
145 int classCount = 0;
146 while (entries.hasMoreElements()) {
147 ZipEntry entry = (ZipEntry) entries.nextElement();
148 String className = entry.getName();
149 if (className.startsWith(path)) {
150 if (className.endsWith(".class")
151 && !className.contains("$")) {
152 classCount++;
153 // The forward slash below is a forwards slash for
154 // both windows and linux
155 classes.add(Class.forName(className.substring(0,
156 className.length() - 6).replace('/', '.')));
157 }
158 }
159 }
160 jarFile.close();
161 // System.out.println("Loaded " + classCount + " classes from "
162 // + pckgname);
163
164 } catch (Exception e) {
165 e.printStackTrace();
166 }
167
168 } else {
169
170 if (directory.exists()) {
171 // Get the list of the files contained in the package
172 String[] files = directory.list();
173 for (int i = 0; i < files.length; i++) {
174 // we are only interested in .class files
175 if (files[i].endsWith(".class") && !files[i].contains("$")
176 && !files[i].equals("Actions.class")) {
177 // removes the .class extension
178 classes
179 .add(Class.forName(pckgname
180 + files[i].substring(0, files[i]
181 .length() - 6)));
182 }
183 }
184 } else {
185 throw new ClassNotFoundException(pckgname + " (" + directory
186 + ") does not appear to be a valid package");
187 }
188 }
189 Class[] classesA = new Class[classes.size()];
190 classes.toArray(classesA);
191 return classesA;
192 }
193
194 /**
195 * Clears out the Action and JAG Hashtables and refills them. Normally this
196 * is only called once when the system starts.
197 *
198 * @return a warning message if there were any problems loading agents or
199 * actions.
200 */
201 public static Collection<String> Init() {
202
203 Collection<String> warnings = new LinkedList<String>();
204 Class[] classes;
205
206 try {
207 classes = getClasses(AGENTS_PACKAGE);
208
209 for (int i = 0; i < classes.length; i++) {
210 String name = classes[i].getSimpleName();
211 // maps lower case name to correct capitalised name
212 _JAGs.put(name.toLowerCase(), classes[i].getName());
213 }
214
215 classes = getClasses(WIDGET_PACKAGE);
216
217 for (int i = 0; i < classes.length; i++) {
218 String name = classes[i].getSimpleName();
219 // maps lower case name to correct capitalised name
220 _IWs.put(name.toLowerCase(), WIDGET_PACKAGE + name);
221 }
222
223 classes = getClasses(CHARTS_PACKAGE);
224
225 for (int i = 0; i < classes.length; i++) {
226 String name = classes[i].getSimpleName();
227 // maps lower case name to correct capitalised name
228 _IWs.put("charts." + name.toLowerCase(), CHARTS_PACKAGE + name);
229 }
230 } catch (Exception e) {
231 warnings.add("You must have Java 1.5 or higher to run Expeditee");
232 warnings.add(e.getMessage());
233 }
234
235 try {
236 classes = getClasses(ACTIONS_PACKAGE);
237
238 for (int i = 0; i < classes.length; i++) {
239 String name = classes[i].getSimpleName();
240 // Ignore the test classes
241 if (name.toLowerCase().contains("test"))
242 continue;
243 // read in all the methods from the class
244 try {
245 // System.out.println(name)
246 LoadMethods(Class.forName(ACTIONS_PACKAGE + name));
247 } catch (ClassNotFoundException e) {
248 Logger.Log(e);
249 e.printStackTrace();
250 }
251 }
252 } catch (Exception e) {
253 warnings.add(e.getMessage());
254 }
255 return warnings;
256 }
257
258 /**
259 * Temporary, if a plugin system is devised then this would porbably become
260 * redundant. For now this allows external agents to be included.
261 *
262 * @param fullClassNames
263 * A set of full class names, that is, the class package and
264 * name. For example" "org.myplugin.agents.SerializedSearch"
265 *
266 * @return A collection of classes their were omitted because either there
267 * was a name clash with existing agents or did not exist. i.e. is
268 * completely successful this will be empty. Never null.
269 *
270 * @throws NullPointerException
271 * If fullClassNames is null.
272 *
273 */
274 public static Collection<String> addAgents(Set<String> fullClassNames) {
275 if (fullClassNames == null)
276 throw new NullPointerException("fullClassNames");
277
278 List<String> omittedAgents = new LinkedList<String>();
279
280 for (String fullName : fullClassNames) {
281
282 if (fullName == null || fullName.length() == 0)
283 continue;
284
285 boolean didAdd = false;
286
287 try {
288 // Does the class even exist?
289 Class c = Class.forName(fullName);
290
291 String name = c.getSimpleName().toLowerCase();
292
293 if (!_JAGs.containsKey(name)) {
294
295 _JAGs.put(name, fullName);
296 didAdd = true;
297
298 }
299
300 } catch (ClassNotFoundException e) { // Nope it does not exist
301 e.printStackTrace();
302 }
303
304 if (!didAdd)
305 omittedAgents.add(fullName);
306
307 }
308
309 return omittedAgents;
310 }
311
312 /**
313 * Loads all the Methods that meet the requirements checked by MethodCheck
314 * into the hashtable.
315 *
316 * @param c
317 * The Class to load the Methods from.
318 */
319 public static void LoadMethods(Class c) {
320 assert (c != null);
321
322 // list of methods to test
323 Method[] toLoad = c.getMethods();
324
325 for (Method m : toLoad) {
326 // only allow methods with the right modifiers
327 if (MethodCheck(m)) {
328 String lowercaseName = m.getName().toLowerCase();
329 if (!(_Actions.containsKey(lowercaseName)))
330 _Actions.put(lowercaseName, m);
331 else {
332 int i = 0;
333 while (_Actions.containsKey(lowercaseName + i))
334 i++;
335
336 _Actions.put(lowercaseName + i, m);
337 }
338
339 }
340 }
341 }
342
343 /**
344 * Checks if the given Method corresponds to the restrictions of Action
345 * commands, namely: Declared (not inherited), Public, and Static, with a
346 * void return type.
347 *
348 * @param m
349 * The Method to check
350 * @return True if the Method meets the above conditions, false otherwise.
351 */
352 private static boolean MethodCheck(Method m) {
353 int mods = m.getModifiers();
354
355 // check the method is declared (not inherited)
356 if ((mods & Method.DECLARED) != Method.DECLARED)
357 return false;
358
359 // check the method is public
360 if ((mods & Modifier.PUBLIC) != Modifier.PUBLIC)
361 return false;
362
363 // check the method is static
364 if ((mods & Modifier.STATIC) != Modifier.STATIC)
365 return false;
366
367 // if we have not returned yet, then the tests have all passed
368 return true;
369 }
370
371 /**
372 * Performs the given action command. The source Frame and Item are given
373 * because they are required by some actions. Note that the source frame
374 * does not have to be the Item's parent Frame.
375 *
376 * @param source
377 * The Frame that the action should apply to
378 * @param launcher
379 * The Item that has the action assigned to it
380 * @param command
381 * The action to perform
382 */
383 public static Object PerformAction(Frame source, Item launcher,
384 String command) throws Exception {
385 // if (!command.equalsIgnoreCase("Restore"))
386 // FrameIO.SaveFrame(source, false);
387 // TODO make restore UNDO the changes made by the last action
388
389 // separate method name and parameter names
390 String mname = getName(command);
391 command = command.substring(mname.length()).trim();
392 // If no params are provided get them from a text item on the cursor
393 if (command.length() == 0 && launcher instanceof Text
394 && launcher.isFloating()) {
395 command = launcher.getText();
396 }
397
398 // Strip off the @ from annotation items
399 if (mname.startsWith("@"))
400 mname = mname.substring(1);
401
402 mname = mname.trim();
403 String lowercaseName = mname.toLowerCase();
404 // check for protection on frame
405 if (ItemUtils.ContainsTag(source.getItems(), "@No" + mname)) {
406 throw new RuntimeException("Frame is protected by @No" + mname
407 + " tag.");
408 }
409
410 // retrieve methods that match the name
411 Method toRun = _Actions.get(lowercaseName);
412
413 // if this is not the name of a method, it may be the name of an agent
414 if (toRun == null) {
415 LaunchAgent(mname, command, source, launcher);
416 return null;
417 }
418
419 // Need to save the frame if we are navigating away from it so we dont
420 // loose changes
421 if (toRun.getDeclaringClass().getName().equals(NAVIGATIONS_CLASS)) {
422 FrameIO.SaveFrame(DisplayIO.getCurrentFrame());
423 }
424
425 // if there are duplicate methods with the same name
426 List<Method> possibles = new LinkedList<Method>();
427 possibles.add(toRun);
428 int i = 0;
429 while (_Actions.containsKey(lowercaseName + i)) {
430 possibles.add(_Actions.get(lowercaseName + i));
431 i++;
432 }
433
434 for (Method possible : possibles) {
435 // try first with the launching item as a parameter
436
437 // run method
438 try {
439 // convert parameters to objects and get the method to invoke
440 Object[] parameters = CreateObjects(possible, source, launcher,
441 command);
442 // Check that there are the same amount of params
443 if (parameters == null) {
444 continue;
445 }
446
447 return possible.invoke(null, parameters);
448 } catch (Exception e) {
449 Logger.Log(e);
450 e.printStackTrace();
451 }
452 }
453 // If the actions was not found... then it is run as an agent
454 assert (possibles.size() > 0);
455 throw new RuntimeException("Incorrect parameters for " + mname);
456 }
457
458 /**
459 * Launches an agent with the given name, and passes in the given parameters
460 *
461 * @param name
462 * The name of the JAG to load
463 * @param parameters
464 * The parameters to pass to the JAG
465 * @param source
466 * The starting Frame that the JAG is being launched on
467 */
468 private static void LaunchAgent(String name, String parameters,
469 Frame source, Item clicked) throws Exception {
470 // Use the correct case version for printing error messages
471 String nameWithCorrectCase = name;
472 name = name.toLowerCase();
473
474 String fullClassName = AGENTS_PACKAGE + name;
475
476 try {
477 // check for stored capitalisation
478 if (_JAGs.containsKey(name)) {
479 fullClassName = _JAGs.get(name);
480 } else if (name.endsWith("tree")) {
481 parameters = name.substring(0, name.length() - "tree".length())
482 + " " + parameters;
483 fullClassName = AGENTS_PACKAGE + "writetree";
484
485 } else if (name.endsWith("frame")) {
486 parameters = name
487 .substring(0, name.length() - "frame".length())
488 + " " + parameters;
489 fullClassName = AGENTS_PACKAGE + "writeframe";
490 }
491
492 // load the JAG class
493 Class agentClass = Class.forName(fullClassName);
494
495 // get the constructor for the JAG class
496 Constructor con = null;
497 Constructor[] constructors = agentClass.getConstructors();
498 Object[] params = null;
499
500 parameters = parameters.trim();
501 // determine correct parameters for constructor
502 for (Constructor c : constructors) {
503 Class[] paramTypes = c.getParameterTypes();
504 int paramCount = paramTypes.length;
505 if (paramCount > 0 && parameters.length() > 0) {
506 params = new Object[paramCount];
507 String[] paramStrings = parameters.split("\\s+");
508 if (paramCount != paramStrings.length)
509 continue;
510 for (int i = 0; i < paramCount; i++) {
511 SString nextParam = new SString(paramStrings[i]);
512 try {
513 params[i] = null;
514 if (paramTypes[i].equals(int.class)
515 || paramTypes[i].equals(Integer.class)) {
516 params[i] = nextParam.integerValue().intValue();
517 } else if (paramTypes[i].equals(long.class)
518 || paramTypes[i].equals(Long.class)) {
519 params[i] = nextParam.integerValue();
520 } else if (paramTypes[i].equals(double.class)
521 || paramTypes[i].equals(Double.class)) {
522 params[i] = nextParam.doubleValue();
523 } else if (paramTypes[i].equals(float.class)
524 || paramTypes[i].equals(Float.class)) {
525 params[i] = nextParam.doubleValue()
526 .floatValue();
527 } else if (paramTypes[i].equals(boolean.class)
528 || paramTypes[i].equals(Boolean.class)) {
529 params[i] = nextParam.booleanValue();
530 } else if (paramTypes[i].equals(String.class)) {
531 params[i] = nextParam.stringValue();
532 } else {
533 continue;
534 }
535 } catch (Exception e) {
536 continue;
537 }
538 }
539 con = c;
540 break;
541 } else if (c.getParameterTypes().length == 0 && con == null) {
542 con = c;
543 params = null;
544 }
545 }
546
547 // if there is no constructor, return
548 if (con == null) {
549 throw new RuntimeException(INVALID_PARAMETERS_ERROR
550 + nameWithCorrectCase);
551 }
552
553 // create the JAG
554 Agent toLaunch = (Agent) con.newInstance(params);
555
556 LaunchAgent(toLaunch, source, clicked);
557
558 } catch (ClassNotFoundException cnf) {
559 _Agent = null;
560 throw new RuntimeException(nameWithCorrectCase
561 + "' is not an action or agent.");
562 }
563 }
564
565 /**
566 * Launches an agent from a aleady instantiated object.
567 *
568 * @param agent
569 * The agent to launch. Must not be null.
570 *
571 * @param source
572 * The calling frame that launched it. Must not be null.
573 *
574 * @param itemParam
575 * The item paremeter for the agent.
576 *
577 * @throws NullPointerException
578 * if any of the arguments are null.
579 */
580 public static void LaunchAgent(Agent agent, Frame source, Item itemParam) {
581
582 if (agent == null)
583 throw new NullPointerException("agent");
584 if (source == null)
585 throw new NullPointerException("source");
586 // if (itemParam == null) throw new NullPointerException("itemParam");
587
588 String nameWithCorrectCase = agent.getClass().getSimpleName();
589
590 try {
591
592 // create the JAG
593 _Agent = agent;
594
595 Thread t = new Thread(_Agent);
596 t.setPriority(Thread.MIN_PRIORITY);
597
598 if (FreeItems.textOnlyAttachedToCursor()) {
599 itemParam = FreeItems.getItemAttachedToCursor();
600 }
601
602 // check for errors during initialisation
603 if (!_Agent.initialise(source, itemParam)) {
604 _Agent = null;
605 throw new RuntimeException("Error initialising agent: "
606 + nameWithCorrectCase);
607 }
608
609 // save the current frame (if necesssary)
610 // TODO make this nicer... ie. make Format an action rather than an
611 // agent and save frames only before running agents
612 if (!nameWithCorrectCase.equalsIgnoreCase("format")
613 && !nameWithCorrectCase.equalsIgnoreCase("sort")) {
614 FrameUtils.LeavingFrame(source);
615 }
616
617 if (_Agent.hasResultString()) {
618 // Just run the agent on this thread... dont run it in the
619 // background
620 t.run();
621 String result = _Agent.toString();
622 // Attach the result to the cursor
623 if (FreeItems.textOnlyAttachedToCursor()) {
624 Item resultItem = FreeItems.getItemAttachedToCursor();
625 resultItem.setText(result);
626 }
627 // if there is a completion frame, then display it to the user
628 } else {
629 t.start();
630 if (_Agent.hasResultFrame()) {
631 // TODO We want to be able to navigate through the frames as
632 // the results are loading
633 Frame next = _Agent.getResultFrame();
634 FrameUtils.DisplayFrame(next, true);
635 }
636 }
637 } catch (Exception e) {
638 _Agent = null;
639 e.printStackTrace();
640 throw new RuntimeException("Error creating Agent: '"
641 + nameWithCorrectCase + "'");
642 }
643 FrameGraphics.refresh(false);
644 }
645
646 /**
647 * Used to determine if the previously launched agent is still executing.
648 *
649 * @return True if the last Agent is still executing, False otherwise.
650 */
651 public static boolean isAgentRunning() {
652 if (_Agent != null)
653 return _Agent.isRunning();
654
655 return false;
656 }
657
658 /**
659 * Stops the currently running Agent (If there is one) by calling
660 * Agent.stop(). Note: This may not stop the Agent immediately, but the
661 * Agent should terminate as soon as it is safe to do so.
662 */
663 public static void stopAgent() {
664 if (_Agent != null && _Agent.isRunning()) {
665 MessageBay.errorMessage("Stopping Agent...");
666 _Agent.stop();
667 }
668 }
669
670 public static void interruptAgent() {
671 if (_Agent != null) {
672 _Agent.interrupt();
673 }
674 }
675
676 /**
677 * Converts the given String of values into an array of Objects
678 *
679 * @param launcher
680 * The Item used to launch the action, it may be required as a
681 * parameter
682 * @param values
683 * A list of space separated String values to convert to objects
684 * @return The created array of Objects
685 */
686 public static Object[] CreateObjects(Method method, Frame source,
687 Item launcher, String values) {
688 // The parameter types that should be created from the given String
689 Class[] paramTypes = method.getParameterTypes();
690
691 int paramCount = paramTypes.length;
692 // if the method has no parameters
693 if (paramCount == 0)
694 return new Object[0];
695
696 Object[] objects = new Object[paramCount];
697 int ind = 0;
698
699 // if the first class in the list is a frame or item, it is the source
700 // or launcher
701 // length must be at least one if we are still running
702 if (paramTypes[ind] == Frame.class) {
703 objects[ind] = source;
704 ind++;
705 }
706
707 // Check if the second item is an item
708 if (paramCount > ind && Item.class.isAssignableFrom(paramTypes[ind])) {
709 objects[ind] = launcher;
710 ind++;
711 }// If there is stuff on the cursor use it for the rest of the params
712 else if (launcher != null && launcher.isFloating()) {
713 values = launcher.getText();
714 }
715
716 String param = values;
717 // convert the rest of the objects
718 for (; ind < objects.length; ind++) {
719 // check if its the last param and combine
720 if (values.length() > 0 && ind == objects.length - 1) {
721 param = values.trim();
722 // check if its a string
723 if (param.length() > 0 && param.charAt(0) == '"') {
724 int endOfString = param.indexOf('"', 1);
725 if (endOfString > 0) {
726 param = param.substring(1, endOfString);
727 }
728 }
729 } else {// strip off the next value
730 param = ParseValue(values);
731 values = RemainingParams(values);
732 }
733 // convert the value to an object
734 try {
735 Object o = Conversion.Convert(paramTypes[ind], param);
736 if (o == null)
737 return null;
738 objects[ind] = o;
739 } catch (Exception e) {
740 return null;
741 }
742 }
743
744 return objects;
745 }
746
747 /**
748 * Returns a string containing the remaining params after ignoring the first
749 * one.
750 *
751 * @param params
752 * a space sparated list of N parameters
753 * @return the remaining N - 1 parameters
754 */
755 public static String RemainingParams(String params) {
756 if (params.length() == 0)
757 return null;
758
759 // remove leading and trailing spaces
760 params = params.trim();
761
762 // if there are no more parameters, we are done
763 if (params.indexOf(" ") < 0) {
764 return "";
765 }
766
767 // Check if we have a string parameter
768 if (params.charAt(0) == '"') {
769 int endOfString = params.indexOf('"', 1);
770 if (endOfString > 0) {
771 if (endOfString > params.length())
772 return "";
773 return params.substring(endOfString + 1).trim();
774 }
775 }
776
777 return params.substring(params.indexOf(" ")).trim();
778 }
779
780 /**
781 * Returns the first value in the space separated String of parameters
782 * passed in. Strings are enclosed in double quotes.
783 *
784 * @param params
785 * The String of space separated values
786 * @return The first value in the String
787 */
788 public static String ParseValue(String params) {
789 if (params.length() == 0)
790 return null;
791
792 // remove leading and trailing spaces
793 String param = params.trim();
794
795 // Check if we have a string parameter
796 if (param.charAt(0) == '"') {
797 int endOfString = param.indexOf('"', 1);
798 if (endOfString > 0)
799 return param.substring(1, endOfString);
800 }
801
802 // if there are no more parameters, we are done
803 if (param.indexOf(" ") < 0) {
804 return param;
805 }
806
807 return param.substring(0, param.indexOf(" "));
808 }
809
810 /**
811 * Separates the name of the given command from any parameters and returns
812 * them
813 *
814 * @param command
815 * The String to separate out the Action or Agent name from
816 * @return The name of the Action of Agent with parameters stripped off
817 */
818 private static String getName(String command) {
819 if (command.indexOf(" ") < 0)
820 return command;
821
822 return command.substring(0, command.indexOf(" "));
823 }
824
825 /**
826 * Gets an uncapitalized font name and returns the capitalized font name.
827 * The capitalized form can be used with the Font.decoded method to get a
828 * corresponding Font object.
829 *
830 * @param fontName
831 * a font name in mixed case
832 * @return the correct capitalized form of the font name
833 */
834 public static String getCapitalizedFontName(String fontName) {
835 // Initialize the fonts if they have not already been loaded
836 initFonts();
837 return _Fonts.get(fontName.toLowerCase());
838 }
839
840 /**
841 * Initialise the fontsList if it has not been done already
842 */
843 private static void initFonts() {
844 if (_Fonts.size() == 0) {
845 String[] availableFonts = GraphicsEnvironment
846 .getLocalGraphicsEnvironment()
847 .getAvailableFontFamilyNames();
848 for (String s : availableFonts) {
849 _Fonts.put(s.toLowerCase(), s);
850 }
851 }
852 }
853
854 public static HashMap<String, String> getFonts() {
855 initFonts();
856 return _Fonts;
857 }
858
859 public static Object PerformActionCatchErrors(Frame current, Item launcher,
860 String command) {
861 try {
862 return PerformAction(current, launcher, command);
863 } catch (Exception e) {
864 MessageBay.errorMessage(e.getMessage());
865 }
866 return null;
867 }
868
869 /**
870 * Gets the full class path for a widget with a given case insensitive name.
871 *
872 * @param widgetName
873 * @return
874 */
875 public static String getClassName(String widgetName) {
876 return _IWs.get(widgetName.toLowerCase());
877 }
878
879 static List<String> getActions() {
880 List<String> actionNames = new LinkedList<String>();
881 for (Method m : _Actions.values()) {
882 StringBuilder sb = new StringBuilder();
883 sb.append(m.getName());
884 for (Class c : m.getParameterTypes()) {
885 sb.append(" ").append(c.getSimpleName());
886 }
887 actionNames.add(sb.toString());
888 }
889
890 return actionNames;
891 }
892
893 static List<String> getAgents() {
894 List<String> agentNames = new LinkedList<String>();
895
896 for (String s : _JAGs.values()) {
897 agentNames.add(s.substring(s.lastIndexOf('.') + 1));
898 }
899
900 return agentNames;
901 }
902}
Note: See TracBrowser for help on using the repository browser.