source: trunk/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java@ 4366

Last change on this file since 4366 was 4366, checked in by kjdon, 21 years ago

re-tabbed the code for java

  • Property svn:keywords set to Author Date Id Revision
File size: 38.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 * <BR><BR>
9 *
10 * Author: John Thompson, Greenstone Digital Library, University of Waikato
11 *
12 * <BR><BR>
13 *
14 * Copyright (C) 1999 New Zealand Digital Library Project
15 *
16 * <BR><BR>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * <BR><BR>
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * <BR><BR>
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 *########################################################################
36 */
37
38
39
40
41
42
43package org.greenstone.gatherer.cdm;
44/**************************************************************************************
45 * Title: Gatherer
46 * Description: The Gatherer: a tool for gathering and enriching a digital collection.
47 * Copyright: Copyright (c) 2001
48 * Company: The University of Waikato
49 * Written: 02/05/02
50 * Revised: 17/11/02 - Commented
51 **************************************************************************************/
52import java.awt.BorderLayout;
53import java.awt.GridLayout;
54import java.awt.event.ActionEvent;
55import java.awt.event.ActionListener;
56import java.awt.event.KeyAdapter;
57import java.awt.event.KeyEvent;
58import java.io.Serializable;
59import java.util.ArrayList;
60import java.util.Collections;
61import java.util.Enumeration;
62import java.util.Hashtable;
63import java.util.Vector;
64import javax.swing.BorderFactory;
65import javax.swing.ButtonGroup;
66import javax.swing.DefaultListModel;
67import javax.swing.JButton;
68import javax.swing.JCheckBox;
69import javax.swing.JComboBox;
70import javax.swing.JLabel;
71import javax.swing.JList;
72import javax.swing.JPanel;
73import javax.swing.JScrollPane;
74import javax.swing.JTabbedPane;
75import javax.swing.JTextArea;
76import javax.swing.JTextField;
77import javax.swing.JToggleButton;
78import javax.swing.ListSelectionModel;
79import javax.swing.event.ListSelectionEvent;
80import javax.swing.event.ListSelectionListener;
81import org.greenstone.gatherer.Gatherer;
82import org.greenstone.gatherer.cdm.Subcollection;
83import org.greenstone.gatherer.cdm.SubIndex;
84import org.greenstone.gatherer.cdm.SubIndexes;
85import org.greenstone.gatherer.msm.ElementWrapper;
86import org.greenstone.gatherer.util.ExclusiveListSelectionListener;
87import org.w3c.dom.Element;
88/** This class maintains a list of subcollections within our collection, and also records which of these subcollections we are building indexes for.
89 * @author John Thompson, Greenstone Digital Library, University of Waikato
90 * @version 2.1
91 */
92public class SubcollectionManager
93 extends DefaultListModel {
94 /** The controls used to edit the settings of this manager. */
95 private Control controls = null;
96 /** A reference to this class so we can use it as a model in our inner classes. */
97 private DefaultListModel model = null;
98 /** The default index for the subcollections. */
99 private DefaultSubIndex default_index = null;
100 /** A reference to the Gatherer. */
101 private Gatherer gatherer = null;
102 /** A hashtable of subcollections, with mappings from name to subcollection. */
103 private Hashtable subcollections = null;
104 /** A vector-type structure of subcollection indexes. */
105 private SubIndexes subindexes = null;
106 /** A vector containing all of the subcollection commands that are unresolved, or in other words require that all 'subcollection <name> "<exp>"' to have been previously parsed before we can be certain their references will make sense. */
107 private ArrayList unresolved = null;
108 /** Constructor.
109 * @param gatherer A reference to the <Strong>Gatherer</strong>.
110 * @see org.greenstone.gatherer.cdm.SubIndexes
111 */
112 public SubcollectionManager(Gatherer gatherer) {
113 super();
114 this.gatherer = gatherer;
115 this.model = this;
116 this.subcollections = new Hashtable();
117 this.subindexes = new SubIndexes();
118 this.unresolved = new ArrayList();
119 }
120 /** Method to add a subindex.
121 * @param subindex A <strong>SubIndex</strong>.
122 * @see org.greenstone.gatherer.Gatherer
123 * @see org.greenstone.gatherer.collection.CollectionManager
124 */
125 public void addSubIndex(SubIndex subindex) {
126 if(!subindexes.contains(subindex)) {
127 subindexes.addElement(subindex);
128 gatherer.c_man.configurationChanged();
129 }
130 }
131 /** Method to add a new subcollection. Adds it to both the underlying list model and the hashtable mapping names to subcollections.
132 * @param sub The <strong>Subcollection</strong> to add.
133 * @return A <i>boolean</i> indicating if the addition was successful (<i>true</i>) or not (<i>false</i>).
134 * @see org.greenstone.gatherer.Gatherer
135 * @see org.greenstone.gatherer.collection.CollectionManager
136 */
137 public boolean addSubcollection(Subcollection sub) {
138 if(!contains(sub)) {
139 addElement(sub);
140 subcollections.put(sub.getName(), sub);
141 gatherer.c_man.configurationChanged();
142 return true;
143 }
144 return false;
145 }
146 /** A method to add a new subcollection, by specifying its name, metadata element if applicable and Perl expression to filter pages into or out of this collection.
147 * @param name A <>>String</>> which is a unique identifier of a subcollection.
148 * @param include A <i>boolean</i> indicating whether this is an inclusion filter (<i>true</i>) or an exclusion one (<i>false</i>).
149 * @param element An <>>Element</>> which is either the metadata whose value should be matched against the given expression, or <i>null</i> if you wish to match against the file name.
150 * @param exp A <>>String</>> containing a Perl expression which is used as the filter for this subcollection.
151 * @param flags A <strong>String<strong> listing any special flags to be applied when matching the expression.
152 * @return A <i>boolean</i> with a value of <i>true</i> if the addition was successful.
153 * @see org.greenstone.gatherer.cdm.Subcollection
154 */
155 public boolean addSubcollection(String name, boolean include, String element, String exp, String flags) {
156 Subcollection sub = null;
157 if(element != null) {
158 sub = new Subcollection(name, include, element, exp, flags);
159 }
160 else {
161 sub = new Subcollection(name, include, exp, flags);
162 }
163 return addSubcollection(sub);
164 }
165 /** Refresh all derived components using this manager as a model.
166 */
167 public void changed() {
168 fireContentsChanged(this, 0, getSize() - 1);
169 }
170 /** Method to retrieve the controls for this manager.
171 * @return A <Strong>Control</strong> object which contains the controls used to edit the subcollection data.
172 */
173 public Control getControls() {
174 if(controls == null) {
175 controls = new Control();
176 }
177 return controls;
178 }
179 /** Method to retrieve the default index.
180 * @return A <strong>DefaultSubIndex</strong> object.
181 */
182 public DefaultSubIndex getDefaultSubIndex() {
183 return default_index;
184 }
185 /** Method to retrieve a certain subcollection by its name.
186 * @param name A <strong>String</strong> which is used as the key for finding the matching subcollection.
187 * @return The requested <strong>Subcollection</strong> or <i>null</i> if no such subcollection exists.
188 */
189 public Subcollection getSubcollection(String name) {
190 return (Subcollection) subcollections.get(name);
191 }
192 /** Method to get all of the subindexes set.
193 * @return A <strong>SubIndexes</strong> object containing all the defined indexes.
194 */
195 public SubIndexes getSubIndexes() {
196 return subindexes;
197 }
198 /** Method to get all of the subcollections defined.
199 * @return A <strong>Vector</strong> of subcollections.
200 */
201 public Vector getSubcollections() {
202 Vector subcollections = new Vector();
203 for(int i = 0; i < size(); i++) {
204 subcollections.add(get(i));
205 }
206 return subcollections;
207 }
208 /** Mark the current controls, if any, as invalid and deallocate them. Any further use of the controls will requires them being rebuilt.
209 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control
210 */
211 public void invalidateControls() {
212 if(controls != null) {
213 controls.destroy();
214 controls = null;
215 }
216 }
217 /** This method attempts to parse a subcollection related command from the given command string. If such a string is successfully parsed, it is immediately added to the data within this collection.
218 * @param command The <strong>String</strong> to be parsed.
219 * @param finished This <i>boolean</i> is usually <i>false</i> when called, unless this parse call is being made -after- the entire collection configuration file has been read in in which case it is <i>true</i>.
220 * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
221 * @see org.greenstone.gatherer.cdm.CommandTokenizer
222 * @see org.greenstone.gatherer.cdm.DefaultSubIndex
223 * @see org.greenstone.gatherer.cdm.Subcollection
224 * @see org.greenstone.gatherer.cdm.SubIndex
225 */
226 public boolean parse(String command, boolean finished) {
227 String temp = command.toLowerCase();
228 CommandTokenizer tokenizer = new CommandTokenizer(command);
229 tokenizer.nextToken(); // Throw away head.
230 if(temp.startsWith("subcollection")) {
231 if(tokenizer.countTokens() >= 2) {
232 String name = tokenizer.nextToken();
233 String pattern = tokenizer.nextToken();
234 addSubcollection(new Subcollection(name, pattern));
235 return true;
236 }
237 }
238 else if(temp.startsWith("indexsubcollections")) {
239 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
240 if(!finished) {
241 unresolved.add(command);
242 }
243 else {
244 while(tokenizer.hasMoreTokens()) {
245 addSubIndex(new SubIndex(tokenizer.nextToken(), this));
246 }
247 }
248 return true;
249 }
250 else if(temp.startsWith("defaultsubcollection")) {
251 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
252 if(!finished) {
253 unresolved.add(command);
254 }
255 else {
256 if(tokenizer.hasMoreTokens()) {
257 setDefaultSubIndex(new DefaultSubIndex(tokenizer.nextToken(), this));
258 }
259 }
260 return true;
261 }
262 return false;
263 }
264 /** Method to remove a certain subindex.
265 * @param subindex The <strong>SubIndex</strong> you wish to remove.
266 * @see org.greenstone.gatherer.Gatherer
267 * @see org.greenstone.gatherer.collection.CollectionManager
268 */
269 public void removeSubIndex(SubIndex subindex) {
270 subindexes.removeElement(subindex);
271 gatherer.c_man.configurationChanged();
272 }
273 /** Method to remove all of the subindexes that contain a certain subcollection.
274 * @param sub The <strong>Subcollection</strong> that you wish to remove.
275 * @see org.greenstone.gatherer.Gatherer
276 * @see org.greenstone.gatherer.cdm.SubIndex
277 * @see org.greenstone.gatherer.collection.CollectionManager
278 */
279 public void removeSubIndexes(Subcollection sub) {
280 for(int i = subindexes.size() - 1; i >= 0; i--) {
281 SubIndex subindex = (SubIndex)subindexes.get(i);
282 if(subindex.containsSubcollection(sub.getName())) {
283 subindexes.removeElement(subindex);
284 }
285 }
286 gatherer.c_man.configurationChanged();
287 }
288 /** Method to remove the given subcollection.
289 * @param sub The <strong>Subcollection</strong> you want to remove.
290 * @see org.greenstone.gatherer.Gatherer
291 * @see org.greenstone.gatherer.collection.CollectionManager
292 */
293 public void removeSubcollection(Subcollection sub) {
294 removeElement(sub);
295 subcollections.remove(sub);
296 gatherer.c_man.configurationChanged();
297 }
298 /** Method to retry the parsing of commands that were previously unable to be parsed as they referenced subcollections that may not have been instantiated.
299 */
300 public void reparseUnresolved() {
301 for(int i = 0; i < unresolved.size(); i++) {
302 parse((String)unresolved.get(i), true);
303 }
304 unresolved.clear();
305 }
306 /** Method to set the default subcollection index.
307 * @param subcollection The <strong>Subcollection</strong> to use as the default index.
308 * @see org.greenstone.gatherer.Gatherer
309 * @see org.greenstone.gatherer.collection.CollectionManager
310 */
311 public void setDefaultSubIndex(DefaultSubIndex subindex) {
312 this.default_index = subindex;
313 if(subindex != null) {
314 addSubIndex(subindex.getSubIndex());
315 }
316 gatherer.c_man.configurationChanged();
317 }
318 /** This method causes the contents of this manager to be converted to a string, which is accomplished by calling <i>toString()</i> on each subcollection, then printing out the contents of the index vector.
319 * @return A <strong>String</strong> containing a block of configuration commands.
320 * @see org.greenstone.gatherer.cdm.SubIndex
321 * @see org.greenstone.gatherer.cdm.Subcollection
322 */
323 public String toString() {
324 String text = "";
325 // Retrieve the subcollection names and sort them.
326 if(subcollections.size() > 0) {
327 Vector names = new Vector(subcollections.keySet());
328 Collections.sort(names);
329 for(int i = 0; i < names.size(); i++) {
330 Subcollection sub =
331 (Subcollection) subcollections.get(names.get(i));
332 text = text + sub.toString();
333 }
334 // Now add a entry, separated by spaces for each subcollection
335 // index.
336 if(subindexes.size() > 0) {
337 text = text + subindexes.toString();
338 }
339 // Finally add the default subcollection index if necessary.
340 if(default_index != null) {
341 text = text + default_index.toString();
342 }
343 text = text + "\n";
344 }
345 // Otherwise if there were no subcollections, there aren't going to be
346 // subcollection indexes, nor a default subcollection index are there.
347 return text;
348 }
349 /** Method to retrieve a phrase from the dictionary based on a key.
350 * @param key A <strong>String</strong> used to find the correct phrase.
351 * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
352 * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
353 */
354 private String get(String key) {
355 return get(key, null);
356 }
357 /** Method to retrieve a phrase from the dictionary based on a key.
358 * @param key A <strong>String</strong> used to find the correct phrase.
359 * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
360 * @see org.greenstone.gatherer.Dictionary
361 * @see org.greenstone.gatherer.Gatherer
362 */
363 private String get(String key, String args[]) {
364 if(key.indexOf(".") == -1) {
365 key = "CDM.SubcollectionManager." + key;
366 }
367 return gatherer.dictionary.get(key, args);
368 }
369 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
370 private class Control
371 extends JPanel {
372 /** <i>true</i> if the current selection has changed. */
373 private boolean changed = false;
374 /** Button to add a subcollection. */
375 private JButton add = null;
376 /** Button to add a subindex. */
377 private JButton add_index = null;
378 /** Button to clear the default subindex. */
379 private JButton clear_default = null;
380 /** Button to remove a subcollection. */
381 private JButton remove = null;
382 /** Button to remove a subindex. */
383 private JButton remove_index = null;
384 /** Button to set the default subindex. */
385 private JButton set_default = null;
386 /** Button to cause an update of the subcollections. */
387 private JButton update = null;
388 /** A combobox allowing you to choose which field the data for matching should be taken from. Includes text body and filename, as well as all assigned metadata elements. */
389 private JComboBox source = null;
390 /** The list of assigned subcollections. */
391 private JList subcollection_list = null;
392 /** The list of subcollections available for the creation of subindexes. */
393 private JList subcollection_list_2 = null;
394 /** The list of assigned subindexes. */
395 private JList subindexes_list = null;
396 /** The label denoting the list of subindexes. */
397 private JLabel subindexes_label = null;
398 /** The panel containing the subcollection controls. */
399 private JPanel subcollection_pane = null;
400 /** The panel containing the subindex controls. */
401 private JPanel subindex_pane = null;
402 /** The tabbed pane used to store the subcollection and subindex controls. */
403 private JTabbedPane tabbed_pane = null;
404 /** The area used to display inline instructions. */
405 private JTextArea instructions = null;
406 /** The field displaying the name of the default subindex. */
407 private JTextField default_value = null;
408 /** A field used for specifying flags for the PERL expression matching, such as 'i' for case insensitive. */
409 private JTextField flags = null;
410 /** The pattern the source text must match. */
411 private JTextField match = null;
412 /** The name of this subcollection. */
413 private JTextField name = null;
414 /** When this button is selected the filter matching files are excluded. */
415 private JToggleButton exclude = null;
416 /** When this button is selected the filter matching files are included. */
417 private JToggleButton include = null;
418 /** The existing subcollection whose details you are reviewing, if any. */
419 private Subcollection current = null;
420 /** Constructor, creates the outer parts of the view, then calls two methods in turn to create the subcollection controls and subindex controls.
421 */
422 public Control() {
423 // Create
424 JPanel border_pane = new JPanel();
425 JPanel header_pane = new JPanel();
426 instructions = new JTextArea(get("Instructions"));
427 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
428 instructions.setEditable(false);
429 instructions.setLineWrap(true);
430 instructions.setRows(5);
431 instructions.setWrapStyleWord(true);
432 tabbed_pane = new JTabbedPane();
433 JLabel title = new JLabel(get("Title"));
434 title.setHorizontalAlignment(JLabel.CENTER);
435 createSubcollection();
436 createSubindex();
437 // Add listeners
438 // Layout
439 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
440 header_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
441 header_pane.setLayout(new BorderLayout());
442 header_pane.add(title, BorderLayout.NORTH);
443 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
444 tabbed_pane.addTab(get("Subcollection_Controls"), subcollection_pane);
445 tabbed_pane.addTab(get("Subindex_Controls"), subindex_pane);
446 border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
447 border_pane.setLayout(new BorderLayout());
448 border_pane.add(tabbed_pane, BorderLayout.CENTER);
449 setLayout(new BorderLayout());
450 add(header_pane, BorderLayout.NORTH);
451 add(border_pane, BorderLayout.CENTER);
452 }
453 /** Create the subcollection controls.
454 * @see org.greenstone.gatherer.Gatherer
455 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddListener
456 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ListListener
457 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveListener
458 * @see org.greenstone.gatherer.collection.CollectionManager
459 * @see org.greenstone.gatherer.msm.MetadataSetManager
460 */
461 public void createSubcollection() {
462 // Create
463 add = new JButton(get("Add"));
464 add.setMnemonic(KeyEvent.VK_A);
465 JPanel button_pane = new JPanel();
466 JPanel button_pane_1 = new JPanel();
467 JPanel button_pane_3 = new JPanel();
468 exclude = new JToggleButton(get("Exclude"));
469 exclude.setMnemonic(KeyEvent.VK_X);
470 flags = new JTextField();
471 JLabel flags_label = new JLabel(get("Flags"));
472 include = new JToggleButton(get("Include"));
473 include.setMnemonic(KeyEvent.VK_I);
474 JLabel inclusive_label = new JLabel(get("Inclusive"));
475 JPanel inclusive_pane = new JPanel();
476 match = new JTextField();
477 JLabel match_label = new JLabel(get("Match"));
478 name = new JTextField();
479 JLabel name_label = new JLabel(get("Name"));
480 remove = new JButton(get("Remove"));
481 remove.setMnemonic(KeyEvent.VK_R);
482 Vector source_model = gatherer.c_man.msm.getAssignedElements();
483 source_model.add(0, "Filename");
484 source = new JComboBox(source_model);
485 JLabel source_label = new JLabel(get("Source"));
486 subcollection_list = new JList(model);
487 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
488 subcollection_pane = new JPanel();
489 ButtonGroup bg = new ButtonGroup();
490 bg.add(include);
491 bg.add(exclude);
492 include.setSelected(true);
493 JPanel subcollection_list_pane = new JPanel();
494 JLabel subcollection_list_label = new JLabel(get("Assigned"));
495
496 // Add listeners
497 add.addActionListener(new AddListener());
498 remove.addActionListener(new RemoveListener());
499 subcollection_list.addListSelectionListener(new ListListener());
500
501 // Layout
502 inclusive_pane.setLayout(new GridLayout());
503 inclusive_pane.add(include);
504 inclusive_pane.add(exclude);
505 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
506 button_pane_1.setLayout(new GridLayout(5, 2));
507 button_pane_1.add(name_label);
508 button_pane_1.add(name);
509 button_pane_1.add(source_label);
510 button_pane_1.add(source);
511 button_pane_1.add(match_label);
512 button_pane_1.add(match);
513 button_pane_1.add(inclusive_label);
514 button_pane_1.add(inclusive_pane);
515 button_pane_1.add(flags_label);
516 button_pane_1.add(flags);
517 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
518 button_pane_3.setLayout(new GridLayout(1,2));
519 button_pane_3.add(add);
520 button_pane_3.add(remove);
521 button_pane.setLayout(new BorderLayout());
522 button_pane.add(button_pane_1, BorderLayout.CENTER);
523 button_pane.add(button_pane_3, BorderLayout.SOUTH);
524 subcollection_list_pane.setLayout(new BorderLayout());
525 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
526 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
527 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
528 subcollection_pane.setLayout(new BorderLayout());
529 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
530 subcollection_pane.add(button_pane, BorderLayout.SOUTH);
531 }
532 /** Create the subindex controls.
533 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddSubIndexListener
534 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ClearDefaultListener
535 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ChangeListener
536 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveSubIndexListener
537 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.SetDefaultListener
538 * @see org.greenstone.gatherer.util.ExclusiveListListener
539 */
540 public void createSubindex() {
541 // Creation
542 add_index = new JButton(get("Add_Subindex"));
543 add_index.setMnemonic(KeyEvent.VK_A);
544 JPanel button_pane_2 = new JPanel();
545 clear_default = new JButton(get("Clear_Default_Subindex"));
546 clear_default.setMnemonic(KeyEvent.VK_C);
547 if(default_index == null) {
548 clear_default.setEnabled(false);
549 }
550 JLabel default_label = new JLabel(get("Default_Subindex"));
551 JPanel default_pane = new JPanel();
552 if(default_index == null) {
553 default_value = new JTextField();
554 }
555 else {
556 default_value = new JTextField(default_index.getSubIndex().toString());
557 }
558 JPanel subindex_inner_pane_1 = new JPanel();
559 JPanel subindex_inner_pane_2 = new JPanel();
560 remove_index = new JButton(get("Remove_Subindex"));
561 remove_index.setMnemonic(KeyEvent.VK_R);
562 set_default = new JButton(get("Set_Default_Subindex"));
563 set_default.setMnemonic(KeyEvent.VK_S);
564 JLabel subcollection_label = new JLabel(get("Subcollection"));
565 subcollection_list_2 = new JList(model);
566 JPanel list_2_pane = new JPanel();
567 subindex_pane = new JPanel();
568 JLabel subindexes_label = new JLabel(get("Subindexes"));
569 subindexes_list = new JList(subindexes);
570 subindexes_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
571 JPanel subindexes_pane = new JPanel();
572
573 // Add listeners
574 ChangeListener cl = new ChangeListener();
575 ExclusiveListSelectionListener ell = new ExclusiveListSelectionListener();
576 ell.add(subcollection_list_2);
577 ell.add(subindexes_list);
578 add_index.addActionListener(new AddSubIndexListener());
579 clear_default.addActionListener(new ClearDefaultListener());
580 exclude.addActionListener(cl);
581 include.addActionListener(cl);
582 remove_index.addActionListener(new RemoveSubIndexListener());
583 set_default.addActionListener(new SetDefaultListener());
584 source.addActionListener(cl);
585 flags.addKeyListener(cl);
586 match.addKeyListener(cl);
587 name.addKeyListener(cl);
588
589 // Layout
590 list_2_pane.setLayout(new BorderLayout());
591 list_2_pane.add(subcollection_label, BorderLayout.NORTH);
592 list_2_pane.add(new JScrollPane(subcollection_list_2), BorderLayout.CENTER);
593 subindexes_pane.setLayout(new BorderLayout());
594 subindexes_pane.add(subindexes_label, BorderLayout.NORTH);
595 subindexes_pane.add(new JScrollPane(subindexes_list), BorderLayout.CENTER);
596 subindex_inner_pane_2.setLayout(new GridLayout(2,1));
597 subindex_inner_pane_2.add(list_2_pane);
598 subindex_inner_pane_2.add(subindexes_pane);
599 default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
600 default_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()), BorderFactory.createEmptyBorder(2,2,2,2)));
601 default_pane.setLayout(new BorderLayout());
602 default_pane.add(default_label, BorderLayout.WEST);
603 default_pane.add(default_value, BorderLayout.CENTER);
604 subindex_inner_pane_1.setLayout(new BorderLayout());
605 subindex_inner_pane_1.add(subindex_inner_pane_2, BorderLayout.CENTER);
606 subindex_inner_pane_1.add(default_pane, BorderLayout.SOUTH);
607 button_pane_2.setLayout(new GridLayout(2,2));
608 button_pane_2.add(add_index);
609 button_pane_2.add(remove_index);
610 button_pane_2.add(clear_default);
611 button_pane_2.add(set_default);
612 subindex_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
613 subindex_pane.setLayout(new BorderLayout());
614 subindex_pane.add(subindex_inner_pane_1, BorderLayout.CENTER);
615 subindex_pane.add(button_pane_2, BorderLayout.SOUTH);
616 }
617 /** Method to unregister any listeners to avoid memory leaks.
618 */
619 public void destroy() {
620 }
621 /** We have overriden this method to provide completely different functionality, given that our JPanel will never actually have focus. We call this method in GUI on the view we are about to replace, and this method checks if a change has occured and if so updates the current object.
622 * @return A <i>boolean</i> which is always <i>false</i>.
623 * @see org.greenstone.gatherer.msm.ElementWrapper
624 */
625 public boolean hasFocus() {
626 // If we have a current metadata open, and something has changed then save the change.
627 if(changed && current != null) {
628 String n = name.getText();
629 String s = null;
630 Object o = source.getSelectedItem();
631 if(o instanceof ElementWrapper) {
632 ElementWrapper e = (ElementWrapper)o;
633 s = e.toString();
634 }
635 String e = match.getText();
636 String f = flags.getText();
637 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
638 current.update(n, s, e, include.isSelected(), f);
639 int index = model.indexOf(current);
640 changed();
641 subindexes.changed();
642 if(default_index != null) {
643 default_value.setText(default_index.getSubIndex().toString());
644 }
645 }
646 changed = false;
647 }
648 return false;
649 }
650 /** Overriden to ensure the instructions are scrolled to top.
651 */
652 public void updateUI() {
653 if(instructions != null) {
654 instructions.setCaretPosition(0);
655 }
656 super.updateUI();
657 }
658 /** Listens for actions apon the 'add' button in the SubcollectionManager controls, and if detected calls the addSubcollection method of the manager with a newly created subcollection. */
659 private class AddListener
660 implements ActionListener {
661 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we wish to retrieve information from the various edit controls, and if we have sufficient data to build a new subcollection do so.
662 * @param event An <strong>ActionEvent</strong> containing information about the event.
663 * @see org.greenstone.gatherer.cdm.Subcollection
664 * @see org.greenstone.gatherer.msm.ElementWrapper
665 */
666 public void actionPerformed(ActionEvent event) {
667 String n = name.getText();
668 String s = null;
669 Object o = source.getSelectedItem();
670 if(o instanceof ElementWrapper) {
671 ElementWrapper e = (ElementWrapper)o;
672 s = e.toString();
673 }
674 String e = match.getText();
675 String f = flags.getText();
676 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
677 Subcollection sub = new Subcollection(n, include.isSelected(), s, e, f);
678 addSubcollection(sub);
679 }
680 changed = false;
681 }
682 }
683 /** Listens for actions apon the 'add subindex' button in the SubcollectionManager controls, and if detected calls the addSubindex method of the manager with a newly created subindex. */
684 private class AddSubIndexListener
685 implements ActionListener {
686 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a series of subcollections selected, and if so build an new subindex based apon them.
687 * @param event An <strong>ActionEvent</strong> containing information about the event.
688 * @see org.greenstone.gatherer.cdm.SubIndex
689 */
690 public void actionPerformed(ActionEvent event) {
691 if(!subcollection_list_2.isSelectionEmpty()) {
692 Vector selected = new Vector();
693 Object raw[] = subcollection_list_2.getSelectedValues();
694 for(int i = 0; i < raw.length; i++) {
695 selected.add(raw[i]);
696 }
697 addSubIndex(new SubIndex(selected));
698 }
699 }
700 }
701 /** This class listens for any key entry in a text field, selection change in a combobox or button click, and when detected sets the changed flag to true. Its also convenient to use this class to test if the add button should be active yet. */
702 public class ChangeListener
703 extends KeyAdapter
704 implements ActionListener {
705 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to record that somethings changed, then validate the controls.
706 * @param event An <strong>ActionEvent</strong> containing information about the event.
707 */
708 public void actionPerformed(ActionEvent event) {
709 changed = true;
710 validate();
711 }
712 /** Any inheritor of KeyAdapter can override this method so we can be informed when an key has been type in one of our target controls. In this case we want to record that somethings changed, then validate the controls.
713 * @param event An <strong>KeyEvent</strong> containing information about the event.
714 */
715 public void keyPressed(KeyEvent event) {
716 changed = true;
717 validate();
718 }
719 /** Method to validate the current editor values, and enable or disable controls based on said values. */
720 private void validate() {
721 if(changed && name.getText().length() > 0 && match.getText().length() > 0) {
722 add.setEnabled(true);
723 }
724 else {
725 add.setEnabled(false);
726 }
727 }
728 }
729 /** Listens for actions apon the 'clear default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex() method of the manager with <i>null</i>. */
730 private class ClearDefaultListener
731 implements ActionListener {
732 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to clear the default subindex.
733 * @param event An <strong>ActionEvent</strong> containing information about the event.
734 */
735 public void actionPerformed(ActionEvent event) {
736 setDefaultSubIndex(null);
737 clear_default.setEnabled(false);
738 default_value.setText("");
739 }
740 }
741 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
742 private class ListListener
743 implements ListSelectionListener {
744 /** Any implementation of ListSelectionListener must include this method so we can be informed when the selection changes. In this case we want to execute any changes the users made to the entry, then update the controls with details of the new selection.
745 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
746 * @see org.greenstone.gatherer.cdm.Subcollection
747 * @see org.greenstone.gatherer.msm.ElementWrapper
748 */
749 public void valueChanged(ListSelectionEvent event) {
750 // If we have a previous collection and the users changed something, but not added, then update subcollection.
751 if(changed && current != null) {
752 String n = name.getText();
753 String s = null;
754 Object o = source.getSelectedItem();
755 if(o instanceof ElementWrapper) {
756 ElementWrapper e = (ElementWrapper)o;
757 s = e.toString();
758 }
759 String e = match.getText();
760 String f = flags.getText();
761 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
762 current.update(n, s, e, include.isSelected(), f);
763 int index = model.indexOf(current);
764 changed();
765 subindexes.changed();
766 if(default_index != null) {
767 default_value.setText(default_index.getSubIndex().toString());
768 }
769 }
770 }
771 // Now load the new entry.
772 if(!subcollection_list.isSelectionEmpty()) {
773 current = (Subcollection) subcollection_list.getSelectedValue();
774 flags.setText(current.getFlags());
775 include.setSelected(current.getInclude());
776 exclude.setSelected(!current.getInclude());
777 match.setText(current.getExpression());
778 name.setText(current.getName());
779 String s = current.getSource();
780 int pos = 0;
781 Object value = source.getItemAt(pos);
782 while(value != null) {
783 if(value instanceof ElementWrapper) {
784 ElementWrapper e = (ElementWrapper) value;
785 if(e.toString().equals(s)) {
786 source.setSelectedIndex(pos);
787 value = null;
788 }
789 else {
790 pos++;
791 value = source.getItemAt(pos);
792 }
793 }
794 else if(value.toString().equals(s)) {
795 source.setSelectedIndex(pos);
796 value = null;
797 }
798 else {
799 pos++;
800 value = source.getItemAt(pos);
801 }
802 }
803 // Can't add one thats already there.
804 add.setEnabled(false);
805 // You can remove it though...
806 remove.setEnabled(true);
807 }
808 else {
809 flags.setText("");
810 include.setSelected(true);
811 match.setText("");
812 name.setText("");
813 source.setSelectedIndex(0);
814 remove.setEnabled(false);
815 }
816 // Have to do this after so we don't get called when nothings actually changed.
817 changed = false;
818 }
819 }
820 /** Listens for actions apon the 'remove' button in the SubcollectionManager controls, and if detected calls the remove method of the manager with the SubIndex selected for removal. */
821 private class RemoveListener
822 implements ActionListener {
823 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subcolleciton selected, and if so remove both it and any subindexes based on it.
824 * @param event An <strong>ActionEvent</strong> containing information about the event.
825 * @see org.greenstone.gatherer.cdm.Subcollection
826 */
827 public void actionPerformed(ActionEvent event) {
828 if(!subcollection_list.isSelectionEmpty()) {
829 Subcollection sub_col = (Subcollection)subcollection_list.getSelectedValue();
830 removeSubIndexes(sub_col);
831 removeSubcollection(sub_col);
832 }
833 }
834 }
835 /** Listens for actions apon the 'remove subindex' button in the SubcollectionManager controls, and if detected calls the removeSubIndex method of the manager with the SubIndex selected for removal. */
836 private class RemoveSubIndexListener
837 implements ActionListener {
838 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subindex selected, and if so remove it.
839 * @param event An <strong>ActionEvent</strong> containing information about the event.
840 * @see org.greenstone.gatherer.cdm.SubIndex
841 */
842 public void actionPerformed(ActionEvent event) {
843 if(!subindexes_list.isSelectionEmpty()) {
844 removeSubIndex((SubIndex)subindexes_list.getSelectedValue());
845 }
846 }
847 }
848 /** Listens for actions apon the 'set default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex method of the manager with the SubIndex selected for default. */
849 private class SetDefaultListener
850 implements ActionListener {
851 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subindex selected, and if so set it as default.
852 * @param event An <strong>ActionEvent</strong> containing information about the event.
853 * @see org.greenstone.gatherer.cdm.DefaultSubIndex
854 * @see org.greenstone.gatherer.cdm.SubIndex
855 */
856 public void actionPerformed(ActionEvent event) {
857 if(!subindexes_list.isSelectionEmpty()) {
858 setDefaultSubIndex(new DefaultSubIndex((SubIndex)subindexes_list.getSelectedValue()));
859 clear_default.setEnabled(true);
860 default_value.setText(default_index.getSubIndex().toString());
861 }
862 }
863 }
864 }
865}
866
867
868
869
870
871
872
873
874
Note: See TracBrowser for help on using the repository browser.