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

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

Changed text handling to use Dictionary.get rather than Dictionary.setText or Dictionary.registerBoth etc. also removed mnemonics cos they suck for other languages.

  • Property svn:keywords set to Author Date Id Revision
File size: 21.3 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(Dictionary.get("CDM.SubcollectionIndexManager.Subindexes"));
258 subcollection_index_list = new JList(model);
259 subcollection_index_list.setCellRenderer(new SubcollectionIndexListCellRenderer());
260 subcollection_index_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
261 subcollection_index_list.setVisibleRowCount(2);
262
263 JPanel movement_pane = new JPanel();
264 move_up_button = new GLIButton(Dictionary.get("CDM.Move.Move_Up"), JarTools.getImage("arrow-up.gif"), Dictionary.get("CDM.Move.Move_Up_Tooltip"));
265 move_up_button.setEnabled(false);
266
267 move_down_button = new GLIButton(Dictionary.get("CDM.Move.Move_Down"), JarTools.getImage("arrow-down.gif"), Dictionary.get("CDM.Move.Move_Down_Tooltip"));
268 move_down_button.setEnabled(false);
269
270 set_default_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Set_Default_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Set_Default_Subindex_Tooltip"));
271 set_default_button.setEnabled(false);
272
273 JPanel index_pane = new JPanel();
274 JPanel details_pane = new JPanel();
275 JPanel labels_pane = new JPanel();
276 JPanel boxes_pane = new JPanel();
277 JPanel content_pane = new JPanel();
278
279 JLabel source_label = new JLabel(Dictionary.get("CDM.SubcollectionIndexManager.Source"));
280
281 source_list = new CheckList(false);
282 source_list.setListData(sources);
283 source_list.setToolTipText(Dictionary.get("CDM.SubcollectionIndexManager.Source_Tooltip"));
284
285 JPanel button_pane = new JPanel();
286 add_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Add_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Add_Subindex_Tooltip"));
287 add_button.setEnabled(false);
288
289 remove_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Remove_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Remove_Subindex_Tooltip"));
290 remove_button.setEnabled(false);
291
292 replace_button = new GLIButton(Dictionary.get("CDM.SubcollectionIndexManager.Replace_Subindex"), Dictionary.get("CDM.SubcollectionIndexManager.Replace_Subindex_Tooltip"));
293 replace_button.setEnabled(false);
294
295 // Listeners
296 add_button.addActionListener(new AddListener());
297 add_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
298 move_down_button.addActionListener(new MoveListener(false));
299 move_down_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
300 move_up_button.addActionListener(new MoveListener(true));
301 move_up_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
302 remove_button.addActionListener(new RemoveListener());
303 remove_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
304 replace_button.addActionListener(new ReplaceListener());
305 replace_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
306 set_default_button.addActionListener(new SetDefaultListener());
307 set_default_button.addActionListener(CollectionDesignManager.buildcol_change_listener);
308 subcollection_index_list.addListSelectionListener(new SubcollectionIndexListListener());
309 source_list.addListSelectionListener(new SourceListListener());
310
311 // Layout
312 movement_pane.setBorder(BorderFactory.createEmptyBorder(0,2,0,0));
313 movement_pane.setLayout(new GridLayout(3,1));
314 movement_pane.add(move_up_button);
315 movement_pane.add(move_down_button);
316 movement_pane.add(set_default_button);
317
318 assigned_indexes_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0));
319 assigned_indexes_pane.setLayout(new BorderLayout());
320 assigned_indexes_pane.add(index_label, BorderLayout.NORTH);
321 assigned_indexes_pane.add(new JScrollPane(subcollection_index_list), BorderLayout.CENTER);
322 assigned_indexes_pane.add(movement_pane, BorderLayout.EAST);
323
324 labels_pane.setLayout(new BorderLayout());
325 labels_pane.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
326 labels_pane.add(source_label, BorderLayout.CENTER);
327
328 boxes_pane.setLayout(new BorderLayout());
329 boxes_pane.add(new JScrollPane(source_list), BorderLayout.CENTER);
330
331 details_pane.setLayout(new BorderLayout());
332 details_pane.add(labels_pane, BorderLayout.WEST);
333 details_pane.add(boxes_pane, BorderLayout.CENTER);
334
335 button_pane.setLayout(new GridLayout(1,3));
336 button_pane.add(add_button);
337 button_pane.add(replace_button);
338 button_pane.add(remove_button);
339
340 index_pane.setLayout(new BorderLayout());
341 index_pane.add(details_pane, BorderLayout.CENTER);
342 index_pane.add(button_pane, BorderLayout.SOUTH);
343
344 content_pane.setLayout(new BorderLayout());
345 content_pane.add(assigned_indexes_pane, BorderLayout.NORTH);
346 content_pane.add(index_pane, BorderLayout.CENTER);
347
348 setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
349 setLayout(new BorderLayout());
350 add(content_pane, BorderLayout.CENTER);
351 }
352
353
354 public void destroy()
355 {
356 }
357
358
359 public void gainFocus()
360 {
361 // Reload the source list
362 ArrayList sources = new ArrayList();
363 ListModel source_model = CollectionDesignManager.subcollection_manager;
364 for (int i = 0; i < source_model.getSize(); i++) {
365 sources.add(source_model.getElementAt(i));
366 }
367 source_list.setListData(sources);
368
369 // Refresh the subcollection index list
370 subcollection_index_list.updateUI();
371
372 // If there is one selected, fill in the controls
373 updateControlsWithSelectedIndex();
374 }
375
376
377 public void loseFocus()
378 {
379 }
380
381
382 private void updateControlsWithSelectedIndex()
383 {
384 SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
385 if (selected_index == null) {
386 return;
387 }
388
389 // Display the selected subcollection index's sources
390 source_list.clearTicked();
391 source_list.setTickedObjects(selected_index.getSources().toArray());
392 }
393
394
395 private void validateControls()
396 {
397 boolean add_enabled = false;
398 boolean replace_enabled = false;
399
400 // Can't add a new index if no sources are selected
401 if (source_list.isNothingTicked()) {
402 add_enabled = false;
403 }
404 // If we get this far, create a dummy index and see if it's already assigned in the collection
405 else {
406 ArrayList sources = source_list.getTicked();
407 SubcollectionIndex subcollection_index = new SubcollectionIndex(sources.toArray());
408
409 // Subcollection index already exists: can't add, but can replace if the name has changed
410 if (model.contains(subcollection_index)) {
411 add_enabled = false;
412
413 // Here we need to check if we have changed the name - if so, we can enable the replace button
414 if (subcollection_index_list.getSelectedIndex() != -1) {
415 SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
416 }
417 }
418
419 // Subcollection index doesn't already exist: can add, or replace if there is something selected
420 else {
421 add_enabled = true;
422 if (subcollection_index_list.getSelectedIndex() != -1) {
423 replace_enabled = true;
424 }
425 }
426 }
427
428 // We should now know the add_button state
429 add_button.setEnabled(add_enabled);
430 replace_button.setEnabled(replace_enabled);
431 }
432
433
434 private class AddListener
435 implements ActionListener
436 {
437 public void actionPerformed(ActionEvent event)
438 {
439 if (!source_list.isNothingTicked()) {// && name.length() != 0) {
440 ArrayList sources = source_list.getTicked();
441 SubcollectionIndex subcollection_index = new SubcollectionIndex(sources.toArray());
442
443 // Before we add the index to the model, we have to add a default collection metadata for this
444 CollectionMeta metadatum = new CollectionMeta("." + subcollection_index.getID());
445 metadatum.setValue(subcollection_index.getID());
446 CollectionDesignManager.collectionmeta_manager.addMetadatum(metadatum);
447
448 // Finally, add the subcollection index
449 addSubcollectionIndex(subcollection_index);
450 subcollection_index_list.setSelectedIndex(model.getSize() - 1);
451 }
452 }
453 }
454
455
456 private class MoveListener
457 implements ActionListener
458 {
459 private boolean move_up;
460
461 public MoveListener(boolean move_up)
462 {
463 this.move_up = move_up;
464 }
465
466 public void actionPerformed(ActionEvent event)
467 {
468 // Retrieve the selected subcollection index
469 SubcollectionIndex subcollection_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
470 if (subcollection_index != null) {
471 int new_position = moveSubcollectionIndex(subcollection_index, move_up);
472 // Ensure the subcollection index that moved is still selected
473 subcollection_index_list.setSelectedIndex(new_position);
474 }
475 }
476 }
477
478
479 /** Listens for key presses within the name field, and enabled or disables controls as appropriate. */
480 private class NameListener
481 implements DocumentListener
482 {
483 public void changedUpdate(DocumentEvent e)
484 {
485 validateControls();
486 }
487
488 public void insertUpdate(DocumentEvent e)
489 {
490 validateControls();
491 }
492
493 public void removeUpdate(DocumentEvent e)
494 {
495 validateControls();
496 }
497 }
498
499
500 private class RemoveListener
501 implements ActionListener
502 {
503 public void actionPerformed(ActionEvent event)
504 {
505 int i = subcollection_index_list.getSelectedIndex();
506 if (i != -1) {
507 removeSubcollectionIndex((SubcollectionIndex) subcollection_index_list.getSelectedValue());
508 }
509
510 int size = subcollection_index_list.getModel().getSize();
511 if (i == size) {
512 i--;
513 }
514 subcollection_index_list.setSelectedIndex(i);
515 validateControls();
516 }
517 }
518
519
520 private class ReplaceListener
521 implements ActionListener
522 {
523 public void actionPerformed(ActionEvent event)
524 {
525 if (subcollection_index_list.isSelectionEmpty()) {
526 // This should never happen, but just in case...
527 replace_button.setEnabled(false);
528 return;
529 }
530
531 // We'll just remove the old one and add the new one
532 removeSubcollectionIndex((SubcollectionIndex) subcollection_index_list.getSelectedValue());
533 replace_button.setEnabled(false);
534 add_button.setEnabled(true);
535 add_button.doClick();
536 add_button.setEnabled(false);
537 }
538 }
539
540
541 private class SetDefaultListener
542 implements ActionListener
543 {
544 public void actionPerformed(ActionEvent event)
545 {
546 SubcollectionIndex subcollection_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
547 if (subcollection_index != null) {
548 setDefaultSubcollectionIndex(subcollection_index);
549 // This should cause a repaint of just the desired row
550 subcollection_index_list.setSelectedValue(subcollection_index, true);
551 }
552 set_default_button.setEnabled(false);
553 }
554 }
555
556
557 private class SourceListListener
558 implements ListSelectionListener
559 {
560 public void valueChanged(ListSelectionEvent event)
561 {
562 validateControls();
563 }
564 }
565
566
567 /** Listens for selections within the list on the SubcollectionIndexManager controls, and if a change is detected enables, or disables, controls appropriately. */
568 private class SubcollectionIndexListListener
569 implements ListSelectionListener
570 {
571 /** 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
572 * @param event A <strong>ListSelectionEvent</strong> containing further information about the list selection.
573 */
574 public void valueChanged(ListSelectionEvent event)
575 {
576 if (event.getValueIsAdjusting()) {
577 return;
578 }
579
580 int i = subcollection_index_list.getSelectedIndex();
581 int size = subcollection_index_list.getModel().getSize();
582 if (i < 0 || i >= size) {
583 move_down_button.setEnabled(false);
584 move_up_button.setEnabled(false);
585 remove_button.setEnabled(false);
586 replace_button.setEnabled(false);
587 set_default_button.setEnabled(false);
588 return;
589 }
590
591 // Enable the buttons appropriately
592 remove_button.setEnabled(true);
593 SubcollectionIndex selected_index = (SubcollectionIndex) subcollection_index_list.getSelectedValue();
594 set_default_button.setEnabled(default_index == null || !default_index.equals(selected_index));
595 if (i > 0) {
596 move_up_button.setEnabled(true);
597 }
598 else {
599 move_up_button.setEnabled(false);
600 }
601 if (i < size-1){
602 move_down_button.setEnabled(true);
603 }
604 else {
605 move_down_button.setEnabled(false);
606 }
607
608 // Need to fill in the rest of the bits
609 updateControlsWithSelectedIndex();
610 }
611 }
612
613
614 private class SubcollectionIndexListCellRenderer
615 extends DefaultListCellRenderer
616 {
617 /** Return a component that has been configured to display the specified value. */
618 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
619 JLabel component = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
620 if (default_index != null && default_index.equals(value)) {
621 component.setText(component.getText() + " " + Dictionary.get("CDM.SubcollectionIndexManager.Default_Partition_Indicator"));
622 }
623 return component;
624 }
625 }
626 }
627}
Note: See TracBrowser for help on using the repository browser.