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

Last change on this file since 18587 was 18587, checked in by kjdon, 15 years ago

GLI three modes change: partition index will now be visible in LIbrarian mode (and whole design pane not available in assistant mode) so removing the card layout and message pane cos it will never be disabled now.

  • Property svn:keywords set to Author Date Id Revision
File size: 22.1 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Digital Library, University of Waikato
9 *
10 * Copyright (C) 1999 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.cdm;
28
29
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.DesignPaneHeader;
40import org.greenstone.gatherer.gui.GLIButton;
41import org.greenstone.gatherer.gui.NonWhitespaceField;
42import org.greenstone.gatherer.metadata.MetadataElement;
43import org.greenstone.gatherer.metadata.MetadataSetManager;
44import org.greenstone.gatherer.util.StaticStrings;
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 }
91 }
92
93 public void destroy() {
94 if(controls != null) {
95 controls.destroy();
96 controls = null;
97 }
98 }
99
100 /** Method to retrieve the controls for this manager.
101 * @return the Control used to edit the subcollection data
102 */
103 public Control getControls() {
104 if(controls == null) {
105 controls = new SubcollectionControl();
106 }
107 return controls;
108 }
109
110 /** Method to retrieve a certain subcollection by its name.
111 * @param name a String which is used as the key for finding the matching subcollection
112 * @return the requested Subcollection or null if no such subcollection exists.
113 */
114 private Subcollection getSubcollection(String name) {
115 Subcollection result = null;
116 int size = getSize();
117 for(int i = 0; i < size; i++) {
118 Subcollection subcollection = (Subcollection) getElementAt(i);
119 if(subcollection.getName().equals(name)) {
120 result = subcollection;
121 }
122 }
123 return result;
124 }
125
126
127 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
128 * @param mode the new mode as an int
129 */
130 public void modeChanged(int mode) {
131 }
132
133 /** Method to remove the given subcollection.
134 * @param subcollection the Subcollection you want to remove
135 * @see org.greenstone.gatherer.Gatherer
136 * @see org.greenstone.gatherer.collection.CollectionManager
137 */
138 private void removeSubcollection(Subcollection subcollection) {
139 remove(subcollection);
140 }
141
142 private void updateSubcollection(Subcollection subcollection, String name, boolean include, String source, String pattern, String flags) {
143 subcollection.setFlags(flags);
144 subcollection.setInclusive(include);
145 subcollection.setName(name);
146 subcollection.setPattern(pattern);
147 subcollection.setSource(source);
148 refresh(subcollection);
149 }
150
151 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */
152 private class SubcollectionControl
153 extends JPanel
154 implements Control, ChangeListener
155 {
156 private JButton add_button;
157 private JButton remove_button;
158 private JButton update_button;
159 private JComboBox source_combobox;
160 private JList subcollection_list;
161 private JTabbedPane tabbed_pane;
162 private JTextField flags_field;
163 private JTextField match_field;
164 private JTextField name_field;
165 private JRadioButton exclude_button;
166 private JRadioButton include_button;
167
168 /** Constructor */
169 public SubcollectionControl() {
170 // Create
171 JPanel header_pane = new DesignPaneHeader("CDM.GUI.Subcollections", "partitionindexes");
172
173 tabbed_pane = new JTabbedPane();
174 tabbed_pane.addChangeListener(this);
175 tabbed_pane.setComponentOrientation(Dictionary.getOrientation());
176
177 JPanel button_pane_3 = new JPanel();
178 button_pane_3.setComponentOrientation(Dictionary.getOrientation());
179 add_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Add"), Dictionary.get("CDM.SubcollectionManager.Add_Tooltip"));
180 add_button.setEnabled(false);
181
182 remove_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Remove"), Dictionary.get("CDM.SubcollectionManager.Remove_Tooltip"));
183 remove_button.setEnabled(false);
184
185 update_button = new GLIButton(Dictionary.get("CDM.SubcollectionManager.Replace"), Dictionary.get("CDM.SubcollectionManager.Replace_Tooltip"));
186 update_button.setEnabled(false);
187
188 JPanel button_pane = new JPanel();
189 button_pane.setComponentOrientation(Dictionary.getOrientation());
190 JPanel button_pane_1 = new JPanel();
191 button_pane_1.setComponentOrientation(Dictionary.getOrientation());
192 include_button = new JRadioButton(Dictionary.get("CDM.SubcollectionManager.Include"));
193 include_button.setComponentOrientation(Dictionary.getOrientation());
194 include_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
195 include_button.setOpaque(false);
196
197 exclude_button = new JRadioButton(Dictionary.get("CDM.SubcollectionManager.Exclude"));
198 exclude_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
199 exclude_button.setOpaque(false);
200 exclude_button.setComponentOrientation(Dictionary.getOrientation());
201
202 JLabel flags_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Flags"));
203 flags_label.setComponentOrientation(Dictionary.getOrientation());
204
205 flags_field = new NonWhitespaceField();
206 flags_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Flags_Tooltip"));
207 flags_field.setComponentOrientation(Dictionary.getOrientation());
208
209 JPanel inclusive_pane = new JPanel();
210 inclusive_pane.setComponentOrientation(Dictionary.getOrientation());
211 JLabel inclusive_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Inclusive"));
212 inclusive_label.setComponentOrientation(Dictionary.getOrientation());
213
214 JLabel match_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Match"));
215 match_label.setComponentOrientation(Dictionary.getOrientation());
216
217 match_field = new JTextField();
218 match_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Match_Tooltip"));
219 match_field.setComponentOrientation(Dictionary.getOrientation());
220
221 JLabel name_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Name"));
222 name_label.setComponentOrientation(Dictionary.getOrientation());
223
224 name_field = new NonWhitespaceField();
225 name_field.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Name_Tooltip"));
226
227 JLabel source_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Source"));
228 source_label.setComponentOrientation(Dictionary.getOrientation());
229
230 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
231 Vector source_model = new Vector(every_metadata_set_element);
232 source_model.add(0, StaticStrings.FILENAME_STR);
233 source_combobox = new JComboBox(source_model);
234 source_combobox.setComponentOrientation(Dictionary.getOrientation());
235 source_combobox.setOpaque(false);
236 source_combobox.setToolTipText(Dictionary.get("CDM.SubcollectionManager.Source_Tooltip"));
237
238 subcollection_list = new JList(model);
239 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
240 JPanel subcollection_pane = new JPanel();
241 subcollection_pane.setComponentOrientation(Dictionary.getOrientation());
242 ButtonGroup bg = new ButtonGroup();
243 bg.add(include_button);
244 bg.add(exclude_button);
245 include_button.setSelected(true);
246 JPanel subcollection_list_pane = new JPanel();
247 subcollection_list_pane.setComponentOrientation(Dictionary.getOrientation());
248 JLabel subcollection_list_label = new JLabel(Dictionary.get("CDM.SubcollectionManager.Assigned"));
249 subcollection_list_label.setComponentOrientation(Dictionary.getOrientation());
250
251 // Add listeners
252 SubCollectionChangeListener cl = new SubCollectionChangeListener();
253 add_button.addActionListener(new AddSubCollectionListener());
254 add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
255 remove_button.addActionListener(new RemoveSubCollectionListener());
256 remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
257 update_button.addActionListener(new UpdateSubCollectionListener());
258 update_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
259 exclude_button.addActionListener(cl);
260 include_button.addActionListener(cl);
261 source_combobox.addActionListener(cl);
262 flags_field.getDocument().addDocumentListener(cl);
263 match_field.getDocument().addDocumentListener(cl);
264 name_field.getDocument().addDocumentListener(cl);
265 subcollection_list.addListSelectionListener(new SubCollectionListListener());
266
267 inclusive_pane.setLayout(new GridLayout());
268 inclusive_pane.add(include_button);
269 inclusive_pane.add(exclude_button);
270
271 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
272 button_pane_1.setLayout(new GridLayout(5, 2));
273 button_pane_1.add(name_label);
274 button_pane_1.add(name_field);
275 button_pane_1.add(source_label);
276 button_pane_1.add(source_combobox);
277 button_pane_1.add(match_label);
278 button_pane_1.add(match_field);
279 button_pane_1.add(inclusive_label);
280 button_pane_1.add(inclusive_pane);
281 button_pane_1.add(flags_label);
282 button_pane_1.add(flags_field);
283
284 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
285 button_pane_3.setLayout(new GridLayout(1,3));
286 button_pane_3.add(add_button);
287 button_pane_3.add(update_button);
288 button_pane_3.add(remove_button);
289
290 button_pane.setLayout(new BorderLayout());
291 button_pane.add(button_pane_1, BorderLayout.CENTER);
292 button_pane.add(button_pane_3, BorderLayout.SOUTH);
293
294 subcollection_list_pane.setLayout(new BorderLayout());
295 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH);
296 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER);
297 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
298 subcollection_pane.setLayout(new BorderLayout());
299 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER);
300 subcollection_pane.add(button_pane, BorderLayout.SOUTH);
301
302 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subcollection_Controls"), subcollection_pane);
303 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Subindex_Controls"), (JPanel) CollectionDesignManager.subcollectionindex_manager.getControls());
304 tabbed_pane.addTab(Dictionary.get("CDM.SubcollectionManager.Language_Controls"), (JPanel) CollectionDesignManager.language_manager.getControls());
305
306 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
307 setLayout(new BorderLayout());
308 add(header_pane, BorderLayout.NORTH);
309 add(tabbed_pane, BorderLayout.CENTER);
310 }
311
312 /** Method to unregister any listeners to avoid memory leaks.
313 */
314 public void destroy() {
315 }
316
317 public void gainFocus() {
318 // Rebuild the sources combobox
319 ArrayList every_metadata_set_element = MetadataSetManager.getEveryMetadataSetElement();
320 Vector source_model = new Vector(every_metadata_set_element);
321 source_model.add(0, "Filename"); // Add filename as a possible source.
322 source_combobox.setModel(new DefaultComboBoxModel(source_model));
323 }
324
325 public void loseFocus() {
326 }
327
328 public void stateChanged(ChangeEvent event)
329 {
330 if (tabbed_pane.getSelectedIndex() == 1) {
331 CollectionDesignManager.subcollectionindex_manager.getControls().gainFocus();
332 }
333 if (tabbed_pane.getSelectedIndex() == 2) {
334 CollectionDesignManager.language_manager.getControls().gainFocus();
335 }
336 }
337
338 /** 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. */
339 private class AddSubCollectionListener
340 implements ActionListener {
341 /** 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.
342 * @param event An <strong>ActionEvent</strong> containing information about the event.
343 * @see org.greenstone.gatherer.cdm.Subcollection
344 */
345 public void actionPerformed(ActionEvent event) {
346 String name = name_field.getText();
347 String source = null;
348 Object object = source_combobox.getSelectedItem();
349 if (object instanceof MetadataElement) {
350 MetadataElement metadata_element = (MetadataElement) object;
351 source = metadata_element.getFullName();
352 }
353 else {
354 source = object.toString();
355 }
356 String pattern = match_field.getText();
357 String flags = flags_field.getText();
358 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
359 Subcollection subcollection = new Subcollection(name, include_button.isSelected(), source, pattern, flags);
360 addSubcollection(subcollection);
361 // Change the selection to the new subcollection
362 subcollection_list.setSelectedValue(subcollection, true);
363 }
364 add_button.setEnabled(false);
365 }
366 }
367
368 /** 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. */
369 private class SubCollectionChangeListener
370 implements DocumentListener, ActionListener {
371 /** 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.
372 * @param event An <strong>ActionEvent</strong> containing information about the event.
373 */
374 public void actionPerformed(ActionEvent event) {
375 validateAdd();
376 }
377
378 public void changedUpdate(DocumentEvent event) {
379 validateAdd();
380 }
381
382 public void insertUpdate(DocumentEvent event) {
383 validateAdd();
384
385 }
386
387 public void removeUpdate(DocumentEvent event) {
388 validateAdd();
389 }
390
391 /** Method to validate the current subcollection editor values, and enable or disable controls (add button) based on said values. */
392 private void validateAdd() {
393 if(name_field.getText().length() > 0 && match_field.getText().length() > 0) {
394 if (getSubcollection(name_field.getText()) == null) {
395 add_button.setEnabled(true);
396 } else {
397 add_button.setEnabled(false);
398 }
399 }
400 else {
401 add_button.setEnabled(false);
402 }
403 }
404 }
405
406 /** 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. */
407 private class RemoveSubCollectionListener
408 implements ActionListener {
409 /** 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.
410 * @param event An <strong>ActionEvent</strong> containing information about the event.
411 * @see org.greenstone.gatherer.cdm.Subcollection
412 */
413 public void actionPerformed(ActionEvent event) {
414 if(!subcollection_list.isSelectionEmpty()) {
415 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
416 removeSubcollection(subcollection);
417 // And remove subcollection indexes dependant on this subcollection
418 CollectionDesignManager.subcollectionindex_manager.removeSubcollectionIndexes(subcollection);
419 }
420 remove_button.setEnabled(false);
421 }
422 }
423
424 private class UpdateSubCollectionListener
425 implements ActionListener {
426 public void actionPerformed(ActionEvent event) {
427 if(!subcollection_list.isSelectionEmpty()) {
428 Subcollection subcollection = (Subcollection)subcollection_list.getSelectedValue();
429 String name = name_field.getText();
430 String source = null;
431 Object object = source_combobox.getSelectedItem();
432 if (object instanceof MetadataElement) {
433 MetadataElement metadata_element = (MetadataElement) object;
434 source = metadata_element.getFullName();
435 }
436 else {
437 source = object.toString();
438 }
439 String pattern = match_field.getText();
440 String flags = flags_field.getText();
441 if(name.length() > 0 && (source == null || source.length() > 0) && pattern.length() > 0) {
442 updateSubcollection(subcollection, name, include_button.isSelected(), source, pattern, flags);
443 }
444 }
445 }
446 }
447
448 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */
449 private class SubCollectionListListener
450 implements ListSelectionListener {
451 /** 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.
452 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event.
453 * @see org.greenstone.gatherer.cdm.Subcollection
454 */
455 public void valueChanged(ListSelectionEvent event) {
456 // Wait until the event stabilises to avoid processing it multiple times
457 if (event.getValueIsAdjusting() == true) {
458 return;
459 }
460 // Now the entry
461 if(!subcollection_list.isSelectionEmpty()) {
462 Subcollection subcollection = (Subcollection) subcollection_list.getSelectedValue();
463 flags_field.setText(subcollection.getFlags());
464 include_button.setSelected(subcollection.isInclusive());
465 exclude_button.setSelected(!subcollection.isInclusive());
466 match_field.setText(subcollection.getPattern());
467 name_field.setText(subcollection.getName());
468 String s = subcollection.getSource();
469 int pos = 0;
470 Object value = source_combobox.getItemAt(pos);
471 //ystem.err.println("Search for: " + s);
472 while (value != null) {
473 if (value instanceof MetadataElement) {
474 MetadataElement metadata_element = (MetadataElement) value;
475 String metadata_element_name = metadata_element.getFullName();
476 //ystem.err.print("Compare to: " + e_name);
477 if (metadata_element_name.equals(s)) {
478 source_combobox.setSelectedIndex(pos);
479 value = null;
480 //ystem.err.println(" - Match");
481 }
482 else {
483 pos++;
484 value = source_combobox.getItemAt(pos);
485 //ystem.err.println(" - Fail");
486 }
487 }
488 else if(value.toString().equals(s)) {
489 source_combobox.setSelectedIndex(pos);
490 value = null;
491 }
492 else {
493 pos++;
494 value = source_combobox.getItemAt(pos);
495 }
496 }
497 // Can't add one thats already there.
498 add_button.setEnabled(false);
499 // You can update or remove it though...
500 remove_button.setEnabled(true);
501 update_button.setEnabled(true);
502 }
503 else {
504 flags_field.setText("");
505 include_button.setSelected(true);
506 match_field.setText("");
507 name_field.setText("");
508 source_combobox.setSelectedIndex(0);
509 remove_button.setEnabled(false);
510 update_button.setEnabled(false);
511 }
512 }
513 }
514 }
515}
Note: See TracBrowser for help on using the repository browser.