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

Last change on this file since 7578 was 7151, checked in by kjdon, 20 years ago

fixed some more static label sizes and deleted a lot of commented out stuff

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