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

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

Rearranged a few things when using classinfo.pl and pluginfo.pl, to make this easier when using a remote Greenstone server.

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