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 | * <BR><BR>
|
---|
9 | *
|
---|
10 | * Author: John Thompson, Greenstone Digital Library, University of Waikato
|
---|
11 | *
|
---|
12 | * <BR><BR>
|
---|
13 | *
|
---|
14 | * Copyright (C) 1999 New Zealand Digital Library Project
|
---|
15 | *
|
---|
16 | * <BR><BR>
|
---|
17 | *
|
---|
18 | * This program is free software; you can redistribute it and/or modify
|
---|
19 | * it under the terms of the GNU General Public License as published by
|
---|
20 | * the Free Software Foundation; either version 2 of the License, or
|
---|
21 | * (at your option) any later version.
|
---|
22 | *
|
---|
23 | * <BR><BR>
|
---|
24 | *
|
---|
25 | * This program is distributed in the hope that it will be useful,
|
---|
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
28 | * GNU General Public License for more details.
|
---|
29 | *
|
---|
30 | * <BR><BR>
|
---|
31 | *
|
---|
32 | * You should have received a copy of the GNU General Public License
|
---|
33 | * along with this program; if not, write to the Free Software
|
---|
34 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
35 | *########################################################################
|
---|
36 | */
|
---|
37 | package org.greenstone.gatherer.gems;
|
---|
38 |
|
---|
39 | import java.io.*;
|
---|
40 | import java.util.*;
|
---|
41 | import java.util.StringTokenizer;
|
---|
42 | import javax.swing.*;
|
---|
43 | import javax.swing.filechooser.*;
|
---|
44 | import javax.swing.tree.TreePath;
|
---|
45 | import org.greenstone.gatherer.Configuration;
|
---|
46 | import org.greenstone.gatherer.DebugStream;
|
---|
47 | import org.greenstone.gatherer.util.Utility;
|
---|
48 | import org.greenstone.gatherer.collection.CollectionManager;
|
---|
49 | import org.greenstone.gatherer.file.*;
|
---|
50 | import org.greenstone.gatherer.util.XMLTools;
|
---|
51 | import org.apache.xerces.parsers.*;
|
---|
52 | import org.apache.xml.serialize.*;
|
---|
53 | import org.w3c.dom.*;
|
---|
54 | import org.xml.sax.*;
|
---|
55 |
|
---|
56 | /** This class is responsible for managing all the metadata sets in the collection and for providing methods for manipulating the aforementioned sets contents.
|
---|
57 | * @author John Thompson, Greenstone Digital Library, University of Waikato
|
---|
58 | * @version 2.3b
|
---|
59 | */
|
---|
60 | public class MetadataSetManager {
|
---|
61 | static final public String HIDDEN = "hidden"; //The name of the hidden, or system, metadata set.
|
---|
62 | static final public int MAX_LOADED_SETS = 64;
|
---|
63 | static public CollectionManager col_man = null;
|
---|
64 | static private Hashtable mds_hashtable = new Hashtable(); //A mapping from metadata namespace to metadata set.
|
---|
65 | public GEMS gemsptr;
|
---|
66 |
|
---|
67 |
|
---|
68 | /** Constructor. */
|
---|
69 | public MetadataSetManager(GEMS gemscopy) {
|
---|
70 | gemsptr = gemscopy;
|
---|
71 | col_man = new CollectionManager();
|
---|
72 | }
|
---|
73 |
|
---|
74 |
|
---|
75 | public MetadataSet addSet(String namespace, String name) {
|
---|
76 | MetadataSet mds = new MetadataSet(GEMS.METADATA_SET_TEMPLATE);
|
---|
77 | mds.setAttribute("creator", "The Greenstone Librarian Interface");
|
---|
78 | // Calculate lastchanged to right now on this machine by this user
|
---|
79 | String user_name = System.getProperty("user.name");
|
---|
80 | String machine_name = Utility.getMachineName();
|
---|
81 | mds.setAttribute("lastchanged", Utility.getDateString() + " - " + user_name + " on " + machine_name);
|
---|
82 | // And the remaining attributes.
|
---|
83 | mds.setAttribute("namespace", namespace);
|
---|
84 | // Add the name element.
|
---|
85 | mds.setName(name);
|
---|
86 | // this is the location for a global metadata set
|
---|
87 | File mds_file = new File(Utility.METADATA_DIR, namespace + ".mds");
|
---|
88 | mds.setFile(mds_file);
|
---|
89 | mds_hashtable.put(namespace, mds);
|
---|
90 | // fireSetChanged(mds);
|
---|
91 | return mds;
|
---|
92 | }
|
---|
93 |
|
---|
94 |
|
---|
95 | /**
|
---|
96 | Method to rename a metadata set.
|
---|
97 | @param: current_set: The metadata set to rename
|
---|
98 | @param: new_namspace: The new namespace for the current_set
|
---|
99 | @param: new_name: The new (language-dependent) name for the current_set. Multiple names in different languages is not yet implemented in GEMS, but when it is, this method will need to be updated.
|
---|
100 |
|
---|
101 | @pre: There is not another metadata set with namespace new_namespace. Ie namespaces are unique.
|
---|
102 | @post: The Name and namespace in the metadata file will have been updated. The filename will stay the same.
|
---|
103 |
|
---|
104 | @author Matthew Whyte
|
---|
105 | Date last modified: 10/01/12
|
---|
106 | */
|
---|
107 | public void renameSet(MetadataSet current_set, String new_namespace, String new_name)
|
---|
108 | {
|
---|
109 | if(current_set != null)
|
---|
110 | {
|
---|
111 | String old_namespace = current_set.getNamespace();
|
---|
112 | current_set.setNamespace(new_namespace); //Update the namespace
|
---|
113 | current_set.setName(new_name); //Update the name
|
---|
114 | mds_hashtable.remove(old_namespace); //Remove the old set from the hashtable
|
---|
115 | mds_hashtable.put(new_namespace, current_set); //Add the new set to the hashtable
|
---|
116 | }
|
---|
117 | else
|
---|
118 | {
|
---|
119 | //This should not happen.
|
---|
120 | System.err.println("Error: no such set \'" + current_set + "\'");
|
---|
121 | }
|
---|
122 | }
|
---|
123 |
|
---|
124 |
|
---|
125 | /** Destructor.
|
---|
126 | */
|
---|
127 | public void destroy() {
|
---|
128 | mds_hashtable.clear();
|
---|
129 | }
|
---|
130 |
|
---|
131 |
|
---|
132 | /** Used to get all the (non-hidden) elements in this manager.
|
---|
133 | * @return A Vector of ElementWrappers.
|
---|
134 | */
|
---|
135 | public Vector getElements() {
|
---|
136 | return getElements(false);
|
---|
137 | }
|
---|
138 |
|
---|
139 | public Vector getElements(boolean all) {
|
---|
140 | return getElements(all, false);
|
---|
141 | }
|
---|
142 |
|
---|
143 |
|
---|
144 | /** Used to get all the elements in this manager.
|
---|
145 | * @param all <i>true</i> if all elements, including hidden, should be returned.
|
---|
146 | * @return A Vector of ElementWrappers.
|
---|
147 | */
|
---|
148 | public Vector getElements(boolean all, boolean force_extracted) {
|
---|
149 | Vector all_elements = new Vector();
|
---|
150 | for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
|
---|
151 | MetadataSet mds = (MetadataSet)mds_hashtable.get(keys.nextElement());
|
---|
152 | if((!mds.getNamespace().equals(Utility.EXTRACTED_METADATA_NAMESPACE) && !mds.getNamespace().equals(HIDDEN))
|
---|
153 | || (mds.getNamespace().equals(Utility.EXTRACTED_METADATA_NAMESPACE) && (Configuration.get("general.view_extracted_metadata", Configuration.COLLECTION_SPECIFIC) || force_extracted))
|
---|
154 | || (mds.getNamespace().equals(Utility.EXTRACTED_METADATA_NAMESPACE) && mds.getNamespace().equals(HIDDEN) && all)) {
|
---|
155 | ArrayList set_elements = mds.getElements();
|
---|
156 | ///ystem.err.println("The set " + mds + " has " + set_elements.getLength() + " elements.");
|
---|
157 | for(int i = 0; i < set_elements.size(); i++) {
|
---|
158 | Element raw_element = (Element)set_elements.get(i);
|
---|
159 | ElementWrapper element = new ElementWrapper(raw_element);
|
---|
160 | // For now we do not add subfield elements and their parents, just the subfields.
|
---|
161 | NodeList child_elements = raw_element.getElementsByTagName("Element");
|
---|
162 | if(child_elements.getLength() == 0) {
|
---|
163 | all_elements.add(element);
|
---|
164 | }
|
---|
165 | }
|
---|
166 | }
|
---|
167 | }
|
---|
168 | Collections.sort(all_elements);
|
---|
169 | return all_elements;
|
---|
170 | }
|
---|
171 |
|
---|
172 |
|
---|
173 | /** Retrieve a metadata element by its index.
|
---|
174 | * @param index The specified index as an int.
|
---|
175 | * @return An ElementWrapper containing the specied element, or <i>null</i> is no such element exists.
|
---|
176 | */
|
---|
177 | public ElementWrapper getElement(int index) {
|
---|
178 | Vector elements = getElements(false);
|
---|
179 | ElementWrapper result = null;
|
---|
180 | if(0 <= index && index < elements.size()) {
|
---|
181 | result = (ElementWrapper) elements.get(index);
|
---|
182 | }
|
---|
183 | return result;
|
---|
184 | }
|
---|
185 |
|
---|
186 | /** Retrieve a metadata element by looking at the current metadata element. Note that this 'index' element may now be disconnected from the DOM model, so we have to reload the target element by the string method.
|
---|
187 | * @param element The possibly out-of-data MetadataElement.
|
---|
188 | * @return An ElementWrapper containing the specied element, or <i>null</i> is no such element exists.
|
---|
189 | */
|
---|
190 | public ElementWrapper getElement(ElementWrapper element) {
|
---|
191 | return getElement(element.toString());
|
---|
192 | }
|
---|
193 |
|
---|
194 | /** Retrieve a metadata element by its fully qualified name.
|
---|
195 | * @param name The elements name as a String.
|
---|
196 | * @return An ElementWrapper containing the specied element, or <i>null</i> is no such element exists.
|
---|
197 | */
|
---|
198 |
|
---|
199 | public ElementWrapper getElement(String name) {
|
---|
200 | return getElement(name, false);
|
---|
201 | }
|
---|
202 |
|
---|
203 | public ElementWrapper getElement(String name, boolean perfect) {
|
---|
204 | ///ystem.err.println("Retrieve element " + name);
|
---|
205 | if(name == null) {
|
---|
206 | ///ystem.err.println("No name!");
|
---|
207 | return null;
|
---|
208 | }
|
---|
209 | ElementWrapper result = null;
|
---|
210 | MetadataSet set = null;
|
---|
211 | String element = null;
|
---|
212 | // First we seperate off what set it is in, where we have '<set><namespace_separator><element>'.
|
---|
213 | if(name.indexOf(MSMUtils.NS_SEP) != -1) {
|
---|
214 | String namespace = name.substring(0, name.indexOf(MSMUtils.NS_SEP));
|
---|
215 | // Retrieve the correct set if possible.
|
---|
216 | set = (MetadataSet)mds_hashtable.get(namespace);
|
---|
217 | namespace = null;
|
---|
218 | // Now retrieve the element name.
|
---|
219 | element = name.substring(name.indexOf(MSMUtils.NS_SEP) + 1);
|
---|
220 | }
|
---|
221 | // If we are looking for a perfect match, we can assume that no namespace means extracted metadata
|
---|
222 | else if(!perfect) {
|
---|
223 | // No namespace so assume that its extracted metadata.
|
---|
224 | set = (MetadataSet)mds_hashtable.get(Utility.EXTRACTED_METADATA_NAMESPACE);
|
---|
225 | element = name;
|
---|
226 | }
|
---|
227 | if(set != null) {
|
---|
228 | // Now we have a set we are ready to locate the requested element. Break the remaining element name down by the subfield separator, attempting to retrieve the element indicated by each step.
|
---|
229 | if(element.indexOf(MSMUtils.SF_SEP) != -1) {
|
---|
230 | StringTokenizer tokenizer = new StringTokenizer(element, new Character(MSMUtils.SF_SEP).toString());
|
---|
231 | // Has to be at least two tokens
|
---|
232 | if(tokenizer.countTokens() >= 2) {
|
---|
233 | Element current_element = set.getElement(tokenizer.nextToken());
|
---|
234 | while(current_element != null && tokenizer.hasMoreTokens()) {
|
---|
235 | current_element = set.getElement(current_element, tokenizer.nextToken());
|
---|
236 | }
|
---|
237 | if(current_element != null) {
|
---|
238 | result = new ElementWrapper(current_element);
|
---|
239 | current_element = null;
|
---|
240 | }
|
---|
241 | }
|
---|
242 | tokenizer = null;
|
---|
243 | }
|
---|
244 | // No subelements - much easier.
|
---|
245 | if(result == null) {
|
---|
246 | ///ystem.err.print("Trying to match element " + element +"?");
|
---|
247 | Element temp = set.getElement(element);
|
---|
248 | if(temp != null) {
|
---|
249 | result = new ElementWrapper(temp);
|
---|
250 | }
|
---|
251 | temp = null;
|
---|
252 | }
|
---|
253 | set = null;
|
---|
254 | }
|
---|
255 | element = null;
|
---|
256 | return result;
|
---|
257 | }
|
---|
258 |
|
---|
259 | /** Retrieve a certain named element from a certain named set.
|
---|
260 | * @param set The metadata set whose element you want.
|
---|
261 | * @param name The name of the element.
|
---|
262 | * @return An ElementWrapper around the requested element, or null if no such set or element.
|
---|
263 | */
|
---|
264 | public ElementWrapper getElement(String set, String name) {
|
---|
265 | if(mds_hashtable.containsKey(set)) {
|
---|
266 | MetadataSet temp = (MetadataSet)mds_hashtable.get(set);
|
---|
267 | return new ElementWrapper(temp.getElement(name));
|
---|
268 | }
|
---|
269 | return null;
|
---|
270 | }
|
---|
271 |
|
---|
272 |
|
---|
273 | /** Retrieve the named metadata set.
|
---|
274 | * @param name The sets name as a String.
|
---|
275 | * @return The MetadataSet as named, or null if no such set.
|
---|
276 | */
|
---|
277 | public MetadataSet getSet(String namespace) {
|
---|
278 | if(mds_hashtable.containsKey(namespace)) {
|
---|
279 | return (MetadataSet) mds_hashtable.get(namespace);
|
---|
280 | }
|
---|
281 | return null;
|
---|
282 | }
|
---|
283 |
|
---|
284 | /** Method to retrieve all of the metadata sets loaded in this collection.
|
---|
285 | * @return A Vector of metadata sets.
|
---|
286 | */
|
---|
287 | public Vector getSets() {
|
---|
288 | return getSets(true);
|
---|
289 | }
|
---|
290 |
|
---|
291 | public Vector getSets(boolean include_greenstone_extracted) {
|
---|
292 | Vector result = new Vector();
|
---|
293 | for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
|
---|
294 | MetadataSet set = (MetadataSet)mds_hashtable.get(keys.nextElement());
|
---|
295 | if(!set.getNamespace().equals(HIDDEN) && (include_greenstone_extracted || !set.getNamespace().equals(Utility.EXTRACTED_METADATA_NAMESPACE))) {
|
---|
296 | result.add(set);
|
---|
297 | }
|
---|
298 | }
|
---|
299 | return result;
|
---|
300 | }
|
---|
301 |
|
---|
302 |
|
---|
303 | public MetadataSet loadMetadataSet(File metadata_set_file)
|
---|
304 | {
|
---|
305 | File[] all_sets = new File[MAX_LOADED_SETS];
|
---|
306 | MetadataSet tempSet;
|
---|
307 | int i = 0;
|
---|
308 | System.err.println("Loading metadata set file " + metadata_set_file + "...");
|
---|
309 | MetadataSet metadata_set = new MetadataSet(metadata_set_file);
|
---|
310 |
|
---|
311 | //write out existing namespaces to all_sets[]...we use this to determine if a set is
|
---|
312 | //already loaded-Attila
|
---|
313 | for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
|
---|
314 | //System.err.println("keys: " + keys.nextElement() + "\n"); //debug
|
---|
315 | tempSet = (MetadataSet)mds_hashtable.get(keys.nextElement());
|
---|
316 | all_sets[i] = tempSet.getFile();
|
---|
317 | i++;
|
---|
318 | }
|
---|
319 |
|
---|
320 | //Now check our metadata.set's namespace to see if it is already loaded in all_sets
|
---|
321 | for(int p = 0 ; p < i; p++) {
|
---|
322 | if(metadata_set.getFile().compareTo(all_sets[p]) == 0) {
|
---|
323 | gemsptr.warn_cant_load_set();
|
---|
324 | return null;
|
---|
325 | }
|
---|
326 | }
|
---|
327 |
|
---|
328 | //check if this metadata set belongs to a collection
|
---|
329 | //if so, then change the metadata set's name in the interface to (collection) dublin core...
|
---|
330 | String sep = new String(metadata_set.getFile().separator);
|
---|
331 | StringTokenizer st = new StringTokenizer(metadata_set.getFile().toString(), sep);
|
---|
332 | String colName = new String("");
|
---|
333 |
|
---|
334 | while ( st.hasMoreTokens() )
|
---|
335 | {
|
---|
336 | if(st.nextToken().compareTo("collect") == 0) {
|
---|
337 | colName = st.nextToken();
|
---|
338 | break;
|
---|
339 | }
|
---|
340 | }
|
---|
341 |
|
---|
342 | if (colName.equals("")) {
|
---|
343 | mds_hashtable.put(metadata_set.getNamespace(), metadata_set);
|
---|
344 | } else {
|
---|
345 | metadata_set.setCollection(colName);
|
---|
346 | mds_hashtable.put(metadata_set.getNamespace(), metadata_set);
|
---|
347 | }
|
---|
348 | return metadata_set;
|
---|
349 | }
|
---|
350 |
|
---|
351 |
|
---|
352 | /**
|
---|
353 | Method to remove an element or subelement from a metadata set
|
---|
354 | @param element the element to remove, as an <strong>ElementWrapper</strong>
|
---|
355 | @param parent the parent of the element, as an <strong>ElementWrapper</strong> This is required if removing a subelement (can be null - this means the parent is the metadataset root.)
|
---|
356 | @return void
|
---|
357 | Modified by Matthew Whyte 19/01/04
|
---|
358 |
|
---|
359 | This should really be totally replaced by MetadataSet.removeElement --Matthew
|
---|
360 | */
|
---|
361 | public void removeElement(ElementWrapper element, ElementWrapper parent) {
|
---|
362 | // Retrieve the metadata set this element belongs to.
|
---|
363 | String namespace = element.getNamespace();
|
---|
364 | //System.err.println("namespace is: " + namespace); //debug
|
---|
365 | MetadataSet set = (MetadataSet) mds_hashtable.get(namespace);
|
---|
366 | if(set != null) {
|
---|
367 | //Remove the element
|
---|
368 | set.removeElement(element.getElement(), parent);
|
---|
369 | }
|
---|
370 | else {
|
---|
371 | //This should not happen - no such set, no such element.
|
---|
372 | System.err.println("Cannot remove element \'" + element + "\' because there is no such set \'" + namespace + "\'");
|
---|
373 | }
|
---|
374 | }
|
---|
375 |
|
---|
376 |
|
---|
377 | /**
|
---|
378 | Rename the metadata element.
|
---|
379 | @param oldElement An <strong>ElementWrapper</strong> we wish to rename
|
---|
380 | @param newName A <strong>String</strong> which contains the new name of the element.
|
---|
381 | @return An <strong>ElementWrapper</strong> around the newly named element
|
---|
382 | */
|
---|
383 | public void renameElement(ElementWrapper oldElement, String newName)
|
---|
384 | {
|
---|
385 | //Retrive the metadata set this element belongs to.
|
---|
386 | String namespace = oldElement.getNamespace();
|
---|
387 | MetadataSet set = (MetadataSet)mds_hashtable.get(namespace);
|
---|
388 | if(set != null)
|
---|
389 | {
|
---|
390 | //System.err.println("newName is: " + newName); //debug
|
---|
391 | set.renameElement(oldElement.getElement(), newName); //Rename the element
|
---|
392 | }
|
---|
393 | else
|
---|
394 | {
|
---|
395 | System.err.println("No such set " + namespace);
|
---|
396 | }
|
---|
397 | }
|
---|
398 |
|
---|
399 |
|
---|
400 | public void save() {
|
---|
401 | File file = new File(Utility.METADATA_DIR);
|
---|
402 |
|
---|
403 | if (!file.exists()) {
|
---|
404 | System.out.println("trying to save a collection and the metadata directory does not exist - creating it!");
|
---|
405 |
|
---|
406 | file.mkdir();
|
---|
407 | }
|
---|
408 | // And make back ups of all existing metadata set files.
|
---|
409 | File temp[] = file.listFiles();
|
---|
410 |
|
---|
411 | // Now save the latest versions of the metadata sets.
|
---|
412 | for(Enumeration keys = mds_hashtable.keys(); keys.hasMoreElements(); ) {
|
---|
413 | String namespace = (String) keys.nextElement();
|
---|
414 | MetadataSet set = (MetadataSet) mds_hashtable.get(namespace);
|
---|
415 | try {
|
---|
416 | // just use the existing file path
|
---|
417 | File mds_file = set.getFile();
|
---|
418 | XMLTools.writeXMLFile(mds_file, set.getDocument());
|
---|
419 | set.setSetChanged(false);
|
---|
420 | }
|
---|
421 | catch (Exception error) {
|
---|
422 | error.printStackTrace();
|
---|
423 | }
|
---|
424 | }
|
---|
425 | }
|
---|
426 |
|
---|
427 | public void removeSet(MetadataSet set) {
|
---|
428 | mds_hashtable.remove(set.getNamespace());
|
---|
429 | File f = set.getFile();
|
---|
430 | f.delete();
|
---|
431 | }
|
---|
432 | }
|
---|