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

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

minor style change

  • Property svn:keywords set to Author Date Id Revision
File size: 31.1 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, String collection) {
301 ///ystem.err.println("Attempting to parse " + classifier + " for collection "+collection);
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 ArrayList args = new ArrayList();
316 if (Utility.isWindows()) {
317 args.add(Configuration.perl_path);
318 args.add("-S");
319 }
320 args.add(LocalGreenstone.getBinScriptDirectoryPath() + "classinfo.pl");
321 args.add("-xml");
322 args.add("-language");
323 args.add(lang);
324 args.add("-collect");
325 args.add(collection);
326 args.add(getClassifierName(classifier));
327
328 // Create the process.
329 Runtime runtime = Runtime.getRuntime();
330 Process process = runtime.exec((String[])args.toArray(new String [0]));
331
332 input_stream = process.getErrorStream();
333 xml = XMLTools.readXMLStream(input_stream);
334 }
335
336 if (xml.length() > 0) {
337 document = CollectionDesignManager.XMLStringToDOM(xml, classifier);
338 }
339 else {
340 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_XML_Parse_Failed", classifier), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
341 }
342 }
343 catch (Exception exception) {
344 DebugStream.println("Failed when trying to parse: " + classifier);
345 DebugStream.printStackTrace(exception);
346 }
347
348 if (document != null) {
349 parseXML(document.getDocumentElement());
350 }
351 }
352
353 /** Method to initially load information from the standard classifiers within the gsdl Perl library.
354 * @see org.greenstone.gatherer.util.Utility
355 */
356 private void loadClassifiers() {
357 // Attempt to restore the cached file.
358 File classifiers_dat_file = new File(Gatherer.getGLIUserDirectoryPath() + "classifiers.dat");
359 try {
360 FileInputStream file = new FileInputStream(classifiers_dat_file);
361 ObjectInputStream input = new ObjectInputStream(file);
362 library = (ArrayList) input.readObject();
363 }
364 catch (Exception error) {
365 DebugStream.println("Unable to open " + classifiers_dat_file);
366 }
367
368 if(library == null) {
369 library = new ArrayList();
370
371 if (Gatherer.isGsdlRemote) {
372 String classinfo_output = RemoteGreenstoneServer.getScriptOptions("classinfo.pl", "&listall=");
373 loadClassifiers(new StringBuffer(classinfo_output));
374 }
375
376 else {
377 // Retrieve the gsdl home directory...
378 String directory = LocalGreenstone.getDirectoryPath();
379 directory = directory + "perllib" + File.separator + "classify" + File.separator;
380
381 String current_lang = Configuration.getLanguage();
382 String collection_name = Gatherer.c_man.getCollection().getName();
383 File files[] = (new File(directory)).listFiles();
384 File coll_files[] = (new File(Gatherer.c_man.getCollectionClassifiersDirectoryPath())).listFiles();
385 int num_files =0;
386 if (files != null) {
387 num_files += files.length;
388 }
389 if (coll_files != null) {
390 num_files += coll_files.length;
391 }
392 if(num_files > 0) {
393 // Create a progress indicator.
394 ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.ClassifierManager.Parsing.Title"), Dictionary.get("CDM.ClassifierManager.Parsing.Message"), num_files);
395 if (coll_files != null) {
396 for (int i=0; i<coll_files.length; i++) {
397
398 if(coll_files[i].getName().endsWith(".pm")) {
399 loadClassifier(coll_files[i].getName(), current_lang, collection_name);
400 }
401 progress.inc();
402 }
403 }
404 if (files != null) {
405 for(int i = 0; i < files.length; i++) {
406 // We only want to check Perl Modules.
407 if(files[i].getName().endsWith(".pm")) {
408 loadClassifier(files[i].getName(), current_lang, collection_name);
409 }
410 progress.inc();
411 }
412 }
413 progress.dispose();
414 progress.destroy();
415 progress = null;
416 }
417 }
418 }
419 }
420
421
422
423 /** 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.
424 * @param input_stream An <strong>InputStream</strong> indicating the where list of classifiers -- encoded in XML -- can be read from
425 */
426 private void loadClassifiers(StringBuffer xml)
427 {
428 Document document = CollectionDesignManager.XMLStringToDOM(xml, "-listall");
429
430 // Parse XML to build up list of classifier names
431 Element root = document.getDocumentElement();
432
433 String num_classifiers_str = root.getAttribute("length");
434 int num_classifiers = Integer.parseInt(num_classifiers_str);
435 String class_list[] = new String[num_classifiers];
436
437 Node node = root.getFirstChild();
438 int i = 0;
439 while (node != null) {
440 if (node.getNodeName().equalsIgnoreCase("ClassifyName")) {
441 class_list[i] = XMLTools.getValue(node);
442 i++;
443 }
444
445 node = node.getNextSibling();
446 }
447
448 String current_lang = Configuration.getLanguage();
449 String collection_name = Gatherer.c_man.getCollection().getName();
450 if (num_classifiers>0) {
451 // Create a progress indicator.
452 ParsingProgress progress = new ParsingProgress(Dictionary.get("CDM.ClassifierManager.Parsing.Title"), Dictionary.get("CDM.ClassifierManager.Parsing.Message"), num_classifiers);
453
454 for (i=0; i<num_classifiers; i++) {
455 String classifier = class_list[i];
456 loadClassifier(classifier, current_lang, collection_name);
457 progress.inc();
458 }
459 progress.dispose();
460 progress.destroy();
461 progress = null;
462 }
463 }
464
465
466 /** Parses a DOM tree model turning it into a Classifier and its associated arguments.
467 * @param root The <strong>Node</strong> at the root of the DOM model.
468 * @return A newly created <strong>Classifier</strong> based on the information parsed from the DOM model.
469 * @see org.greenstone.gatherer.cdm.Argument
470 */
471 private Classifier parseXML(Node root) {
472 Classifier classifier = new Classifier();
473 String node_name = null;
474 for(Node node = root.getFirstChild(); node != null;
475 node = node.getNextSibling()) {
476 node_name = node.getNodeName();
477 if(node_name.equals("Name")) {
478 String name = XMLTools.getValue(node);
479 // 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.
480 Classifier existing = getBaseClassifier(name);
481 if(existing != null) {
482 return existing;
483 }
484 classifier.setName(name);
485 }
486 else if(node_name.equals("Desc")) {
487 classifier.setDescription(XMLTools.getValue(node));
488 }
489 else if(node_name.equals("Abstract")) {
490 classifier.setIsAbstract(XMLTools.getValue(node).equalsIgnoreCase(CollectionConfiguration.YES_STR));
491 }
492 // Parse the multitude of arguments.
493 else if(node_name.equals("Arguments")) {
494 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) {
495 node_name = arg.getNodeName();
496 // An option.
497 if(node_name.equals("Option")) {
498 Argument argument = new Argument();
499 argument.parseXML((Element)arg);
500 classifier.addArgument(argument);
501 }
502 }
503 }
504 // A super classifier class.
505 else if(node_name.equals("ClassInfo")) {
506 Classifier super_classifier = parseXML(node);
507 classifier.setSuper(super_classifier);
508 }
509
510 }
511 if(classifier.getName() != null) {
512 addClassifier(classifier);
513 return classifier;
514 }
515 return null;
516 }
517
518 /** A class which provides controls for assigned and editing classifiers. */
519 private class ClassifierControl
520 extends JPanel
521 implements Control {
522 /** A combobox containing all of the known classifiers, including those that may have already been assigned. */
523 private JComboBox classifier_combobox = null;
524 /** Button for adding classifiers. */
525 private JButton add = null;
526 /** Button for configuring the selected classifier. */
527 private JButton configure = null;
528 private JButton move_down_button;
529 private JButton move_up_button;
530
531 /** Button to remove the selected classifier. */
532 private JButton remove = null;
533
534 /** A list of assigned classifiers. */
535 private JList classifier_list = null;
536
537 /** Constructor.
538 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.AddListener
539 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.ConfigureListener
540 * @see org.greenstone.gatherer.cdm.ClassifierManager.ClassifierControl.RemoveListener
541 */
542 public ClassifierControl() {
543 Collections.sort(library);
544 // Create
545 add = new GLIButton(Dictionary.get("CDM.ClassifierManager.Add"), Dictionary.get("CDM.ClassifierManager.Add_Tooltip"));
546
547 JPanel button_pane = new JPanel();
548 JPanel central_pane = new JPanel();
549
550configure = new GLIButton(Dictionary.get("CDM.ClassifierManager.Configure"), Dictionary.get("CDM.ClassifierManager.Configure_Tooltip"));
551 configure.setEnabled(false);
552
553 JPanel header_pane = new DesignPaneHeader("CDM.GUI.Classifiers", "classifiers");
554
555 ClassifierComboboxListener ccl = new ClassifierComboboxListener();
556 classifier_combobox = new JComboBox(getAvailable());
557 classifier_combobox.setEditable(false);
558 if(classifier_combobox.getItemCount() > 0) {
559 classifier_combobox.setSelectedIndex(0);
560 ccl.itemStateChanged(new ItemEvent(classifier_combobox, 0, null, ItemEvent.SELECTED));
561 }
562
563 JLabel classifier_label = new JLabel(Dictionary.get("CDM.ClassifierManager.Classifier"));
564
565 classifier_list = new JList(model);
566 classifier_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
567 JLabel classifier_list_label = new JLabel(Dictionary.get("CDM.ClassifierManager.Assigned"));
568
569 classifier_list_label.setOpaque(true);
570
571 JPanel classifier_list_pane = new JPanel();
572 JPanel classifier_pane = new JPanel();
573 remove = new GLIButton(Dictionary.get("CDM.ClassifierManager.Remove"), Dictionary.get("CDM.ClassifierManager.Remove_Tooltip"));
574 remove.setEnabled(false);
575
576 JPanel temp = new JPanel(new BorderLayout());
577
578 JPanel move_button_pane = new JPanel();
579
580 move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
581 move_up_button.setEnabled(false);
582
583 move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
584 move_down_button.setEnabled(false);
585
586 // Listeners
587 add.addActionListener(new AddListener());
588 add.addActionListener(CollectionDesignManager.buildcol_change_listener);
589 classifier_combobox.addItemListener(ccl);
590 configure.addActionListener(new ConfigureListener());
591 configure.addActionListener(CollectionDesignManager.buildcol_change_listener);
592 remove.addActionListener(new RemoveListener());
593 remove.addActionListener(CollectionDesignManager.buildcol_change_listener);
594 classifier_list.addMouseListener(new ClickListener());
595 classifier_list.addListSelectionListener(new ListListener());
596 ccl = null;
597
598 MoveListener ml = new MoveListener();
599 move_down_button.addActionListener(ml);
600 move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
601 move_up_button.addActionListener(ml);
602 move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
603
604 // Layout
605 move_button_pane.setLayout(new GridLayout(4,1));
606 move_button_pane.add(move_up_button);
607 move_button_pane.add(new JPanel());
608 move_button_pane.add(new JPanel());
609 move_button_pane.add(move_down_button);
610
611 classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2));
612
613 classifier_list_pane.setLayout(new BorderLayout());
614 classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH);
615 classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER);
616 classifier_list_pane.add(move_button_pane, BorderLayout.EAST);
617
618 classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
619
620 classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
621 classifier_pane.setLayout(new BorderLayout(5,0));
622 classifier_pane.add(classifier_label, BorderLayout.WEST);
623 classifier_pane.add(classifier_combobox, BorderLayout.CENTER);
624
625 button_pane.setLayout(new GridLayout(1, 3));
626 button_pane.add(add);
627 button_pane.add(configure);
628 button_pane.add(remove);
629
630 temp.add(classifier_pane, BorderLayout.NORTH);
631 temp.add(button_pane, BorderLayout.SOUTH);
632
633 central_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
634 central_pane.setLayout(new BorderLayout());
635 central_pane.add(classifier_list_pane, BorderLayout.CENTER);
636 central_pane.add(temp, BorderLayout.SOUTH);
637
638 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
639 setLayout(new BorderLayout());
640 add(header_pane, BorderLayout.NORTH);
641 add(central_pane, BorderLayout.CENTER);
642 }
643
644 /** Method which acts like a destructor, tidying up references to persistant objects.
645 */
646 public void destroy() {
647 add = null;
648 classifier_combobox = null;
649 classifier_list = null;
650 configure = null;
651 //instructions = null;
652 remove = null;
653 }
654
655 public void gainFocus() {
656 }
657
658 public void loseFocus() {
659 }
660
661 /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method.
662 */
663 private class AddListener
664 implements ActionListener {
665 /** 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.
666 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
667 * @see org.greenstone.gatherer.Gatherer
668 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
669 * @see org.greenstone.gatherer.cdm.Classifier
670 */
671 public void actionPerformed(ActionEvent event) {
672 Object selected_object = classifier_combobox.getSelectedItem();
673 // If there is something in the combobox, but we haven't registered a selection, then add the object and select it!
674 if(selected_object != null) {
675 // Retrieve the base classifier
676 Classifier base_classifier = getBaseClassifier(selected_object.toString());
677
678 // Create a new element in the DOM
679 Element element = CollectionDesignManager.collect_config.document.createElement(CollectionConfiguration.CLASSIFY_ELEMENT);
680 element.setAttribute(CollectionConfiguration.TYPE_ATTRIBUTE, base_classifier.getName());
681 Classifier new_classifier = new Classifier(element, base_classifier);
682
683 element = null;
684 // Automatically chain to configuration. This ensures required arguments are filled out.
685 ArgumentConfiguration ac = new ArgumentConfiguration(new_classifier);
686 if(ac.display()) {
687 if(!model.contains(new_classifier)) {
688 assignClassifier(new_classifier);
689 classifier_list.setSelectedValue(new_classifier, true);
690 }
691 else {
692 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("CDM.ClassifierManager.Classifier_Exists"), Dictionary.get("General.Error"), JOptionPane.ERROR_MESSAGE);
693 }
694 }
695 ac = null;
696 new_classifier = null;
697 }
698 }
699 }
700
701 /** This listener reacts to changes in the current selection of the classifier combobox. */
702 private class ClassifierComboboxListener
703 implements ItemListener {
704 /** When a user selects a certain plugin, update the tooltip to show the plugin description. */
705 public void itemStateChanged(ItemEvent event) {
706 if(event.getStateChange() == ItemEvent.SELECTED) {
707 // Retrieve the selected plugin
708 Classifier current_selection = (Classifier) classifier_combobox.getSelectedItem();
709 // And reset the tooltip.
710 classifier_combobox.setToolTipText(Utility.formatHTMLWidth(current_selection.getDescription(), 40));
711 current_selection = null;
712 }
713 }
714 }
715
716 /** Listens for double clicks apon the list and react as if the configure button was pushed. */
717 private class ClickListener
718 extends MouseAdapter {
719 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt.
720 * @param event A <strong>MouseEvent</strong> containing information about the mouse click.
721 */
722 public void mouseClicked(MouseEvent event) {
723 if(event.getClickCount() == 2 ) {
724 if(!classifier_list.isSelectionEmpty()) {
725 Classifier classifier = (Classifier) classifier_list.getSelectedValue();
726 ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
727 if(ac.display()) {
728 refresh(classifier);
729 }
730 ac.destroy();
731 ac = null;
732 // 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
733 Gatherer.c_man.configurationChanged();
734 }
735 }
736 }
737 }
738
739 /** 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.
740 */
741 private class ConfigureListener
742 implements ActionListener {
743 /** 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.
744 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
745 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration
746 * @see org.greenstone.gatherer.cdm.Classifier
747 */
748 public void actionPerformed(ActionEvent event) {
749 if(!classifier_list.isSelectionEmpty()) {
750 Classifier classifier = (Classifier) classifier_list.getSelectedValue();
751 ArgumentConfiguration ac = new ArgumentConfiguration(classifier);
752 if(ac.display()) {
753 refresh(classifier);
754 }
755 ac.destroy();
756 ac = null;
757 // 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
758 Gatherer.c_man.configurationChanged();
759 }
760 }
761 }
762
763 /** 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 */
764 private class ListListener
765 implements ListSelectionListener {
766
767 public void valueChanged(ListSelectionEvent e) {
768 if (!e.getValueIsAdjusting()) { // we get two events for one change in list selection - use the false one ( the second one)
769 if (classifier_list.isSelectionEmpty()) {
770 move_up_button.setEnabled(false);
771 move_down_button.setEnabled(false);
772 configure.setEnabled(false);
773 remove.setEnabled(false);
774 }
775 else {
776 configure.setEnabled(true);
777 remove.setEnabled(true);
778 int selected_index = classifier_list.getSelectedIndex();
779 move_up_button.setEnabled(selected_index !=0);
780 move_down_button.setEnabled(selected_index != model.getSize()-1);
781 }
782 }
783 }
784 }
785
786 /** 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. */
787 private class MoveListener
788 implements ActionListener {
789 /** 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.
790 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
791 */
792 public void actionPerformed(ActionEvent event) {
793 if(!classifier_list.isSelectionEmpty()) {
794 Object object = classifier_list.getSelectedValue();
795 if(object instanceof Classifier) {
796 Classifier classifier = (Classifier) object;
797 if(event.getSource() == move_up_button) {
798 moveClassifier(classifier, true, false);
799 }
800 else if(event.getSource() == move_down_button) {
801 moveClassifier(classifier, false, false);
802 }
803 classifier_list.setSelectedValue(classifier, true);
804 }
805 }
806 }
807 }
808
809 /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removeClassifier()</i> method.
810 */
811 private class RemoveListener
812 implements ActionListener {
813 /** 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.
814 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action.
815 */
816 public void actionPerformed(ActionEvent event) {
817 if(classifier_list.isSelectionEmpty()) {
818 remove.setEnabled(false);
819 return;
820 }
821 int selected_index = classifier_list.getSelectedIndex();
822 Object selected_classifier = classifier_list.getSelectedValue();
823 if (!(selected_classifier instanceof Classifier)) {
824 return; // what else could we have here???
825 }
826 removeClassifier((Classifier)selected_classifier);
827
828 if (selected_index >= classifier_list.getModel().getSize()) {
829 selected_index--;
830 }
831 if (selected_index >=0) {
832 classifier_list.setSelectedIndex(selected_index);
833 } else {
834 // no more classifiers in the list
835 remove.setEnabled(false);
836 }
837 }
838 }
839 }
840}
Note: See TracBrowser for help on using the repository browser.