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

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

(MAJOR CHANGE) This is the remote Greenstone building functionality implemented for the West Yorkshire Fire and Rescue Service. It allows collections to be built without having a local version of Greenstone, using either a stand-alone version of the GLI or the applet.

The collections are stored on the server (allowing people to collaborate on collections -- but not at the same time), and only what is necessary to let the user edit the collection is downloaded. Any changes to the collection are uploaded to the server.

An access restriction mechanism is implemented which uses the standard Greenstone user database to control who has access to collections.

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