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

Last change on this file since 8853 was 8576, checked in by mdewsnip, 20 years ago

Removed some redundant files and made a few minor tidy ups.

  • Property svn:keywords set to Author Date Id Revision
File size: 23.3 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
30import java.awt.*;
31import java.awt.event.*;
32import java.util.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import org.greenstone.gatherer.Configuration;
36import org.greenstone.gatherer.DebugStream;
37import org.greenstone.gatherer.Dictionary;
38import org.greenstone.gatherer.Gatherer;
39import org.greenstone.gatherer.gui.GLIButton;
40import org.greenstone.gatherer.gui.NonWhitespaceField;
41import org.greenstone.gatherer.metadata.MetadataElement;
42import org.greenstone.gatherer.metadata.MetadataSetManager;
43import org.greenstone.gatherer.util.StaticStrings;
44import org.greenstone.gatherer.util.Utility;
45import org.w3c.dom.*;
46
47/** This class maintains a list of subcollections within our collection.
48 * @author John Thompson, Greenstone Digital Library, University of Waikato
49 * @version 2.4
50 */
51public class SubcollectionManager
52 extends DOMProxyListModel {
53
54 static final private String DISABLED_CONTROLS = "Disabled";
55 static final private String ENABLED_CONTROLS = "Normal";
56 static final private String CLASS_DICTIONARY_NAME = "CDM.SubcollectionManager.";
57
58 /** The controls used to edit the settings of this manager. */
59 private Control controls = null;
60
61 private DOMProxyListModel model;
62
63 /** Constructor.
64 * @see org.greenstone.gatherer.Gatherer
65 * @see org.greenstone.gatherer.cdm.CollectionConfiguration
66 * @see org.greenstone.gatherer.cdm.CollectionDesignManager
67 * @see org.greenstone.gatherer.cdm.DOMProxyListModel
68 * @see org.greenstone.gatherer.cdm.Subcollection
69 */
70 public SubcollectionManager() {
71 super(CollectionDesignManager.collect_config.getDocumentElement(), StaticStrings.SUBCOLLECTION_ELEMENT, new Subcollection());
72 DebugStream.println("SubcollectionManager: " + getSize() + " subcollections parsed.");
73 this.model = this;
74 }
75
76 /** Method to add a new subcollection.
77 * @param subcollection the Subcollection to add
78 * @see org.greenstone.gatherer.Gatherer
79 * @see org.greenstone.gatherer.cdm.CollectionConfiguration
80 * @see org.greenstone.gatherer.cdm.DOMProxyListModel
81 * @see org.greenstone.gatherer.collection.CollectionManager
82 */
83 private void addSubcollection(Subcollection subcollection) {
84 if(!contains(subcollection)) {
85 Element element = subcollection.getElement();
86 // Locate where we should insert this new subcollection.
87 Node target_node = CollectionConfiguration.findInsertionPoint(element);
88 // Failing that we insert immediately after a language string
89 add(root, subcollection, target_node);
90 Gatherer.c_man.configurationChanged();
91 }
92 }
93
94 public void destroy() {
95 if(controls != null) {
96 controls.destroy();
97 controls = null;
98 }
99 }
100
101 /** Method to retrieve the controls for this manager.
102 * @return the Control used to edit the subcollection data
103 */
104 public Control getControls() {
105 if(controls == null) {
106 controls = new SubcollectionControl();
107 }
108 return controls;
109 }
110
111 /** Method to retrieve a certain subcollection by its name.
112 * @param name a String which is used as the key for finding the matching subcollection
113 * @return the requested Subcollection or null if no such subcollection exists.
114 */
115 private Subcollection getSubcollection(String name) {
116 Subcollection result = null;
117 int size = getSize();
118 for(int i = 0; i < size; i++) {
119 Subcollection subcollection = (Subcollection) getElementAt(i);
120 if(subcollection.getName().equals(name)) {
121 result = subcollection;
122 }
123 }
124 return result;
125 }
126
127
128 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
129 * @param mode the new mode as an int
130 */
131 public void modeChanged(int mode) {
132 if(controls != null) {
133 ((SubcollectionControl)controls).modeChanged(mode);
134 }
135 }
136
137 /** Method to remove the given subcollection.
138 * @param subcollection the Subcollection you want to remove
139 * @see org.greenstone.gatherer.Gatherer
140 * @see org.greenstone.gatherer.collection.CollectionManager
141 */
142 private void removeSubcollection(Subcollection subcollection) {
143 remove(subcollection);
144 Gatherer.c_man.configurationChanged();
145 }
146
147 private void updateSubcollection(Subcollection subcollection, String name, boolean include, String source, String pattern, String flags) {
148 subcollection.setFlags(flags);
149 subcollection.setInclusive(include);
150 subcollection.setName(name);
151 subcollection.setPattern(pattern);
152 subcollection.setSource(source);
153 refresh(subcollection);
154 Gatherer.c_man.configurationChanged();
155 }
156
157 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
158 private class SubcollectionControl
159 extends JPanel
160 implements Control {
161
162 private CardLayout card_layout;
163 private JButton add_button;
164 private JButton remove_button;
165 private JButton update_button;
166 private JComboBox source_combobox;
167 private JList subcollection_list;
168 private JPanel border_pane;
169 private JTabbedPane tabbed_pane;
170 private JTextArea instructions_area;
171 private JTextField flags_field;
172 private JTextField match_field;
173 private JTextField name_field;
174 private JRadioButton exclude_button;
175 private JRadioButton include_button;
176
177 /** Constructor */
178 public SubcollectionControl() {
179 // Create
180 JPanel header_pane = new JPanel();
181 instructions_area = new JTextArea();
182 instructions_area.setEditable(false);
183 instructions_area.setLineWrap(true);
184 instructions_area.setRows(6);
185 instructions_area.setWrapStyleWord(true);
186 Dictionary.registerText(instructions_area, "CDM.SubcollectionManager.Instructions");
187
188 border_pane = new JPanel();
189 card_layout = new CardLayout();
190
191 tabbed_pane = new JTabbedPane();
192 JLabel title = new JLabel();
193 title.setHorizontalAlignment(JLabel.CENTER);
194 Dictionary.registerText(title, "CDM.SubcollectionManager.Title");
195
196 JPanel button_pane_3 = new JPanel();
197 add_button = new GLIButton();
198 add_button.setMnemonic(KeyEvent.VK_A);
199 add_button.setEnabled(false);
200 Dictionary.registerBoth(add_button, "CDM.SubcollectionManager.Add", "CDM.SubcollectionManager.Add_Tooltip");
201 remove_button = new GLIButton();
202 remove_button.setMnemonic(KeyEvent.VK_R);
203 remove_button.setEnabled(false);
204 Dictionary.registerBoth(remove_button, "CDM.SubcollectionManager.Remove", "CDM.SubcollectionManager.Remove_Tooltip");
205 update_button = new GLIButton();
206 update_button.setMnemonic(KeyEvent.VK_C);
207 update_button.setEnabled(false);
208 Dictionary.registerBoth(update_button, "CDM.SubcollectionManager.Replace", "CDM.SubcollectionManager.Replace_Tooltip");
209
210 JPanel button_pane = new JPanel();
211 JPanel button_pane_1 = new JPanel();
212 include_button = new JRadioButton();
213 include_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
214 include_button.setMnemonic(KeyEvent.VK_I);
215 include_button.setOpaque(false);
216 Dictionary.registerText(include_button, "CDM.SubcollectionManager.Include");
217 exclude_button = new JRadioButton();
218 exclude_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
219 exclude_button.setMnemonic(KeyEvent.VK_X);
220 exclude_button.setOpaque(false);
221 Dictionary.registerText(exclude_button, "CDM.SubcollectionManager.Exclude");
222
223 JLabel flags_label = new JLabel();
224 Dictionary.registerText(flags_label, "CDM.SubcollectionManager.Flags");
225 flags_field = new NonWhitespaceField();
226 Dictionary.registerTooltip(flags_field, "CDM.SubcollectionManager.Flags_Tooltip");
227
228 JPanel inclusive_pane = new JPanel();
229 JLabel inclusive_label = new JLabel();
230 Dictionary.registerText(inclusive_label, "CDM.SubcollectionManager.Inclusive");
231
232 JLabel match_label = new JLabel();
233 Dictionary.registerText(match_label, "CDM.SubcollectionManager.Match");
234 match_field = new JTextField();
235 Dictionary.registerTooltip(match_field, "CDM.SubcollectionManager.Match_Tooltip");
236
237 JLabel name_label = new JLabel();
238 Dictionary.registerText(name_label, "CDM.SubcollectionManager.Name");
239 name_field = new NonWhitespaceField();
240 Dictionary.registerTooltip(name_field, "CDM.SubcollectionManager.Name_Tooltip");
241
242 JLabel source_label = new JLabel();
243 Dictionary.registerText(source_label, "CDM.SubcollectionManager.Source");
244 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
245 Vector source_model = new Vector(every_metadata_set_element);
246 source_model.add(0, StaticStrings.FILENAME_STR);
247 source_combobox = new JComboBox(source_model);
248 Dictionary.registerTooltip(source_combobox, "CDM.SubcollectionManager.Source_Tooltip");
249
250 subcollection_list = new JList(model);
251 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
252 JPanel subcollection_pane = new JPanel();
253 ButtonGroup bg = new ButtonGroup();
254 bg.add(include_button);
255 bg.add(exclude_button);
256 include_button.setSelected(true);
257 JPanel subcollection_list_pane = new JPanel();
258 JLabel subcollection_list_label = new JLabel();
259 Dictionary.registerText(subcollection_list_label, "CDM.SubcollectionManager.Assigned");
260
261 // Create a message pane which explains why these controls are not currently active
262 JPanel message_pane = new JPanel();
263 String args[] = new String[3];
264 args[0] = Configuration.getModeAsString();
265 args[1] = Dictionary.get("Preferences.Mode.Systems");
266 args[2] = Dictionary.get("Preferences.Mode.Expert");
267 JTextArea message_textarea = new JTextArea();
268 Dictionary.registerText(message_textarea, "CDM.SubcollectionManager.Partitions_Disabled", args);
269 message_textarea.setEditable(false);
270 message_textarea.setHighlighter(null); // Prevent highlighting
271 message_textarea.setLineWrap(true);
272 message_textarea.setOpaque(false); // Make it transparent
273 message_textarea.setWrapStyleWord(true);
274
275 // Add listeners
276 SubCollectionChangeListener cl = new SubCollectionChangeListener();
277 add_button.addActionListener(new AddSubCollectionListener());
278 remove_button.addActionListener(new RemoveSubCollectionListener());
279 update_button.addActionListener(new UpdateSubCollectionListener());
280 exclude_button.addActionListener(cl);
281 include_button.addActionListener(cl);
282 source_combobox.addActionListener(cl);
283 flags_field.getDocument().addDocumentListener(cl);
284 match_field.getDocument().addDocumentListener(cl);
285 name_field.getDocument().addDocumentListener(cl);
286 subcollection_list.addListSelectionListener(new SubCollectionListListener());
287
288 // Layout
289 instructions_area.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
290
291 header_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
292 header_pane.setLayout(new BorderLayout());
293 header_pane.add(title, BorderLayout.NORTH);
294 header_pane.add(new JScrollPane(instructions_area), BorderLayout.CENTER);
295
296 inclusive_pane.setLayout(new GridLayout());
297 inclusive_pane.add(include_button);
298 inclusive_pane.add(exclude_button);
299
300 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
301 button_pane_1.setLayout(new GridLayout(5, 2));
302 button_pane_1.add(name_label);
303 button_pane_1.add(name_field);
304 button_pane_1.add(source_label);
305 button_pane_1.add(source_combobox);
306 button_pane_1.add(match_label);
307 button_pane_1.add(match_field);
308 button_pane_1.add(inclusive_label);
309 button_pane_1.add(inclusive_pane);
310 button_pane_1.add(flags_label);
311 button_pane_1.add(flags_field);
312
313 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
314 button_pane_3.setLayout(new GridLayout(1,3));
315 button_pane_3.add(add_button);
316 button_pane_3.add(update_button);
317 button_pane_3.add(remove_button);
318
319 button_pane.setLayout(new BorderLayout());
320 button_pane.add(button_pane_1, BorderLayout.CENTER);
321 button_pane.add(button_pane_3, BorderLayout.SOUTH);
322
323 subcollection_list_pane.setLayout(new BorderLayout());
324 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
325 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
326 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
327 subcollection_pane.setLayout(new BorderLayout());
328 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
329 subcollection_pane.add(button_pane, BorderLayout.SOUTH);
330
331 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subcollection_Controls"), subcollection_pane);
332 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subindex_Controls"), (JPanel) CollectionDesignManager.subcollectionindex_manager.getControls());
333 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Language_Controls"), (JPanel) CollectionDesignManager.language_manager.getControls());
334
335 message_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
336 message_pane.setLayout(new GridLayout(3,1,0,0));
337 message_pane.add(new JPanel());
338 message_pane.add(message_textarea);
339 message_pane.add(new JPanel());
340
341 border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5));
342 border_pane.setLayout(card_layout);
343 if(Configuration.getMode() > Configuration.LIBRARIAN_MODE) {
344 border_pane.add(tabbed_pane, ENABLED_CONTROLS);
345 border_pane.add(message_pane, DISABLED_CONTROLS);
346 }
347 else {
348 border_pane.add(message_pane, DISABLED_CONTROLS);
349 border_pane.add(tabbed_pane, ENABLED_CONTROLS);
350 }
351
352 setLayout(new BorderLayout());
353 add(header_pane, BorderLayout.NORTH);
354 add(border_pane, BorderLayout.CENTER);
355 }
356
357 /** Method to unregister any listeners to avoid memory leaks.
358 */
359 public void destroy() {
360 }
361
362 public void gainFocus() {
363 // Rebuild the sources combobox
364 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
365 Vector source_model = new Vector(every_metadata_set_element);
366 source_model.add(0, "Filename"); // Add filename as a possible source.
367 source_combobox.setModel(new DefaultComboBoxModel(source_model));
368 }
369
370 public void loseFocus() {
371 }
372
373 /** Called when the detail mode has changed which in turn controls if any of the partition controls are visible, or if they are instead replaced with a message explaining why they are not.
374 * @param mode the new mode as an int
375 */
376 public void modeChanged(int mode) {
377 if(mode > Configuration.LIBRARIAN_MODE) {
378 card_layout.show(border_pane, ENABLED_CONTROLS);
379 }
380 else {
381 card_layout.show(border_pane, DISABLED_CONTROLS);
382 }
383 }
384
385 /** 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. */
386 private class AddSubCollectionListener
387 implements ActionListener {
388 /** 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.
389 * @param event An <strong>ActionEvent</strong> containing information about the event.
390 * @see org.greenstone.gatherer.cdm.Subcollection
391 */
392 public void actionPerformed(ActionEvent event) {
393 String name = name_field.getText();
394 String source = null;
395 Object object = source_combobox.getSelectedItem();
396 if (object instanceof MetadataElement) {
397 MetadataElement metadata_element = (MetadataElement) object;
398 source = metadata_element.getFullName();
399 }
400 else {
401 source = object.toString();
402 }
403 String pattern = match_field.getText();
404 String flags = flags_field.getText();
405 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
406 Subcollection subcollection = new Subcollection(name, include_button.isSelected(), source, pattern, flags);
407 addSubcollection(subcollection);
408 // Change the selection to the new subcollection
409 subcollection_list.setSelectedValue(subcollection, true);
410 }
411 add_button.setEnabled(false);
412 }
413 }
414
415 /** This class listens for any key entry in a text field, selection change in a combobox or button click, and updates a subcollection as appropriate. Its also convenient to use this class to test if the add button should be active yet. */
416 private class SubCollectionChangeListener
417 implements DocumentListener, ActionListener {
418 /** 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.
419 * @param event An <strong>ActionEvent</strong> containing information about the event.
420 */
421 public void actionPerformed(ActionEvent event) {
422 validateAdd();
423 }
424
425 public void changedUpdate(DocumentEvent event) {
426 validateAdd();
427 }
428
429 public void insertUpdate(DocumentEvent event) {
430 validateAdd();
431
432 }
433
434 public void removeUpdate(DocumentEvent event) {
435 validateAdd();
436 }
437
438 /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values. */
439 private void validateAdd() {
440 if(name_field.getText().length() > 0 && match_field.getText().length() > 0) {
441 if (getSubcollection(name_field.getText()) == null) {
442 add_button.setEnabled(true);
443 } else {
444 add_button.setEnabled(false);
445 }
446 }
447 else {
448 add_button.setEnabled(false);
449 }
450 }
451 }
452
453 /** 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. */
454 private class RemoveSubCollectionListener
455 implements ActionListener {
456 /** 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.
457 * @param event An <strong>ActionEvent</strong> containing information about the event.
458 * @see org.greenstone.gatherer.cdm.Subcollection
459 */
460 public void actionPerformed(ActionEvent event) {
461 if(!subcollection_list.isSelectionEmpty()) {
462 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
463 removeSubcollection(subcollection);
464 // And remove subcollection indexes dependant on this subcollection
465 CollectionDesignManager.subcollectionindex_manager.removeSubcollectionIndexes(subcollection);
466 }
467 remove_button.setEnabled(false);
468 }
469 }
470
471 private class UpdateSubCollectionListener
472 implements ActionListener {
473 public void actionPerformed(ActionEvent event) {
474 if(!subcollection_list.isSelectionEmpty()) {
475 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
476 String name = name_field.getText();
477 String source = null;
478 Object object = source_combobox.getSelectedItem();
479 if (object instanceof MetadataElement) {
480 MetadataElement metadata_element = (MetadataElement) object;
481 source = metadata_element.getFullName();
482 }
483 else {
484 source = object.toString();
485 }
486 String pattern = match_field.getText();
487 String flags = flags_field.getText();
488 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
489 updateSubcollection(subcollection, name, include_button.isSelected(), source, pattern, flags);
490 }
491 }
492 }
493 }
494
495 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
496 private class SubCollectionListListener
497 implements ListSelectionListener {
498 /** 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.
499 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
500 * @see org.greenstone.gatherer.cdm.Subcollection
501 */
502 public void valueChanged(ListSelectionEvent event) {
503 // Wait until the event stabilises to avoid processing it multiple times
504 if (event.getValueIsAdjusting() == true) {
505 return;
506 }
507 // Now the entry
508 if(!subcollection_list.isSelectionEmpty()) {
509 Subcollection subcollection = (Subcollection) subcollection_list.getSelectedValue();
510 flags_field.setText(subcollection.getFlags());
511 include_button.setSelected(subcollection.isInclusive());
512 exclude_button.setSelected(!subcollection.isInclusive());
513 match_field.setText(subcollection.getPattern());
514 name_field.setText(subcollection.getName());
515 String s = subcollection.getSource();
516 int pos = 0;
517 Object value = source_combobox.getItemAt(pos);
518 //ystem.err.println("Search for: " + s);
519 while (value != null) {
520 if (value instanceof MetadataElement) {
521 MetadataElement metadata_element = (MetadataElement) value;
522 String metadata_element_name = metadata_element.getFullName();
523 //ystem.err.print("Compare to: " + e_name);
524 if (metadata_element_name.equals(s)) {
525 source_combobox.setSelectedIndex(pos);
526 value = null;
527 //ystem.err.println(" - Match");
528 }
529 else {
530 pos++;
531 value = source_combobox.getItemAt(pos);
532 //ystem.err.println(" - Fail");
533 }
534 }
535 else if(value.toString().equals(s)) {
536 source_combobox.setSelectedIndex(pos);
537 value = null;
538 }
539 else {
540 pos++;
541 value = source_combobox.getItemAt(pos);
542 }
543 }
544 // Can't add one thats already there.
545 add_button.setEnabled(false);
546 // You can update or remove it though...
547 remove_button.setEnabled(true);
548 update_button.setEnabled(true);
549 }
550 else {
551 flags_field.setText("");
552 include_button.setSelected(true);
553 match_field.setText("");
554 name_field.setText("");
555 source_combobox.setSelectedIndex(0);
556 remove_button.setEnabled(false);
557 update_button.setEnabled(false);
558 }
559 }
560 }
561 }
562}
Note: See TracBrowser for help on using the repository browser.