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

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

Updated mail stuff and networking stuff!!

File size: 25.6 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}
Note: See TracBrowser for help on using the repository browser.