source: trunk/gli/src/org/greenstone/gatherer/gui/NewCollectionDetailsPrompt.java@ 11939

Last change on this file since 11939 was 11939, checked in by mdewsnip, 18 years ago

Users now have an option to create a "personal" or "shared" collection when creating a new collection using remote building. Personal collections have the user's username prefixed.

  • Property svn:keywords set to Author Date Id Revision
File size: 15.2 KB
Line 
1/**
2 *#########################################################################
3 *
4 * A component of the Gatherer application, part of the Greenstone digital
5 * library suite from the New Zealand Digital Library Project at the
6 * University of Waikato, New Zealand.
7 *
8 * Author: John Thompson, Greenstone Project, NZDL, University of Waikato
9 *
10 * Copyright (C) 2003 New Zealand Digital Library Project
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 *########################################################################
26 */
27package org.greenstone.gatherer.gui;
28
29import java.awt.*;
30import java.awt.event.*;
31import java.io.File;
32import java.util.*;
33import javax.swing.*;
34import javax.swing.event.*;
35import javax.swing.text.*;
36import org.greenstone.gatherer.Configuration;
37import org.greenstone.gatherer.Dictionary;
38import org.greenstone.gatherer.Gatherer;
39import org.greenstone.gatherer.collection.BasicCollectionConfiguration;
40import org.greenstone.gatherer.remote.RemoteGreenstoneServer;
41import org.greenstone.gatherer.util.StaticStrings;
42import org.greenstone.gatherer.util.Utility;
43
44public class NewCollectionDetailsPrompt
45 extends ModalDialog {
46
47 static public boolean titleClashes(String title, File current_config_file) {
48 // An empty collection title never clashes with anything. It may look ugly in the final collection but there is nothing wrong with having no title for a particular language.
49 if(title == null || title.length() == 0) {
50 return false;
51 }
52 File collect_directory = new File(Gatherer.getCollectDirectoryPath());
53 File children[] = collect_directory.listFiles();
54 for(int i = 0; children != null && i < children.length; i++) {
55 if(children[i].isDirectory()) {
56 File config_file = new File(children[i], Utility.CONFIG_FILE);
57 if(current_config_file == null || !config_file.equals(current_config_file)) {
58 BasicCollectionConfiguration other_collection = new BasicCollectionConfiguration(config_file);
59 if(other_collection.getName().equalsIgnoreCase(title)) {
60 return true;
61 }
62 other_collection = null;
63 }
64 config_file = null;
65 }
66 }
67 return false;
68 }
69
70 private boolean cancelled;
71 private File base_final;
72 private JButton create_button;
73 private JComboBox base_collection;
74 private JDialog self;
75 private JRadioButton personal_collection_button = null;
76 private JTextArea description;
77 private JTextField title;
78 private String description_final;
79 private String title_final="";
80 static private Dimension COMPONENT_SIZE = new Dimension(230, 25);
81 /** The size of this new collection dialog box. */
82 static private Dimension SIZE = new Dimension(600, 280);
83 static private int FILENAME_SIZE = 8;
84
85 /** Constructor.
86 * @see org.greenstone.gatherer.util.Utility
87 */
88 public NewCollectionDetailsPrompt() {
89 super(Gatherer.g_man, true);
90 this.cancelled = true;
91 this.self = this;
92 // Setup
93 setJMenuBar(new SimpleMenuBar("creatingacollection"));
94 setSize(SIZE);
95 Dictionary.setText(this, "NewCollectionPrompt.Title");
96
97 // Model building. Build a model of all of the collections in the gsdl collect directory with the appropriate directories.
98 Vector base_collection_model = new Vector();
99 // need to modify this to base a coll on any collection from any site
100 if (Gatherer.GS3) {
101 File sites_dir = new File(Gatherer.getSitesDirectoryPath());
102 File [] sites = sites_dir.listFiles();
103 for (int i=0; i<sites.length; i++) {
104 File collect_directory = new File(sites_dir + sites[i].getName() + File.separator + "collect");
105 if (collect_directory.exists()) {
106 addCollectionsToModel(base_collection_model, collect_directory, sites[i].getName());
107 }
108 }
109 } else {
110 File collect_directory = new File(Gatherer.getCollectDirectoryPath());
111 addCollectionsToModel(base_collection_model, collect_directory, null);
112 }
113
114 // Sort the result.
115 Collections.sort(base_collection_model);
116 base_collection_model.add(0, new Item(null, Dictionary.get("NewCollectionPrompt.NewCollection")));
117
118 // Creation
119 JPanel content_pane = (JPanel) getContentPane();
120 content_pane.setOpaque(true);
121 JPanel upper_pane = new JPanel();
122 JLabel instructions_label = new JLabel();
123 Dictionary.setText(instructions_label, "NewCollectionPrompt.Instructions");
124 JPanel title_pane = new JPanel();
125 JLabel title_label = new JLabel();
126 Dictionary.setText(title_label, "CDM.General.Collection_Name");
127 title = new JTextField();
128 title.setPreferredSize(COMPONENT_SIZE);
129 Dictionary.setTooltip(title, "CDM.General.Collection_Name_Tooltip");
130 JPanel name_pane = new JPanel();
131 JLabel name_label = new JLabel();
132 Dictionary.setText(name_label, "NewCollectionPrompt.Collection_Name");
133
134 JPanel center_pane = new JPanel();
135 JPanel description_pane = new JPanel();
136 JLabel description_label = new JLabel();
137 Dictionary.setText(description_label, "NewCollectionPrompt.Collection_Description");
138 description = new JTextArea();
139 description.setBackground(Configuration.getColor("coloring.editable_background", false));
140 description.setForeground(Configuration.getColor("coloring.editable_foreground", false));
141 description.setRows(5);
142 Dictionary.setTooltip(description, "CDM.General.Collection_Extra_Tooltip");
143
144 JPanel bottom_pane = new JPanel();
145 // Base Collection
146 JPanel base_collection_pane = new JPanel();
147 JLabel base_collection_label = new JLabel();
148 Dictionary.setText(base_collection_label, "NewCollectionPrompt.Base_Collection");
149 base_collection = new JComboBox(base_collection_model);
150 Dictionary.setTooltip(base_collection, "NewCollectionPrompt.Base_Collection_Tooltip");
151
152 JPanel collection_scope_pane = new JPanel();
153 personal_collection_button = new JRadioButton();
154 personal_collection_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
155 personal_collection_button.setOpaque(false);
156 Dictionary.setText(personal_collection_button, "NewCollectionPrompt.Collection_Scope_Personal");
157 JRadioButton shared_collection_button = new JRadioButton();
158 shared_collection_button.setBackground(Configuration.getColor("coloring.collection_tree_background", false));
159 shared_collection_button.setOpaque(false);
160 Dictionary.setText(shared_collection_button, "NewCollectionPrompt.Collection_Scope_Shared");
161 ButtonGroup collection_scope_group = new ButtonGroup();
162 collection_scope_group.add(personal_collection_button);
163 collection_scope_group.add(shared_collection_button);
164 personal_collection_button.setSelected(true);
165
166 JPanel button_pane = new JPanel();
167 create_button = new GLIButton();
168 create_button.setMnemonic(KeyEvent.VK_O);
169 Dictionary.setBoth(create_button, "General.OK", "General.OK_Tooltip");
170 JButton cancel_button = new GLIButton();
171 cancel_button.setMnemonic(KeyEvent.VK_C);
172 Dictionary.setBoth(cancel_button, "General.Cancel", "General.Cancel_Tooltip");
173 // Connection
174 cancel_button.addActionListener(new CancelListener());
175 create_button.addActionListener(new CreateListener());
176 description.addKeyListener(new DescriptionListener());
177
178 // Layout
179 title_pane.setLayout(new BorderLayout(5,0));
180 title_pane.add(title_label, BorderLayout.WEST);
181 title_pane.add(title, BorderLayout.CENTER);
182
183 upper_pane.setLayout(new GridLayout(2,1));
184 upper_pane.add(instructions_label);
185 upper_pane.add(title_pane);
186
187 description_pane.setLayout(new BorderLayout());
188 description_pane.add(description_label, BorderLayout.NORTH);
189 description_pane.add(new JScrollPane(description), BorderLayout.CENTER);
190
191 base_collection_pane.setLayout(new BorderLayout(5,0));
192 base_collection_pane.add(base_collection_label, BorderLayout.WEST);
193 base_collection_pane.add(base_collection, BorderLayout.CENTER);
194
195 collection_scope_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
196 collection_scope_pane.setLayout(new GridLayout(1,2));
197 collection_scope_pane.add(personal_collection_button);
198 collection_scope_pane.add(shared_collection_button);
199
200 center_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
201 center_pane.setLayout(new BorderLayout());
202 center_pane.add(description_pane, BorderLayout.CENTER);
203
204 bottom_pane.setLayout(new BorderLayout());
205 bottom_pane.add(base_collection_pane, BorderLayout.NORTH);
206 if (Gatherer.isGsdlRemote) {
207 bottom_pane.add(collection_scope_pane, BorderLayout.CENTER);
208 bottom_pane.add(button_pane, BorderLayout.SOUTH);
209 }
210 else {
211 bottom_pane.add(button_pane, BorderLayout.CENTER);
212 }
213
214 button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
215 button_pane.setLayout(new GridLayout(1,2));
216 button_pane.add(create_button);
217 button_pane.add(cancel_button);
218
219 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
220 content_pane.setLayout(new BorderLayout());
221 content_pane.add(upper_pane, BorderLayout.NORTH);
222 content_pane.add(center_pane, BorderLayout.CENTER);
223 content_pane.add(bottom_pane, BorderLayout.SOUTH);
224 // Final dialog setup & positioning.
225 Dimension screen_size = Configuration.screen_size;
226 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2);
227 setVisible(true);
228 }
229
230 public boolean isCancelled() {
231 return cancelled;
232 }
233
234 public File getBase() {
235 return base_final;
236 }
237
238 public String getDescription() {
239 return description_final;
240 }
241
242 /** Generates the collection short filename by taking the first eight characters of the title (spaces removed) and then adjusting by further truncating and then adding an unique suffix as necessary.
243 * @return the filename as a String
244 */
245 public String getName()
246 {
247 // Retrieve the first 8 non-whitespace ASCII characters of title_final.
248 StringBuffer name_buffer = new StringBuffer("");
249 for (int i = 0, u = 0; (i < title_final.length() && u < 8); i++) {
250 // To be safe we make sure the internal collection name (folder name) contains only ASCII characters
251 char c = title_final.charAt(i);
252 if ((int) c < 128 && Character.isLetterOrDigit(c)) {
253 name_buffer.append(Character.toLowerCase(c));
254 u++;
255 }
256 }
257
258 // Use "col" as the base collection name if we have nothing left
259 if (name_buffer.length() == 0) {
260 name_buffer = new StringBuffer("col");
261 }
262
263 // Remote collections that aren't shared have the user's username prefixed to the collection name
264 if (Gatherer.isGsdlRemote && personal_collection_button.isSelected()) {
265 name_buffer = new StringBuffer(RemoteGreenstoneServer.getUsername() + "-" + name_buffer.toString());
266 }
267
268 // We need to ensure the filename is unique
269 int counter = 0;
270 StringBuffer new_name_buffer = new StringBuffer(name_buffer.toString());
271 while(filenameClashes(new_name_buffer.toString())) {
272 new_name_buffer = new StringBuffer(name_buffer.toString());
273 counter++;
274 String suffix = String.valueOf(counter);
275 // If we have to truncate the namestring so as to fit the suffix
276 if(suffix.length() + new_name_buffer.length() > 8) {
277 new_name_buffer.replace(new_name_buffer.length() - suffix.length(), new_name_buffer.length(), suffix);
278 }
279 // Or just append it if that isn't necessary
280 else {
281 new_name_buffer.append(suffix);
282 }
283 }
284
285 // All done
286 return new_name_buffer.toString();
287 }
288
289 private boolean filenameClashes(String filename)
290 {
291 File collect_directory = new File(Gatherer.getCollectDirectoryPath());
292 File children[] = collect_directory.listFiles();
293 for(int i = 0; children != null && i < children.length; i++) {
294 if(children[i].getName().equals(filename)) {
295 return true;
296 }
297 }
298 return false;
299 }
300
301 public String getTitle() {
302 return title_final;
303 }
304
305 private void addCollectionsToModel(Vector base_collection_model, File collect_directory, String site) {
306 File[] possible_collections = collect_directory.listFiles();
307 for (int i = 0; possible_collections != null && i < possible_collections.length; i++) {
308 // If the directory has a etc/collect.cfg file then it looks like a collection
309 File collect_cfg_file = new File(possible_collections[i], Utility.CONFIG_FILE);
310 if (collect_cfg_file.exists()) {
311 // If the directory has a metadata/ then the collection can be used as a base
312 File metadata_directory = new File(possible_collections[i], "metadata");
313 if (metadata_directory.exists()) {
314 // Add to model
315 BasicCollectionConfiguration collect_cfg = new BasicCollectionConfiguration(collect_cfg_file);
316 if (Gatherer.GS3 && site != null) {
317 collect_cfg.setSite(site);
318 }
319 Item item = new Item(possible_collections[i], collect_cfg);
320 if (!base_collection_model.contains(item)) {
321 base_collection_model.add(item);
322 }
323 }
324 }
325 }
326
327 }
328
329 private class CancelListener
330 implements ActionListener {
331 public void actionPerformed(ActionEvent event) {
332 cancelled = true;
333 self.dispose();
334 }
335 }
336
337
338 private class CreateListener
339 implements ActionListener {
340
341 public void actionPerformed(ActionEvent event) {
342 // Validate.
343 title_final = title.getText();
344 if(title_final.length() == 0) {
345 JOptionPane.showMessageDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Error"), Dictionary.get("NewCollectionPrompt.Error"), JOptionPane.ERROR_MESSAGE);
346 return;
347 }
348 // We must ensure that the collection title is unique. This is a pain in the nether regions as we are forced to load the collect.cfg of each other collection in turn looking for a conflicting title
349 else {
350 if(titleClashes(title_final, null)) {
351 if (JOptionPane.showConfirmDialog(Gatherer.g_man, Dictionary.get("NewCollectionPrompt.Title_Clash"), Dictionary.get("General.Warning"), JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) {
352 return;
353 }
354 }
355 }
356
357 description_final = description.getText();
358
359 // If we got this far there are no errors.
360 Item item_final = (Item) base_collection.getSelectedItem();
361 base_final = item_final.getFile();
362
363 cancelled = false;
364
365 self.dispose();
366 }
367 }
368
369 private class DescriptionListener
370 extends KeyAdapter {
371 public void keyPressed(KeyEvent event) {
372 if(event.getKeyCode() == KeyEvent.VK_TAB) {
373 event.consume();
374 base_collection.grabFocus();
375 }
376 }
377 }
378
379 private class Item
380 implements Comparable {
381 private BasicCollectionConfiguration config;
382 private File file;
383 private String name;
384 public Item(File file, BasicCollectionConfiguration config) {
385 this.config = config;
386 this.file = file;
387 this.name = null;
388 }
389 public Item(File file, String name) {
390 this.config = null;
391 this.file = file;
392 this.name = name;
393 }
394 public int compareTo(Object other) {
395 return toString().toLowerCase().compareTo(other.toString().toLowerCase());
396 }
397 public boolean equals(Object other) {
398 return compareTo(other) == 0;
399 }
400 public File getFile() {
401 return file;
402 }
403 public String toString() {
404 if(name == null && config != null) {
405 name = config.toString();
406 }
407 return name;
408 }
409 }
410}
411
412
413
Note: See TracBrowser for help on using the repository browser.