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

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

Moved clear() and setValue() functions from MSMUtils into XMLTools. Moved NS_SEP string from MSMUtils into StaticStrings.

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