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

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

Removed all occurrences of classes explicitly importing other classes in the same package.

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