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

Last change on this file since 8266 was 8249, checked in by mdewsnip, 20 years ago

Moved the XMLStringToDOM() function from Utility into CollectionDesignManager, as it depends on the Gatherer class.

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