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

Last change on this file since 4967 was 4960, checked in by jmt12, 21 years ago

Removed custom package from cdm (I'll put it back one day)

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