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

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

New code for "incremental" building, by Matthew Whyte.

I've only had time to look at this briefly; I've fixed a few obvious problems but I imagine this will be pretty flaky for a while.

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