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

Last change on this file since 10342 was 10342, checked in by mdewsnip, 19 years ago

Tidied up a lot of path variables. These were all over the place, and were often duplicated. Now all GLI related paths are accessed via static methods in the Gatherer class.

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