source: trunk/gli/src/org/greenstone/gatherer/cdm/SubcollectionIndexManager.java@ 12091

Last change on this file since 12091 was 12091, checked in by kjdon, 18 years ago

subcollection index names no longer appear on this panel - done using searchmetadatamanager.

  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 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
29import java.awt.*;
30import java.awt.event.*;
31import java.util.*;
32import javax.swing.*;
33import javax.swing.event.*;
34import org.greenstone.gatherer.DebugStream;
35import org.greenstone.gatherer.Dictionary;
36import org.greenstone.gatherer.Gatherer;
37import org.greenstone.gatherer.gui.GLIButton;
38import org.greenstone.gatherer.util.CheckList;
39import org.greenstone.gatherer.util.JarTools;
40import org.w3c.dom.*;
41
42
43/** This class maintains a list of indexes partitions for the purpose of defining subcollections.
44 * @author John Thompson, Greenstone Digital Library, University of Waikato
45 * @version 2.4
46 */
47public class SubcollectionIndexManager
48 extends DOMProxyListModel
49{
50 static final private Dimension FIELD_SIZE = new Dimension(200, 30);
51
52 private Control controls;
53 private DOMProxyListModel model;
54 private SubcollectionIndex default_index;
55
56
57 /** Constructor. */
58 public SubcollectionIndexManager(Element subindexes)
59 {
60 super(subindexes, CollectionConfiguration.INDEX_ELEMENT, new SubcollectionIndex());
61 DebugStream.println("SubcollectionIndexManager: " + getSize() + " subcollection indexes parsed.");
62 model = this;
63
64 // Parse and retrieve the default index
65 NodeList default_index_elements = CollectionDesignManager.collect_config.getDocumentElement().getElementsByTagName(CollectionConfiguration.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
66 if (default_index_elements.getLength() > 0) {
67 default_index = new SubcollectionIndex((Element) default_index_elements.item(0));
68 }
69 }
70
71
72 /** Method to add a subindex.
73 * @param subindex a SubcollectionIndex
74 * @see org.greenstone.gatherer.Gatherer
75 * @see org.greenstone.gatherer.collection.CollectionManager
76 */
77 private void addSubcollectionIndex(SubcollectionIndex subcollection_index)
78 {
79 if (!contains(subcollection_index)) {
80 add(getSize(), subcollection_index);
81 Gatherer.c_man.configurationChanged();
82 }
83 }
84
85
86 public void destroy()
87 {
88 if (controls != null) {
89 controls.destroy();
90 controls = null;
91 }
92 default_index = null;
93 model = null;
94 }
95
96
97 public Control getControls()
98 {
99 if (controls == null) {
100 controls = new SubcollectionIndexControls();
101 }
102 return controls;
103 }
104
105
106 /** Method to get all of the subindexes set.
107 * @return an ArrayList containing all the defined indexes
108 */
109 public ArrayList getSubcollectionIndexes()
110 {
111 return children();
112 }
113
114
115 private int moveSubcollectionIndex(SubcollectionIndex subcollection_index, boolean move_up)
116 {
117 // Determine the current position of the subcollection index
118 int position = indexOf(subcollection_index);
119 int new_position;
120
121 // Attempt to move the subcollection index up
122 if (move_up) {
123 // Check it's not already at the top
124 if (position == 0) {
125 return position;
126 }
127
128 // This automatically removes the index first, as an Element can only exist once in a particular document
129 new_position = position - 1;
130 addBefore(subcollection_index, (SubcollectionIndex) getElementAt(new_position));
131 }
132
133 // Attempt to move the subcollection index down
134 else {
135 // Check it's not already at the bottom
136 if (position == (getSize()) - 1) {
137 return position;
138 }
139
140 // This automatically removes the index first, as an Element can only exist once in a particular document
141 new_position = position + 1;
142 addAfter(subcollection_index, (SubcollectionIndex) getElementAt(new_position));
143 }
144
145 // Schedule the collection for saving
146 Gatherer.c_man.configurationChanged();
147 return new_position;
148 }
149
150
151 /** Method to remove a certain subcollection index. */
152 private void removeSubcollectionIndex(SubcollectionIndex subcollection_index)
153 {
154 if (subcollection_index != null) {
155 // Remove any current metadata from this index
156 CollectionDesignManager.collectionmeta_manager.removeMetadata("." + subcollection_index.getID());
157
158 // Check if the index removed happens to be the default index
159 if (default_index != null && default_index.equals(subcollection_index)) {
160 // If so our first solution is to set the first subcollection index to be the default
161 if (getSize() > 0) {
162 setDefaultSubcollectionIndex((SubcollectionIndex) getElementAt(0));
163 }
164 else {
165 default_index.setAssigned(false);
166 }
167 }
168
169 // Remove the index
170 remove(subcollection_index);
171 Gatherer.c_man.configurationChanged();
172 }
173 }
174
175
176 /** Method to remove all of the subindexes that contain a certain subcollection.
177 * @param subcollection the Subcollection that has been removed
178 * @see org.greenstone.gatherer.cdm.Subcollection
179 * @see org.greenstone.gatherer.cdm.SubcollectionIndex
180 */
181 public void removeSubcollectionIndexes(Subcollection subcollection)
182 {
183 String subcollection_name = subcollection.getName();
184 int size = getSize();
185 for(int i = size - 1; i >= 0; i--) {
186 SubcollectionIndex subcollection_index = (SubcollectionIndex) getElementAt(i);
187 if (subcollection_index.getSources().contains(subcollection_name)) {
188 removeSubcollectionIndex(subcollection_index);
189 }
190 }
191 }
192
193
194 /** Method to set the default subcollection index.
195 * @param index The <strong>SubcollectionIndex</strong> to use as the default index.
196 * @see org.greenstone.gatherer.Gatherer
197 * @see org.greenstone.gatherer.collection.CollectionManager
198 * @see org.greenstone.gatherer.cdm.SubcollectionIndex
199 */
200 private void setDefaultSubcollectionIndex(SubcollectionIndex subcollection_index)
201 {
202 if (subcollection_index != null) {
203 if (default_index == null) {
204 // Create the default index element, and place immediately after indexes element.
205 Element default_index_element = root.getOwnerDocument().createElement(CollectionConfiguration.SUBCOLLECTION_DEFAULT_INDEX_ELEMENT);
206 default_index = new SubcollectionIndex(default_index_element);
207 Node target_node = CollectionConfiguration.findInsertionPoint(default_index_element);
208 if (target_node != null) {
209 root.getOwnerDocument().getDocumentElement().insertBefore(default_index_element, target_node);
210 }
211 else {
212 root.getOwnerDocument().getDocumentElement().appendChild(default_index_element);
213 }
214 }
215 default_index.setAssigned(true);
216 default_index.setSources(subcollection_index.getSources());
217 }
218 else {
219 if (default_index != null) {
220 default_index.setAssigned(false);
221 }
222 }
223 Gatherer.c_man.configurationChanged();
224 }
225
226
227 /** This class creates a set of controls for editing the indexes. */
228 private class SubcollectionIndexControls
229 extends JPanel
230 implements Control
231 {
232 private CheckList source_list;
233 private JButton add_button;
234 private JButton move_down_button;
235 private JButton move_up_button;
236 private JButton remove_button;
237 private JButton replace_button;
238 private JButton set_default_button;
239 private JList subcollection_index_list;
240 private JTextField subcollection_index_name_textfield;
241
242
243 /** Constructor.
244 */
245 public SubcollectionIndexControls()
246 {
247 super();
248
249 ArrayList sources = new ArrayList();
250 ListModel source_model = CollectionDesignManager.subcollection_manager;
251 for (int i = 0; i < source_model.getSize(); i++) {
252 sources.add(source_model.getElementAt(i));
253 }
254
255 // Creation
256 JPanel assigned_indexes_pane = new JPanel();
257 JLabel index_label = new JLabel();
258 Dictionary.registerText(index_label, "CDM.SubcollectionIndexManager.Subindexes");
259 subcollection_index_list = new JList(model);
260 subcollection_index_list.setCellRenderer(new SubcollectionIndexListCellRenderer());
261 subcollection_index_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
262 subcollection_index_list.setVisibleRowCount(2);
263
264 JPanel movement_pane = new JPanel();
265 move_up_button = new GLIButton("", JarTools.getImage("arrow-up.gif"));
266 move_up_button.setEnabled(false);
267 move_up_button.setMnemonic(KeyEvent.VK_U);
268 Dictionary.registerBoth(move_up_button, "CDM.Move.Move_Up", "CDM.Move.Move_Up_Tooltip");
269
270 move_down_button = new GLIButton("", JarTools.getImage("arrow-down.gif"));
271 move_down_button.setEnabled(false);
272 move_down_button.setMnemonic(KeyEvent.VK_D);
273 Dictionary.registerBoth(move_down_button, "CDM.Move.Move_Down", "CDM.Move.Move_Down_Tooltip");
274
275 set_default_button = new GLIButton();
276 set_default_button.setEnabled(false);
277 set_default_button.setMnemonic(KeyEvent.VK_S);
278 Dictionary.registerBoth(set_default_button, "CDM.SubcollectionIndexManager.Set_Default_Subindex", "CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip");
279
280 JPanel index_pane = new JPanel();
281 JPanel details_pane = new JPanel();
282 JPanel labels_pane = new JPanel();
283 JPanel boxes_pane = new JPanel();
284 JPanel content_pane = new JPanel();
285
286 JLabel source_label = new JLabel();
287 Dictionary.registerText(source_label, "CDM.SubcollectionIndexManager.Source");
288 source_list = new CheckList(false);
289 source_list.setListData(sources);
290 Dictionary.registerTooltip(source_list, "CDM.SubcollectionIndexManager.Source_Tooltip");
291
292 JPanel button_pane = new JPanel();
293 add_button = new GLIButton();
294 add_button.setEnabled(false);
295 add_button.setMnemonic(KeyEvent.VK_A);
296 Dictionary.registerBoth(add_button, "CDM.SubcollectionIndexManager.Add_Subindex", "CDM.SubcollectionIndexManager.Add_Subindex_Tooltip");
297
298 remove_button = new GLIButton();
299 remove_button.setEnabled(false);
300 remove_button.setMnemonic(KeyEvent.VK_R);
301 Dictionary.registerBoth(remove_button, "CDM.SubcollectionIndexManager.Remove_Subindex", "CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip");
302
303 replace_button = new GLIButton();
304 replace_button.setEnabled(false);
305 replace_button.setMnemonic(KeyEvent.VK_P);
306 Dictionary.registerBoth(replace_button, "CDM.SubcollectionIndexManager.Replace_Subindex", "CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip");
307
308 // Listeners
309 add_button.addActionListener(new AddListener());
310 add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
311 move_down_button.addActionListener(new MoveListener(false));
312 move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
313 move_up_button.addActionListener(new MoveListener(true));
314 move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
315 remove_button.addActionListener(new RemoveListener());
316 remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
317 replace_button.addActionListener(new ReplaceListener());
318 replace_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
319 set_default_button.addActionListener(new SetDefaultListener());
320 set_default_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
321 subcollection_index_list.addListSelectionListener(new SubcollectionIndexListListener());
322 source_list.addListSelectionListener(new SourceListListener());
323
324 // Layout
325 movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
326 movement_pane.setLayout(new GridLayout(3,1));
327 movement_pane.add(move_up_button);
328 movement_pane.add(move_down_button);
329 movement_pane.add(set_default_button);
330
331 assigned_indexes_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
332 assigned_indexes_pane.setLayout(new BorderLayout());
333 assigned_indexes_pane.add(index_label, BorderLayout.NORTH);
334 assigned_indexes_pane.add(new JScrollPane(subcollection_index_list), BorderLayout.CENTER);
335 assigned_indexes_pane.add(movement_pane, BorderLayout.EAST);
336
337 labels_pane.setLayout(new BorderLayout());
338 labels_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
339 labels_pane.add(source_label, BorderLayout.CENTER);
340
341 boxes_pane.setLayout(new BorderLayout());
342 boxes_pane.add(new JScrollPane(source_list), BorderLayout.CENTER);
343
344 details_pane.setLayout(new BorderLayout());
345 details_pane.add(labels_pane, BorderLayout.WEST);
346 details_pane.add(boxes_pane, BorderLayout.CENTER);
347
348 button_pane.setLayout(new GridLayout(1,3));
349 button_pane.add(add_button);
350 button_pane.add(replace_button);
351 button_pane.add(remove_button);
352
353 index_pane.setLayout(new BorderLayout());
354 index_pane.add(details_pane, BorderLayout.CENTER);
355 index_pane.add(button_pane, BorderLayout.SOUTH);
356
357 content_pane.setLayout(new BorderLayout());
358 content_pane.add(assigned_indexes_pane, BorderLayout.NORTH);
359 content_pane.add(index_pane, BorderLayout.CENTER);
360
361 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
362 setLayout(new BorderLayout());
363 add(content_pane, BorderLayout.CENTER);
364 }
365
366
367 public void destroy()
368 {
369 }
370
371
372 public void gainFocus()
373 {
374 // Reload the source list
375 ArrayList sources = new ArrayList();
376 ListModel source_model = CollectionDesignManager.subcollection_manager;
377 for (int i = 0; i < source_model.getSize(); i++) {
378 sources.add(source_model.getElementAt(i));
379 }
380 source_list.setListData(sources);
381
382 // Refresh the subcollection index list
383 subcollection_index_list.updateUI();
384
385 // If there is one selected, fill in the controls
386 updateControlsWithSelectedIndex();
387 }
388
389
390 public void loseFocus()
391 {
392 }
393
394
395 private void updateControlsWithSelectedIndex()
396 {
397 SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
398 if (selected_index == null) {
399 return;
400 }
401
402 // Display the selected subcollection index's sources
403 source_list.clearTicked();
404 source_list.setTickedObjects(selected_index.getSources().toArray());
405 }
406
407
408 private void validateControls()
409 {
410 boolean add_enabled = false;
411 boolean replace_enabled = false;
412
413 // Can't add a new index if no sources are selected
414 if (source_list.isNothingTicked()) {
415 add_enabled = false;
416 }
417 // If we get this far, create a dummy index and see if it's already assigned in the collection
418 else {
419 ArrayList sources = source_list.getTicked();
420 SubcollectionIndex subcollection_index = new SubcollectionIndex(sources.toArray());
421
422 // Subcollection index already exists: can't add, but can replace if the name has changed
423 if (model.contains(subcollection_index)) {
424 add_enabled = false;
425
426 // Here we need to check if we have changed the name - if so, we can enable the replace button
427 if (subcollection_index_list.getSelectedIndex() != -1) {
428 SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
429 }
430 }
431
432 // Subcollection index doesn't already exist: can add, or replace if there is something selected
433 else {
434 add_enabled = true;
435 if (subcollection_index_list.getSelectedIndex() != -1) {
436 replace_enabled = true;
437 }
438 }
439 }
440
441 // We should now know the add_button state
442 add_button.setEnabled(add_enabled);
443 replace_button.setEnabled(replace_enabled);
444 }
445
446
447 private class AddListener
448 implements ActionListener
449 {
450 public void actionPerformed(ActionEvent event)
451 {
452 if (!source_list.isNothingTicked()) {// && name.length() != 0) {
453 ArrayList sources = source_list.getTicked();
454 SubcollectionIndex subcollection_index = new SubcollectionIndex(sources.toArray());
455
456 // Before we add the index to the model, we have to add a default collection metadata for this
457 CollectionMeta metadatum = new CollectionMeta("." + subcollection_index.getID());
458 metadatum.setValue(subcollection_index.getID());
459 CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
460
461 // Finally, add the subcollection index
462 addSubcollectionIndex(subcollection_index);
463 subcollection_index_list.setSelectedIndex(model.getSize() - 1);
464 }
465 }
466 }
467
468
469 private class MoveListener
470 implements ActionListener
471 {
472 private boolean move_up;
473
474 public MoveListener(boolean move_up)
475 {
476 this.move_up = move_up;
477 }
478
479 public void actionPerformed(ActionEvent event)
480 {
481 // Retrieve the selected subcollection index
482 SubcollectionIndex subcollection_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
483 if (subcollection_index != null) {
484 int new_position = moveSubcollectionIndex(subcollection_index, move_up);
485 // Ensure the subcollection index that moved is still selected
486 subcollection_index_list.setSelectedIndex(new_position);
487 }
488 }
489 }
490
491
492 /** Listens for key presses within the name field, and enabled or disables controls as appropriate. */
493 private class NameListener
494 implements DocumentListener
495 {
496 public void changedUpdate(DocumentEvent e)
497 {
498 validateControls();
499 }
500
501 public void insertUpdate(DocumentEvent e)
502 {
503 validateControls();
504 }
505
506 public void removeUpdate(DocumentEvent e)
507 {
508 validateControls();
509 }
510 }
511
512
513 private class RemoveListener
514 implements ActionListener
515 {
516 public void actionPerformed(ActionEvent event)
517 {
518 int i = subcollection_index_list.getSelectedIndex();
519 if (i != -1) {
520 removeSubcollectionIndex((SubcollectionIndex) subcollection_index_list.getSelectedValue());
521 }
522
523 int size = subcollection_index_list.getModel().getSize();
524 if (i == size) {
525 i--;
526 }
527 subcollection_index_list.setSelectedIndex(i);
528 validateControls();
529 }
530 }
531
532
533 private class ReplaceListener
534 implements ActionListener
535 {
536 public void actionPerformed(ActionEvent event)
537 {
538 if (subcollection_index_list.isSelectionEmpty()) {
539 // This should never happen, but just in case...
540 replace_button.setEnabled(false);
541 return;
542 }
543
544 // We'll just remove the old one and add the new one
545 removeSubcollectionIndex((SubcollectionIndex) subcollection_index_list.getSelectedValue());
546 replace_button.setEnabled(false);
547 add_button.setEnabled(true);
548 add_button.doClick();
549 add_button.setEnabled(false);
550 }
551 }
552
553
554 private class SetDefaultListener
555 implements ActionListener
556 {
557 public void actionPerformed(ActionEvent event)
558 {
559 SubcollectionIndex subcollection_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
560 if (subcollection_index != null) {
561 setDefaultSubcollectionIndex(subcollection_index);
562 // This should cause a repaint of just the desired row
563 subcollection_index_list.setSelectedValue(subcollection_index, true);
564 }
565 set_default_button.setEnabled(false);
566 }
567 }
568
569
570 private class SourceListListener
571 implements ListSelectionListener
572 {
573 public void valueChanged(ListSelectionEvent event)
574 {
575 validateControls();
576 }
577 }
578
579
580 /** Listens for selections within the list on the SubcollectionIndexManager controls, and if a change is detected enables, or disables, controls appropriately. */
581 private class SubcollectionIndexListListener
582 implements ListSelectionListener
583 {
584 /** This method is called whenever the source list selection changes. When it does we need to fill in the various parts of the list description panel
585 * @param event A <strong>ListSelectionEvent</strong> containing further information about the list selection.
586 */
587 public void valueChanged(ListSelectionEvent event)
588 {
589 if (event.getValueIsAdjusting()) {
590 return;
591 }
592
593 int i = subcollection_index_list.getSelectedIndex();
594 int size = subcollection_index_list.getModel().getSize();
595 if (i < 0 || i >= size) {
596 move_down_button.setEnabled(false);
597 move_up_button.setEnabled(false);
598 remove_button.setEnabled(false);
599 replace_button.setEnabled(false);
600 set_default_button.setEnabled(false);
601 return;
602 }
603
604 // Enable the buttons appropriately
605 remove_button.setEnabled(true);
606 SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
607 set_default_button.setEnabled(default_index == null || !default_index.equals(selected_index));
608 if (i > 0) {
609 move_up_button.setEnabled(true);
610 }
611 else {
612 move_up_button.setEnabled(false);
613 }
614 if (i < size-1){
615 move_down_button.setEnabled(true);
616 }
617 else {
618 move_down_button.setEnabled(false);
619 }
620
621 // Need to fill in the rest of the bits
622 updateControlsWithSelectedIndex();
623 }
624 }
625
626
627 private class SubcollectionIndexListCellRenderer
628 extends DefaultListCellRenderer
629 {
630 /** Return a component that has been configured to display the specified value. */
631 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
632 JLabel component = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
633 if (default_index != null && default_index.equals(value)) {
634 component.setText(component.getText() + " " + Dictionary.get("CDM.SubcollectionIndexManager.Default_Partition_Indicator"));
635 }
636 return component;
637 }
638 }
639 }
640}
Note: See TracBrowser for help on using the repository browser.