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

Last change on this file since 12072 was 12072, checked in by kjdon, 18 years ago

all these managers now implement modeChanged()

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