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

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

forgot to remove my print statements in the last commit

  • Property svn:keywords set to Author Date Id Revision
File size: 41.5 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.*;
53import java.awt.event.*;
54import java.util.*;
55import javax.swing.*;
56import javax.swing.event.*;
57import org.greenstone.gatherer.Gatherer;
58import org.greenstone.gatherer.cdm.Subcollection;
59import org.greenstone.gatherer.cdm.SubIndex;
60import org.greenstone.gatherer.cdm.SubIndexes;
61import org.greenstone.gatherer.msm.ElementWrapper;
62import org.greenstone.gatherer.util.ExclusiveListSelectionListener;
63import org.w3c.dom.Element;
64/** This class maintains a list of subcollections within our collection, and also records which of these subcollections we are building indexes for.
65 * @author John Thompson, Greenstone Digital Library, University of Waikato
66 * @version 2.1
67 */
68public class SubcollectionManager
69 extends DefaultListModel {
70 /** A reference to the manager so we can get access to languages. */
71 private CollectionDesignManager manager;
72 /** The controls used to edit the settings of this manager. */
73 private Control controls = null;
74 /** A reference to this class so we can use it as a model in our inner classes. */
75 private DefaultListModel model = null;
76 /** The default index for the subcollections. */
77 private DefaultSubIndex default_index = null;
78 /** A reference to the Gatherer. */
79 private Gatherer gatherer = null;
80 /** A hashtable of subcollections, with mappings from name to subcollection. */
81 private Hashtable subcollections = null;
82 /** A vector-type structure of subcollection indexes. */
83 private SubIndexes subindexes = null;
84 /** 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. */
85 private ArrayList unresolved = null;
86 /** Constructor.
87 * @param gatherer A reference to the <Strong>Gatherer</strong>.
88 * @see org.greenstone.gatherer.cdm.SubIndexes
89 */
90 public SubcollectionManager(Gatherer gatherer, CollectionDesignManager manager) {
91 super();
92 this.gatherer = gatherer;
93 this.manager = manager;
94 this.model = this;
95 this.subcollections = new Hashtable();
96 this.subindexes = new SubIndexes();
97 this.unresolved = new ArrayList();
98 }
99 /** Method to add a subindex.
100 * @param subindex A <strong>SubIndex</strong>.
101 * @see org.greenstone.gatherer.Gatherer
102 * @see org.greenstone.gatherer.collection.CollectionManager
103 */
104 public void addSubIndex(SubIndex subindex) {
105 if(!subindexes.contains(subindex)) {
106 subindexes.addElement(subindex);
107 gatherer.c_man.configurationChanged();
108 }
109 }
110 /** Method to add a new subcollection. Adds it to both the underlying list model and the hashtable mapping names to subcollections.
111 * @param sub The <strong>Subcollection</strong> to add.
112 * @return A <i>boolean</i> indicating if the addition was successful (<i>true</i>) or not (<i>false</i>).
113 * @see org.greenstone.gatherer.Gatherer
114 * @see org.greenstone.gatherer.collection.CollectionManager
115 */
116 public boolean addSubcollection(Subcollection sub) {
117 if(!contains(sub)) {
118 addElement(sub);
119 subcollections.put(sub.getName(), sub);
120 gatherer.c_man.configurationChanged();
121 return true;
122 }
123 return false;
124 }
125 /** 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.
126 * @param name A <>>String</>> which is a unique identifier of a subcollection.
127 * @param include A <i>boolean</i> indicating whether this is an inclusion filter (<i>true</i>) or an exclusion one (<i>false</i>).
128 * @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.
129 * @param exp A <>>String</>> containing a Perl expression which is used as the filter for this subcollection.
130 * @param flags A <strong>String<strong> listing any special flags to be applied when matching the expression.
131 * @return A <i>boolean</i> with a value of <i>true</i> if the addition was successful.
132 * @see org.greenstone.gatherer.cdm.Subcollection
133 */
134 public boolean addSubcollection(String name, boolean include, String element, String exp, String flags) {
135 Subcollection sub = null;
136 if(element != null) {
137 sub = new Subcollection(name, include, element, exp, flags);
138 }
139 else {
140 sub = new Subcollection(name, include, exp, flags);
141 }
142 return addSubcollection(sub);
143 }
144 /** Refresh all derived components using this manager as a model.
145 */
146 public void changed() {
147 fireContentsChanged(this, 0, getSize() - 1);
148 }
149 /** Method to retrieve the controls for this manager.
150 * @return A <Strong>Control</strong> object which contains the controls used to edit the subcollection data.
151 */
152 public Control getControls() {
153 if(controls == null) {
154 controls = new Control();
155 }
156 return controls;
157 }
158 /** Method to retrieve the default index.
159 * @return A <strong>DefaultSubIndex</strong> object.
160 */
161 public DefaultSubIndex getDefaultSubIndex() {
162 return default_index;
163 }
164 /** Method to retrieve a certain subcollection by its name.
165 * @param name A <strong>String</strong> which is used as the key for finding the matching subcollection.
166 * @return The requested <strong>Subcollection</strong> or <i>null</i> if no such subcollection exists.
167 */
168 public Subcollection getSubcollection(String name) {
169 return (Subcollection) subcollections.get(name);
170 }
171
172 /** Retrieve a certain subindex given its name.
173 * @param name the String representation of a subindex.
174 * @return the SubIndex requested or null if no such subindex.
175 */
176 public SubIndex getSubIndex(String name) {
177 for(int i = 0; i < subindexes.size(); i++) {
178 SubIndex subindex = (SubIndex) subindexes.get(i);
179 if(subindex.toString().equals(name)) {
180 return subindex;
181 }
182 }
183 return null;
184 }
185
186 /** Method to get all of the subindexes set.
187 * @return A <strong>SubIndexes</strong> object containing all the defined indexes.
188 */
189 public SubIndexes getSubIndexes() {
190 return subindexes;
191 }
192 /** Method to get all of the subcollections defined.
193 * @return A <strong>Vector</strong> of subcollections.
194 */
195 public Vector getSubcollections() {
196 Vector subcollections = new Vector();
197 for(int i = 0; i < size(); i++) {
198 subcollections.add(get(i));
199 }
200 return subcollections;
201 }
202 /** Mark the current controls, if any, as invalid and deallocate them. Any further use of the controls will requires them being rebuilt.
203 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control
204 */
205 public void invalidateControls() {
206 if(controls != null) {
207 controls.destroy();
208 controls = null;
209 }
210 }
211 /** 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.
212 * @param command The <strong>String</strong> to be parsed.
213 * @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>.
214 * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise.
215 * @see org.greenstone.gatherer.cdm.CommandTokenizer
216 * @see org.greenstone.gatherer.cdm.DefaultSubIndex
217 * @see org.greenstone.gatherer.cdm.Subcollection
218 * @see org.greenstone.gatherer.cdm.SubIndex
219 */
220 public boolean parse(String command, boolean finished) {
221 String temp = command.toLowerCase();
222 CommandTokenizer tokenizer = new CommandTokenizer(command);
223 tokenizer.nextToken(); // Throw away head.
224 if(temp.startsWith("subcollection")) {
225 if(tokenizer.countTokens() >= 2) {
226 String name = tokenizer.nextToken();
227 String pattern = tokenizer.nextToken();
228 addSubcollection(new Subcollection(name, pattern));
229 return true;
230 }
231 }
232 else if(temp.startsWith("indexsubcollections")) {
233 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
234 if(!finished) {
235 unresolved.add(command);
236 }
237 else {
238 while(tokenizer.hasMoreTokens()) {
239 addSubIndex(new SubIndex(tokenizer.nextToken(), this));
240 }
241 }
242 return true;
243 }
244 else if(temp.startsWith("defaultsubcollection")) {
245 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete.
246 if(!finished) {
247 unresolved.add(command);
248 }
249 else {
250 if(tokenizer.hasMoreTokens()) {
251 setDefaultSubIndex(new DefaultSubIndex(tokenizer.nextToken(), this));
252 }
253 }
254 return true;
255 }
256 return false;
257 }
258 /** Method to remove a certain subindex.
259 * @param subindex The <strong>SubIndex</strong> you wish to remove.
260 * @see org.greenstone.gatherer.Gatherer
261 * @see org.greenstone.gatherer.collection.CollectionManager
262 */
263 public void removeSubIndex(SubIndex subindex) {
264 subindexes.removeElement(subindex);
265 gatherer.c_man.configurationChanged();
266 }
267 /** Method to remove all of the subindexes that contain a certain subcollection.
268 * @param sub The <strong>Subcollection</strong> that you wish to remove.
269 * @see org.greenstone.gatherer.Gatherer
270 * @see org.greenstone.gatherer.cdm.SubIndex
271 * @see org.greenstone.gatherer.collection.CollectionManager
272 */
273 public void removeSubIndexes(Subcollection sub) {
274 for(int i = subindexes.size() - 1; i >= 0; i--) {
275 SubIndex subindex = (SubIndex)subindexes.get(i);
276 if(subindex.containsSubcollection(sub.getName())) {
277 subindexes.removeElement(subindex);
278 }
279 }
280 gatherer.c_man.configurationChanged();
281 }
282 /** Method to remove the given subcollection.
283 * @param sub The <strong>Subcollection</strong> you want to remove.
284 * @see org.greenstone.gatherer.Gatherer
285 * @see org.greenstone.gatherer.collection.CollectionManager
286 */
287 public void removeSubcollection(Subcollection sub) {
288 removeElement(sub);
289 subcollections.remove(sub);
290 gatherer.c_man.configurationChanged();
291 }
292 /** Method to retry the parsing of commands that were previously unable to be parsed as they referenced subcollections that may not have been instantiated.
293 */
294 public void reparseUnresolved() {
295 for(int i = 0; i < unresolved.size(); i++) {
296 parse((String)unresolved.get(i), true);
297 }
298 unresolved.clear();
299 }
300 /** Method to set the default subcollection index.
301 * @param subcollection The <strong>Subcollection</strong> to use as the default index.
302 * @see org.greenstone.gatherer.Gatherer
303 * @see org.greenstone.gatherer.collection.CollectionManager
304 */
305 public void setDefaultSubIndex(DefaultSubIndex subindex) {
306 this.default_index = subindex;
307 if(subindex != null) {
308 addSubIndex(subindex.getSubIndex());
309 }
310 gatherer.c_man.configurationChanged();
311 }
312 /** 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.
313 * @return A <strong>String</strong> containing a block of configuration commands.
314 * @see org.greenstone.gatherer.cdm.SubIndex
315 * @see org.greenstone.gatherer.cdm.Subcollection
316 */
317 public String toString() {
318 String text = "";
319 // Retrieve the subcollection names and sort them.
320 if(subcollections.size() > 0) {
321 Vector names = new Vector(subcollections.keySet());
322 Collections.sort(names);
323 for(int i = 0; i < names.size(); i++) {
324 Subcollection sub =
325 (Subcollection) subcollections.get(names.get(i));
326 text = text + sub.toString();
327 }
328 // Now add a entry, separated by spaces for each subcollection
329 // index.
330 if(subindexes.size() > 0) {
331 text = text + subindexes.toString();
332 }
333 // Finally add the default subcollection index if necessary.
334 if(default_index != null) {
335 text = text + default_index.toString();
336 }
337 text = text + "\n";
338 }
339 // Otherwise if there were no subcollections, there aren't going to be
340 // subcollection indexes, nor a default subcollection index are there.
341 return text;
342 }
343 /** Method to retrieve a phrase from the dictionary based on a key.
344 * @param key A <strong>String</strong> used to find the correct phrase.
345 * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase.
346 * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
347 */
348 private String get(String key) {
349 return get(key, null);
350 }
351 /** Method to retrieve a phrase from the dictionary based on a key.
352 * @param key A <strong>String</strong> used to find the correct phrase.
353 * @return A <strong>String</strong> containing the correct phrase with the correct formatting.
354 * @see org.greenstone.gatherer.Dictionary
355 * @see org.greenstone.gatherer.Gatherer
356 */
357 private String get(String key, String args[]) {
358 if(key.indexOf(".") == -1) {
359 key = "CDM.SubcollectionManager." + key;
360 }
361 return gatherer.dictionary.get(key, args);
362 }
363 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
364 private class Control
365 extends JPanel {
366 /** <i>true</i> if the current selection has changed. */
367 private boolean changed = false;
368 /** Button to add a subcollection. */
369 private JButton add = null;
370 /** Button to add a subindex. */
371 private JButton add_index = null;
372 /** Button to clear the default subindex. */
373 private JButton clear_default = null;
374 /** Button to remove a subcollection. */
375 private JButton remove = null;
376 /** Button to remove a subindex. */
377 private JButton remove_index = null;
378 /** Button to set the default subindex. */
379 private JButton set_default = null;
380 /** Button to cause an update of the subcollections. */
381 private JButton update = null;
382 /** 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. */
383 private JComboBox source = null;
384 /** The list of assigned subcollections. */
385 private JList subcollection_list = null;
386 /** The list of subcollections available for the creation of subindexes. */
387 private JList subcollection_list_2 = null;
388 /** The list of assigned subindexes. */
389 private JList subindexes_list = null;
390 /** The label denoting the list of subindexes. */
391 private JLabel subindexes_label = null;
392 /** The panel containing the subcollection controls. */
393 private JPanel subcollection_pane = null;
394 /** The panel containing the subindex controls. */
395 private JPanel subindex_pane = null;
396 /** The tabbed pane used to store the subcollection and subindex controls. */
397 private JTabbedPane tabbed_pane = null;
398 /** The area used to display inline instructions. */
399 private JTextArea instructions = null;
400 /** The field displaying the name of the default subindex. */
401 private JTextField default_value = null;
402 /** A field used for specifying flags for the PERL expression matching, such as 'i' for case insensitive. */
403 private JTextField flags = null;
404 /** The pattern the source text must match. */
405 private JTextField match = null;
406 /** The name of this subcollection. */
407 private JTextField name = null;
408 /** The name of this subindex. */
409 private JTextField subindex_name;
410 /** When this button is selected the filter matching files are excluded. */
411 private JToggleButton exclude = null;
412 /** When this button is selected the filter matching files are included. */
413 private JToggleButton include = null;
414 /** The existing subcollection whose details you are reviewing, if any. */
415 private Subcollection current = null;
416 /** Constructor, creates the outer parts of the view, then calls two methods in turn to create the subcollection controls and subindex controls.
417 */
418 public Control() {
419 // Create
420 JPanel border_pane = new JPanel();
421 JPanel header_pane = new JPanel();
422 instructions = new JTextArea(get("Instructions"));
423 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
424 instructions.setEditable(false);
425 instructions.setLineWrap(true);
426 instructions.setRows(5);
427 instructions.setWrapStyleWord(true);
428 tabbed_pane = new JTabbedPane();
429 JLabel title = new JLabel(get("Title"));
430 title.setHorizontalAlignment(JLabel.CENTER);
431 createSubCollection();
432 createSubIndex();
433 // Add listeners
434 // Layout
435 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
436 header_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
437 header_pane.setLayout(new BorderLayout());
438 header_pane.add(title, BorderLayout.NORTH);
439 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
440 tabbed_pane.addTab(get("Subcollection_Controls"), subcollection_pane);
441 tabbed_pane.addTab(get("Subindex_Controls"), subindex_pane);
442 tabbed_pane.addTab(get("Language_Controls"), manager.languages.getControls());
443 border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
444 border_pane.setLayout(new BorderLayout());
445 border_pane.add(tabbed_pane, BorderLayout.CENTER);
446 setLayout(new BorderLayout());
447 add(header_pane, BorderLayout.NORTH);
448 add(border_pane, BorderLayout.CENTER);
449 }
450 /** Create the subcollection controls.
451 * @see org.greenstone.gatherer.Gatherer
452 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddListener
453 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ListListener
454 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveListener
455 * @see org.greenstone.gatherer.collection.CollectionManager
456 * @see org.greenstone.gatherer.msm.MetadataSetManager
457 */
458 public void createSubCollection() {
459 // Create
460 add = new JButton(get("Add"));
461 add.setMnemonic(KeyEvent.VK_A);
462 add.setEnabled(false);
463 JPanel button_pane = new JPanel();
464 JPanel button_pane_1 = new JPanel();
465 JPanel button_pane_3 = new JPanel();
466 exclude = new JToggleButton(get("Exclude"));
467 exclude.setMnemonic(KeyEvent.VK_X);
468 flags = new JTextField();
469 JLabel flags_label = new JLabel(get("Flags"));
470 include = new JToggleButton(get("Include"));
471 include.setMnemonic(KeyEvent.VK_I);
472 JLabel inclusive_label = new JLabel(get("Inclusive"));
473 JPanel inclusive_pane = new JPanel();
474 match = new JTextField();
475 JLabel match_label = new JLabel(get("Match"));
476 name = new JTextField();
477 JLabel name_label = new JLabel(get("Name"));
478 remove = new JButton(get("Remove"));
479 remove.setMnemonic(KeyEvent.VK_R);
480 remove.setEnabled(false);
481 Vector source_model = gatherer.c_man.msm.getAssignedElements();
482 source_model.add(0, "Filename");
483 source = new JComboBox(source_model);
484 JLabel source_label = new JLabel(get("Source"));
485 subcollection_list = new JList(model);
486 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
487 subcollection_pane = new JPanel();
488 ButtonGroup bg = new ButtonGroup();
489 bg.add(include);
490 bg.add(exclude);
491 include.setSelected(true);
492 JPanel subcollection_list_pane = new JPanel();
493 JLabel subcollection_list_label = new JLabel(get("Assigned"));
494
495 // Add listeners
496 SubCollectionChangeListener cl = new SubCollectionChangeListener();
497 add.addActionListener(new AddSubCollectionListener());
498 remove.addActionListener(new RemoveSubCollectionListener());
499 subcollection_list.addListSelectionListener(new SubCollectionListListener());
500 //exclude.addActionListener(cl);
501 //include.addActionListener(cl);
502 //source.addActionListener(cl);
503 //flags.addDocumentListener(cl);
504 match.getDocument().addDocumentListener(cl);
505 name.getDocument().addDocumentListener(cl);
506
507 // Layout
508 inclusive_pane.setLayout(new GridLayout());
509 inclusive_pane.add(include);
510 inclusive_pane.add(exclude);
511 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
512 button_pane_1.setLayout(new GridLayout(5, 2));
513 button_pane_1.add(name_label);
514 button_pane_1.add(name);
515 button_pane_1.add(source_label);
516 button_pane_1.add(source);
517 button_pane_1.add(match_label);
518 button_pane_1.add(match);
519 button_pane_1.add(inclusive_label);
520 button_pane_1.add(inclusive_pane);
521 button_pane_1.add(flags_label);
522 button_pane_1.add(flags);
523 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
524 button_pane_3.setLayout(new GridLayout(1,2));
525 button_pane_3.add(add);
526 button_pane_3.add(remove);
527 button_pane.setLayout(new BorderLayout());
528 button_pane.add(button_pane_1, BorderLayout.CENTER);
529 button_pane.add(button_pane_3, BorderLayout.SOUTH);
530 subcollection_list_pane.setLayout(new BorderLayout());
531 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
532 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
533 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
534 subcollection_pane.setLayout(new BorderLayout());
535 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
536 subcollection_pane.add(button_pane, BorderLayout.SOUTH);
537 }
538 /** Create the subindex controls.
539 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddSubIndexListener
540 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ClearDefaultListener
541 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ChangeListener
542 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.RemoveSubIndexListener
543 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.SetDefaultListener
544 * @see org.greenstone.gatherer.util.ExclusiveListListener
545 */
546 public void createSubIndex() {
547 // Creation
548 JPanel subindex_name_panel = new JPanel();
549 JLabel subindex_name_label = new JLabel(get("PartitionName"));
550 subindex_name = new JTextField();
551
552 add_index = new JButton(get("Add_Subindex"));
553 add_index.setMnemonic(KeyEvent.VK_A);
554 add_index.setEnabled(false);
555 JPanel button_pane_2 = new JPanel();
556 clear_default = new JButton(get("Clear_Default_Subindex"));
557 clear_default.setMnemonic(KeyEvent.VK_C);
558 if(default_index == null) {
559 clear_default.setEnabled(false);
560 }
561 JLabel default_label = new JLabel(get("Default_Subindex"));
562 JPanel default_pane = new JPanel();
563 if(default_index == null) {
564 default_value = new JTextField();
565 }
566 else {
567 default_value = new JTextField(default_index.getSubIndex().toString());
568 }
569 default_value.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
570 default_value.setEditable(false);
571 JPanel subindex_inner_pane_1 = new JPanel();
572 JPanel subindex_inner_pane_2 = new JPanel();
573 remove_index = new JButton(get("Remove_Subindex"));
574 remove_index.setMnemonic(KeyEvent.VK_R);
575 set_default = new JButton(get("Set_Default_Subindex"));
576 set_default.setMnemonic(KeyEvent.VK_S);
577 JLabel subcollection_label = new JLabel(get("Subcollection"));
578 subcollection_list_2 = new JList(model);
579 JPanel list_2_pane = new JPanel();
580 subindex_pane = new JPanel();
581 JLabel subindexes_label = new JLabel(get("Subindexes"));
582 subindexes_list = new JList(subindexes);
583 subindexes_list.setCellRenderer(new SubIndexListCellRenderer());
584 subindexes_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
585 JPanel subindexes_pane = new JPanel();
586
587 // Add listeners
588 ExclusiveListSelectionListener ell = new ExclusiveListSelectionListener();
589 ell.add(subcollection_list_2);
590 ell.add(subindexes_list);
591 add_index.addActionListener(new AddSubIndexListener());
592 clear_default.addActionListener(new ClearDefaultSubIndexListener());
593 remove_index.addActionListener(new RemoveSubIndexListener());
594 set_default.addActionListener(new SetDefaultSubIndexListener());
595
596 subindex_name.getDocument().addDocumentListener(new SubIndexNameDocumentListener());
597 subcollection_list_2.addListSelectionListener(new SubCollectionList2Listener());
598
599 // Layout
600 subindex_name_panel.setLayout(new BorderLayout());
601 subindex_name_panel.add(subindex_name_label, BorderLayout.WEST);
602 subindex_name_panel.add(subindex_name, BorderLayout.CENTER);
603
604 list_2_pane.setLayout(new BorderLayout());
605 list_2_pane.add(subcollection_label, BorderLayout.NORTH);
606 list_2_pane.add(new JScrollPane(subcollection_list_2), BorderLayout.CENTER);
607
608 subindexes_pane.setLayout(new BorderLayout());
609 subindexes_pane.add(subindexes_label, BorderLayout.NORTH);
610 subindexes_pane.add(new JScrollPane(subindexes_list), BorderLayout.CENTER);
611
612 subindex_inner_pane_2.setLayout(new GridLayout(1,2,0,5));
613 subindex_inner_pane_2.add(list_2_pane);
614 subindex_inner_pane_2.add(subindexes_pane);
615
616 default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
617 default_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()), BorderFactory.createEmptyBorder(2,2,2,2)));
618 default_pane.setLayout(new BorderLayout());
619 default_pane.add(default_label, BorderLayout.WEST);
620 default_pane.add(default_value, BorderLayout.CENTER);
621
622 subindex_inner_pane_1.setLayout(new BorderLayout());
623 subindex_inner_pane_1.add(subindex_name_panel, BorderLayout.NORTH);
624 subindex_inner_pane_1.add(subindex_inner_pane_2, BorderLayout.CENTER);
625 subindex_inner_pane_1.add(default_pane, BorderLayout.SOUTH);
626
627 button_pane_2.setLayout(new GridLayout(2,2));
628 button_pane_2.add(add_index);
629 button_pane_2.add(remove_index);
630 button_pane_2.add(clear_default);
631 button_pane_2.add(set_default);
632
633 subindex_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
634 subindex_pane.setLayout(new BorderLayout());
635 subindex_pane.add(subindex_inner_pane_1, BorderLayout.CENTER);
636 subindex_pane.add(button_pane_2, BorderLayout.SOUTH);
637 }
638
639
640 /** Method to unregister any listeners to avoid memory leaks.
641 */
642 public void destroy() {
643 }
644 /** 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.
645 * @return A <i>boolean</i> which is always <i>false</i>.
646 * @see org.greenstone.gatherer.msm.ElementWrapper
647 */
648 public boolean hasFocus() {
649 // If we have a current metadata open, and something has changed then save the change.
650 if(changed && current != null) {
651 String n = name.getText();
652 String s = null;
653 Object o = source.getSelectedItem();
654 if(o instanceof ElementWrapper) {
655 ElementWrapper e = (ElementWrapper)o;
656 s = e.toString();
657 }
658 String e = match.getText();
659 String f = flags.getText();
660 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
661 current.update(n, s, e, include.isSelected(), f);
662 int index = model.indexOf(current);
663 changed();
664 subindexes.changed();
665 if(default_index != null) {
666 default_value.setText(default_index.getSubIndex().toString());
667 }
668 }
669 changed = false;
670 }
671 return false;
672 }
673 /** Overriden to ensure the instructions are scrolled to top.
674 */
675 public void updateUI() {
676 if(instructions != null) {
677 instructions.setCaretPosition(0);
678 }
679 super.updateUI();
680 }
681
682 /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values.
683 * we want to disable add until a new name is present
684 */
685 protected void validateAdd() {
686 if(changed && name.getText().length() > 0 && match.getText().length() > 0) {
687 if (subcollections.containsKey(name.getText())) {
688 add.setEnabled(false);
689 } else {
690 add.setEnabled(true);
691 }
692 }
693 else {
694 add.setEnabled(false);
695 }
696 }
697 /** 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. */
698 private class AddSubCollectionListener
699 implements ActionListener {
700 /** 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.
701 * @param event An <strong>ActionEvent</strong> containing information about the event.
702 * @see org.greenstone.gatherer.cdm.Subcollection
703 * @see org.greenstone.gatherer.msm.ElementWrapper
704 */
705 public void actionPerformed(ActionEvent event) {
706 String n = name.getText(); // not allowed spaces!
707 if (n.indexOf(' ')!=-1) {
708 n = n.substring(0, n.indexOf(' '));
709 name.setText(n);
710 }
711 String s = null;
712 Object o = source.getSelectedItem();
713 if(o instanceof ElementWrapper) {
714 ElementWrapper e = (ElementWrapper)o;
715 s = e.toString();
716 }
717 String e = match.getText();
718 String f = flags.getText();
719 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
720 Subcollection sub = new Subcollection(n, include.isSelected(), s, e, f);
721 addSubcollection(sub);
722 }
723 changed = false;
724 validateAdd();
725 }
726 }
727 /** 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. */
728 private class AddSubIndexListener
729 implements ActionListener {
730 /** 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.
731 * @param event An <strong>ActionEvent</strong> containing information about the event.
732 * @see org.greenstone.gatherer.cdm.SubIndex
733 */
734 public void actionPerformed(ActionEvent event) {
735 if(!subcollection_list_2.isSelectionEmpty() && subindex_name.getText().length() > 0) {
736 Vector selected = new Vector();
737 Object raw[] = subcollection_list_2.getSelectedValues();
738 for(int i = 0; i < raw.length; i++) {
739 selected.add(raw[i]);
740 }
741 SubIndex subindex = new SubIndex(selected);
742 addSubIndex(subindex);
743 // Add the subindexes name.
744 CollectionMeta metadata = new CollectionMeta(manager, subindex, manager.languages.getDefaultLanguage(), subindex_name.getText());
745 manager.collectionmetadatum.addMetadata(metadata);
746 }
747 }
748 }
749 /** 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. */
750 private class SubCollectionChangeListener
751 implements DocumentListener, ActionListener {
752 /** 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.
753 * @param event An <strong>ActionEvent</strong> containing information about the event.
754 */
755 public void actionPerformed(ActionEvent event) {
756 changed = true;
757 validateAdd();
758 }
759
760 public void changedUpdate(DocumentEvent event) {
761 changed = true;
762 validateAdd();
763 }
764 public void insertUpdate(DocumentEvent event) {
765 changed = true;
766 validateAdd();
767
768 }
769
770 public void removeUpdate(DocumentEvent event) {
771 changed = true;
772 validateAdd();
773 }
774 }
775 /** 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>. */
776 private class ClearDefaultSubIndexListener
777 implements ActionListener {
778 /** 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.
779 * @param event An <strong>ActionEvent</strong> containing information about the event.
780 */
781 public void actionPerformed(ActionEvent event) {
782 setDefaultSubIndex(null);
783 clear_default.setEnabled(false);
784 default_value.setText("");
785 }
786 }
787 /** 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. */
788 private class RemoveSubCollectionListener
789 implements ActionListener {
790 /** 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.
791 * @param event An <strong>ActionEvent</strong> containing information about the event.
792 * @see org.greenstone.gatherer.cdm.Subcollection
793 */
794 public void actionPerformed(ActionEvent event) {
795 if(!subcollection_list.isSelectionEmpty()) {
796 Subcollection sub_col = (Subcollection)subcollection_list.getSelectedValue();
797 removeSubIndexes(sub_col);
798 removeSubcollection(sub_col);
799 }
800 }
801 }
802 /** 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. */
803 private class RemoveSubIndexListener
804 implements ActionListener {
805 /** 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.
806 * @param event An <strong>ActionEvent</strong> containing information about the event.
807 * @see org.greenstone.gatherer.cdm.SubIndex
808 */
809 public void actionPerformed(ActionEvent event) {
810 if(!subindexes_list.isSelectionEmpty()) {
811 removeSubIndex((SubIndex)subindexes_list.getSelectedValue());
812 }
813 }
814 }
815 /** 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. */
816 private class SetDefaultSubIndexListener
817 implements ActionListener {
818 /** 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.
819 * @param event An <strong>ActionEvent</strong> containing information about the event.
820 * @see org.greenstone.gatherer.cdm.DefaultSubIndex
821 * @see org.greenstone.gatherer.cdm.SubIndex
822 */
823 public void actionPerformed(ActionEvent event) {
824 if(!subindexes_list.isSelectionEmpty()) {
825 setDefaultSubIndex(new DefaultSubIndex((SubIndex)subindexes_list.getSelectedValue()));
826 clear_default.setEnabled(true);
827 default_value.setText(default_index.getSubIndex().toString());
828 }
829 }
830 }
831
832
833 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
834 private class SubCollectionListListener
835 implements ListSelectionListener {
836 /** 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.
837 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
838 * @see org.greenstone.gatherer.cdm.Subcollection
839 * @see org.greenstone.gatherer.msm.ElementWrapper
840 */
841 public void valueChanged(ListSelectionEvent event) {
842 // If we have a previous collection and the users changed something, but not added, then update subcollection.
843 if(changed && current != null) {
844 String n = name.getText();
845 String s = null;
846 Object o = source.getSelectedItem();
847 if(o instanceof ElementWrapper) {
848 ElementWrapper e = (ElementWrapper)o;
849 s = e.toString();
850 }
851 String e = match.getText();
852 String f = flags.getText();
853 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) {
854 current.update(n, s, e, include.isSelected(), f);
855 int index = model.indexOf(current);
856 changed();
857 subindexes.changed();
858 if(default_index != null) {
859 default_value.setText(default_index.getSubIndex().toString());
860 }
861 }
862 }
863 // Now load the new entry.
864 if(!subcollection_list.isSelectionEmpty()) {
865 current = (Subcollection) subcollection_list.getSelectedValue();
866 flags.setText(current.getFlags());
867 include.setSelected(current.getInclude());
868 exclude.setSelected(!current.getInclude());
869 match.setText(current.getExpression());
870 name.setText(current.getName());
871 String s = current.getSource();
872 int pos = 0;
873 Object value = source.getItemAt(pos);
874 while(value != null) {
875 if(value instanceof ElementWrapper) {
876 ElementWrapper e = (ElementWrapper) value;
877 if(e.toString().equals(s)) {
878 source.setSelectedIndex(pos);
879 value = null;
880 }
881 else {
882 pos++;
883 value = source.getItemAt(pos);
884 }
885 }
886 else if(value.toString().equals(s)) {
887 source.setSelectedIndex(pos);
888 value = null;
889 }
890 else {
891 pos++;
892 value = source.getItemAt(pos);
893 }
894 }
895 // Can't add one thats already there.
896 add.setEnabled(false);
897 // You can remove it though...
898 remove.setEnabled(true);
899 }
900 else {
901 flags.setText("");
902 include.setSelected(true);
903 match.setText("");
904 name.setText("");
905 source.setSelectedIndex(0);
906 remove.setEnabled(false);
907 }
908 // Have to do this after so we don't get called when nothings actually changed.
909 changed = false;
910
911 }
912 }
913
914 private class SubCollectionList2Listener
915 implements ListSelectionListener {
916
917 public void valueChanged(ListSelectionEvent event) {
918 if(!event.getValueIsAdjusting()) {
919 add_index.setEnabled(!subcollection_list_2.isSelectionEmpty() && subindex_name.getText().length() > 0);
920 }
921 }
922 }
923
924 private class SubIndexListCellRenderer
925 extends DefaultListCellRenderer {
926
927 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
928 StringBuffer text = new StringBuffer(value.toString());
929 // Retrieve the indexes name if any.
930 CollectionMeta metadata = manager.collectionmetadatum.getMetadata(value, manager.languages.getDefaultLanguage(), true);
931 if(metadata != null) {
932 text.append(" \"");
933 text.append(metadata.getValue());
934 text.append("\"");
935 }
936 return super.getListCellRendererComponent(list, text.toString(), index, isSelected, cellHasFocus);
937 }
938
939 }
940
941 private class SubIndexNameDocumentListener
942 implements DocumentListener {
943 /** Gives notification that an attribute or set of attributes changed. */
944 public void changedUpdate(DocumentEvent e) {
945 update();
946 }
947 /** Gives notification that there was an insert into the document. */
948 public void insertUpdate(DocumentEvent e) {
949 update();
950 }
951 /** Gives notification that a portion of the document has been removed. */
952 public void removeUpdate(DocumentEvent e) {
953 update();
954 }
955 /** The text area has changed in some way. Given that this can only happed when we are editing or adding a text fragment we better respond appropriately. */
956 private void update() {
957 add_index.setEnabled(!subcollection_list_2.isSelectionEmpty() && subindex_name.getText().length() > 0);
958 }
959 }
960
961 }
962}
963
964
965
966
967
968
969
970
971
Note: See TracBrowser for help on using the repository browser.