source: gli/branches/rtl-gli/src/org/greenstone/gatherer/cdm/SubcollectionIndexManager.java@ 18368

Last change on this file since 18368 was 14746, checked in by anna, 16 years ago

same changes as in trunk.

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