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

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

Replaced all Gatherer.print* with DebugStream.print*.

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