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

Last change on this file since 4932 was 4932, checked in by jmt12, 21 years ago

Major CDM rewrite so it uses DOM.

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