source: gli/trunk/src/org/greenstone/gatherer/cdm/DepositorMetadataManager.java@ 19797

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

when a collection only had ex metadata set, we were removing it from our local list, then loading up dublin core and asking for the list of metadata sets again - which includes ex. doh. now just ask for the dublin core set

File size: 18.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.BorderLayout;
30import java.awt.Color;
31import java.awt.Component;
32import java.awt.Dimension;
33import java.awt.event.ActionEvent;
34import java.awt.event.ActionListener;
35import java.io.File;
36import java.util.ArrayList;
37
38import javax.swing.BorderFactory;
39import javax.swing.BoxLayout;
40import javax.swing.JCheckBox;
41import javax.swing.JComboBox;
42import javax.swing.JComponent;
43import javax.swing.JOptionPane;
44import javax.swing.JPanel;
45import javax.swing.JScrollPane;
46
47import org.greenstone.gatherer.Configuration;
48import org.greenstone.gatherer.Dictionary;
49import org.greenstone.gatherer.Gatherer;
50import org.greenstone.gatherer.collection.CollectionManager;
51import org.greenstone.gatherer.gui.DesignPaneHeader;
52import org.greenstone.gatherer.gui.GComboBox;
53import org.greenstone.gatherer.metadata.MetadataElement;
54import org.greenstone.gatherer.metadata.MetadataSet;
55import org.greenstone.gatherer.metadata.MetadataSetManager;
56import org.greenstone.gatherer.util.Utility;
57
58/**
59 * This manager implements the "Depositor Metadata" section in GLI Format Panel, where
60 * users can customize which metadata elements will be used to describe an item when deposited in the Depositor.
61 *
62 * @author Anna Huang, Greenstone Digital Library, University of Waikato
63 * @version 1.0
64 */
65public class DepositorMetadataManager {
66 /** Display controls of the element */
67 static private Dimension LABEL_SIZE = new Dimension(150, 15);
68 static private Dimension ROW_SIZE = new Dimension(400, 20);
69 static private Dimension MAX_ROW_SIZE = new Dimension(1000, 30);
70
71 /** Available types, corresponds to the HTML input types */
72 static private String[] TYPEOPTIONS = new String[]{"text", "textarea"};
73 /** Default elements to be used in Depositor */
74 static private String DEFAULT_METADATA_ELEMENTS = "dc.Title, dc.Creator, dc.Description";
75 /** Definition attribute of a metadata element */
76 static private String DEFINITION = "definition";
77
78 /** Display controls */
79 private Control controls;
80 /** List of MetadataElementEntry objects, each represents a metadata element */
81 private ArrayList metadata_checklist_model = null;
82 /** Collection configuration file manager */
83 private CollectionMetaManager collmeta_manager = CollectionDesignManager.collectionmeta_manager;
84
85 public DepositorMetadataManager() {
86 }
87
88 /** Destructor. */
89 public void destroy() {
90 if (controls != null) {
91 controls.destroy();
92 controls = null;
93 }
94 if(metadata_checklist_model != null) {
95 metadata_checklist_model.clear();
96 metadata_checklist_model = null;
97 }
98 }
99
100 public Control getControls() {
101 if (controls == null) {
102 controls = new DepositorControl();
103 }
104 return controls;
105 }
106
107 /** Called when the detail mode has changed which in turn may cause several design elements to be available/hidden
108 * @param mode the new mode as an int
109 */
110 public void modeChanged(int mode) {
111 }
112
113 /**
114 * The implementation of this display control is similar to the <code>ArgumentConfiguration</code>,
115 * where each component in the central panel is another JPanel component consists of a checkbox and a drop down list.
116 */
117 private class DepositorControl
118 extends JPanel
119 implements Control {
120
121 private JPanel central_pane = null;
122
123 public DepositorControl() {
124 super();
125 this.setComponentOrientation(Dictionary.getOrientation());
126 JPanel header_panel = new DesignPaneHeader("CDM.GUI.DepositorMetadata", "depositormetadatasettings");
127
128 // load all possible metadata sets, and existing configuration
129 buildModel();
130
131 central_pane = new JPanel();
132 central_pane.setComponentOrientation(Dictionary.getOrientation());
133 central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
134 central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS));
135
136 // build the central pane, ie. create gui component for each metadata element
137 buildPane();
138
139 JPanel collection_checklist_pane = new JPanel();
140 collection_checklist_pane.setComponentOrientation(Dictionary.getOrientation());
141 collection_checklist_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
142 collection_checklist_pane.setLayout(new BorderLayout());
143 collection_checklist_pane.add(new JScrollPane(central_pane), BorderLayout.CENTER);
144
145 setBorder(BorderFactory.createEmptyBorder(0,5,0,0));
146 setLayout(new BorderLayout());
147 add(header_panel, BorderLayout.NORTH);
148 add(collection_checklist_pane, BorderLayout.CENTER);
149 }
150
151 public void destroy() {
152 }
153
154 public void gainFocus() {
155 }
156
157 public void loseFocus() {
158 StringBuffer converted_javascript = new StringBuffer();
159
160 // get currently selected metadata elements and create the javascript associative array variable
161 if (metadata_checklist_model != null) {
162 int size = metadata_checklist_model.size();
163 for(int i = 0; i < size; i++) {
164 MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
165
166 if (entry.isSelected()) {
167 StringBuffer element = new StringBuffer();
168 element.append("{\"name\":\"").append(entry.name).append("\",");
169 element.append("\"label\":\"").append(entry.label).append("\",");
170 element.append("\"tooltip\":\"").append(entry.name).append(": ").append(entry.tooltip).append("\",");
171 element.append("\"type\":\"").append(entry.getType()).append("\"}");
172 if(converted_javascript.length() != 0) {
173 converted_javascript.append(", ");
174 }
175 converted_javascript.append(element);
176 element = null;
177 }
178 }
179
180 // if none of the elements were selected, use the default setting
181 if (converted_javascript.length() == 0) {
182 System.err.println("Error: DepositorMetadataMananger should have at least one selected metadata element.");
183 }
184
185 // save to the configuration file
186 CollectionMeta depositor_metadata_meta = collmeta_manager.getMetadatum("depositormetadata", true);
187 depositor_metadata_meta.setValue(converted_javascript.toString());
188 }
189 }
190
191 private void buildModel()
192 {
193 metadata_checklist_model = new ArrayList();
194 String current_coll_name = CollectionManager.getLoadedCollectionName();
195
196 // get the elements that have already been used in depositor
197 // add the "depositormetadata" meta if not found in the configuration file
198 CollectionMeta depositor_metadata_meta = collmeta_manager.getMetadatum("depositormetadata", true);
199 String selected_metadata_javascript = depositor_metadata_meta.getValue(true);
200
201 // load all MDSets in the collection, ie. .mds files in the collection's metadata directory
202 String file_name = Gatherer.getCollectDirectoryPath() + File.separator + current_coll_name + File.separator + "metadata";
203 ArrayList metadata_sets = MetadataSetManager.listMetadataSets(new File(file_name));
204 if (metadata_sets != null) {
205 // unload the ex mds
206 for (int i = 0, j = metadata_sets.size(); i < j; i++) {
207 if (((MetadataSet) metadata_sets.get(i)).getNamespace().equals("ex")) {
208 metadata_sets.remove(i);
209 break;
210 }
211 }
212 }
213
214 if (metadata_sets == null) {
215 metadata_sets = new ArrayList();
216 }
217 if (metadata_sets.size() == 0) {
218 // load dublin core
219 file_name = org.greenstone.gatherer.gems.MetadataSetManager.getGLIMetadataDirectoryPath();
220 file_name += "dublin.mds";
221 File dublin_mds_file = new File(file_name);
222 if (dublin_mds_file.exists()) {
223 MetadataSetManager.loadMetadataSet(dublin_mds_file);
224 MetadataSet dc = MetadataSetManager.getMetadataSet("dc");
225 metadata_sets.add(dc);
226 }
227 }
228 // if we are still empty :-(
229 if (metadata_sets.size() == 0) {
230 System.err.println("Error: DepositorMetadataMananger can't find any valid metadata set files.");
231 return;
232 }
233
234 // load all the metadata elements
235 for (int i = 0, j = metadata_sets.size(); i < j; i++) {
236 MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
237 ArrayList elements = metadata_set.getMetadataSetElements();
238
239 for (int k = 0; elements != null && k < elements.size(); k++) {
240 MetadataElement element = (MetadataElement) elements.get(k);
241 // all names are language independent at the moment.
242 MetadataElementEntry entry = new MetadataElementEntry (element.getFullName(), element.getName(), false);
243 entry.setToolTip(element.getAttribute(DEFINITION, "en"));
244 metadata_checklist_model.add(entry);
245 }
246 }
247
248 if (!selected_metadata_javascript.equals("")) {
249 for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
250 MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
251
252 String temp = "\"name\":\"" + entry.name + "\"";
253 if (selected_metadata_javascript.indexOf(temp) != -1) {
254 entry.setSelected(true);
255 entry.type = getValueFromJSAssociatedArray(selected_metadata_javascript, entry.name, "type");
256 }
257 temp = null;
258 }
259 } else {
260 // use default elements
261 for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
262 MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
263 if (DEFAULT_METADATA_ELEMENTS.indexOf(entry.name) != -1) {
264 entry.setSelected(true);
265 entry.type = TYPEOPTIONS[0];
266 }
267 }
268 }
269 }
270
271 private void buildPane() {
272 // use different background color for two adjacent metadata sets
273 String current_namespace = null;
274 String current_bgcolor_name = null;
275 for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
276 MetadataElementEntry entry = (MetadataElementEntry) metadata_checklist_model.get(i);
277
278 if (current_namespace == null) {
279 current_namespace = entry.namespace;
280 current_bgcolor_name = "coloring.collection_tree_background";
281 } else {
282 if (!entry.namespace.equals(current_namespace)) {
283 current_namespace = entry.namespace;
284 current_bgcolor_name = (current_bgcolor_name == "coloring.collection_tree_background") ? "coloring.collection_heading_background" : "coloring.collection_tree_background";
285 }
286 }
287
288 if (entry.getGUIControl() == null) {
289 MetadataElementControl element_control = entry.initGUIControl(current_bgcolor_name);
290 central_pane.add(element_control, BorderLayout.NORTH);
291 }
292 }
293
294 }
295
296 /**
297 * Retrieve the value for the specified element in the given javascript associative array expression
298 *
299 * @param text
300 * @param identifier
301 * @param elem_name
302 * @return
303 */
304 private String getValueFromJSAssociatedArray(String text, String identifier, String elem_name) {
305 int p = text.indexOf(elem_name, text.indexOf(identifier));
306 if (p == -1) {
307 return null;
308 }
309 p = text.indexOf("\":\"", p);
310 if (p == -1) {
311 return null;
312 }
313 p += 3;
314
315 return text.substring(p, text.indexOf("\"", p));
316 }
317 }
318
319 private class MetadataElementControl extends JPanel {
320
321 private JCheckBox enabled = null;
322 private JComponent value_control = null;
323
324 public MetadataElementControl (MetadataElementEntry entry, String background_color_name) {
325
326 this.setComponentOrientation(Dictionary.getOrientation());
327 String tip = "<html>" + entry.tooltip + "</html>";
328 tip = Utility.formatHTMLWidth(tip, 80);
329
330 setBackground(Configuration.getColor(background_color_name, false));
331 setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
332 setLayout(new BorderLayout());
333 setPreferredSize(ROW_SIZE);
334 setMaximumSize(MAX_ROW_SIZE);
335
336 // the checkbox component
337 enabled = new JCheckBox(entry.name);
338 enabled.setComponentOrientation(Dictionary.getOrientation());
339 enabled.setSelected(entry.selected);
340 enabled.setOpaque(false);
341 enabled.setPreferredSize(LABEL_SIZE);
342 enabled.setToolTipText(entry.tooltip);
343 add(enabled, BorderLayout.LINE_START);
344
345 // the drop down list component
346 ArrayList option_list = new ArrayList();
347 for (int i = 0; i < TYPEOPTIONS.length; i++) {
348 option_list.add(TYPEOPTIONS[i]);
349 }
350 value_control = new GComboBox(option_list.toArray(), false, false);
351 value_control.setComponentOrientation(Dictionary.getOrientation());
352 selectValue((JComboBox)value_control, entry.type);
353 value_control.setOpaque(true);
354 if (entry.selected) {
355 value_control.setBackground(Color.white);
356 value_control.setEnabled(true);
357 } else {
358 value_control.setBackground(Color.lightGray);
359 value_control.setEnabled(false);
360 value_control.setVisible(false);
361 }
362 add(value_control, BorderLayout.CENTER);
363
364 enabled.addActionListener(new EnabledListener(value_control));
365 }
366
367 private boolean selectValue(JComboBox combobox, String target) {
368 if (target == null) {
369 combobox.setSelectedIndex(0);
370 return false;
371 }
372
373 for (int i = 0; i < combobox.getItemCount(); i++) {
374 if (combobox.getItemAt(i).toString().equals(target)) {
375 combobox.setSelectedIndex(i);
376 return true;
377 }
378 }
379 return false;
380 }
381
382 private class EnabledListener
383 implements ActionListener {
384 private JComponent target = null;
385
386 public EnabledListener(JComponent target) {
387 this.target = target;
388 }
389
390 public void actionPerformed(ActionEvent event) {
391 JCheckBox source = (JCheckBox)event.getSource();
392
393 // check at least one of the elements should be ticked
394 checkTickedElements(source);
395
396 // update the status of the drop-down list component associated with the current checkbox
397 if (this.target == null) {
398 return;
399 }
400
401 if(source.isSelected()) {
402 target.setBackground(Color.white);
403 target.setEnabled(true);
404 target.setVisible(true);
405 }
406 else {
407 target.setBackground(Color.lightGray);
408 target.setEnabled(false);
409 target.setVisible(false);
410 }
411 }
412
413 private void checkTickedElements(JCheckBox source) {
414 if (source.isSelected()) {
415 return;
416 }
417
418 boolean b = false;
419 for (int i = 0, j = metadata_checklist_model.size(); i < j; i++) {
420 if (((MetadataElementEntry) metadata_checklist_model.get(i)).gui_object.enabled.isSelected()) {
421 b = true;
422 break;
423 }
424 }
425
426 // there must be at least one element selected in the list
427 if (b == false) {
428 Object[] options = {Dictionary.get("General.OK")};
429 JOptionPane.showOptionDialog(Gatherer.g_man, Dictionary.get("CDM.DepositorMetadataManager.Warning"), Dictionary.get("General.Warning"), JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]);
430
431 source.setSelected(true);
432 }
433 }
434 }
435
436 }
437
438 private class MetadataElementEntry implements Comparable {
439 /** namespace, used to distinguish different metadata sets and use different colors when displaying */
440 String namespace = null;
441 /** identifier, with namespace */
442 String name = null;
443 /** language independent label, without namespace, used for display in the depositor web page, eg. Title */
444 String label = null;
445 /** type of the element: text or textarea */
446 String type = null;
447 /** description of the element, used in web page */
448 String tooltip = null;
449 /** whether current element is selected or not */
450 boolean selected ;
451 /** GUI component object associated with this element */
452 MetadataElementControl gui_object = null;
453
454 /**
455 * Constructor
456 * @param name Language independent identifier of the element with namespace, eg. dc.Title
457 * @param label Language independent label of the element, without namespace, eg. Title
458 * @param selected Whether the current element has been selected as depositor metadata element
459 */
460 public MetadataElementEntry(String name, String label, boolean selected) {
461 this.name = name;
462 this.label = label;
463 this.selected = selected;
464
465 if (name.indexOf(".") != -1) {
466 namespace = name.substring(0, name.indexOf("."));
467 }
468 }
469
470 /**
471 * Initiate the <code>MetadataElementControl<code> GUI component object associated with this element, with the specified background color
472 * @param background_color_name System configured color name for the background, eg. "coloring.collection_heading_background", or "coloring.collection_tree_background"
473 * @return the initialized component object
474 */
475 public MetadataElementControl initGUIControl (String background_color_name) {
476 gui_object = new MetadataElementControl(this, background_color_name);
477 return gui_object;
478 }
479
480 /**
481 * Get the associated GUI component
482 * @return
483 */
484 public MetadataElementControl getGUIControl() {
485 return gui_object;
486 }
487
488 /**
489 * Set selected
490 * @param b
491 */
492 public void setSelected(boolean b) {
493 this.selected = b;
494 }
495
496 public boolean isSelected() {
497 return gui_object.enabled.isSelected();
498 }
499
500 /**
501 * Get the selected type for the element
502 * @return type
503 */
504 public String getType() {
505 return ((JComboBox) gui_object.value_control).getSelectedItem().toString();
506 }
507
508 public void setToolTip (String tip) {
509 if (tip == null) {
510 tooltip = "";
511 return;
512 }
513 this.tooltip = tip;
514 }
515
516 public int compareTo(Object obj) {
517 return compareTo((MetadataElementEntry) obj);
518 }
519
520 public int compareTo(MetadataElementEntry obj) {
521 return this.name.compareTo(obj.name);
522 }
523
524 }
525
526}
Note: See TracBrowser for help on using the repository browser.