1 | package org.greenstone.gatherer.collection;
|
---|
2 | /**
|
---|
3 | *#########################################################################
|
---|
4 | *
|
---|
5 | * A component of the Gatherer application, part of the Greenstone digital
|
---|
6 | * library suite from the New Zealand Digital Library Project at the
|
---|
7 | * University of Waikato, New Zealand.
|
---|
8 | *
|
---|
9 | * <BR><BR>
|
---|
10 | *
|
---|
11 | * Author: John Thompson, Greenstone Digital Library, University of Waikato
|
---|
12 | *
|
---|
13 | * <BR><BR>
|
---|
14 | *
|
---|
15 | * Copyright (C) 1999 New Zealand Digital Library Project
|
---|
16 | *
|
---|
17 | * <BR><BR>
|
---|
18 | *
|
---|
19 | * This program is free software; you can redistribute it and/or modify
|
---|
20 | * it under the terms of the GNU General Public License as published by
|
---|
21 | * the Free Software Foundation; either version 2 of the License, or
|
---|
22 | * (at your option) any later version.
|
---|
23 | *
|
---|
24 | * <BR><BR>
|
---|
25 | *
|
---|
26 | * This program is distributed in the hope that it will be useful,
|
---|
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
29 | * GNU General Public License for more details.
|
---|
30 | *
|
---|
31 | * <BR><BR>
|
---|
32 | *
|
---|
33 | * You should have received a copy of the GNU General Public License
|
---|
34 | * along with this program; if not, write to the Free Software
|
---|
35 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
36 | *########################################################################
|
---|
37 | */
|
---|
38 | import java.io.*;
|
---|
39 | import java.lang.Class;
|
---|
40 | import java.util.*;
|
---|
41 | import javax.swing.*;
|
---|
42 | import javax.swing.event.*;
|
---|
43 | import javax.swing.tree.*;
|
---|
44 | import org.greenstone.gatherer.Gatherer;
|
---|
45 | import org.greenstone.gatherer.Message;
|
---|
46 | import org.greenstone.gatherer.cdm.CollectionDesignManager;
|
---|
47 | import org.greenstone.gatherer.cdm.CommandTokenizer;
|
---|
48 | import org.greenstone.gatherer.collection.Collection;
|
---|
49 | import org.greenstone.gatherer.collection.SaveCollectionTask;
|
---|
50 | import org.greenstone.gatherer.file.FileNode;
|
---|
51 | import org.greenstone.gatherer.file.FileSystemModel;
|
---|
52 | import org.greenstone.gatherer.gui.LockFileDialog;
|
---|
53 | import org.greenstone.gatherer.gui.NewCollectionMetadataPrompt;
|
---|
54 | import org.greenstone.gatherer.msm.ElementWrapper;
|
---|
55 | import org.greenstone.gatherer.msm.GDMManager;
|
---|
56 | import org.greenstone.gatherer.msm.GreenstoneArchiveParser;
|
---|
57 | import org.greenstone.gatherer.msm.MetadataSet;
|
---|
58 | import org.greenstone.gatherer.msm.MetadataSetManager;
|
---|
59 | import org.greenstone.gatherer.msm.MSMEvent;
|
---|
60 | import org.greenstone.gatherer.msm.MSMListener;
|
---|
61 | import org.greenstone.gatherer.msm.MSMProfiler;
|
---|
62 | import org.greenstone.gatherer.msm.MSMUtils;
|
---|
63 | import org.greenstone.gatherer.shell.GShell;
|
---|
64 | import org.greenstone.gatherer.shell.GShellEvent;
|
---|
65 | import org.greenstone.gatherer.shell.GShellListener;
|
---|
66 | import org.greenstone.gatherer.shell.GShellProgressMonitor;
|
---|
67 | import org.greenstone.gatherer.undo.UndoManager;
|
---|
68 | import org.greenstone.gatherer.util.ArrayTools;
|
---|
69 | import org.greenstone.gatherer.util.Codec;
|
---|
70 | import org.greenstone.gatherer.util.GSDLSiteConfig;
|
---|
71 | import org.greenstone.gatherer.util.MetadataXML;
|
---|
72 | import org.greenstone.gatherer.util.StaticStrings;
|
---|
73 | import org.greenstone.gatherer.util.SynchronizedTreeModelTools;
|
---|
74 | import org.greenstone.gatherer.util.Utility;
|
---|
75 | import org.w3c.dom.*;
|
---|
76 | /** This class manages many aspects of the collection, from its creation via scripts, data access via methods and its importing and building into the final collection. It is also resposible for firing appropriate event when significant changes have occured within the collection, and for creating a new metadata set manager as necessary.
|
---|
77 | * @author John Thompson
|
---|
78 | * @version 2.3
|
---|
79 | */
|
---|
80 | public class CollectionManager
|
---|
81 | implements GShellListener, MSMListener {
|
---|
82 | /** A reference to the metadata set manager. */
|
---|
83 | public MetadataSetManager msm;
|
---|
84 | /** A reference to the undo manager. Although only one instance is shared between all collections, the undo queues are emptied between each. */
|
---|
85 | public UndoManager undo;
|
---|
86 | /** Are we currently in the process of building? */
|
---|
87 | private boolean building = false;
|
---|
88 | /** Are we currently in the process of importing? */
|
---|
89 | private boolean importing = false;
|
---|
90 | /** The collection this manager is managing! */
|
---|
91 | private Collection collection = null;
|
---|
92 | /** The collection_model. */
|
---|
93 | private FileSystemModel collection_model = null;
|
---|
94 | /** The workspace model. This becomes invalid on a collection change. */
|
---|
95 | private FileSystemModel workspace_model = null;
|
---|
96 | /** An inner class listener responsible for noting tree changes and resetting saved when they occur. */
|
---|
97 | private FMTreeModelListener fm_tree_model_listener = null;
|
---|
98 | /** The monitor resposible for parsing the build process. */
|
---|
99 | private GShellProgressMonitor build_monitor = null;
|
---|
100 | /** The monitor resposible for parsing the copy process. */
|
---|
101 | private GShellProgressMonitor copy_monitor = null;
|
---|
102 | /** The monitor resposible for parsing the import process. */
|
---|
103 | private GShellProgressMonitor import_monitor = null;
|
---|
104 |
|
---|
105 | private int special_case = -1;
|
---|
106 | /** Holds a reference to the thread responsible for closing the collection. If non-null then only calls from the given thread will see the collection is non-ready. All other threads will have to wait until closing thread, and all of it consequential calls, are completely finished. */
|
---|
107 | private Thread closing_thread = null;
|
---|
108 |
|
---|
109 | /** The name of the standard lock file. */
|
---|
110 | static final public String LOCK_FILE = "gli.lck";
|
---|
111 | static final public int NO_SPECIAL_CASE = -1;
|
---|
112 | static final public int SPECIAL_DLS = 0;
|
---|
113 | /** Constructor. */
|
---|
114 | public CollectionManager() {
|
---|
115 | // Initialisation.
|
---|
116 | this.building = false;
|
---|
117 | this.importing = false;
|
---|
118 | this.collection = null;
|
---|
119 | this.undo = new UndoManager();
|
---|
120 | }
|
---|
121 | /** Add a special directory mapping.
|
---|
122 | * @param name The name for this directory mapping as a <strong>String</strong>.
|
---|
123 | * @param file The directory this mapping maps to as a <strong>File</strong>.
|
---|
124 | */
|
---|
125 | public void addDirectoryMapping(String name, File file) {
|
---|
126 | if(ready()) {
|
---|
127 | // Update the information stored in the collection
|
---|
128 | collection.addDirectoryMapping(name, file);
|
---|
129 | // Now update the tree
|
---|
130 | FileSystemModel model = (FileSystemModel) Gatherer.g_man.collection_pane.getWorkspaceTree().getModel();
|
---|
131 | FileNode parent = (FileNode) model.getRoot();
|
---|
132 | FileNode target = new FileNode(file, name);
|
---|
133 | SynchronizedTreeModelTools.insertNodeInto(model, parent, target);
|
---|
134 | }
|
---|
135 | }
|
---|
136 | /** This method calls the builcol.pl scripts via a GShell so as to not lock up the processor.
|
---|
137 | * @see org.greenstone.gatherer.Configuration
|
---|
138 | * @see org.greenstone.gatherer.Gatherer
|
---|
139 | * @see org.greenstone.gatherer.Message
|
---|
140 | * @see org.greenstone.gatherer.collection.Collection
|
---|
141 | * @see org.greenstone.gatherer.gui.BuildOptions
|
---|
142 | * @see org.greenstone.gatherer.shell.GShell
|
---|
143 | * @see org.greenstone.gatherer.shell.GShellListener
|
---|
144 | * @see org.greenstone.gatherer.shell.GShellProgressMonitor
|
---|
145 | * @see org.greenstone.gatherer.util.Utility
|
---|
146 | */
|
---|
147 | public void buildCollection() {
|
---|
148 | Gatherer.println("CollectionManager.buildCollection()");
|
---|
149 | building = true;
|
---|
150 |
|
---|
151 | String args[];
|
---|
152 | if(Utility.isWindows()) {
|
---|
153 | args = new String[4];
|
---|
154 | args[0] = Gatherer.config.perl_path;
|
---|
155 | args[1] = "-S";
|
---|
156 | args[2] = Gatherer.config.getScriptPath() + "buildcol.pl";
|
---|
157 | args[3] = collection.getName();
|
---|
158 | }
|
---|
159 | else {
|
---|
160 | args = new String[2];
|
---|
161 | args[0] = Gatherer.config.getScriptPath() + "buildcol.pl";
|
---|
162 | args[1] = collection.getName();
|
---|
163 | }
|
---|
164 | args = ArrayTools.add(args, collection.build_options.getBuildValues());
|
---|
165 | GShell shell = new GShell(args, GShell.BUILD, Message.BUILDING, this, build_monitor, GShell.GSHELL_BUILD);
|
---|
166 | shell.addGShellListener(Gatherer.g_man.create_pane);
|
---|
167 | shell.start();
|
---|
168 | Gatherer.println("CollectionManager.buildCollection().return");
|
---|
169 | }
|
---|
170 | /** Used to determine whether the currently active collection has been built.
|
---|
171 | * @return A boolean indicating the built status of the collection.
|
---|
172 | */
|
---|
173 | public boolean built() {
|
---|
174 | if(collection != null) {
|
---|
175 | // Determine if the collection has been built by looking for the build.cfg file
|
---|
176 | File build_cfg_file = new File(getCollectionIndex() + Utility.BUILD_CFG_FILENAME);
|
---|
177 | return build_cfg_file.exists();
|
---|
178 | }
|
---|
179 | return false;
|
---|
180 | }
|
---|
181 | /** Called to close the current collection and remove its lock file.
|
---|
182 | * @see org.greenstone.gatherer.Gatherer
|
---|
183 | * @see org.greenstone.gatherer.collection.Collection
|
---|
184 | * @see org.greenstone.gatherer.util.Utility
|
---|
185 | */
|
---|
186 | public void closeCollection() {
|
---|
187 | Gatherer.println("Close collection: " + collection.getName());
|
---|
188 | // We set the closing thread, as it should be the only one who can actually see the collection is closed, at least until the closing thread expires.
|
---|
189 | closing_thread = Thread.currentThread();
|
---|
190 | // Remove the lock on this file, then remove the collection.
|
---|
191 | File lock_file = new File(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + LOCK_FILE);
|
---|
192 | lock_file.delete();
|
---|
193 | collection.msm.destroy();
|
---|
194 | collection = null;
|
---|
195 | collection_model = null;
|
---|
196 | workspace_model = null;
|
---|
197 | undo.clear();
|
---|
198 | Gatherer.config.setCollectionConfiguration(null);
|
---|
199 | Gatherer.g_man.collectionChanged(false);
|
---|
200 | // All of the consequences of a close should have been processed by now, so others should now see the collection as non-ready.
|
---|
201 | closing_thread = null;
|
---|
202 | }
|
---|
203 |
|
---|
204 | /** Method that is called whenever something has changed in the configuration of this collection. */
|
---|
205 | public void configurationChanged() {
|
---|
206 | if(collection != null) {
|
---|
207 | collection.setSaved(false);
|
---|
208 | }
|
---|
209 | }
|
---|
210 |
|
---|
211 | /** Used to set the current collection to the given collection. Note that this call should -always- be proceeded by a ready call, and if the colection is ready and the saved flag is unset then the user should be prompted to save. Also note that this method creates yet another GShell to run buildcol.pl.
|
---|
212 | * @param description a description of the collection as a String
|
---|
213 | * @param email the email address of the author/maintainer as a String
|
---|
214 | * @param name the short name of the collection, which will subsequently be used to refer to this particular collection, as a String
|
---|
215 | * @param title the longer title of the collection as a String
|
---|
216 | * @param base_collection_directory if the user has chosen to base their new collection on an existing one, this is the directory where this base collection can be found, as a File, otherwise its null
|
---|
217 | * @param metadata_sets if the user has decided to select several metadata sets with which to initially populate the GLI then this is an ArrayList of metadata set file names, otherwise its null
|
---|
218 | */
|
---|
219 | public void createCollection(String description, String email, String name, String title, File base_collection_directory, ArrayList metadata_sets) {
|
---|
220 | boolean cancelled = false;
|
---|
221 | special_case = NO_SPECIAL_CASE;
|
---|
222 | try {
|
---|
223 | // Create a progress monitor.
|
---|
224 | ProgressMonitor progress = new ProgressMonitor(Gatherer.g_man, get("CollectionManager.Creating_New"), "mkcol.pl", 0, 7);
|
---|
225 | // Create the new collection.
|
---|
226 | makeCollection(description, email, name, title);
|
---|
227 | progress.setProgress(1);
|
---|
228 |
|
---|
229 | String a_dir = Utility.getCollectionDir(Gatherer.config.gsdl_path) + name + File.separator;
|
---|
230 |
|
---|
231 | // ACTIVE_DIR/gcache/
|
---|
232 | File gcache_dir_temp = new File(Utility.getCacheDir(a_dir)+"temp.dat");
|
---|
233 | File gcache_dir = gcache_dir_temp.getParentFile();
|
---|
234 | gcache_dir.mkdirs();
|
---|
235 | if(progress != null) {
|
---|
236 | progress.setNote(get("CollectionManager.Gcache_Created"));
|
---|
237 | }
|
---|
238 |
|
---|
239 | // ACTIVE_DIR/log/
|
---|
240 | File log_dir_temp = new File(Utility.getLogDir(a_dir)+"temp.dat");
|
---|
241 | File log_dir = log_dir_temp.getParentFile();
|
---|
242 | log_dir.mkdirs();
|
---|
243 | if(progress != null) {
|
---|
244 | progress.setNote(get("CollectionManager.Log_Created"));
|
---|
245 | }
|
---|
246 |
|
---|
247 | progress.setProgress(2);
|
---|
248 |
|
---|
249 | // Now create the collection object around the directory.
|
---|
250 | collection = new Collection(new File(a_dir, name + ".col"));
|
---|
251 | collection.msm = new MetadataSetManager();
|
---|
252 | msm = collection.msm; // Legacy
|
---|
253 | collection.msm.load();
|
---|
254 |
|
---|
255 | // Import default metadata sets if any.
|
---|
256 | for(int i = 0; metadata_sets != null && i < metadata_sets.size(); i++) {
|
---|
257 | MetadataSet metadata_set = (MetadataSet) metadata_sets.get(i);
|
---|
258 | collection.msm.importMDS(metadata_set.getFile(), false);
|
---|
259 | }
|
---|
260 |
|
---|
261 | // Before we create the CollectionDesignManager we have to check if we are basing it upon some other collection.
|
---|
262 | if(base_collection_directory != null) {
|
---|
263 | Gatherer.println("Basing new collection on existing one: " + base_collection_directory);
|
---|
264 | // Try to import any existing metadata sets for this collection. Look in base_collection_directory/metadata and import any metadata sets found.
|
---|
265 | File base_metadata = new File(base_collection_directory, Utility.META_DIR);
|
---|
266 | if(base_metadata.exists()) {
|
---|
267 | Gatherer.println("Found the metadata directory.");
|
---|
268 | File[] possible_metadata_sets = base_metadata.listFiles();
|
---|
269 | for(int i = 0; possible_metadata_sets != null && i < possible_metadata_sets.length; i++) {
|
---|
270 | String filename = possible_metadata_sets[i].getName();
|
---|
271 | if(filename.endsWith(".mds")) {
|
---|
272 | Gatherer.println("+ Found a metadata set. Importing: " + possible_metadata_sets[i].getAbsolutePath());
|
---|
273 | collection.msm.importMDS(possible_metadata_sets[i], false);
|
---|
274 | }
|
---|
275 | }
|
---|
276 | }
|
---|
277 | else {
|
---|
278 | Gatherer.println("This base collection has no metadata directory.");
|
---|
279 | }
|
---|
280 | // If no sets were imported, then create a new metadata with this new collections name. Note that if this is one of the 'big five' collections then I already know the importing mappings as well.
|
---|
281 | boolean skip_import_phase = false;
|
---|
282 | if(collection.msm.getSets().size() == 0) {
|
---|
283 | Gatherer.println("As there are no metadata sets loaded yet, we'll make special checks for the collections available on the GS2.39CD.");
|
---|
284 | CollectionConfiguration col_con = new CollectionConfiguration(new File(base_collection_directory, Utility.CONFIG_DIR));
|
---|
285 | // If the source collection is one of the 'big five' then we know what the metadata set is.
|
---|
286 | String collection_name = col_con.getName();
|
---|
287 | // Demo collection - part of the DLS
|
---|
288 | if(collection_name.equals(Utility.COLLECTION_DEMO) || collection_name.equals(Utility.COLLECTION_DLS)) {
|
---|
289 | Gatherer.println("+ This is a DLS.mds collection.");
|
---|
290 | special_case = SPECIAL_DLS;
|
---|
291 | String demo_directory = (new File(base_collection_directory.getParentFile(), Utility.COLLECTION_DEMO_DIRECTORY)).getAbsolutePath();
|
---|
292 | String dls_directory = (new File(base_collection_directory.getParentFile(), Utility.COLLECTION_DLS_DIRECTORY)).getAbsolutePath();
|
---|
293 | // Add the dls.mds
|
---|
294 | collection.msm.importMDS(new File(Utility.METADATA_DIR + Utility.DLS_MDS), false);
|
---|
295 | // Add the mappings for the dls (even if its not present).
|
---|
296 | collection.msm.profiler.addAction(dls_directory, "AZList", "dls.AZList");
|
---|
297 | collection.msm.profiler.addAction(dls_directory, "Keyword", "dls.Keyword");
|
---|
298 | collection.msm.profiler.addAction(dls_directory, "Language", "dls.Language");
|
---|
299 | collection.msm.profiler.addAction(dls_directory, "Organization", "dls.Organization");
|
---|
300 | collection.msm.profiler.addAction(dls_directory, "Subject", "dls.Subject");
|
---|
301 | collection.msm.profiler.addAction(dls_directory, "Title", "dls.Title");
|
---|
302 | // Add the mappings for the demo dls (even if its not present).
|
---|
303 | collection.msm.profiler.addAction(demo_directory, "AZList", "dls.AZList");
|
---|
304 | collection.msm.profiler.addAction(demo_directory, "Keyword", "dls.Keyword");
|
---|
305 | collection.msm.profiler.addAction(demo_directory, "Language", "dls.Language");
|
---|
306 | collection.msm.profiler.addAction(demo_directory, "Organization", "dls.Organization");
|
---|
307 | collection.msm.profiler.addAction(demo_directory, "Subject", "dls.Subject");
|
---|
308 | collection.msm.profiler.addAction(demo_directory, "Title", "dls.Title");
|
---|
309 | // Skip the import phase
|
---|
310 | skip_import_phase = true;
|
---|
311 | }
|
---|
312 | // Prompt the user so that they can choose at least one initial metadata set. We're sneaky here and just create a ncm_prompt
|
---|
313 | else {
|
---|
314 | Gatherer.println("This collection has no metadata sets, nor is it one of our special collections, thus we cannot import any metadata sets automatically. Present the user with the metadata set selection prompt.");
|
---|
315 | NewCollectionMetadataPrompt ncm_prompt = new NewCollectionMetadataPrompt();
|
---|
316 | // If cancelled then they really do mean to start a collection with no metadata sets.
|
---|
317 | if(!ncm_prompt.isCancelled()) {
|
---|
318 | ArrayList initial_sets = ncm_prompt.getSets();
|
---|
319 | for(int i = 0; initial_sets != null && i < initial_sets.size(); i++) {
|
---|
320 | MetadataSet metadata_set = (MetadataSet) initial_sets.get(i);
|
---|
321 | collection.msm.importMDS(metadata_set.getFile(), false);
|
---|
322 | metadata_set = null;
|
---|
323 | }
|
---|
324 | initial_sets = null;
|
---|
325 | }
|
---|
326 | ncm_prompt.dispose();
|
---|
327 | ncm_prompt = null;
|
---|
328 | }
|
---|
329 | }
|
---|
330 | // Do a dry metadata import run over the entire base collection, recording profile mappings. We do this by finding the archive files, and then iterating over them using the GreenstoneArchiveParser to retrieve metadata from them. We then process the importing of new metadata elements using the selectElement prompt used in a file action metadata import. However the big change is that we don't actually import any metadata, just create importing profiles.
|
---|
331 | if(!skip_import_phase) {
|
---|
332 | File base_archive = new File(base_collection_directory, Utility.ARCHIVE_DIR);
|
---|
333 | if(base_archive.exists()) {
|
---|
334 | Gatherer.println("+ Archive directory found. Inspecting archives for metadata information.");
|
---|
335 | ArrayList metadata_elements = GreenstoneArchiveParser.extractMetadataElements(base_archive);
|
---|
336 | for(int i = 0; !cancelled && i < metadata_elements.size(); i++) {
|
---|
337 | String metadata_name = (String) metadata_elements.get(i);
|
---|
338 | ElementWrapper target = collection.msm.prompt.selectElement(metadata_name);
|
---|
339 | cancelled = Gatherer.c_man.getCollection().msm.prompt.wasDialogCancelled();
|
---|
340 | if(!cancelled) {
|
---|
341 | if(target != null) {
|
---|
342 | collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), metadata_name, target.getName());
|
---|
343 | }
|
---|
344 | else {
|
---|
345 | collection.msm.profiler.addAction(base_collection_directory.getAbsolutePath(), metadata_name, null);
|
---|
346 | }
|
---|
347 | }
|
---|
348 | }
|
---|
349 | // Hopefully mappings should now be in place for metadata extracted from this collection.
|
---|
350 | }
|
---|
351 | else {
|
---|
352 | Gatherer.println("+ Searching files for metadata.xml information.");
|
---|
353 | // Find the import directory
|
---|
354 | File base_import = new File(base_collection_directory, Utility.IMPORT_DIR);
|
---|
355 | if(base_import.exists()) {
|
---|
356 | searchForMetadata(base_import);
|
---|
357 | }
|
---|
358 | }
|
---|
359 | }
|
---|
360 | // And if that fails then we must have been asked by Satan himself to build the very digital collections of hell, because they don't match any goodly greenstone collection I have ever seen, so you can't blame me if I can't import them.
|
---|
361 |
|
---|
362 |
|
---|
363 | // Now we update our collect.cfg
|
---|
364 | Gatherer.println("Copy and update collect.cfg from base collection.");
|
---|
365 | updateCollectionCFG(new File(base_collection_directory, Utility.CONFIG_DIR), new File(a_dir, Utility.CONFIG_DIR), description, email, title);
|
---|
366 | }
|
---|
367 |
|
---|
368 | // Always import the extracted metadata set
|
---|
369 | collection.msm.importMDS(new File(Utility.METADATA_DIR + Utility.EXTRACTED_METADATA_NAMESPACE + StaticStrings.METADATA_SET_EXTENSION), false);
|
---|
370 |
|
---|
371 | collection.cdm = new CollectionDesignManager(new File(getCollectionConfig()));
|
---|
372 | collection.gdm = new GDMManager();
|
---|
373 |
|
---|
374 | progress.setProgress(3);
|
---|
375 |
|
---|
376 | // Has to be done after creating metadata set manager.
|
---|
377 | File gmeta_dir_temp = new File(getCollectionMetadata()+"temp.dat");
|
---|
378 | File gmeta_dir = gmeta_dir_temp.getParentFile();
|
---|
379 | gmeta_dir.mkdirs();
|
---|
380 | if(progress != null) {
|
---|
381 | progress.setNote("GMeta created");
|
---|
382 | }
|
---|
383 | progress.setProgress(4);
|
---|
384 |
|
---|
385 | progress.setProgress(6);
|
---|
386 | // Register ourselves as being interested in what the msm has to say.
|
---|
387 | collection.msm.addMSMListener(this);
|
---|
388 | // Create a lock file.
|
---|
389 | File lock_file = new File(a_dir, LOCK_FILE);
|
---|
390 | FileOutputStream out = new FileOutputStream(lock_file);
|
---|
391 | out.write(LOCK_FILE.getBytes());
|
---|
392 | out.close();
|
---|
393 | out = null;
|
---|
394 | progress.setProgress(7);
|
---|
395 | String args[] = new String[1];
|
---|
396 | args[0] = name;
|
---|
397 | progress.setNote(get("CollectionManager.Session_Ready", args));
|
---|
398 | progress.close();
|
---|
399 | }
|
---|
400 | catch (Exception error) {
|
---|
401 | Gatherer.printStackTrace(error);
|
---|
402 | }
|
---|
403 | // Done.
|
---|
404 | if(Gatherer.g_man != null) {
|
---|
405 | workspace_model = null;
|
---|
406 | // set the view to Gather pane
|
---|
407 | Gatherer.g_man.setSelectedView(Gatherer.g_man.collection_pane);
|
---|
408 | Gatherer.g_man.collectionChanged(ready());
|
---|
409 | }
|
---|
410 | }
|
---|
411 |
|
---|
412 | public void createLockFile(File destination) {
|
---|
413 | try {
|
---|
414 | Document default_lockfile = Utility.parse("xml/" + LOCK_FILE, true);
|
---|
415 | String user_name = System.getProperty("user.name");
|
---|
416 | Element person_element = (Element) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "User");
|
---|
417 | person_element.appendChild(default_lockfile.createTextNode(user_name));
|
---|
418 | person_element = null;
|
---|
419 | user_name = null;
|
---|
420 | String machine_name = Utility.getMachineName();
|
---|
421 | Element machine_element = (Element) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "Machine");
|
---|
422 | machine_element.appendChild(default_lockfile.createTextNode(machine_name));
|
---|
423 | machine_element = null;
|
---|
424 | machine_name = null;
|
---|
425 | String date_time = Utility.getDateString();
|
---|
426 | Element date_element = (Element) MSMUtils.getNodeFromNamed(default_lockfile.getDocumentElement(), "Date");
|
---|
427 | date_element.appendChild(default_lockfile.createTextNode(date_time));
|
---|
428 | date_element = null;
|
---|
429 | date_time = null;
|
---|
430 | Utility.export(default_lockfile, destination);
|
---|
431 | }
|
---|
432 | catch (Exception error) {
|
---|
433 | Gatherer.printStackTrace(error);
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 | /** Method that is called whenever an element within a set is changed or modified. We want to mark the collection so that it needs saving again.
|
---|
438 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
439 | * @see org.greenstone.gatherer.collection.Collection
|
---|
440 | */
|
---|
441 | public void elementChanged(MSMEvent event) {
|
---|
442 | // This means the state of the collections has changed, so we should set saved to false.
|
---|
443 | collection.setSaved(false);
|
---|
444 | }
|
---|
445 | /** Used to retrieve the build options associated with the currently loaded collection. If none yet exist, default ones are created.
|
---|
446 | * @return A <strong>BuildOptions</strong> object containing the build options for the current collection.
|
---|
447 | * @see org.greenstone.gatherer.collection.Collection
|
---|
448 | */
|
---|
449 | public BuildOptions getBuildOptions() {
|
---|
450 | return collection.build_options;
|
---|
451 | }
|
---|
452 |
|
---|
453 | /** Retrieve the current collection.
|
---|
454 | * @return The <strong>Collection</strong> itself.
|
---|
455 | */
|
---|
456 | public Collection getCollection() {
|
---|
457 | return collection;
|
---|
458 | }
|
---|
459 | /** Constructs the absolute filename of the collection archive directory, which should resemble "$GSDLHOME/collect/<col_name>/archive/"
|
---|
460 | * @return A <strong>String</strong> containing the filename.
|
---|
461 | * @see org.greenstone.gatherer.Configuration
|
---|
462 | * @see org.greenstone.gatherer.Gatherer
|
---|
463 | * @see org.greenstone.gatherer.collection.Collection
|
---|
464 | * @see org.greenstone.gatherer.util.Utility
|
---|
465 | */
|
---|
466 | public String getCollectionArchive() {
|
---|
467 | return Utility.getArchiveDir(Gatherer.config.gsdl_path, collection.getName());
|
---|
468 | }
|
---|
469 | /** Constructs the absolute filename of the collection building directory, which should resemble "$GSDLHOME/collect/<col_name>/building/"
|
---|
470 | * @return A <strong>String</strong> containing the filename.
|
---|
471 | * @see org.greenstone.gatherer.Configuration
|
---|
472 | * @see org.greenstone.gatherer.Gatherer
|
---|
473 | * @see org.greenstone.gatherer.collection.Collection
|
---|
474 | * @see org.greenstone.gatherer.util.Utility
|
---|
475 | */
|
---|
476 | public String getCollectionBuild() {
|
---|
477 | return Utility.getBuildDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
478 | }
|
---|
479 | /** Constructs the absolute filename of the collection cache directory, which should resemble "$GSDLHOME/collect/<col_name>/gcache/"
|
---|
480 | * @return A <strong>String</strong> containing the filename.
|
---|
481 | * @see org.greenstone.gatherer.Configuration
|
---|
482 | * @see org.greenstone.gatherer.Gatherer
|
---|
483 | * @see org.greenstone.gatherer.collection.Collection
|
---|
484 | * @see org.greenstone.gatherer.util.Utility
|
---|
485 | */
|
---|
486 | public String getCollectionCache() {
|
---|
487 | return Utility.getCacheDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
488 | }
|
---|
489 | /** Constructs the absolute filename of the collection config file, which should resemble "$GSDLHOME/collect/<col_name>/etc/collect.cfg"
|
---|
490 | * @return A <strong>String</strong> containing the filename.
|
---|
491 | * @see org.greenstone.gatherer.Configuration
|
---|
492 | * @see org.greenstone.gatherer.Gatherer
|
---|
493 | * @see org.greenstone.gatherer.collection.Collection
|
---|
494 | * @see org.greenstone.gatherer.util.Utility
|
---|
495 | */
|
---|
496 | public String getCollectionConfig() {
|
---|
497 | return Utility.getConfigDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
498 | }
|
---|
499 |
|
---|
500 | /** Constructs the absolute filename of the collection directory, which should resemble "$GSDLHOME/collect/<col_name>"
|
---|
501 | * @return A <strong>String</strong> containing the directory name.
|
---|
502 | * @see org.greenstone.gatherer.Configuration
|
---|
503 | * @see org.greenstone.gatherer.Gatherer
|
---|
504 | * @see org.greenstone.gatherer.collection.Collection
|
---|
505 | * @see org.greenstone.gatherer.util.Utility
|
---|
506 | */
|
---|
507 | public String getCollectionDirectory() {
|
---|
508 | return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator;
|
---|
509 | }
|
---|
510 |
|
---|
511 | /** Constructs the absolute filename of the collection etc directory, which should resemble "$GSDLHOME/collect/<col_name>/etc/"
|
---|
512 | * @return A <strong>String</strong> containing the filename.
|
---|
513 | * @see org.greenstone.gatherer.Configuration
|
---|
514 | * @see org.greenstone.gatherer.Gatherer
|
---|
515 | * @see org.greenstone.gatherer.collection.Collection
|
---|
516 | * @see org.greenstone.gatherer.util.Utility
|
---|
517 | */
|
---|
518 | public String getCollectionEtc() {
|
---|
519 | return Utility.getEtcDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
520 | }
|
---|
521 | /** Constructs the absolute filename of the collection file, which should resemble "$GSDLHOME/collect/<col_name>/<col_name>.col"
|
---|
522 | * @return A <strong>String</strong> containing the filename.
|
---|
523 | * @see org.greenstone.gatherer.Configuration
|
---|
524 | * @see org.greenstone.gatherer.Gatherer
|
---|
525 | * @see org.greenstone.gatherer.collection.Collection
|
---|
526 | * @see org.greenstone.gatherer.util.Utility
|
---|
527 | */
|
---|
528 | public String getCollectionFilename() {
|
---|
529 | return Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator + collection.getName() + ".col";
|
---|
530 | }
|
---|
531 | /** Constructs the absolute filename of the collection import directory, which should resemble "$GSDLHOME/collect/<col_name>/import/"
|
---|
532 | * @return A <strong>String</strong> containing the filename.
|
---|
533 | * @see org.greenstone.gatherer.Configuration
|
---|
534 | * @see org.greenstone.gatherer.Gatherer
|
---|
535 | * @see org.greenstone.gatherer.collection.Collection
|
---|
536 | * @see org.greenstone.gatherer.util.Utility
|
---|
537 | */
|
---|
538 | public String getCollectionImport() {
|
---|
539 | return Utility.getImportDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
540 | }
|
---|
541 | /** Constructs the absolute filename of the collection index directory, which should resemble "$GSDLHOME/collect/<col_name>/index/"
|
---|
542 | * @return A <strong>String</strong> containing the filename.
|
---|
543 | * @see org.greenstone.gatherer.Configuration
|
---|
544 | * @see org.greenstone.gatherer.Gatherer
|
---|
545 | * @see org.greenstone.gatherer.collection.Collection
|
---|
546 | * @see org.greenstone.gatherer.util.Utility
|
---|
547 | */
|
---|
548 | public String getCollectionIndex() {
|
---|
549 | return Utility.getIndexDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
550 | }
|
---|
551 | /** Constructs the absolute filename of the collection log directory, which should resemble "$GSDLHOME/collect/<col_name>/log/"
|
---|
552 | * @return A <strong>String</strong> containing the filename.
|
---|
553 | * @see org.greenstone.gatherer.Configuration
|
---|
554 | * @see org.greenstone.gatherer.Gatherer
|
---|
555 | * @see org.greenstone.gatherer.collection.Collection
|
---|
556 | * @see org.greenstone.gatherer.util.Utility
|
---|
557 | */
|
---|
558 | public String getCollectionLog() {
|
---|
559 | return Utility.getLogDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
560 | }
|
---|
561 | /** Constructs the absolute filename of the collection metadata directory, which should resemble "$GSDLHOME/collect/<col_name>/metadata/"
|
---|
562 | * @return A <strong>String</strong> containing the filename.
|
---|
563 | * @see org.greenstone.gatherer.Configuration
|
---|
564 | * @see org.greenstone.gatherer.Gatherer
|
---|
565 | * @see org.greenstone.gatherer.collection.Collection
|
---|
566 | * @see org.greenstone.gatherer.util.Utility
|
---|
567 | */
|
---|
568 | public String getCollectionMetadata() {
|
---|
569 | return Utility.getMetadataDir(Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName() + File.separator);
|
---|
570 | }
|
---|
571 |
|
---|
572 | /** This method either returns the title of the current collection, or a placeholder string of 'No Collection'.
|
---|
573 | * @return A <strong>String</strong> which represents what we wish to display for a collection title.
|
---|
574 | * @see org.greenstone.gatherer.collection.Collection
|
---|
575 | */
|
---|
576 | public String getCollectionTitle() {
|
---|
577 | if(collection != null) {
|
---|
578 | return collection.getTitle();
|
---|
579 | }
|
---|
580 | return get("Collection.No_Collection");
|
---|
581 | }
|
---|
582 |
|
---|
583 | /** Retrieve the record set (tree model) associated with the current collection. */
|
---|
584 | public TreeModel getRecordSet() {
|
---|
585 | if(collection_model == null && collection != null) {
|
---|
586 | // Use the import directory to generate a new FileSystemModel
|
---|
587 | collection_model = new FileSystemModel(new FileNode(new File(getCollectionImport()), false));
|
---|
588 | // Ensure that the manager is a change listener for the tree.
|
---|
589 | if(fm_tree_model_listener == null) {
|
---|
590 | fm_tree_model_listener = new FMTreeModelListener();
|
---|
591 | }
|
---|
592 | collection_model.addTreeModelListener(fm_tree_model_listener);
|
---|
593 | }
|
---|
594 | return collection_model;
|
---|
595 | }
|
---|
596 | /** Create and return the model behind the workspace tree. Quite an extensive method, as it must first map known greenstone collections, then the local file system and finally any public or private download workspaces. */
|
---|
597 | public TreeModel getWorkspace() {
|
---|
598 | ///ystem.err.println("Get Workspace");
|
---|
599 | if(workspace_model != null) {
|
---|
600 | return workspace_model;
|
---|
601 | }
|
---|
602 | // Determine the local collection directory if any
|
---|
603 | String current_collection_directory = null;
|
---|
604 | if(collection != null) {
|
---|
605 | current_collection_directory = Utility.getCollectionDir(Gatherer.config.gsdl_path) + collection.getName();
|
---|
606 | }
|
---|
607 | // Create the workspace tree.
|
---|
608 | FileNode workspace_root = new FileNode("ABS_ROOT");
|
---|
609 | workspace_model = new FileSystemModel(workspace_root);
|
---|
610 | // Create and add Greenstone collections node.
|
---|
611 | // Starting at the collection directory of gsdl...
|
---|
612 | FileNode world_root = new FileNode(get("Tree.World"));
|
---|
613 | world_root.unmap();
|
---|
614 | workspace_root.insert(world_root);
|
---|
615 | // Create Local File space.
|
---|
616 | // Get all the available roots mounted on the system.
|
---|
617 | File roots[] = File.listRoots();
|
---|
618 | // If there is just one root use it as the tree root (linux)
|
---|
619 | if(roots != null) {
|
---|
620 | FileNode file_root;
|
---|
621 | String name = get("Tree.Root");
|
---|
622 | if(roots.length == 1) {
|
---|
623 | file_root = new FileNode(roots[0], name);
|
---|
624 | workspace_root.insert(file_root);
|
---|
625 | }
|
---|
626 | // Otherwise build a dummy node which has these nodes as children.
|
---|
627 | else {
|
---|
628 | file_root = new FileNode(name);
|
---|
629 | workspace_root.insert(file_root);
|
---|
630 | // Hopefully this does an alphabetic sort.
|
---|
631 | ArrayTools.sort(roots);
|
---|
632 | for(int i = 0; i < roots.length; i++) {
|
---|
633 | FileNode child_root = new FileNode(roots[i]);
|
---|
634 | file_root.insert(child_root);
|
---|
635 | child_root = null;
|
---|
636 | }
|
---|
637 | }
|
---|
638 | name = null;
|
---|
639 | file_root = null;
|
---|
640 | }
|
---|
641 |
|
---|
642 | // Now if we can determine user home folder information, generate a 'special mapping' to it
|
---|
643 | String home_folder_str = System.getProperty("user.home");
|
---|
644 | if(home_folder_str != null && home_folder_str.length() > 0) {
|
---|
645 | File home_folder = new File(home_folder_str);
|
---|
646 | FileNode home_folder_node = new FileNode(home_folder, get("Tree.Home", home_folder.getName()));
|
---|
647 | workspace_root.insert(home_folder_node);
|
---|
648 | }
|
---|
649 |
|
---|
650 | // If mirroring is enabled show the public and private caches.
|
---|
651 | if(Gatherer.config.get("workflow.mirror", false)) {
|
---|
652 | // Add Public workspace
|
---|
653 | FileNode public_root = new FileNode(new File(Utility.CACHE_DIR), get("Tree.Public"));
|
---|
654 | workspace_root.insert(public_root);
|
---|
655 | // Add Private workspace if a collection has been loaded.
|
---|
656 | if(ready()) {
|
---|
657 | FileNode private_root = new FileNode(new File(getCollectionCache()), get("Tree.Private"));
|
---|
658 | workspace_root.insert(private_root);
|
---|
659 | }
|
---|
660 | }
|
---|
661 | // Finally we retrieve and map any predefined special directories.
|
---|
662 | if(ready()) {
|
---|
663 | HashMap mappings = collection.getDirectoryMappings();
|
---|
664 | for(Iterator names = mappings.keySet().iterator(); names.hasNext(); ) {
|
---|
665 | String name = (String) names.next();
|
---|
666 | File file = (File) mappings.get(name);
|
---|
667 | FileNode special_root = new FileNode(file, name);
|
---|
668 | //workspace_root.insert(special_root);
|
---|
669 | SynchronizedTreeModelTools.insertNodeInto(workspace_model, workspace_root, special_root);
|
---|
670 | }
|
---|
671 | }
|
---|
672 | ///ystem.err.println("Returning for getWorkspace()");
|
---|
673 | return workspace_model;
|
---|
674 | }
|
---|
675 | /** This method when called, creates a new GShell in order to run the import.pl script.
|
---|
676 | * @see org.greenstone.gatherer.Configuration
|
---|
677 | * @see org.greenstone.gatherer.Gatherer
|
---|
678 | * @see org.greenstone.gatherer.Message
|
---|
679 | * @see org.greenstone.gatherer.gui.BuildOptions
|
---|
680 | * @see org.greenstone.gatherer.shell.GShell
|
---|
681 | * @see org.greenstone.gatherer.shell.GShellListener
|
---|
682 | * @see org.greenstone.gatherer.shell.GShellProgressMonitor
|
---|
683 | * @see org.greenstone.gatherer.util.Utility
|
---|
684 | */
|
---|
685 | public void importCollection() {
|
---|
686 | Gatherer.println("CollectionManager.importCollection()");
|
---|
687 | if(!saved()) {
|
---|
688 | import_monitor.saving();
|
---|
689 | // Force save.
|
---|
690 | try {
|
---|
691 | SaveCollectionTask save_task = new SaveCollectionTask(collection);
|
---|
692 | save_task.setImportAfter(true);
|
---|
693 | save_task.start();
|
---|
694 | }
|
---|
695 | catch(Exception error) {
|
---|
696 | Gatherer.printStackTrace(error);
|
---|
697 | }
|
---|
698 | }
|
---|
699 | else {
|
---|
700 | importing = true;
|
---|
701 | // Remove erroneous file windows file separator as it causes problems when running import.pl
|
---|
702 | String collection_import = getCollectionImport();
|
---|
703 | if(collection_import.length() > 2 && collection_import.endsWith("\\")) {
|
---|
704 | collection_import = collection_import.substring(0, collection_import.length() - 1);
|
---|
705 | }
|
---|
706 | String args[];
|
---|
707 | if(Utility.isWindows()) {
|
---|
708 | args = new String[6];
|
---|
709 | args[0] = Gatherer.config.perl_path;
|
---|
710 | args[1] = "-S";
|
---|
711 | args[2] = Gatherer.config.getScriptPath() + "import.pl";
|
---|
712 | args[3] = "-importdir";
|
---|
713 | args[4] = collection_import;
|
---|
714 | args[5] = collection.getName();
|
---|
715 | }
|
---|
716 | else {
|
---|
717 | args = new String[4];
|
---|
718 | args[0] = Gatherer.config.getScriptPath() + "import.pl";
|
---|
719 | args[1] = "-importdir";
|
---|
720 | args[2] = collection_import;
|
---|
721 | args[3] = collection.getName();
|
---|
722 | }
|
---|
723 | collection_import = null;
|
---|
724 | args = ArrayTools.add(args, collection.build_options.getImportValues());
|
---|
725 | GShell shell = new GShell(args, GShell.IMPORT, Message.BUILDING, this, import_monitor, GShell.GSHELL_IMPORT);
|
---|
726 | shell.addGShellListener(Gatherer.g_man.create_pane);
|
---|
727 | shell.start();
|
---|
728 | }
|
---|
729 | Gatherer.println("CollectionManager.importCollection().return");
|
---|
730 | }
|
---|
731 | /** Attempts to load the given collection. Currently uses simple serialization of the collection class.
|
---|
732 | * @param location The path to the collection as a <strong>String</strong>.
|
---|
733 | * @see org.greenstone.gatherer.Configuration
|
---|
734 | * @see org.greenstone.gatherer.Gatherer
|
---|
735 | * @see org.greenstone.gatherer.Message
|
---|
736 | * @see org.greenstone.gatherer.collection.Collection
|
---|
737 | * @see org.greenstone.gatherer.msm.MetadataSetManager
|
---|
738 | * @see org.greenstone.gatherer.msm.MSMListener
|
---|
739 | * @see org.greenstone.gatherer.util.Utility
|
---|
740 | */
|
---|
741 | public boolean loadCollection(String location) {
|
---|
742 | Gatherer.println("Load Collection '" + location + "'");
|
---|
743 | String[] args2 = new String[1];
|
---|
744 | args2[0] = location;
|
---|
745 | boolean result = false;
|
---|
746 | // Check we have actually been given a .col file.
|
---|
747 | if(location.endsWith(".col")) {
|
---|
748 | File collection_file = new File(location);
|
---|
749 | // Ensure that the directory exists.
|
---|
750 | File collection_directory = collection_file.getParentFile();
|
---|
751 | if(collection_directory.exists()) {
|
---|
752 | // Special case of a user trying to open an old greenstone collection. One day this will be supported, but for now complain, and explain how to actually re-build this collection
|
---|
753 | File metadata_directory = new File(collection_directory, Utility.META_DIR);
|
---|
754 | if(!metadata_directory.exists()) {
|
---|
755 | JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.Old_Collection", args2), get("General.Warning"), JOptionPane.INFORMATION_MESSAGE);
|
---|
756 | }
|
---|
757 | // Normal GLI collection
|
---|
758 | else {
|
---|
759 | String name = collection_directory.getName();
|
---|
760 | File lock_file = new File(collection_file.getParentFile(), LOCK_FILE);
|
---|
761 | // Now determine if a lock already exists on this collection.
|
---|
762 | int choice = LockFileDialog.YES_OPTION;
|
---|
763 | if(lock_file.exists()) {
|
---|
764 | LockFileDialog dialog = new LockFileDialog(Gatherer.g_man, name, lock_file);
|
---|
765 | choice = dialog.getChoice();
|
---|
766 | dialog.dispose();
|
---|
767 | dialog = null;
|
---|
768 | }
|
---|
769 | if(choice == LockFileDialog.YES_OPTION) {
|
---|
770 | try {
|
---|
771 | if(lock_file.exists()) {
|
---|
772 | lock_file.delete();
|
---|
773 | }
|
---|
774 | // Create a lock file.
|
---|
775 | createLockFile(lock_file);
|
---|
776 | // Open the collection file
|
---|
777 | collection = new Collection(collection_file);
|
---|
778 | ///ystem.err.println("In CollectionManager::loadCollection(), collection: " + collection);
|
---|
779 | collection.msm = new MetadataSetManager();
|
---|
780 | msm = collection.msm; // Legacy
|
---|
781 | collection.msm.load();
|
---|
782 | collection.cdm = new CollectionDesignManager(new File(collection_file.getParent(), Utility.CONFIG_DIR));
|
---|
783 | collection.gdm = new GDMManager();
|
---|
784 | // Tell everyone that it worked.
|
---|
785 | Gatherer.println(get("CollectionManager.Loading_Successful", name));
|
---|
786 | // Now we need to hook up classes that depend on messages from the metadata set manager to keep their content fresh.
|
---|
787 | collection.msm.addMSMListener(this);
|
---|
788 | // We're done. Let everyone know.
|
---|
789 | if(Gatherer.g_man != null) {
|
---|
790 | workspace_model = null;
|
---|
791 | Gatherer.g_man.collectionChanged(ready());
|
---|
792 | }
|
---|
793 | result = true;
|
---|
794 | ///ystem.err.println("Done loadCollection().");
|
---|
795 | } catch (Exception error) {
|
---|
796 | // There is obviously no existing collection present.
|
---|
797 | Gatherer.printStackTrace(error);
|
---|
798 | JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.Cannot_Open", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE);
|
---|
799 | }
|
---|
800 | }
|
---|
801 | lock_file = null;
|
---|
802 | }
|
---|
803 | }
|
---|
804 | else {
|
---|
805 | JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.File_Not_Found", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE);
|
---|
806 | }
|
---|
807 | collection_directory = null;
|
---|
808 | }
|
---|
809 | else {
|
---|
810 | JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.Not_Col_File", args2), get("General.Error"), JOptionPane.ERROR_MESSAGE);
|
---|
811 | Gatherer.println("Not a Gatherer Collection.");
|
---|
812 | }
|
---|
813 | args2 = null;
|
---|
814 | return result;
|
---|
815 | }
|
---|
816 |
|
---|
817 | public void makeCollection(String description, String email, String name, String title) {
|
---|
818 | // Encode the description so it is safe to write to shell
|
---|
819 | if(Utility.isWindows()) {
|
---|
820 | description = Codec.transform(description, Codec.TEXT_TO_SHELL_WINDOWS);
|
---|
821 | }
|
---|
822 | else {
|
---|
823 | description = Codec.transform(description, Codec.TEXT_TO_SHELL_UNIX);
|
---|
824 | }
|
---|
825 | // Run the mkcol command.
|
---|
826 | String command[];
|
---|
827 | if(Utility.isWindows()) {
|
---|
828 | if(description == null || email == null || title == null) {
|
---|
829 | command = new String[4];
|
---|
830 | }
|
---|
831 | else {
|
---|
832 | command = new String[10];
|
---|
833 | }
|
---|
834 | command[0] = Gatherer.config.perl_path;
|
---|
835 | command[1] = "-S";
|
---|
836 | command[2] = Gatherer.config.getScriptPath() + "mkcol.pl";
|
---|
837 | if(description == null || email == null || title == null) {
|
---|
838 | command[3] = name;
|
---|
839 | }
|
---|
840 | else {
|
---|
841 | command[3] = "-title";
|
---|
842 | command[4] = title;
|
---|
843 | command[5] = "-creator";
|
---|
844 | command[6] = email;
|
---|
845 | command[7] = "-about";
|
---|
846 | command[8] = description;
|
---|
847 | command[9] = name;
|
---|
848 | }
|
---|
849 | }
|
---|
850 | else {
|
---|
851 | if(description == null || email == null || title == null) {
|
---|
852 | command = new String[2];
|
---|
853 | command[0] = "mkcol.pl";
|
---|
854 | command[1] = name;
|
---|
855 | }
|
---|
856 | else {
|
---|
857 | command = new String[8];
|
---|
858 | command[0] = "mkcol.pl";
|
---|
859 | command[1] = "-title";
|
---|
860 | command[2] = title;
|
---|
861 | command[3] = "-creator";
|
---|
862 | command[4] = email;
|
---|
863 | command[5] = "-about";
|
---|
864 | command[6] = description;
|
---|
865 | command[7] = name;
|
---|
866 | }
|
---|
867 | }
|
---|
868 | GShell process = new GShell(command, GShell.NEW, Message.COLLECT, this, null, GShell.GSHELL_NEW);
|
---|
869 | process.addGShellListener(this);
|
---|
870 | process.run(); // Don't bother threading this... yet
|
---|
871 | }
|
---|
872 |
|
---|
873 | /** Any implementation of GShellListener must include this method to allow the GShell to send messages to listeners. However in this case the CollectionManager is in no way interested in what the messages are, just the import events which have a specific type and are handled elsewhere. Thus we can safely ignore this event.
|
---|
874 | * @param event A <strong>GShellEvent</strong> which contains a the message.
|
---|
875 | */
|
---|
876 | public synchronized void message(GShellEvent event) {
|
---|
877 | }
|
---|
878 | /** Called whenever the metadata value changes in some way, such as the addition of a new value. We want to mark the collection so that it needs saving again.
|
---|
879 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
880 | * @see org.greenstone.gatherer.collection.Collection
|
---|
881 | */
|
---|
882 | public void metadataChanged(MSMEvent event) {
|
---|
883 | // Again this change means we need to save the collection again.
|
---|
884 | collection.setSaved(false);
|
---|
885 | }
|
---|
886 | /** This call is fired whenever a process within a GShell created by this class begins.
|
---|
887 | * @param event A <strong>GShellEvent</strong> containing information about the GShell process.
|
---|
888 | * @see org.greenstone.gatherer.Gatherer
|
---|
889 | * @see org.greenstone.gatherer.gui.GUIManager
|
---|
890 | * @see org.greenstone.gatherer.shell.GShell
|
---|
891 | */
|
---|
892 | public synchronized void processBegun(GShellEvent event) {
|
---|
893 | Gatherer.println("CollectionManager.processBegun(" + event.getType() + ")");
|
---|
894 | ///ystem.err.println("ProcessBegun " + event.getType());
|
---|
895 | // If this is one of the types where we wish to lock user control
|
---|
896 | Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), true);
|
---|
897 | }
|
---|
898 | /** This call is fired whenever a process within a GShell created by this class ends.
|
---|
899 | * @param event A <strong>GShellEvent</strong> containing information about the GShell process.
|
---|
900 | * @see org.greenstone.gatherer.Gatherer
|
---|
901 | * @see org.greenstone.gatherer.gui.GUIManager
|
---|
902 | * @see org.greenstone.gatherer.shell.GShell
|
---|
903 | */
|
---|
904 | public synchronized void processComplete(GShellEvent event) {
|
---|
905 | Gatherer.println("CollectionManager.processComplete(" + event.getType() + ")");
|
---|
906 | ///ystem.err.println("ProcessComplete " + event.getType());
|
---|
907 | Gatherer.g_man.lockCollection((event.getType() == GShell.IMPORT), false);
|
---|
908 | ///ystem.err.println("Recieved process complete event - " + event);
|
---|
909 | // If we were running an import, now run a build.
|
---|
910 | if(event.getType() == GShell.IMPORT && event.getStatus() != GShell.ERROR) {
|
---|
911 | // Finish import.
|
---|
912 | collection.setImported(true);
|
---|
913 | buildCollection();
|
---|
914 | }
|
---|
915 | // If we were running a build, now is when we move files across.
|
---|
916 | else if(event.getType() == GShell.BUILD && event.getStatus() != GShell.ERROR) {
|
---|
917 | ///ystem.err.println("Installing collection.");
|
---|
918 | installCollection();
|
---|
919 | // If we have a local library running (that we know about) then we ask it to add our newly create collection
|
---|
920 | ///ystem.err.println("Check if we should reset local server.");
|
---|
921 | if(Gatherer.config.exec_file != null) {
|
---|
922 | ///ystem.err.println("Local Library Found!");
|
---|
923 | Gatherer.g_man.preview_pane.configServer(GSDLSiteConfig.ADD_COMMAND + collection.getName());
|
---|
924 | }
|
---|
925 | //else {
|
---|
926 | ///ystem.err.println("GLI can't recognize a local library.");
|
---|
927 | //}
|
---|
928 | // Signal collection changed.
|
---|
929 | workspace_model = null;
|
---|
930 | Gatherer.g_man.collectionChanged(ready());
|
---|
931 | JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.Preview_Ready"), get("CollectionManager.Preview_Ready_Title"), JOptionPane.INFORMATION_MESSAGE);
|
---|
932 | }
|
---|
933 | else if(event.getStatus() == GShell.ERROR) {
|
---|
934 | JOptionPane.showMessageDialog(Gatherer.g_man, get("CollectionManager.Preview_Ready_Failed"), get("CollectionManager.Preview_Ready_Title"), JOptionPane.ERROR_MESSAGE);
|
---|
935 | Gatherer.g_man.collectionChanged(ready());
|
---|
936 | }
|
---|
937 | }
|
---|
938 | /** Determine if the manager is ready for actions apon its collection.
|
---|
939 | * @return A <i>boolean</i> which is <i>true</i> to indicate a collection has been loaded and thus the collection is ready for editing, <i>false</i> otherwise.
|
---|
940 | */
|
---|
941 |
|
---|
942 | public synchronized boolean ready() {
|
---|
943 | if(collection != null) {
|
---|
944 | return true;
|
---|
945 | }
|
---|
946 | else {
|
---|
947 | return false;
|
---|
948 | }
|
---|
949 | }
|
---|
950 |
|
---|
951 | public synchronized boolean reallyReady() {
|
---|
952 | // If the closing thread is non-null we should only allow that thread to see the collection as closed.
|
---|
953 | if(closing_thread != null) {
|
---|
954 | // Only the closing thread sees the truth
|
---|
955 | if(Thread.currentThread() == closing_thread) {
|
---|
956 | return (collection == null);
|
---|
957 | }
|
---|
958 | // All other threads are told a lie.
|
---|
959 | else {
|
---|
960 | return true;
|
---|
961 | }
|
---|
962 | }
|
---|
963 | else {
|
---|
964 | if(collection != null) {
|
---|
965 | return true;
|
---|
966 | }
|
---|
967 | else {
|
---|
968 | return false;
|
---|
969 | }
|
---|
970 | }
|
---|
971 | }
|
---|
972 |
|
---|
973 | /** Refresh the Greenstone Collections special mapping in the workspace tree to account for collections being added/removed
|
---|
974 | */
|
---|
975 | public void refreshGreenstoneCollections() {
|
---|
976 | FileNode root = (FileNode) workspace_model.getRoot();
|
---|
977 | FileNode greenstone_collections_node = null;
|
---|
978 | int root_child_count = root.getChildCount();
|
---|
979 | String greenstone_collections_str = get("Tree.World");
|
---|
980 | for(int i = 0; greenstone_collections_node == null && i < root_child_count; i++) {
|
---|
981 | TreeNode child = root.getChildAt(i);
|
---|
982 | if(child.toString().equals(greenstone_collections_str)) {
|
---|
983 | greenstone_collections_node = (FileNode) child;
|
---|
984 | }
|
---|
985 | child = null;
|
---|
986 | }
|
---|
987 | greenstone_collections_str = null;
|
---|
988 | root = null;
|
---|
989 | if(greenstone_collections_node != null) {
|
---|
990 | TreePath greenstone_collections_path = new TreePath(greenstone_collections_node.getPath());
|
---|
991 | workspace_model.refresh(greenstone_collections_path);
|
---|
992 | greenstone_collections_path = null;
|
---|
993 | greenstone_collections_node = null;
|
---|
994 | }
|
---|
995 | }
|
---|
996 |
|
---|
997 | /** Called to refresh the models upon which the trees are based.
|
---|
998 | * @see org.greenstone.gatherer.collection.Collection
|
---|
999 | */
|
---|
1000 | public void refreshTrees() {
|
---|
1001 | }
|
---|
1002 | /** This method associates the collection build monitor with the build monitor created in CreatePane.
|
---|
1003 | * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the build monitor.
|
---|
1004 | */
|
---|
1005 | public void registerBuildMonitor(GShellProgressMonitor monitor) {
|
---|
1006 | build_monitor = monitor;
|
---|
1007 | }
|
---|
1008 | /** This method associates the collection copy monitor with the copy monitor created in CreatePane.
|
---|
1009 | * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the copy monitor.
|
---|
1010 | */
|
---|
1011 | public void registerCopyMonitor(GShellProgressMonitor monitor) {
|
---|
1012 | copy_monitor = monitor;
|
---|
1013 | }
|
---|
1014 | /** This method associates the collection import monitor with the import monitor created in CreatePane.
|
---|
1015 | * @param monitor A <strong>GShellProgressMonitor</strong> which we will use as the import monitor.
|
---|
1016 | */
|
---|
1017 | public void registerImportMonitor(GShellProgressMonitor monitor) {
|
---|
1018 | import_monitor = monitor;
|
---|
1019 | }
|
---|
1020 | /** Remove a previously assigned special directory mapping.
|
---|
1021 | * @param name The symbolic name of the special directory mapping to remove as a <strong>String</strong>.
|
---|
1022 | * @return The <strong>File</strong> of the mapping removed.
|
---|
1023 | */
|
---|
1024 | public File removeDirectoryMapping(FileNode target) {
|
---|
1025 | File file = null;
|
---|
1026 | if(ready()) {
|
---|
1027 | // Remove from collection, remembering file
|
---|
1028 | file = collection.removeDirectoryMapping(target.toString());
|
---|
1029 | // Update tree.
|
---|
1030 | FileSystemModel model = (FileSystemModel) Gatherer.g_man.collection_pane.getWorkspaceTree().getModel();
|
---|
1031 | SynchronizedTreeModelTools.removeNodeFromParent(model, target);
|
---|
1032 | }
|
---|
1033 | return file;
|
---|
1034 | }
|
---|
1035 | /** Used to check whether all open collections have a 'saved' state.
|
---|
1036 | * @return A <i>boolean</i> which is <i>true</i> if the collection has been saved.
|
---|
1037 | * @see org.greenstone.gatherer.collection.Collection
|
---|
1038 | */
|
---|
1039 | public boolean saved() {
|
---|
1040 | boolean result = true;
|
---|
1041 | if(collection != null) {
|
---|
1042 | result = collection.getSaved();
|
---|
1043 | }
|
---|
1044 | return result;
|
---|
1045 | }
|
---|
1046 | /** Saves a collection by serializing it to file.
|
---|
1047 | * @param close_after <i>true</i> to cause the Gatherer to close the collection once save is complete, <i>false</i> otherwise.
|
---|
1048 | * @param exit_after <i>true</i> to cause the Gatherer to exit once save is complete, <i>false</i> otherwise.
|
---|
1049 | * @see org.greenstone.gatherer.Gatherer
|
---|
1050 | * @see org.greenstone.gatherer.Message
|
---|
1051 | * @see org.greenstone.gatherer.gui.GUIManager
|
---|
1052 | * @see org.greenstone.gatherer.gui.GConfigPane
|
---|
1053 | * @see org.greenstone.gatherer.collection.Collection
|
---|
1054 | */
|
---|
1055 | public void saveCollection(boolean close_after, boolean exit_after) {
|
---|
1056 | Gatherer.println("Save collection: " + collection.getName());
|
---|
1057 | try {
|
---|
1058 | SaveCollectionTask save_task = new SaveCollectionTask(collection, close_after, exit_after);
|
---|
1059 | save_task.start();
|
---|
1060 | // Run this in the same thread
|
---|
1061 | //save_task.run();
|
---|
1062 | }
|
---|
1063 | catch(Exception error) {
|
---|
1064 | Gatherer.printStackTrace(error);
|
---|
1065 | }
|
---|
1066 | }
|
---|
1067 | /** Saves the current collection to a new filename, then restores the original collection. Finally opens the collection copy.
|
---|
1068 | * @param name The name collection name.
|
---|
1069 | */
|
---|
1070 | public void saveCollectionAs(String name) {
|
---|
1071 | // We need to do this in a separate thread so create a SaveCollectionAsTask
|
---|
1072 | try {
|
---|
1073 | SaveCollectionTask save_task = new SaveCollectionTask(collection, name);
|
---|
1074 | save_task.start();
|
---|
1075 | }
|
---|
1076 | catch(Exception error) {
|
---|
1077 | Gatherer.printStackTrace(error);
|
---|
1078 | }
|
---|
1079 | }
|
---|
1080 |
|
---|
1081 | /** Method that is called whenever the metadata set collection changes in some way, such as the addition of a new set or the merging of two sets. We want to mark the collection so that it needs saving again.
|
---|
1082 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
1083 | * @see org.greenstone.gatherer.collection.Collection
|
---|
1084 | */
|
---|
1085 | public void setChanged(MSMEvent event) {
|
---|
1086 | // Invalidate saved
|
---|
1087 | collection.setSaved(false);
|
---|
1088 | }
|
---|
1089 |
|
---|
1090 | /** Updates the given workspace tree model to reference the private cache of the currently loaded collection. */
|
---|
1091 | public void updatePrivateWorkspace(DefaultTreeModel model) {
|
---|
1092 | // Add Private workspace if a collection has been loaded.
|
---|
1093 | if(ready() && !Gatherer.config.get("workflow.mirror", true)) {
|
---|
1094 | FileNode root = (FileNode)model.getRoot();
|
---|
1095 | // Remove old private workspace
|
---|
1096 | FileNode old = (FileNode)model.getChild(root, 2);
|
---|
1097 | model.removeNodeFromParent(old);
|
---|
1098 | // Create and insert new.
|
---|
1099 | FileNode private_workspace = new FileNode(new File(getCollectionCache()), get("Tree.Private"));
|
---|
1100 | model.insertNodeInto(private_workspace, root, 2);
|
---|
1101 | }
|
---|
1102 | }
|
---|
1103 | /** Called whenever the value tree of an metadata element changes in some way, such as the addition of a new value. We want to mark the collection so that it needs saving again.
|
---|
1104 | * @param event A <strong>MSMEvent</strong> containing details of the event that caused this message to be fired.
|
---|
1105 | * @see org.greenstone.gatherer.collection.Collection
|
---|
1106 | */
|
---|
1107 | public void valueChanged(MSMEvent event) {
|
---|
1108 | collection.setSaved(false);
|
---|
1109 | }
|
---|
1110 | /** Used to retrive a value from the dictionary based on the key.
|
---|
1111 | * @param key A <strong>String</strong> indicating what value to retrieve.
|
---|
1112 | * @return A <strong>String</strong> representing the value.
|
---|
1113 | */
|
---|
1114 | private String get(String key) {
|
---|
1115 | return get(key, (String[])null);
|
---|
1116 | }
|
---|
1117 |
|
---|
1118 | /** Used to retrive a value from the dictionary based on the key. */
|
---|
1119 | private String get(String key, String arg) {
|
---|
1120 | String[] args = new String[1];
|
---|
1121 | args[0] = arg;
|
---|
1122 | return get(key, args);
|
---|
1123 | }
|
---|
1124 |
|
---|
1125 | /** Used to retrive a value from the dictionary based on the key, and an array of arguments.
|
---|
1126 | * @param key A <strong>String</strong> indicating what value to retrieve.
|
---|
1127 | * @param args A <strong>String[]</strong> of arguments to be inserted into the phrase.
|
---|
1128 | * @return A <strong>String</strong> representing the value.
|
---|
1129 | */
|
---|
1130 | private String get(String key, String args[]) {
|
---|
1131 | if(key.indexOf('.') == -1) {
|
---|
1132 | key = "CollectionManager." + key;
|
---|
1133 | }
|
---|
1134 | return Gatherer.dictionary.get(key, args);
|
---|
1135 | }
|
---|
1136 | /** Install collection by moving its files from building to index after a successful build.
|
---|
1137 | * @see org.greenstone.gatherer.Gatherer
|
---|
1138 | * @see org.greenstone.gatherer.util.Utility
|
---|
1139 | */
|
---|
1140 | private void installCollection() {
|
---|
1141 | Gatherer.println("Build complete. Moving files.");
|
---|
1142 |
|
---|
1143 |
|
---|
1144 | try {
|
---|
1145 | // We have to ensure that the local library
|
---|
1146 | if(Gatherer.config.exec_file != null) {
|
---|
1147 | ///ystem.err.println("Local Library Found!");
|
---|
1148 | Gatherer.g_man.preview_pane.configServer(GSDLSiteConfig.RELEASE_COMMAND + collection.getName());
|
---|
1149 | }
|
---|
1150 |
|
---|
1151 | File index_dir = new File(getCollectionIndex(), "temp.txt");
|
---|
1152 | index_dir = index_dir.getParentFile();
|
---|
1153 | Gatherer.println("Index = " + index_dir.getAbsolutePath());
|
---|
1154 |
|
---|
1155 | File build_dir = new File(getCollectionBuild(), "temp.txt");
|
---|
1156 | build_dir = build_dir.getParentFile();
|
---|
1157 | Gatherer.println("Build = " + build_dir.getAbsolutePath());
|
---|
1158 |
|
---|
1159 | // Get the build mode from the build options
|
---|
1160 | String build_mode = collection.build_options.getBuildValue("mode");
|
---|
1161 |
|
---|
1162 | // Special case for build mode "all": replace index dir with building dir
|
---|
1163 | if (build_mode == null || build_mode.equals(get("CreatePane.Mode_All"))) {
|
---|
1164 | // Remove the old index directory
|
---|
1165 | if (index_dir.exists()) {
|
---|
1166 | Utility.delete(index_dir);
|
---|
1167 | // Check the delete worked
|
---|
1168 | if (index_dir.exists()) {
|
---|
1169 | throw new Exception("Index directory cannot be removed.");
|
---|
1170 | }
|
---|
1171 | }
|
---|
1172 |
|
---|
1173 | // Move the building directory to become the new index directory
|
---|
1174 | if (build_dir.renameTo(index_dir) == false) {
|
---|
1175 | throw new Exception("Build directory cannot be moved.");
|
---|
1176 | }
|
---|
1177 |
|
---|
1178 | // Create a new building directory
|
---|
1179 | File new_build = new File(getCollectionBuild(), "temp.txt");
|
---|
1180 | new_build = new_build.getParentFile();
|
---|
1181 | new_build.mkdir();
|
---|
1182 | }
|
---|
1183 |
|
---|
1184 | // Otherwise copy everything in the building dir into the index dir
|
---|
1185 | else {
|
---|
1186 | File[] build_files = build_dir.listFiles();
|
---|
1187 | for (int i = 0; i < build_files.length; i++) {
|
---|
1188 | File build_file = build_files[i];
|
---|
1189 | File index_equivalent = new File(index_dir, build_file.getName());
|
---|
1190 |
|
---|
1191 | // Remove the old file in the index directory (if it exists)
|
---|
1192 | if (index_equivalent.exists()) {
|
---|
1193 | Utility.delete(index_equivalent);
|
---|
1194 | // Check the delete worked
|
---|
1195 | if (index_equivalent.exists()) {
|
---|
1196 | throw new Exception("Index file " + index_equivalent + " cannot be removed.");
|
---|
1197 | }
|
---|
1198 | }
|
---|
1199 |
|
---|
1200 | // Move the file into the index directory
|
---|
1201 | if (build_file.renameTo(index_equivalent) == false) {
|
---|
1202 | throw new Exception("File " + build_file + " cannot be moved into index directory.");
|
---|
1203 | }
|
---|
1204 | }
|
---|
1205 | }
|
---|
1206 | }
|
---|
1207 | catch (Exception exception) {
|
---|
1208 | JOptionPane.showMessageDialog(Gatherer.g_man, "Exception detected during collection install.\nMost likely caused by Windows or Local Library holding locks on files:\n" + exception.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
---|
1209 | }
|
---|
1210 | }
|
---|
1211 | /** Creates and dispatches a message given the initial details.
|
---|
1212 | * @param level An <i>int</i> indicating the message level for this message.
|
---|
1213 | * @param message A <strong>String</strong> which contains the payload of this message.
|
---|
1214 | * @see org.greenstone.gatherer.Log
|
---|
1215 | * @see org.greenstone.gatherer.Message
|
---|
1216 | */
|
---|
1217 | private void message(int level, String message) {
|
---|
1218 | Message msg = new Message(Message.COLLECT, level, message);
|
---|
1219 | if(Gatherer.g_man != null) {
|
---|
1220 | Gatherer.log.add(msg);
|
---|
1221 | } else {
|
---|
1222 | Gatherer.println(msg.toString());
|
---|
1223 | }
|
---|
1224 | }
|
---|
1225 |
|
---|
1226 | private boolean searchArchivesForMetadata(File archive_directory) {
|
---|
1227 | /** @todo - ensure GreenstoneArchiveParser works as expected. */
|
---|
1228 | return true;
|
---|
1229 | }
|
---|
1230 |
|
---|
1231 | private boolean searchForMetadata(File current_file) {
|
---|
1232 | boolean cancelled = false;
|
---|
1233 | if(current_file.isFile() && current_file.getName().equals(Utility.METADATA_XML)) {
|
---|
1234 | cancelled = collection.msm.searchForMetadata(null, new FileNode(current_file), false, true); // A dummy run only.
|
---|
1235 | }
|
---|
1236 | else {
|
---|
1237 | File[] children_files = current_file.listFiles();
|
---|
1238 | for(int i = 0; !cancelled && children_files != null && i < children_files.length; i++) {
|
---|
1239 | cancelled = searchForMetadata(children_files[i]);
|
---|
1240 | }
|
---|
1241 | }
|
---|
1242 | return cancelled;
|
---|
1243 | }
|
---|
1244 |
|
---|
1245 | private void updateCollectionCFG(File base_cfg, File new_cfg, String description, String email, String title) {
|
---|
1246 | boolean first_name = true;
|
---|
1247 | boolean first_extra = true;
|
---|
1248 | String collection_path = (base_cfg.getParentFile().getParentFile()).getAbsolutePath();
|
---|
1249 |
|
---|
1250 | HashMap mappings = collection.msm.profiler.getActions(collection_path);
|
---|
1251 | if(mappings == null) {
|
---|
1252 | Gatherer.println("Mappings is null, which is odd. Leaving all configuration commands which use metadata as they are.");
|
---|
1253 | }
|
---|
1254 |
|
---|
1255 | // Now read in base_cfg line by line, parsing important onces and/or replacing them with information pertinent to our collection. Each line is then written back out to the new collect.cfg file.
|
---|
1256 | try {
|
---|
1257 | BufferedReader in = new BufferedReader(new FileReader(base_cfg));
|
---|
1258 | BufferedWriter out = new BufferedWriter(new FileWriter(new_cfg, false)); // Overwrite whats there.
|
---|
1259 | String command = null;
|
---|
1260 | while((command = in.readLine()) != null) {
|
---|
1261 | // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat.
|
---|
1262 | while(command.trim().endsWith("\\")) {
|
---|
1263 | command = command.substring(0, command.lastIndexOf("\\"));
|
---|
1264 | String next_line = in.readLine();
|
---|
1265 | if(next_line != null) {
|
---|
1266 | command = command + next_line;
|
---|
1267 | }
|
---|
1268 | }
|
---|
1269 | ///ystem.err.println("Read: " + command);
|
---|
1270 | // Now we've finished parsing a line, determine what to do with it.
|
---|
1271 | String command_lc = command.toLowerCase();
|
---|
1272 | // We replace the creator string with our own.
|
---|
1273 | if(command_lc.startsWith(Utility.CFG_CREATOR)) {
|
---|
1274 | write(out, Utility.CFG_CREATOR + " " + email);
|
---|
1275 | }
|
---|
1276 | else if(command_lc.startsWith(Utility.CFG_MAINTAINER)) {
|
---|
1277 | write(out, Utility.CFG_MAINTAINER + " " + email);
|
---|
1278 | }
|
---|
1279 | else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONNAME)) {
|
---|
1280 | if(first_name) {
|
---|
1281 | write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONNAME + " \"" + title + "\"");
|
---|
1282 | first_name = false;
|
---|
1283 | }
|
---|
1284 | }
|
---|
1285 | else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA)) {
|
---|
1286 | if(first_extra) {
|
---|
1287 | write(out, Utility.CFG_COLLECTIONMETA_COLLECTIONEXTRA + " \"" + description + "\"");
|
---|
1288 | first_extra = false;
|
---|
1289 | }
|
---|
1290 | }
|
---|
1291 | else if(command_lc.startsWith(Utility.CFG_COLLECTIONMETA_ICONCOLLECTION)) {
|
---|
1292 | write(out, Utility.CFG_COLLECTIONMETA_ICONCOLLECTION + " \"\"");
|
---|
1293 | }
|
---|
1294 |
|
---|
1295 | // Just before we try more general parsing there are the special cases to check. These are explicit changes required by some collections to produce sensible results.
|
---|
1296 | else if(special_case == SPECIAL_DLS && command_lc.equals("classify hierarchy -hfile azlist.txt -metadata azlist -sort title -buttonname title -hlist_at_top")) {
|
---|
1297 | write(out, "classify AZList -metadata dls.Title -buttonname Title");
|
---|
1298 | }
|
---|
1299 | else if(command_lc.startsWith(Utility.CFG_CLASSIFY)) {
|
---|
1300 | StringTokenizer tokenizer = new StringTokenizer(command);
|
---|
1301 | StringBuffer text = new StringBuffer(tokenizer.nextToken());
|
---|
1302 | // Read in the classifier command watching for hfile, metadata and sort arguments.
|
---|
1303 | String buttonname = null;
|
---|
1304 | String hfile = null;
|
---|
1305 | String new_metadata = null;
|
---|
1306 | String old_metadata = null;
|
---|
1307 | while(tokenizer.hasMoreTokens()) {
|
---|
1308 | String token = tokenizer.nextToken();
|
---|
1309 | if(token.equals(Utility.CFG_CLASSIFY_HFILE)) {
|
---|
1310 | if(tokenizer.hasMoreTokens()) {
|
---|
1311 | text.append(" ");
|
---|
1312 | text.append(token);
|
---|
1313 | token = tokenizer.nextToken();
|
---|
1314 | hfile = token;
|
---|
1315 | }
|
---|
1316 | }
|
---|
1317 | else if(token.equals(Utility.CFG_CLASSIFY_METADATA)) {
|
---|
1318 | if(tokenizer.hasMoreTokens()) {
|
---|
1319 | text.append(" ");
|
---|
1320 | text.append(token);
|
---|
1321 | String temp_metadata = tokenizer.nextToken();
|
---|
1322 | String replacement = null;
|
---|
1323 | if(mappings != null) {
|
---|
1324 | replacement = (String) mappings.get(temp_metadata);
|
---|
1325 | }
|
---|
1326 | if(replacement != null) {
|
---|
1327 | token = replacement;
|
---|
1328 | old_metadata = temp_metadata;
|
---|
1329 | new_metadata = replacement;
|
---|
1330 | }
|
---|
1331 | else {
|
---|
1332 | token = temp_metadata;
|
---|
1333 | }
|
---|
1334 | temp_metadata = null;
|
---|
1335 | replacement = null;
|
---|
1336 | }
|
---|
1337 | }
|
---|
1338 | else if(token.equals(Utility.CFG_CLASSIFY_SORT)) {
|
---|
1339 | if(tokenizer.hasMoreTokens()) {
|
---|
1340 | text.append(" ");
|
---|
1341 | text.append(token);
|
---|
1342 | String temp_metadata = tokenizer.nextToken();
|
---|
1343 | String replacement = null;
|
---|
1344 | if(mappings != null) {
|
---|
1345 | replacement = (String) mappings.get(temp_metadata);
|
---|
1346 | }
|
---|
1347 | if(replacement != null) {
|
---|
1348 | token = replacement;
|
---|
1349 | }
|
---|
1350 | else {
|
---|
1351 | token = temp_metadata;
|
---|
1352 | }
|
---|
1353 | temp_metadata = null;
|
---|
1354 | replacement = null;
|
---|
1355 | }
|
---|
1356 | }
|
---|
1357 | else if(token.equals(Utility.CFG_CLASSIFY_BUTTONNAME)) {
|
---|
1358 | buttonname = token;
|
---|
1359 | }
|
---|
1360 | text.append(' ');
|
---|
1361 | text.append(token);
|
---|
1362 | token = null;
|
---|
1363 | }
|
---|
1364 | tokenizer = null;
|
---|
1365 |
|
---|
1366 | // If we replaced the metadata argument and didn't encounter a buttonname, then add one now pointing back to the old metadata name in order to accomodate macro files which required such names (buttonname is metadata name by default)!
|
---|
1367 | if(old_metadata != null && new_metadata != null && buttonname == null) {
|
---|
1368 | text.append(' ');
|
---|
1369 | text.append(Utility.CFG_CLASSIFY_BUTTONNAME);
|
---|
1370 | text.append(' ');
|
---|
1371 | text.append(old_metadata);
|
---|
1372 | }
|
---|
1373 | command = text.toString();
|
---|
1374 | // Replace the hfile if we found it
|
---|
1375 | if(hfile != null && new_metadata != null) {
|
---|
1376 | command = command.replaceAll(hfile, new_metadata + ".txt");
|
---|
1377 | }
|
---|
1378 | buttonname = null;
|
---|
1379 | hfile = null;
|
---|
1380 | new_metadata = null;
|
---|
1381 | old_metadata = null;
|
---|
1382 | write(out, command);
|
---|
1383 | }
|
---|
1384 | else {
|
---|
1385 | // There is still one special case, that of the format command. In such a command we have to search for [<target>] to ensure we don't change parts of the format which have nothing to do with the metadata elements.
|
---|
1386 | boolean format_command = command_lc.startsWith(Utility.CFG_FORMAT);
|
---|
1387 | // Replace mapping strings
|
---|
1388 | if(mappings != null) {
|
---|
1389 | for(Iterator keys = mappings.keySet().iterator(); keys.hasNext(); ) {
|
---|
1390 | String target = (String) keys.next();
|
---|
1391 | String replacement = (String) mappings.get(target);
|
---|
1392 | if(format_command) {
|
---|
1393 | target = "\\[" + target + "\\]";
|
---|
1394 | replacement = "{Or}{[" + replacement + "]," + target + "}";
|
---|
1395 | }
|
---|
1396 | command = command.replaceAll(target, replacement);
|
---|
1397 | }
|
---|
1398 | }
|
---|
1399 | write(out, command);
|
---|
1400 | }
|
---|
1401 | }
|
---|
1402 | in.close();
|
---|
1403 | in = null;
|
---|
1404 | out.flush();
|
---|
1405 | out.close();
|
---|
1406 | out = null;
|
---|
1407 | }
|
---|
1408 | catch(Exception error) {
|
---|
1409 | Gatherer.printStackTrace(error);
|
---|
1410 | }
|
---|
1411 | // All done, I hope.
|
---|
1412 | }
|
---|
1413 |
|
---|
1414 | private void write(BufferedWriter out, String message)
|
---|
1415 | throws Exception {
|
---|
1416 | ///ystem.err.println("Writing: " + message);
|
---|
1417 | out.write(message, 0, message.length());
|
---|
1418 | out.newLine();
|
---|
1419 | }
|
---|
1420 |
|
---|
1421 | /** The CollectionManager class is getting too confusing by half so I'll implement this TreeModelListener in a private class to make responsibility clear. */
|
---|
1422 | private class FMTreeModelListener
|
---|
1423 | implements TreeModelListener {
|
---|
1424 | /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
|
---|
1425 | * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
|
---|
1426 | */
|
---|
1427 | public void treeNodesChanged(TreeModelEvent event) {
|
---|
1428 | if(collection != null) {
|
---|
1429 | collection.setSaved(false);
|
---|
1430 | }
|
---|
1431 | }
|
---|
1432 | /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
|
---|
1433 | * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
|
---|
1434 | */
|
---|
1435 | public void treeNodesInserted(TreeModelEvent event) {
|
---|
1436 | if(collection != null) {
|
---|
1437 | collection.setSaved(false);
|
---|
1438 | }
|
---|
1439 | }
|
---|
1440 | /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
|
---|
1441 | * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
|
---|
1442 | */
|
---|
1443 | public void treeNodesRemoved(TreeModelEvent event) {
|
---|
1444 | if(collection != null) {
|
---|
1445 | collection.setSaved(false);
|
---|
1446 | }
|
---|
1447 | }
|
---|
1448 | /** Any action that changes one of the tree models within a collection, which are the only models we listen to, mean the collections contents have changed and so saved should be set to false.
|
---|
1449 | * @param event A <strong>TreeModelEvent</strong> encompassing all the information about the event which has changed the tree.
|
---|
1450 | */
|
---|
1451 | public void treeStructureChanged(TreeModelEvent event) {
|
---|
1452 | if(collection != null) {
|
---|
1453 | collection.setSaved(false);
|
---|
1454 | }
|
---|
1455 | }
|
---|
1456 | }
|
---|
1457 | }
|
---|