source: trunk/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java@ 8853

Last change on this file since 8853 was 8782, checked in by mdewsnip, 19 years ago

Removed some unused imports.

  • Property svn:keywords set to Author Date Id Revision
File size: 36.0 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.io.*;
32import java.net.*;
33import java.util.*;
34import java.util.jar.*;
35import javax.swing.*;
36import javax.swing.event.*;
37import org.apache.xerces.parsers.*;
38import org.greenstone.gatherer.Configuration;
39import org.greenstone.gatherer.DebugStream;
40import org.greenstone.gatherer.Dictionary;
41import org.greenstone.gatherer.Gatherer;
42import org.greenstone.gatherer.gui.GComboBox;
43import org.greenstone.gatherer.gui.GLIButton;
44import org.greenstone.gatherer.util.StaticStrings;
45import org.greenstone.gatherer.util.Utility;
46import org.greenstone.gatherer.util.XMLTools;
47import org.w3c.dom.*;
48import org.xml.sax.*;
49
50/** This class is responsible for keeping track of all the classifiers assigned to this collection, and providing methods for adding and removing them.
51 * @author John Thompson, Greenstone Digital Library, University of Waikato
52 * @version 2.3
53 */
54public class ClassifierManager
55 extends DOMProxyListModel {
56
57 /** A list of known, but currently unassigned, classifiers. */
58 private ArrayList library = null;
59 /** The controls for editing the contents of this manager. */
60 private Control controls = null;
61
62 private DOMProxyListModel model;
63
64 /** Constructor.
65 * @see org.greenstone.gatherer.cdm.DynamicListModel
66 * @see org.greenstone.gatherer.collection.CollectionManager
67 */
68 public ClassifierManager() {
69 super(CollectionDesignManager.collect_config.getDocumentElement(), CollectionConfiguration.CLASSIFY_ELEMENT, new Classifier());
70 this.model = this;
71 DebugStream.println("ClassifierManager: " + getSize() + " classifiers parsed.");
72 // Reload/Create the library
73 loadClassifiers();
74 saveClassifiers();
75 }
76
77 /** Method to add a new classifier to library.
78 * @param classifier The new <strong>Classifier</strong>.
79 * @see org.greenstone.gatherer.cdm.DynamicListModel
80 */
81 private void addClassifier(Classifier classifier) {
82 if(!library.contains(classifier)) {
83 library.add(classifier);
84 }
85 }
86
87 /** Method to assign a classifier.
88 * @param classifier The base <strong>Classifier</strong> to assign.
89 * @see org.greenstone.gatherer.cdm.DynamicListModel
90 */
91 private void assignClassifier(Classifier classifier) {
92 if(!contains(classifier)) {
93 Element element = classifier.getElement();
94 // Locate where we should insert this new classifier.
95 Node target_node = CollectionConfiguration.findInsertionPoint(element);
96 add(root, classifier, target_node);
97 Gatherer.c_man.configurationChanged();
98 }
99 }
100
101 public static boolean clearClassifierCache() {
102
103 DebugStream.println("deleting classifiers.dat");
104 File class_file = new File(Utility.getGLIUserFolder(), "classifiers.dat");
105 if (class_file.exists()) {
106 return Utility.delete(class_file);
107 }
108 return true;
109 }
110 /** Destructor.
111 * @see org.greenstone.gatherer.Gatherer
112 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
113 * @see org.greenstone.gatherer.cdm.DynamicListModel
114 */
115 public void destroy() {
116 if(controls != null) {
117 controls.destroy();
118 controls = null;
119 }
120 library.clear();
121 library = null;
122 }
123
124 public Classifier getBaseClassifier(String name) {
125 int library_size = library.size();
126 for(int i = 0; i < library_size; i++) {
127 Classifier classifier = (Classifier) library.get(i);
128 if(classifier.getName().equals(name)) {
129 return classifier;
130 }
131 }
132 // No success.
133 return null;
134 }
135
136 /** Method to retrieve the classifier with the given index.
137 * @param index The index of the desired classifier as an <i>int</i>.
138 * @return The requested Classifier or <i>null</i> if no such classifier exists.
139 */
140 public Classifier getClassifier(int index) {
141 if(0 <= index && index < getSize()) {
142 return (Classifier) getElementAt(index);
143 }
144 return null;
145 }
146
147 /** Method to retrieve the control for this manager.
148 * @return the Control for editing classifiers
149 */
150 public Control getControls() {
151 if(controls == null) {
152 // Build controls
153 this.controls = new ClassifierControl();
154 }
155 return controls;
156 }
157
158 public ArrayList getHierarchyClassifiers() {
159 ArrayList result = new ArrayList();
160 for(int i = 0; i < getSize(); i++) {
161 Classifier classifier = (Classifier) getElementAt(i);
162 if(classifier.getName().equalsIgnoreCase(StaticStrings.HIERARCHY_CLASSIFIER)) {
163 result.add(classifier);
164 }
165 classifier = null;
166 }
167 return result;
168
169 }
170
171 /** Determine if the Phind classifier has been assigned.
172 * @return true if it has, false otherwise
173 */
174 public boolean isPhindClassifierAssigned() {
175 for(int i = 0; i < getSize(); i++) {
176 Classifier classifier = (Classifier) getElementAt(i);
177 if(classifier.getName().equalsIgnoreCase(StaticStrings.PHIND_CLASSIFIER)) {
178 return true;
179 }
180 classifier = null;
181 }
182 return false;
183 }
184
185 /** Method to move a classifier in the list order.
186 * @param classifier the Classifier you want to move.
187 * @param direction true to move the classifier up, false to move it down.
188 * @param all true to move to move all the way, false for a single step.
189 */
190 private void moveClassifier(Classifier classifier, boolean direction, boolean all) {
191 if(getSize() < 2) {
192 DebugStream.println("Not enough classifiers to allow moving.");
193 return;
194 }
195 if(all) {
196 // Move to top
197 if(direction) {
198 // Remove the moving classifier
199 remove(classifier);
200 // Retrieve the first classifier
201 Classifier first_classifier = (Classifier) getElementAt(0);
202 // Add the moving classifier before the first classifier
203 addBefore(classifier, first_classifier);
204 first_classifier = null;
205 Gatherer.c_man.configurationChanged();
206 }
207 else {
208 // Remove the moving classifier
209 remove(classifier);
210 // And add after last classifier
211 add(getSize(), classifier);
212 }
213 }
214 else {
215 // Try to move the classifier one step in the desired direction.
216 int index = indexOf(classifier);
217 ///ystem.err.println("Index of " + classifier + " = " + index);
218 if(direction) {
219 index--;
220 if(index < 0) {
221 String args[] = new String[2];
222 args[0] = Dictionary.get("CDM.ClassifierManager.Classifier");
223 args[1] = classifier.getName();
224 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Top", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
225 return;
226 }
227 remove(classifier);
228 add(index, classifier);
229 Gatherer.c_man.configurationChanged();
230 }
231 else {
232 index++;
233 if(index >= getSize()) {
234 String args[] = new String[2];
235 args[0] = Dictionary.get("CDM.ClassifierManager.Classifier_Str");
236 args[1] = classifier.getName();
237 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.Move.At_Bottom", args), Dictionary.get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE);
238 return;
239 }
240 remove(classifier);
241 add(index, classifier);
242 Gatherer.c_man.configurationChanged();
243 }
244 }
245 }
246
247 /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the library.
248 * @param classifier The Classifier to remove
249 * @see org.greenstone.gatherer.cdm.DynamicListModel
250 */
251 private void removeClassifier(Classifier classifier) {
252 remove(classifier);
253 Gatherer.c_man.configurationChanged();
254 }
255
256 /** Method to cache the current contents of library (known classifiers) to file.
257 * @see org.greenstone.gatherer.util.Utility
258 */
259 private void saveClassifiers() {
260 try {
261 File classifiers_dat_file = new File(Utility.getGLIUserFolder(), "classifiers.dat");
262 FileOutputStream file = new FileOutputStream(classifiers_dat_file);
263 ObjectOutputStream out = new ObjectOutputStream(file);
264 out.writeObject(library);
265 out.close();
266 }
267 catch (Exception error) {
268 }
269 }
270
271 private Object[] getAvailable() {
272 ArrayList available = new ArrayList();
273 int library_size = library.size();
274 for(int i = 0; i < library_size; i++) {
275 Classifier classifier = (Classifier) library.get(i);
276 if(!classifier.isAbstract()) {
277 available.add(classifier);
278 }
279 classifier = null;
280 }
281 return available.toArray();
282 }
283
284 /** Method to extract just the classifiers name from a file object.
285 * @param classifier The <strong>File</strong> which references a certain classifier.
286 * @return A <strong>String</strong> containing just the classifiers name, without extension.
287 */
288 private String getClassifierName(String filename) {
289 String name = filename;
290 if(name.indexOf(".") != -1) {
291 name = name.substring(0, name.indexOf("."));
292 }
293 return name;
294 }
295
296 /** Method to load the details of a single plug-in.
297 * @param classifier The classifier <strong>File</strong> you wish to load.
298 */
299 private void loadClassifier(String classifier, String lang) {
300 ///ystem.err.println("Attempting to parse " + classifier);
301 Document document = null;
302 InputStream input_stream = null;
303
304 long start;
305 long end;
306 // Run classinfo on this classifier, and then send the results for parsing.
307 try {
308 if (Gatherer.isGsdlRemote) {
309 String launch = Gatherer.cgiBase + "launch";
310 launch += "?cmd=classinfo.pl";
311 launch += "&xml=&language="+lang;
312 launch += "&class=" + getClassifierName(classifier);
313
314 System.err.println("*** launch = " + launch);
315
316 URL launch_url = new URL(launch);
317 URLConnection launch_connection = launch_url.openConnection();
318 input_stream = launch_connection.getInputStream();
319 }
320 else {
321 String args[] = null;
322 if(Utility.isWindows()) {
323 args = new String[6];
324 if(Configuration.perl_path != null) {
325 args[0] = Configuration.perl_path;
326 }
327 else {
328 args[0] = "Perl.exe";
329 }
330 args[1] = Configuration.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl";
331 args[2] = "-xml";
332 args[3] = "-language";
333 args[4] = lang;
334 args[5] = getClassifierName(classifier);
335 }
336 else {
337 args = new String[5];
338 args[0] = "classinfo.pl";
339 args[1] = "-xml";
340 args[2] = "-language";
341 args[3] = lang;
342 args[4] = getClassifierName(classifier);
343 }
344
345 // Create the process.
346 Runtime runtime = Runtime.getRuntime();
347 Process process = runtime.exec(args);
348
349 input_stream = process.getErrorStream();
350 }
351
352 StringBuffer xml = Utility.readXMLStream(input_stream);
353 document = CollectionDesignManager.XMLStringToDOM(xml,classifier);
354 }
355 catch (Exception error) {
356 error.printStackTrace();
357 ///ystem.err.println("Error: Cannot parse " + getClassifierName(classifier));
358 }
359 if(document != null) {
360 parseXML(document.getDocumentElement());
361 }
362 }
363
364 /** Method to initially load information from the standard classifiers within the gsdl Perl library.
365 * @see org.greenstone.gatherer.util.Utility
366 */
367 private void loadClassifiers() {
368 // Attempt to restore the cached file.
369 File classifiers_dat_file = new File(Utility.getGLIUserFolder(), "classifiers.dat");
370 try {
371 FileInputStream file = new FileInputStream(classifiers_dat_file);
372 ObjectInputStream input = new ObjectInputStream(file);
373 library = (ArrayList) input.readObject();
374 }
375 catch (Exception error) {
376 DebugStream.println("Unable to open " + classifiers_dat_file);
377 }
378
379 if(library == null) {
380 library = new ArrayList();
381
382 if (Gatherer.isGsdlRemote) {
383
384 String lang = Configuration.getLanguage();
385
386 String launch = Gatherer.cgiBase + "launch";
387 launch += "?cmd=classinfo.pl";
388 launch += "&xml=&language="+lang;
389 launch += "&listall=";
390
391 System.err.println("*** launch = " + launch);
392
393 try {
394 URL launch_url = new URL(launch);
395 URLConnection launch_connection = launch_url.openConnection();
396 InputStream input_stream = launch_connection.getInputStream();
397 loadClassifiers(input_stream);
398 }
399 catch (Exception error) {
400 System.err.println("Failed when trying to connect to : " + launch);
401 error.printStackTrace();
402 }
403
404 }
405 else {
406
407 // Retrieve the gsdl home directory...
408 String directory = Configuration.gsdl_path;
409 directory = directory + "perllib" + File.separator + "classify" + File.separator;
410
411 String current_lang = Configuration.getLanguage();
412 File files[] = (new File(directory)).listFiles();
413 if(files != null) {
414 // Create a progress indicator.
415 ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.ClassifierManager.Parsing.Title"), Dictionary.get("CDM.ClassifierManager.Parsing.Message"), files.length);
416 for(int i = 0; i < files.length; i++) {
417 // We only want to check Perl Modules.
418 if(files[i].getName().endsWith(".pm")) {
419 loadClassifier(files[i].getName(), current_lang);
420 }
421 progress.inc();
422 }
423 progress.dispose();
424 progress.destroy();
425 progress = null;
426 }
427 }
428 }
429 }
430
431
432
433 /** Method to load classifier information from a specified input stream (could be local or through URL). Of course no classifiers may be found at this location.
434 * @param input_stream An <strong>InputStream</strong> indicating the where list of classifiers -- encoded in XML -- can be read from
435 */
436 private void loadClassifiers(InputStream input_stream)
437 {
438 StringBuffer xml = Utility.readXMLStream(input_stream);
439 Document document = CollectionDesignManager.XMLStringToDOM(xml, "-listall");
440
441 // Parse XML to build up list of classifier names
442 Node root = document.getDocumentElement();
443
444 NamedNodeMap attributes = root.getAttributes();
445 Node length_node = attributes.getNamedItem("length");
446 String num_classifiers_str = length_node.getNodeValue();
447 int num_classifiers = Integer.parseInt(num_classifiers_str);
448 String class_list[] = new String[num_classifiers];
449
450 Node node = root.getFirstChild();
451 int i = 0;
452 while (node != null) {
453 String node_name = node.getNodeName();
454 if (node_name.equalsIgnoreCase("ClassifyName")) {
455 String name = XMLTools.getValue(node);
456 class_list[i] = name;
457 i++;
458 }
459
460 node = node.getNextSibling();
461 }
462
463 String current_lang = Configuration.getLanguage();
464 if (num_classifiers>0) {
465 // Create a progress indicator.
466 ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.ClassifierManager.Parsing.Title"), Dictionary.get("CDM.ClassifierManager.Parsing.Message"), num_classifiers);
467
468 for (i=0; i<num_classifiers; i++) {
469 String classifier = class_list[i];
470 loadClassifier(classifier, current_lang);
471 progress.inc();
472 }
473 progress.dispose();
474 progress.destroy();
475 progress = null;
476 }
477 }
478
479
480 /** Parses a DOM tree model turning it into a Classifier and its associated arguments.
481 * @param root The <strong>Node</strong> at the root of the DOM model.
482 * @return A newly created <strong>Classifier</strong> based on the information parsed from the DOM model.
483 * @see org.greenstone.gatherer.cdm.Argument
484 */
485 private Classifier parseXML(Node root) {
486 Classifier classifier = new Classifier();
487 String node_name = null;
488 for(Node node = root.getFirstChild(); node != null;
489 node = node.getNextSibling()) {
490 node_name = node.getNodeName();
491 if(node_name.equals("Name")) {
492 String name = XMLTools.getValue(node);
493 // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it.
494 Classifier existing = getBaseClassifier(name);
495 if(existing != null) {
496 return existing;
497 }
498 classifier.setName(name);
499 }
500 else if(node_name.equals("Desc")) {
501 classifier.setDescription(XMLTools.getValue(node));
502 }
503 else if(node_name.equals("Abstract")) {
504 classifier.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(CollectionConfiguration.YES_STR));
505 }
506 // Parse the multitude of arguments.
507 else if(node_name.equals("Arguments")) {
508 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
509 node_name = arg.getNodeName();
510 // An option.
511 if(node_name.equals("Option")) {
512 Argument argument = new Argument();
513 // If its an option we parse the multitude of details an options might have.
514 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) {
515 node_name = det.getNodeName();
516 if(node_name.equals("Name")) {
517 argument.setName(XMLTools.getValue(det));
518 }
519 else if(node_name.equals("Desc")) {
520 argument.setDescription(XMLTools.getValue(det));
521 }
522 else if(node_name.equals("Type")) {
523 argument.setType(XMLTools.getValue(det));
524 }
525 else if(node_name.equals("Default")) {
526 argument.setDefaultValue(XMLTools.getValue(det));
527 }
528 else if(node_name.equals("List")) {
529 // Two final loops are required to parse lists.
530 for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) {
531 if(value.getNodeName().equals("Value")) {
532 String key = null;
533 String desc = "";
534 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) {
535 node_name = subvalue.getNodeName();
536 if(node_name.equals("Name")) {
537 key = XMLTools.getValue(subvalue);
538 }
539 else if(node_name.equals("Desc")) {
540 desc = XMLTools.getValue(subvalue);
541 }
542 }
543 if(key != null) {
544 argument.addOption(key, desc);
545 }
546 }
547 }
548 }
549 else if(node_name.equals("Required")) {
550 String v = XMLTools.getValue(det);
551 ///ystem.err.println("Required = " + v);
552 if(v.equalsIgnoreCase("yes")) {
553 ///ystem.err.println("Setting required to true.");
554 argument.setRequired(true);
555 }
556 }
557 else if(node_name.equals(StaticStrings.RANGE_ELEMENT)) {
558 String range_raw = XMLTools.getValue(det);
559 int index = -1;
560 if((index = range_raw.indexOf(StaticStrings.COMMA_CHARACTER)) != -1) {
561 if(index > 0) {
562 try {
563 String first_number = range_raw.substring(0, index);
564 argument.setMinimum(Integer.parseInt(first_number));
565 first_number = null;
566 }
567 catch(Exception exception) {
568 }
569 }
570
571 if(index + 1 < range_raw.length()) {
572 try {
573 String second_number = range_raw.substring(index + 1);
574 argument.setMaximum(Integer.parseInt(second_number));
575 second_number = null;
576
577 }
578 catch(Exception exception) {
579 }
580 }
581
582 }
583 // Else it wasn't a valid range anyway, so ignore it
584 }
585 }
586 classifier.addArgument(argument);
587 }
588 // A super classifier class.
589 else if(node_name.equals("ClassInfo")) {
590 Classifier super_classifier = parseXML(arg);
591 classifier.setSuper(super_classifier);
592 }
593 }
594 }
595 }
596 if(classifier.getName() != null) {
597 addClassifier(classifier);
598 return classifier;
599 }
600 return null;
601 }
602
603 /** A class which provides controls for assigned and editing classifiers. */
604 private class ClassifierControl
605 extends JPanel
606 implements Control {
607 /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
608 private GComboBox classifier = null;
609 /** Button for adding classifiers. */
610 private JButton add = null;
611 /** Button for configuring the selected classifier. */
612 private JButton configure = null;
613
614 //private JButton move_bottom_button;
615
616 private JButton move_down_button;
617
618 //private JButton move_top_button;
619
620 private JButton move_up_button;
621
622 /** Button to remove the selected classifier. */
623 private JButton remove = null;
624
625 /** A list of assigned classifiers. */
626 private JList classifier_list = null;
627 /** The text area containing instructions on the use of this control. */
628 private JTextArea instructions = null;
629
630 /** Constructor.
631 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.AddListener
632 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.ConfigureListener
633 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.RemoveListener
634 */
635 public ClassifierControl() {
636 Collections.sort(library);
637 // Create
638 add = new GLIButton();
639 add.setMnemonic(KeyEvent.VK_A);
640 Dictionary.registerBoth(add, "CDM.ClassifierManager.Add", "CDM.ClassifierManager.Add_Tooltip");
641 JPanel button_pane = new JPanel();
642 JPanel central_pane = new JPanel();
643 configure = new GLIButton();
644 configure.setEnabled(false);
645 configure.setMnemonic(KeyEvent.VK_C);
646 Dictionary.registerBoth(configure, "CDM.ClassifierManager.Configure", "CDM.ClassifierManager.Configure_Tooltip");
647 JPanel header_pane = new JPanel();
648 instructions = new JTextArea();
649 instructions.setEditable(false);
650 instructions.setLineWrap(true);
651 instructions.setRows(6);
652 instructions.setWrapStyleWord(true);
653 Dictionary.registerText(instructions, "CDM.ClassifierManager.Instructions");
654
655 ClassifierComboboxListener ccl = new ClassifierComboboxListener();
656 classifier = new GComboBox(getAvailable());
657 classifier.setBackgroundNonSelectionColor(Configuration.getColor("coloring.editable_background", false));
658 classifier.setBackgroundSelectionColor(Configuration.getColor("coloring.collection_selection_background", false));
659 classifier.setEditable(true);
660 classifier.setTextNonSelectionColor(Configuration.getColor("coloring.workspace_tree_foreground", false));
661 classifier.setTextSelectionColor(Configuration.getColor("coloring.collection_selection_foreground", false));
662 if(classifier.getItemCount() > 0) {
663 classifier.setSelectedIndex(0);
664 ccl.itemStateChanged(new ItemEvent(classifier, 0, null, ItemEvent.SELECTED));
665 }
666
667 JLabel classifier_label = new JLabel();
668 Dictionary.registerText(classifier_label, "CDM.ClassifierManager.Classifier");
669 classifier_list = new JList(model);
670 classifier_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
671 JLabel classifier_list_label = new JLabel();
672 classifier_list_label.setHorizontalAlignment(JLabel.CENTER);
673 classifier_list_label.setOpaque(true);
674 Dictionary.registerText(classifier_list_label, "CDM.ClassifierManager.Assigned");
675 JPanel classifier_list_pane = new JPanel();
676 JPanel classifier_pane = new JPanel();
677 remove = new GLIButton();
678 remove.setEnabled(false);
679 remove.setMnemonic(KeyEvent.VK_R);
680 Dictionary.registerBoth(remove, "CDM.ClassifierManager.Remove", "CDM.ClassifierManager.Remove_Tooltip");
681
682 JLabel title = new JLabel();
683 title.setHorizontalAlignment(JLabel.CENTER);
684 title.setOpaque(true);
685 Dictionary.registerText(title, "CDM.ClassifierManager.Title");
686
687 JPanel temp = new JPanel(new BorderLayout());
688
689 JPanel move_button_pane = new JPanel();
690
691 move_up_button = new JButton("", Utility.getImage("arrow-up.gif"));
692 move_up_button.setEnabled(false);
693 move_up_button.setMnemonic(KeyEvent.VK_U);
694 //move_up_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
695 Dictionary.registerBoth(move_up_button, "CDM.Move.Move_Up", "CDM.Move.Move_Up_Tooltip");
696
697 move_down_button = new JButton("", Utility.getImage("arrow-down.gif"));
698 move_down_button.setEnabled(false);
699 move_down_button.setMnemonic(KeyEvent.VK_D);
700 //move_down_button.setPreferredSize(Utility.DOUBLE_IMAGE_BUTTON_SIZE);
701 Dictionary.registerBoth(move_down_button, "CDM.Move.Move_Down", "CDM.Move.Move_Down_Tooltip");
702
703 // Listeners
704 add.addActionListener(new AddListener());
705 classifier.addItemListener(ccl);
706 configure.addActionListener(new ConfigureListener());
707 remove.addActionListener(new RemoveListener());
708 classifier_list.addMouseListener(new ClickListener());
709 classifier_list.addListSelectionListener(new ListListener());
710 ccl = null;
711
712 MoveListener ml = new MoveListener();
713 //move_bottom_button.addActionListener(ml);
714 move_down_button.addActionListener(ml);
715 //move_top_button.addActionListener(ml);
716 move_up_button.addActionListener(ml);
717
718 // Layout
719 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0));
720
721 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
722
723 header_pane.setLayout(new BorderLayout());
724 header_pane.add(title, BorderLayout.NORTH);
725 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
726
727 move_button_pane.setLayout(new GridLayout(4,1));
728 move_button_pane.add(move_up_button);
729 move_button_pane.add(new JPanel());
730 move_button_pane.add(new JPanel());
731 move_button_pane.add(move_down_button);
732
733 classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
734
735 classifier_list_pane.setLayout(new BorderLayout());
736 classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH);
737 classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER);
738 classifier_list_pane.add(move_button_pane, BorderLayout.EAST);
739
740 classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
741
742 classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
743 classifier_pane.setLayout(new BorderLayout(5,0));
744 classifier_pane.add(classifier_label, BorderLayout.WEST);
745 classifier_pane.add(classifier, BorderLayout.CENTER);
746
747 button_pane.setLayout(new GridLayout(1, 3));
748 button_pane.add(add);
749 button_pane.add(configure);
750 button_pane.add(remove);
751
752 // Scope these mad bordering skillz.
753 temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(Dictionary.get("CDM.ClassifierManager.Controls")), BorderFactory.createEmptyBorder(2,2,2,2))));
754 temp.add(classifier_pane, BorderLayout.NORTH);
755 temp.add(button_pane, BorderLayout.SOUTH);
756
757 central_pane.setLayout(new BorderLayout());
758 central_pane.add(classifier_list_pane, BorderLayout.CENTER);
759 central_pane.add(temp, BorderLayout.SOUTH);
760
761 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
762 setLayout(new BorderLayout());
763 add(header_pane, BorderLayout.NORTH);
764 add(central_pane, BorderLayout.CENTER);
765 }
766
767 /** Method which acts like a destructor, tidying up references to persistant objects.
768 */
769 public void destroy() {
770 add = null;
771 classifier = null;
772 classifier_list = null;
773 configure = null;
774 instructions = null;
775 remove = null;
776 }
777
778 /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called.
779 */
780 public void gainFocus() {
781 if(instructions != null) {
782 instructions.setCaretPosition(0);
783 }
784 }
785
786 public void loseFocus() {
787 }
788
789 /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method.
790 */
791 private class AddListener
792 implements ActionListener {
793 /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of our target controls, so that we can add the selected Classifier.
794 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
795 * @see org.greenstone.gatherer.Gatherer
796 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
797 * @see org.greenstone.gatherer.cdm.Classifier
798 */
799 public void actionPerformed(ActionEvent event) {
800 Object selected_object = classifier.getSelectedItem();
801 // If there is something in the combobox, but we haven't registered a selection, then add the object and select it!
802 if(selected_object != null) {
803 // Retrieve the base classifier
804 Classifier base_classifier = getBaseClassifier(selected_object.toString());
805
806 // Create a new element in the DOM
807 Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.CLASSIFY_ELEMENT);
808 Classifier new_classifier = null;
809 if(base_classifier != null) {
810 DebugStream.println("Creating Classifier based on existing Classifer.");
811 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_classifier.getName());
812 new_classifier = new Classifier(element, base_classifier);
813 }
814 else {
815 DebugStream.println("Creating new custom Classifier.");
816 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, selected_object.toString());
817 new_classifier = new Classifier(element, null);
818 // Also we add the custom classifier name to the combobox for convienence.
819 classifier.addItem(selected_object);
820 }
821 element = null;
822 // Automatically chain to configuration. This ensures required arguments are filled out.
823 ArgumentConfiguration ac = new ArgumentConfiguration(new_classifier);
824 if(ac.display()) {
825 if(!model.contains(new_classifier)) {
826 assignClassifier(new_classifier);
827 classifier_list.setSelectedValue(new_classifier, true);
828 }
829 else {
830 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
831 }
832 }
833 ac = null;
834 new_classifier = null;
835 }
836 }
837 }
838
839 /** This listener reacts to changes in the current selection of the classifier combobox. */
840 private class ClassifierComboboxListener
841 implements ItemListener {
842 /** When a user selects a certain plugin, update the tooltip to show the plugin description. */
843 public void itemStateChanged(ItemEvent event) {
844 if(event.getStateChange() == ItemEvent.SELECTED) {
845 // Retrieve the selected plugin
846 Object current_selection = classifier.getSelectedItem();
847 // And reset the tooltip. If the plugin is null or is a string, then go back to the default message
848 if(current_selection == null || current_selection instanceof String) {
849 Dictionary.registerTooltip(classifier, "CDM.ClassifierManager.Classifier_Tooltip");
850 }
851 else {
852 Classifier current_classifier = (Classifier) current_selection;
853 Dictionary.registerTooltipText(classifier, Utility.formatHTMLWidth(current_classifier.getDescription(), 40));
854 current_classifier = null;
855 }
856 current_selection = null;
857 }
858 }
859 }
860
861 /** Listens for double clicks apon the list and react as if the configure button was pushed. */
862 private class ClickListener
863 extends MouseAdapter {
864 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
865 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
866 */
867 public void mouseClicked(MouseEvent event) {
868 if(event.getClickCount() == 2 ) {
869 if(!classifier_list.isSelectionEmpty()) {
870 Classifier classifier = (Classifier) classifier_list.getSelectedValue();
871 ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
872 if(ac.display()) {
873 refresh(classifier);
874 }
875 ac.destroy();
876 ac = null;
877 }
878 }
879 }
880 }
881
882 /** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration.
883 */
884 private class ConfigureListener
885 implements ActionListener {
886 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
887 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
888 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
889 * @see org.greenstone.gatherer.cdm.Classifier
890 */
891 public void actionPerformed(ActionEvent event) {
892 if(!classifier_list.isSelectionEmpty()) {
893 Classifier classifier = (Classifier) classifier_list.getSelectedValue();
894 ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
895 if(ac.display()) {
896 refresh(classifier);
897 }
898 ac.destroy();
899 ac = null;
900 }
901 }
902 }
903
904 /** listens for changes in the list selection and enables the configure and remove buttons if there is a selection, disables them if there is no selection */
905 private class ListListener
906 implements ListSelectionListener {
907
908 public void valueChanged(ListSelectionEvent e) {
909 if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
910 if (classifier_list.isSelectionEmpty()) {
911 //move_top_button.setEnabled(false);
912 move_up_button.setEnabled(false);
913 move_down_button.setEnabled(false);
914 //move_bottom_button.setEnabled(false);
915 configure.setEnabled(false);
916 remove.setEnabled(false);
917 }
918 else {
919 //move_top_button.setEnabled(true);
920 move_up_button.setEnabled(true);
921 move_down_button.setEnabled(true);
922 //move_bottom_button.setEnabled(true);
923 configure.setEnabled(true);
924 remove.setEnabled(true);
925 }
926 }
927 }
928 }
929
930 /** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>moveClassifier()</i> method of the manager with the appropriate details. */
931 private class MoveListener
932 implements ActionListener {
933 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
934 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
935 */
936 public void actionPerformed(ActionEvent event) {
937 if(!classifier_list.isSelectionEmpty()) {
938 Object object = classifier_list.getSelectedValue();
939 if(object instanceof Classifier) {
940 Classifier classifier = (Classifier) object;
941 //if(event.getSource() == move_top_button) {
942 // moveClassifier(classifier, true, true);
943 //}
944 //else
945 if(event.getSource() == move_up_button) {
946 moveClassifier(classifier, true, false);
947 }
948 else if(event.getSource() == move_down_button) {
949 moveClassifier(classifier, false, false);
950 }
951 //else {
952 // moveClassifier(classifier, false, true);
953 //}
954 classifier_list.setSelectedValue(classifier, true);
955 }
956 }
957 }
958 }
959
960 /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removeClassifier()</i> method.
961 */
962 private class RemoveListener
963 implements ActionListener {
964 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls.
965 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
966 */
967 public void actionPerformed(ActionEvent event) {
968 if(classifier_list.isSelectionEmpty()) {
969 remove.setEnabled(false);
970 return;
971 }
972 int selected_index = classifier_list.getSelectedIndex();
973 Object selected_classifier = classifier_list.getSelectedValue();
974 if (!(selected_classifier instanceof Classifier)) {
975 return; // what else could we have here???
976 }
977 removeClassifier((Classifier)selected_classifier);
978
979 if (selected_index >= classifier_list.getModel().getSize()) {
980 selected_index--;
981 }
982 if (selected_index >=0) {
983 classifier_list.setSelectedIndex(selected_index);
984 } else {
985 // no more classifiers in the list
986 remove.setEnabled(false);
987 }
988
989 }
990 }
991 }
992
993
994
995}
Note: See TracBrowser for help on using the repository browser.