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

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

Major CDM rewrite so it uses DOM.

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