Changeset 4366 for trunk/gli/src/org/greenstone/gatherer/cdm
- Timestamp:
- 2003-05-27T15:57:37+12:00 (21 years ago)
- Location:
- trunk/gli/src/org/greenstone/gatherer/cdm
- Files:
-
- 29 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/gli/src/org/greenstone/gatherer/cdm/Argument.java
r4293 r4366 69 69 70 70 public class Argument 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 71 implements Comparable, Serializable { 72 /** If this argument has multiple values, then they are stored here. This was originally a Hashtable, but since the synchronization overhead is unwarrented it was changed to a HashMap. */ 73 private ArrayList values = null; 74 /** <i>true</i> if this argument is required for the applicable script to work properly, <i>false</i> otherwise. */ 75 private boolean required = false; 76 /** The type of this argument. Initially an int, but bytes are cheaper. */ 77 private byte type = FLAG; 78 /** If the argument is of type ENUM then this map holds all the various options. Each entry is an <option value> -> <description> mapping. */ 79 private HashMap list = null; 80 /** A default value for parameter-type arguments. May be a Perl pattern. */ 81 private String default_value = null; 82 /** The text description of this argument parsed from the pluginfo output. */ 83 private String desc = null; 84 /** The argument flag as it appears in the command. Also used as the unique identifier of an argument. */ 85 private String name = null; 86 /** The plugin that owns this argument, for the purposes of visualising inheritance. */ 87 private String owner = null; 88 /** If this argument has been assigned, what is its value. Must be non-null for the argument to be printed. */ 89 private String value = null; 90 /** An element of the argument type enumeration. */ 91 static final public byte ENUM = 0; 92 /** An element of the argument type enumeration. */ 93 static final public byte FLAG = 1; 94 /** An element of the argument type enumeration. */ 95 static final public byte HIERARCHY = 2; 96 /** An element of the argument type enumeration. */ 97 static final public byte INTEGER = 3; 98 /** An element of the argument type enumeration. */ 99 static final public byte LANGUAGE = 4; 100 /** An element of the argument type enumeration. */ 101 static final public byte METADATA = 5; 102 /** An element of the argument type enumeration. */ 103 static final public byte METADATUM = 6; 104 /** An element of the argument type enumeration. */ 105 static final public byte STRING = 7; 106 /** Default Constructor. */ 107 public Argument() { 108 } 109 /** Normal Constructor, based on data parsed from an information script. 110 110 * @param name The argument flag as it appears in the command, as a <strong>String</strong>. Also used as the unique identifier of an argument. 111 111 * @param desc The text description of this argument parsed from the output as a <strong>String</strong>. … … 113 113 * @param default_value The default value for a parameter type argument, which may include a Perl type regular expression, as a <strong>String</strong>. 114 114 */ 115 116 117 118 119 120 121 122 123 124 125 126 127 115 public Argument(String name, String desc, byte type, String default_value) { 116 this.default_value = default_value; 117 this.desc = desc; 118 this.name = name; 119 this.type = type; 120 if(type == ENUM) { 121 this.list = new HashMap(); 122 } 123 if(type == METADATUM) { 124 values = new ArrayList(); 125 } 126 } 127 /** Method to add an element to the option list. 128 128 * @param name The name value of the option as a <strong>String</strong>. 129 129 * @param desc The description of this options as a <strong>String</strong>. 130 130 */ 131 132 133 134 135 136 137 138 139 140 141 131 public void addOption(String name, String desc) { 132 if(type == ENUM && name != null) { 133 if(desc == null) { 134 desc = ""; 135 } 136 if(!list.containsKey(name)) { 137 list.put(name, desc); 138 } 139 } 140 } 141 /** Method to compare two arguments for ordering. 142 142 * @param object The argument we are comparing to, as an <strong>Object</strong>. 143 143 * @return An <i>int</i> specifying the argument order, using values as set out in String. … … 145 145 * @see org.greenstone.gatherer.cdm.Argument 146 146 */ 147 148 149 150 151 147 public int compareTo(Object object) { 148 Argument argument = (Argument)object; 149 return getName().compareTo(argument.getName()); 150 } 151 /** Method to deep copy this argument. 152 152 * @return A newly created <strong>Argument</strong> which has the same details as this one. 153 153 */ 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 154 public Argument copy() { 155 Argument copy = new Argument(name, desc, type, default_value); 156 copy.setRequired(required); 157 if(values != null) { 158 copy.setValues(values); 159 } 160 if(list != null) { 161 HashMap list_deep_copy = new HashMap(); 162 Iterator it = list.keySet().iterator(); 163 while(it.hasNext()) { 164 String key = (String) it.next(); 165 String desc = (String) list.get(key); 166 list_deep_copy.put(new String(key), new String(desc)); 167 } 168 copy.setOptions(list_deep_copy); 169 } 170 return copy; 171 } 172 /** Method to determine if two arguments are equal. 173 173 * @param object The argument to test against, as an <strong>Object</strong>. 174 174 * @return <i>true</i> if the arguments names match, <i>false</i> otherwise. 175 175 */ 176 177 178 179 176 public boolean equals(Object object) { 177 return (compareTo(object) == 0); 178 } 179 /** Method to retrieve the value of default_value. 180 180 * @return A <strong>String</strong> containing the default value. 181 181 */ 182 183 184 185 182 public String getDefaultValue() { 183 return default_value; 184 } 185 /** Method to retrieve this arguments description. 186 186 * @return A <strong>String</strong> containing the description. 187 187 */ 188 189 190 191 188 public String getDesc() { 189 return desc; 190 } 191 /** Method to retrieve the description of a certain list option value. 192 192 * @param key The <strong>String</strong> whose description we are searching for. 193 193 * @return The description of the desired key as a <strong>String</strong> which may be empty if no such key exists. 194 194 */ 195 196 197 198 199 200 201 195 public String getDesc(String key) { 196 if(list.containsKey(key)) { 197 return (String)list.get(key); 198 } 199 return ""; 200 } 201 /** Method to retrieve the option list for this argument. 202 202 * @return A <strong>HashMap</strong> containing <option value> -> <description> entries. 203 203 */ 204 205 206 207 204 public HashMap getList() { 205 return list; 206 } 207 /** Method to retrieve the value of name. 208 208 * @return A <strong>String</strong> containing the argument name. 209 209 */ 210 211 212 213 210 public String getName() { 211 return name; 212 } 213 /** Retrieve the name of the owner of this argument. 214 214 * @return The owners name as a <strong>String</strong>. 215 215 */ 216 217 218 219 216 public String getOwner() { 217 return owner; 218 } 219 /** Method to determine the type of this argument. 220 220 * @return An <i>byte</i> specifying the type. 221 221 */ 222 223 224 225 222 public byte getType() { 223 return type; 224 } 225 /** Method to retrieve the value of value. 226 226 * @return The value of value as a <strong>String</strong>. 227 227 */ 228 229 230 231 228 public String getValue() { 229 return value; 230 } 231 /** Retrieve the vector of values. 232 232 * @return An <strong>ArrayList</strong> of values. 233 233 */ 234 235 236 237 234 public ArrayList getValues() { 235 return values; 236 } 237 /** Method to determine if this argument has been assigned. 238 238 * @return <i>true</i> if it has, <i>false</i> otherwise. 239 239 */ 240 241 242 243 240 public boolean isAssigned() { 241 return (required || value != null || (values != null && values.size() > 0)); 242 } 243 /** Method to determine of this argument is required for the associated script to work. 244 244 * @return <i>true</i> if this argument is required, <i>false</i> otherwise. 245 245 */ 246 247 248 249 246 public boolean isRequired() { 247 return required; 248 } 249 /** Method to allow for the activation of arguments that might never have their setValue() method called. 250 250 * @param new_state The required state as a <i>boolean</i>. 251 251 */ 252 253 254 255 256 257 258 259 260 252 public void setAssigned(boolean new_state) { 253 if(new_state && (value == null || values == null)) { 254 value = ""; 255 } 256 else { 257 value = null; 258 } 259 } 260 /** Sets the value of default_value. 261 261 * @param new_default_value The new value for default_value as a <strong>String</strong>. 262 262 */ 263 264 265 266 263 public void setDefault(String new_default_value) { 264 default_value = new_default_value; 265 } 266 /** Set the value of desc. 267 267 * @param new_desc The new value of desc as a <strong>String</strong>. 268 268 */ 269 270 271 272 269 public void setDesc(String new_desc) { 270 desc = new_desc; 271 } 272 /** Set the value of name. 273 273 * @param new_name The new value of name as a <strong>String</strong>. 274 274 */ 275 276 277 278 275 public void setName(String new_name) { 276 name = new_name; 277 } 278 /** Sets the value of the options list. 279 279 * @param new_list The new options list as a <strong>HashMap</strong>. 280 280 */ 281 282 283 284 281 public void setOptions(HashMap new_list) { 282 list = new_list; 283 } 284 /** Set the owner of this argument. 285 285 * @param owner The name of the owner of this argument as a <strong>String</strong>. 286 286 */ 287 288 289 290 287 public void setOwner(String owner) { 288 this.owner = owner; 289 } 290 /** Set the value of required. 291 291 * @param new_required The new value of required as a <i>boolean</i>. 292 292 */ 293 294 295 296 293 public void setRequired(boolean new_required) { 294 required = new_required; 295 } 296 /** Set the value of type. 297 297 * @param new_type The new value of type as an <i>byte</i>. 298 298 */ 299 300 301 302 303 304 305 306 307 308 299 public void setType(byte new_type) { 300 type = new_type; 301 if(type == ENUM) { 302 list = new HashMap(); 303 } 304 if(type == METADATUM && values == null) { 305 values = new ArrayList(); 306 } 307 } 308 /** Set the value of type, by matching a type to the given string. 309 309 * @param new_type A <strong>String</strong> which contains the name of a certain argument type. 310 310 */ 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 311 public void setType(String new_type) { 312 if(new_type.equalsIgnoreCase("enum")) { 313 this.type = ENUM; 314 list = new HashMap(); 315 } 316 else if(new_type.equalsIgnoreCase("flag")) { 317 this.type = FLAG; 318 } 319 else if(new_type.equalsIgnoreCase("hierarchy")) { 320 this.type = HIERARCHY; 321 } 322 else if(new_type.equalsIgnoreCase("int")) { 323 this.type = INTEGER; 324 } 325 else if(new_type.equalsIgnoreCase("language")) { 326 this.type = LANGUAGE; 327 } 328 else if(new_type.equalsIgnoreCase("metadata")) { 329 this.type = METADATA; 330 } 331 else if(new_type.equalsIgnoreCase("metadatum")) { 332 this.type = METADATUM; 333 if(values == null) { 334 values = new ArrayList(); 335 } 336 } 337 else if(new_type.equalsIgnoreCase("string")) { 338 this.type = STRING; 339 } 340 } 341 /** Method to set the value of value. 342 342 * @param new_value The new value of value as a <strong>String</strong>. 343 343 */ 344 345 346 347 344 public void setValue(String new_value) { 345 this.value = new_value; 346 } 347 /** Set the values vector to the given values. Currently I just assign the new values, whereas I may later want to implement a deep clone. 348 348 * @param new_values An <strong>ArrayList</strong> of values. 349 349 */ 350 351 352 353 350 public void setValues(ArrayList new_values) { 351 values = new_values; 352 } 353 /** Method for translating the data of this class into a string. 354 354 * @return A <strong>String</strong> containing a fragment of the total arguments string. 355 355 */ 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 356 public String toString() { 357 switch(type) { 358 case FLAG: 359 return "-" + name; 360 case METADATUM: 361 String text = "-" + name + " "; 362 for(int i = 0; i < values.size(); i++) { 363 text = text + values.get(i).toString(); 364 if(i < values.size() - 1) { 365 text = text + ","; 366 } 367 } 368 return text; 369 default: 370 return "-" + name + " " + value; 371 } 372 } 373 373 } 374 374 -
trunk/gli/src/org/greenstone/gatherer/cdm/ArgumentConfiguration.java
r4293 r4366 103 103 104 104 public class ArgumentConfiguration 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 105 extends JDialog 106 implements ActionListener { 107 /** The data whose arguments we are editing. */ 108 private ArgumentContainer data = null; 109 /** Argument these argument controls coloured or uncoloured (alternates to indicate inheritance). */ 110 private boolean coloured = false; 111 /** Whether we have successfully edited the arguments associated with the ArgumentContainer or if we have failed to enter required arguments and have instead cancelled (which would cause argument additions to roll back). */ 112 private boolean success = false; 113 /** A reference to the main CollectionDesignManager class for access to other managers. */ 114 private CollectionDesignManager manager = null; 115 /** A reference to the Gatherer. */ 116 private Gatherer gatherer = null; 117 /** A button to cancel this dialog. */ 118 private JButton cancel = null; 119 /** A button to accept the changes and close the dialog. */ 120 private JButton ok = null; 121 /** A reference to the ourselves so our inner classes can dispose us like a dialog. */ 122 private ArgumentConfiguration self = null; 123 /** The central pane where a list of known arguments is displayed. */ 124 private JPanel central_pane = null; 125 /** The field for entering custom arguments. */ 126 private JTextField custom = null; 127 /** The name of the owner of the last argument control. */ 128 private String previous_owner = null; 129 /** The size used for an argument label. */ 130 static final private Dimension LABEL_SIZE = new Dimension(225, 25); 131 /** Size of a list. */ 132 static final private Dimension LIST_SIZE = new Dimension(380, 50); 133 /** The size used for the dialog. */ 134 static final private Dimension SIZE = new Dimension(800, 400); 135 /** Constructor. 136 * @param gatherer A reference to the <strong>Gatherer</strong>. 137 * @param manager The <strong>CollectionDesignManager</strong> for access to other configuration managers. 138 * @param data The plugin or classifier whose arguments we are configuring, in the form of its supported <strong>ArgumentContainer</strong> interface. 139 * @see org.greenstone.gatherer.Configuration 140 */ 141 public ArgumentConfiguration(Gatherer gatherer, CollectionDesignManager manager, ArgumentContainer data) { 142 super(gatherer.g_man); 143 this.data = data; 144 this.gatherer = gatherer; 145 this.manager = manager; 146 this.self = this; 147 String custom_str = data.getCustom(); 148 // Create 149 setModal(true); 150 setSize(SIZE); 151 setTitle(get("Title")); 152 JPanel button_pane = new JPanel(); 153 cancel = new JButton(get("General.Cancel")); 154 cancel.setMnemonic(KeyEvent.VK_C); 155 central_pane = new JPanel(); 156 JPanel content_pane = (JPanel) getContentPane(); 157 if(custom_str != null) { 158 custom = new JTextField(custom_str); 159 } 160 else { 161 custom = new JTextField(); 162 } 163 JLabel custom_label = new JLabel(get("Custom")); 164 custom_label.setPreferredSize(LABEL_SIZE); 165 JPanel custom_pane = new JPanel(); 166 String args[] = new String[1]; 167 args[0] = data.getName(); 168 JLabel header = new JLabel(get("Header",args)); 169 args = null; 170 header.setHorizontalAlignment(JLabel.CENTER); 171 header.setOpaque(true); 172 JPanel header_pane = new JPanel(); 173 ok = new JButton(get("General.OK")); 174 ok.setMnemonic(KeyEvent.VK_O); 175 // Listeners 176 cancel.addActionListener(this); 177 ok.addActionListener(this); 178 // Layout 179 custom_pane.setLayout(new BorderLayout()); 180 custom_pane.add(custom_label, BorderLayout.WEST); 181 custom_pane.add(custom, BorderLayout.CENTER); 182 183 header_pane.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 184 header_pane.setLayout(new BorderLayout()); 185 header_pane.add(header, BorderLayout.NORTH); 186 header_pane.add(custom_pane, BorderLayout.CENTER); 187 188 button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); 189 button_pane.setLayout(new GridLayout(1,2)); 190 button_pane.add(ok); 191 button_pane.add(cancel); 192 193 central_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 194 central_pane.setLayout(new BoxLayout(central_pane, BoxLayout.Y_AXIS)); 195 196 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 197 content_pane.setLayout(new BorderLayout()); 198 content_pane.add(header_pane, BorderLayout.NORTH); 199 content_pane.add(new JScrollPane(central_pane), BorderLayout.CENTER); 200 content_pane.add(button_pane, BorderLayout.SOUTH); 201 202 // Now generate a set of controls for each of the arguments. 203 generateControls(); 204 205 // Display on screen. 206 Dimension screen_size = gatherer.config.screen_size; 207 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2); 208 screen_size = null; 209 } 210 /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of the controls we are listening to. 211 211 * @param event An <strong>ActionEvent</strong> containing pertinant information about the event that fired this call. 212 212 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl 213 213 * @see org.greenstone.gatherer.cdm.ArgumentContainer 214 214 */ 215 216 217 215 public void actionPerformed(ActionEvent event) { 216 boolean cont = true; 217 if(event.getSource() == ok) { 218 218 // Update the details stored in the data objects arguments. 219 220 221 219 if(custom.getText().length() > 0) { 220 data.setCustom(custom.getText()); 221 } 222 222 // Loop through each of the controls in the central pane, updating the matching argument as necessary. 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 223 for(int i = 0; i < central_pane.getComponentCount(); i++) { 224 Component component = central_pane.getComponent(i); 225 if(component instanceof ArgumentControl) { 226 // Once cont goes false it stays false 227 cont = cont && ((ArgumentControl)component).updateArgument(); 228 } 229 } 230 if(cont) { 231 success = true; 232 } 233 } 234 if(cont) { 235 dispose(); 236 } 237 } 238 /** Destructor. */ 239 public void destroy() { 240 cancel = null; 241 central_pane = null; 242 custom = null; 243 data = null; 244 gatherer = null; 245 manager = null; 246 ok = null; 247 self = null; 248 } 249 /** Method which actually forces the dialog to be shown on screen. 250 250 * @return <i>true</i> if the user completed configuration and pressed ok, <i>false</i> otherwise. 251 251 */ 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 252 public boolean display() { 253 show(); 254 return success; 255 } 256 257 private void addHeader(String name, Color color) { 258 JPanel header = new JPanel(); 259 header.setBackground(color); 260 JPanel inner_pane = new JPanel(); 261 inner_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder())); 262 inner_pane.setBackground(color); 263 JLabel header_label = new JLabel("<html><strong>" + name + "</strong></html>"); 264 header_label.setBackground(Gatherer.config.getColor("coloring.collection_heading_background", false)); 265 header_label.setHorizontalAlignment(JLabel.CENTER); 266 header_label.setOpaque(true); 267 // Layout. 268 inner_pane.setLayout(new BorderLayout()); 269 inner_pane.add(header_label, BorderLayout.CENTER); 270 271 header.setLayout(new BorderLayout()); 272 header.add(inner_pane, BorderLayout.CENTER); 273 central_pane.add(header); 274 } 275 276 /** Method to iterate through the arguments associated with whatever argument container we are building an argument control view for, creating the appropriate controls for each. 277 277 * @see org.greenstone.gatherer.cdm.Argument 278 278 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl 279 279 */ 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 280 private void generateControls() { 281 ArrayList arguments = data.getArguments(); 282 int total_height = 250; 283 int size = arguments.size(); 284 for(int i = 0; i < size; i++) { 285 Argument argument = (Argument) arguments.get(i); 286 ArgumentControl argument_control = new ArgumentControl(argument); 287 total_height = total_height - argument_control.getPreferredSize().height; 288 central_pane.add(argument_control); 289 } 290 if(total_height > 0) { 291 JPanel filler = new JPanel(); 292 filler.setPreferredSize(new Dimension(100, total_height)); 293 filler.setSize(new Dimension(100, total_height)); 294 central_pane.add(filler); 295 } 296 } 297 /** Method to retrieve a phrase from the dictionary based on a key. 298 298 * @param key A <strong>String</strong> used to find the correct phrase. 299 299 * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase. 300 300 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. 301 301 */ 302 303 304 305 302 private String get(String key) { 303 return get(key, null); 304 } 305 /** Method to retrieve a phrase from the dictionary based on a key. 306 306 * @param key A <strong>String</strong> used to find the correct phrase. 307 307 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. 308 308 */ 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 309 private String get(String key, String args[]) { 310 if(key.indexOf(".") == -1) { 311 key = "CDM.ArgumentConfiguration." + key; 312 } 313 return gatherer.dictionary.get(key, args); 314 } 315 /** This class encapsulates all the technical difficulty of creating a specific control based on an Argument. */ 316 private class ArgumentControl 317 extends JPanel { 318 /** The Argument this control will be based on. */ 319 private Argument argument = null; 320 /** One of a possible two buttons available for adding to this control. */ 321 private JButton one = null; 322 /** The second of two buttons available for adding to this control. */ 323 private JButton two = null; 324 /** A checkbox to allow enabling or diabling of this Argument. */ 325 private JCheckBox enabled = null; 326 /** Some form of editor component, such as a JComboBox or JTextField, used to set parameters to an Argument. */ 327 private JComponent value = null; 328 /** Can be used in place of the other editor components if a list is required. */ 329 private JList list = null; 330 /** Constructor. 331 * @param argument The <strong>Argument</strong> this control will be built around. 332 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.AddListener 333 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.EnabledListener 334 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.HierarchyListener 335 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption 336 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.RemoveListener 337 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ToolTipUpdater 338 */ 339 public ArgumentControl(Argument argument) { 340 this.argument = argument; 341 String tip = "<html>" + argument.getDesc() + "</html>"; 342 tip = Utility.formatHTMLWidth(tip, 60); 343 343 // If this is the first control, there is no history. 344 if(previous_owner == null) { 345 previous_owner = argument.getOwner(); 346 addHeader(previous_owner, Color.white); 344 if(previous_owner == null) { 345 previous_owner = argument.getOwner(); 346 addHeader(previous_owner, Color.white); 347 } 348 // Otherwise if the owner of the control has changed since the last argument, toggle the colouring of the control. 349 else if(previous_owner != argument.getOwner()) { 350 coloured = !coloured; 351 previous_owner = argument.getOwner(); 352 addHeader(previous_owner, (coloured ? Gatherer.config.getColor("coloring.collection_tree_background", false) : Color.white)); 353 } 354 // Create 355 if(coloured) { 356 setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 357 } 358 else { 359 setBackground(Color.white); 360 } 361 JLabel owner_label = new JLabel(argument.getOwner()); 362 owner_label.setOpaque(false); 363 JLabel label = new JLabel(argument.getName()); 364 label.setOpaque(false); 365 label.setPreferredSize(LABEL_SIZE); 366 label.setToolTipText(tip); 367 enabled = new JCheckBox(argument.getName()); 368 enabled.setOpaque(false); 369 enabled.setPreferredSize(LABEL_SIZE); 370 enabled.setToolTipText(tip); 371 JPanel inner_pane = new JPanel(); 372 inner_pane.setOpaque(false); 373 String existing_value = argument.getValue(); 374 String default_value = argument.getDefaultValue(); 375 switch(argument.getType()) { 376 case Argument.ENUM: 377 // Build an option model, wrapping each entry of the list table. 378 HashMap arg_list = argument.getList(); 379 ArrayList options_model = new ArrayList(); 380 Iterator it = arg_list.keySet().iterator(); 381 while(it.hasNext()) { 382 String key = (String) it.next(); 383 options_model.add(new ListOption(key, (String)arg_list.get(key))); 384 } 385 Collections.sort(options_model); 386 value = new JComboBox(options_model.toArray()); 387 ((JComboBox)value).addActionListener(new ToolTipUpdater()); 388 if(existing_value != null) { 389 // Select the correct value. Since they're all text strings we better iterate to be safe. 390 selectValue((JComboBox)value, existing_value); 391 } 392 else if(default_value != null) { 393 // Same as above except for default value. 394 selectValue((JComboBox)value, default_value); 395 } 396 break; 397 case Argument.FLAG: 398 // Only need the check box. 399 break; 400 case Argument.HIERARCHY: 401 value = new JComboBox(gatherer.c_man.msm.getAssignedElements(true)); 402 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */ 403 ((JComboBox)value).setEditable(true); 404 ((JComboBox)value).addItemListener(new HierarchyListener()); 405 // Now ensure we have the existing value or default value selected if either exist. 406 if(existing_value != null) { 407 selectValue((JComboBox)value, existing_value); 408 } 409 else if(default_value != null) { 410 selectValue((JComboBox)value, default_value); 411 } 412 break; 413 case Argument.INTEGER: 414 case Argument.STRING: 415 // Use a standard text field 416 if(existing_value != null) { 417 value = new JTextField(existing_value); 418 } 419 else { 420 if(default_value != null) { 421 value = new JTextField(default_value); 422 } 423 // Special test just for the hfile field. 424 else if(argument.getName().equals("hfile")) { 425 // Work through previous controls looking for the metadata one. 426 for(int i = 0; i < central_pane.getComponentCount(); i++) { 427 Object object = central_pane.getComponent(i); 428 if(object instanceof ArgumentControl) { 429 ArgumentControl control = (ArgumentControl) object; 430 if(control.toString().equals("metadata")) { 431 Object temp = control.getValue(); 432 if(temp != null) { 433 value = new JTextField(temp.toString() + ".txt"); 434 } 347 435 } 348 // Otherwise if the owner of the control has changed since the last argument, toggle the colouring of the control. 349 else if(previous_owner != argument.getOwner()) { 350 coloured = !coloured; 351 previous_owner = argument.getOwner(); 352 addHeader(previous_owner, (coloured ? Gatherer.config.getColor("coloring.collection_tree_background", false) : Color.white)); 353 } 354 // Create 355 if(coloured) { 356 setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 357 } 358 else { 359 setBackground(Color.white); 360 } 361 JLabel owner_label = new JLabel(argument.getOwner()); 362 owner_label.setOpaque(false); 363 JLabel label = new JLabel(argument.getName()); 364 label.setOpaque(false); 365 label.setPreferredSize(LABEL_SIZE); 366 label.setToolTipText(tip); 367 enabled = new JCheckBox(argument.getName()); 368 enabled.setOpaque(false); 369 enabled.setPreferredSize(LABEL_SIZE); 370 enabled.setToolTipText(tip); 371 JPanel inner_pane = new JPanel(); 372 inner_pane.setOpaque(false); 373 String existing_value = argument.getValue(); 374 String default_value = argument.getDefaultValue(); 375 switch(argument.getType()) { 376 case Argument.ENUM: 377 // Build an option model, wrapping each entry of the list table. 378 HashMap arg_list = argument.getList(); 379 ArrayList options_model = new ArrayList(); 380 Iterator it = arg_list.keySet().iterator(); 381 while(it.hasNext()) { 382 String key = (String) it.next(); 383 options_model.add(new ListOption(key, (String)arg_list.get(key))); 384 } 385 Collections.sort(options_model); 386 value = new JComboBox(options_model.toArray()); 387 ((JComboBox)value).addActionListener(new ToolTipUpdater()); 388 if(existing_value != null) { 389 // Select the correct value. Since they're all text strings we better iterate to be safe. 390 selectValue((JComboBox)value, existing_value); 391 } 392 else if(default_value != null) { 393 // Same as above except for default value. 394 selectValue((JComboBox)value, default_value); 395 } 396 break; 397 case Argument.FLAG: 398 // Only need the check box. 399 break; 400 case Argument.HIERARCHY: 401 value = new JComboBox(gatherer.c_man.msm.getAssignedElements(true)); 402 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */ 403 ((JComboBox)value).setEditable(true); 404 ((JComboBox)value).addItemListener(new HierarchyListener()); 405 // Now ensure we have the existing value or default value selected if either exist. 406 if(existing_value != null) { 407 selectValue((JComboBox)value, existing_value); 408 } 409 else if(default_value != null) { 410 selectValue((JComboBox)value, default_value); 411 } 412 break; 413 case Argument.INTEGER: 414 case Argument.STRING: 415 // Use a standard text field 416 if(existing_value != null) { 417 value = new JTextField(existing_value); 418 } 419 else { 420 if(default_value != null) { 421 value = new JTextField(default_value); 422 } 423 // Special test just for the hfile field. 424 else if(argument.getName().equals("hfile")) { 425 // Work through previous controls looking for the metadata one. 426 for(int i = 0; i < central_pane.getComponentCount(); i++) { 427 Object object = central_pane.getComponent(i); 428 if(object instanceof ArgumentControl) { 429 ArgumentControl control = (ArgumentControl) object; 430 if(control.toString().equals("metadata")) { 431 Object temp = control.getValue(); 432 if(temp != null) { 433 value = new JTextField(temp.toString() + ".txt"); 434 } 435 } 436 437 } 438 } 439 } 440 else { 441 value = new JTextField(); 442 } 443 } 444 break; 445 case Argument.LANGUAGE: 446 value = new JComboBox(manager.languages.getLanguageCodes().toArray()); 447 // Now ensure we have the existing value or default value selected if either exist. 448 Language selected = null; 449 if(existing_value != null) { 450 selected = manager.languages.getLanguage(existing_value, false); 451 } 452 else if(default_value != null) { 453 selected = manager.languages.getLanguage(default_value, false); 454 } 455 if(selected != null) { 456 ((JComboBox)value).setSelectedItem(selected); 457 } 458 break; 459 case Argument.METADATA: 460 value = new JComboBox(gatherer.c_man.msm.getAssignedElements()); 461 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */ 462 ((JComboBox)value).setEditable(true); 463 // Now ensure we have the existing value or default value selected if either exist. 464 if(existing_value != null) { 465 selectValue((JComboBox)value, existing_value); 466 } 467 else if(default_value != null) { 468 selectValue((JComboBox)value, default_value); 469 } 470 break; 471 case Argument.METADATUM: 472 // Comma separated metadata values. 473 ArrayList values = argument.getValues(); 474 value = new JComboBox(gatherer.c_man.msm.getAssignedElements()); 475 DefaultListModel model = new DefaultListModel(); 476 list = new JList(model); 477 list.setVisibleRowCount(3); 478 for(int i = 0; i < values.size(); i++) { 479 model.addElement(values.get(i)); 480 } 481 one = new JButton(get("Add")); 482 one.addActionListener(new AddListener((JComboBox)value, list)); 483 two = new JButton(get("Remove")); 484 two.addActionListener(new RemoveListener(list)); 485 if(argument.getValues().size() > 0 || argument.isRequired()) { 486 enabled.setSelected(true); 487 list.setBackground(Color.white); 488 list.setEnabled(true); 489 one.setEnabled(true); 490 two.setEnabled(true); 491 value.setEnabled(true); 492 } 493 else { 494 enabled.setSelected(false); 495 list.setBackground(Color.lightGray); 496 list.setEnabled(false); 497 one.setEnabled(false); 498 two.setEnabled(false); 499 value.setEnabled(false); 500 } 501 break; 502 } 436 437 } 438 } 439 } 440 else { 441 value = new JTextField(); 442 } 443 } 444 break; 445 case Argument.LANGUAGE: 446 value = new JComboBox(manager.languages.getLanguageCodes().toArray()); 447 // Now ensure we have the existing value or default value selected if either exist. 448 Language selected = null; 449 if(existing_value != null) { 450 selected = manager.languages.getLanguage(existing_value, false); 451 } 452 else if(default_value != null) { 453 selected = manager.languages.getLanguage(default_value, false); 454 } 455 if(selected != null) { 456 ((JComboBox)value).setSelectedItem(selected); 457 } 458 break; 459 case Argument.METADATA: 460 value = new JComboBox(gatherer.c_man.msm.getAssignedElements()); 461 /** @TODO - figure out a smarter way of allowing Greenstone extracted metadata to be selected. */ 462 ((JComboBox)value).setEditable(true); 463 // Now ensure we have the existing value or default value selected if either exist. 464 if(existing_value != null) { 465 selectValue((JComboBox)value, existing_value); 466 } 467 else if(default_value != null) { 468 selectValue((JComboBox)value, default_value); 469 } 470 break; 471 case Argument.METADATUM: 472 // Comma separated metadata values. 473 ArrayList values = argument.getValues(); 474 value = new JComboBox(gatherer.c_man.msm.getAssignedElements()); 475 DefaultListModel model = new DefaultListModel(); 476 list = new JList(model); 477 list.setVisibleRowCount(3); 478 for(int i = 0; i < values.size(); i++) { 479 model.addElement(values.get(i)); 480 } 481 one = new JButton(get("Add")); 482 one.addActionListener(new AddListener((JComboBox)value, list)); 483 two = new JButton(get("Remove")); 484 two.addActionListener(new RemoveListener(list)); 485 if(argument.getValues().size() > 0 || argument.isRequired()) { 486 enabled.setSelected(true); 487 list.setBackground(Color.white); 488 list.setEnabled(true); 489 one.setEnabled(true); 490 two.setEnabled(true); 491 value.setEnabled(true); 492 } 493 else { 494 enabled.setSelected(false); 495 list.setBackground(Color.lightGray); 496 list.setEnabled(false); 497 one.setEnabled(false); 498 two.setEnabled(false); 499 value.setEnabled(false); 500 } 501 break; 502 } 503 503 // Enable or disable as necessary. 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 504 if(argument.isRequired() || argument.isAssigned()) { 505 enabled.setSelected(true); 506 if(value != null) { 507 value.setOpaque(true); 508 value.setBackground(Color.white); 509 value.setEnabled(true); 510 } 511 } 512 else { 513 enabled.setSelected(false); 514 if(value != null) { 515 value.setOpaque(true); 516 value.setBackground(Color.lightGray); 517 value.setEnabled(false); 518 } 519 } 520 520 // Listener 521 522 523 521 if(value != null && !argument.isRequired()) { 522 enabled.addActionListener(new EnabledListener(one, two, list, value)); 523 } 524 524 // Layout 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 525 if(list == null) { 526 enabled.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 527 inner_pane.setLayout(new BorderLayout()); 528 if(argument.isRequired()) { 529 inner_pane.add(label, BorderLayout.WEST); 530 } 531 else { 532 inner_pane.add(enabled, BorderLayout.WEST); 533 } 534 if(value != null) { 535 inner_pane.add(value, BorderLayout.CENTER); 536 } 537 } 538 else { 539 JPanel control_pane = new JPanel(new GridLayout(2,1)); 540 control_pane.add(enabled); 541 control_pane.add(value); 542 control_pane.setOpaque(false); 543 544 JPanel left_pane = new JPanel(new BorderLayout()); 545 left_pane.add(control_pane, BorderLayout.CENTER); 546 left_pane.add(one, BorderLayout.SOUTH); 547 left_pane.setOpaque(false); 548 549 JPanel right_pane = new JPanel(new BorderLayout()); 550 right_pane.add(new JScrollPane(list), BorderLayout.CENTER); 551 right_pane.add(two, BorderLayout.SOUTH); 552 right_pane.setOpaque(false); 553 554 inner_pane.setLayout(new GridLayout(1,2)); 555 inner_pane.add(left_pane); 556 inner_pane.add(right_pane); 557 } 558 setLayout(new BorderLayout()); 559 559 //add(owner_label, BorderLayout.NORTH); 560 561 562 563 564 565 566 567 568 569 570 571 560 add(inner_pane, BorderLayout.CENTER); 561 } 562 public Object getValue() { 563 if(value instanceof JComboBox) { 564 return ((JComboBox)value).getSelectedItem(); 565 } 566 else if(value instanceof JTextField) { 567 return ((JTextField)value).getText(); 568 } 569 return null; 570 } 571 /** Identifies this control by returning the name of the Argument it is based on. 572 572 * @return The name of the Argument as a <strong>String</strong>. 573 573 * @see org.greenstone.gatherer.cdm.Argument 574 574 */ 575 576 577 578 575 public String toString() { 576 return argument.getName(); 577 } 578 /** Updates the enwrapped Argument using the values provided by the controls. 579 579 * @return <i>true</i> if the update was successful, <i>false</i> otherwise. 580 580 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration.ArgumentControl.ListOption … … 582 582 * @see org.greenstone.gatherer.msm.ElementWrapper 583 583 */ 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 584 public boolean updateArgument() { 585 if(enabled.isSelected() || argument.isRequired()) { 586 argument.setAssigned(true); 587 String result = null; 588 switch(argument.getType()) { 589 case Argument.ENUM: 590 ListOption option = (ListOption)((JComboBox)value).getSelectedItem(); 591 result = option.getValue(); 592 if(result.length() > 0) { 593 argument.setValue(result); 594 } 595 else { 596 if(argument.isRequired()) { 597 String args[] = new String[1]; 598 args[0] = argument.getName(); 599 JOptionPane.showMessageDialog(self, get("Required_Argument", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE); 600 args = null; 601 return false; 602 } 603 else { 604 argument.setValue(null); 605 } 606 } 607 return true; 608 case Argument.FLAG: 609 // Should have already been handled above. 610 return true; 611 case Argument.INTEGER: 612 result = ((JTextField)value).getText(); 613 if(result.length() > 0) { 614 // Test if the value entered is a valid int. 615 try { 616 int x = Integer.parseInt(result); 617 } 618 catch(NumberFormatException nfe) { 619 String args[] = new String[2]; 620 args[0] = argument.getName(); 621 args[1] = result; 622 JOptionPane.showMessageDialog(self, get("Bad_Integer", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE); 623 args = null; 624 return false; 625 } 626 argument.setValue(result); 627 } 628 else { 629 if(argument.isRequired()) { 630 String args[] = new String[1]; 631 args[0] = argument.getName(); 632 JOptionPane.showMessageDialog(self, get("Required_Argument", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE); 633 args = null; 634 return false; 635 } 636 else { 637 argument.setValue(null); 638 } 639 } 640 return true; 641 case Argument.LANGUAGE: 642 Language language = (Language) ((JComboBox)value).getSelectedItem(); 643 argument.setValue(language.getCode()); 644 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted. 645 return true; 646 case Argument.METADATA: 647 case Argument.HIERARCHY: 648 argument.setValue(((JComboBox)value).getSelectedItem().toString()); 649 // Kinda lucked out here. Its impossible not to choose an entry from these comboboxes as they are restricted. 650 return true; 651 case Argument.METADATUM: 652 DefaultListModel model = (DefaultListModel)list.getModel(); 653 ArrayList values = new ArrayList(); 654 for(int i = 0; i < model.size(); i++) { 655 values.add(model.get(i)); 656 } 657 argument.setValues(values); 658 return true; 659 case Argument.STRING: 660 result = ((JTextField)value).getText(); 661 if(result.length() > 0) { 662 argument.setValue(result); 663 } 664 else { 665 if(argument.isRequired()) { 666 String args[] = new String[1]; 667 args[0] = argument.getName(); 668 JOptionPane.showMessageDialog(self, get("Required_Argument", args), get("Error_Title"), JOptionPane.ERROR_MESSAGE); 669 return false; 670 } 671 else { 672 argument.setValue(null); 673 } 674 } 675 return true; 676 } 677 return false; 678 } 679 else { 680 argument.setAssigned(false); 681 return true; 682 } 683 } 684 /** Method to ensure that a certain value is selected, if it exists within that combobox to begin with. 685 685 * @param combobox The <strong>JComboBox</strong> whose selection we are trying to preset. 686 686 * @param target The desired value of the selection as a <strong>String</strong>. … … 688 688 * @see org.greenstone.gatherer.msm.ElementWrapper 689 689 */ 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 690 public void selectValue(JComboBox combobox, String target) { 691 for(int i = 0; i < combobox.getItemCount(); i++) { 692 Object object = combobox.getItemAt(i); 693 if(object instanceof ListOption) { 694 ListOption lo = (ListOption) object; 695 if(lo.getValue().equals(target)) { 696 combobox.setSelectedIndex(i); 697 return; 698 } 699 } 700 else if(object instanceof ElementWrapper) { 701 if(object.toString().equals(target)) { 702 combobox.setSelectedIndex(i); 703 return; 704 } 705 } 706 } 707 } 708 /** Forces the control into an 'enabled' mode. */ 709 public void setEnabled() { 710 enabled.setSelected(true); 711 } 712 /** Explicitly sets the value of a JTextField type control to the given String. 713 713 * @param value_str The new value of the control as a <strong>String</strong>. 714 714 */ 715 716 717 718 719 720 715 public void setValue(String value_str) { 716 ((JTextField)value).setText(value_str); 717 } 718 /** Listener which adds entries to a list from a combobox when fired. */ 719 private class AddListener 720 implements ActionListener { 721 721 /** The model behind the target list. */ 722 722 private DefaultListModel model = null; 723 723 /** The source for data to be added to the list. */ 724 724 private JComboBox source = null; 725 725 /** The list to add data to. */ 726 726 private JList target = null; 727 727 /** Constructor. 728 728 * @param source A <strong>JComboBox</strong> which serves as the source for data. 729 729 * @param target A <strong>JList</strong> which serves as the target for data. 730 730 */ 731 732 733 734 735 731 public AddListener(JComboBox source, JList target) { 732 this.model = (DefaultListModel) target.getModel(); 733 this.source = source; 734 this.target = target; 735 } 736 736 /** When the add button is clicked, we attempt to add the selected metadata from the source into the target. 737 737 * @param event An <strong>ActionEvent</strong> containing information about the event. 738 738 * @see org.greenstone.gatherer.msm.ElementWrapper 739 739 */ 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 740 public void actionPerformed(ActionEvent event) { 741 ElementWrapper element = (ElementWrapper) source.getSelectedItem(); 742 String name = element.toString(); 743 if(!model.contains(name)) { 744 boolean found = false; 745 int index = 0; 746 while(!found && index < model.size()) { 747 String sibling = (String) model.get(index); 748 if(name.compareTo(sibling) < 0) { 749 model.add(index, name); 750 found = true; 751 } 752 else { 753 index++; 754 } 755 } 756 if(!found) { 757 model.addElement(name); 758 } 759 } 760 } 761 } 762 /** Listens for actions apon the enable checkbox, and if detected enables or diables control appropriately. */ 763 private class EnabledListener 764 implements ActionListener { 765 765 /** One of two possible buttons that might have their enabled state changed by this listener. */ 766 766 private JButton one = null; 767 767 /** One of two possible buttons that might have their enabled state changed by this listener. */ 768 768 private JButton two = null; 769 769 /** An editor component, such as a JComboBox or JTextField, that might have its enabled state changed by this listener. */ 770 770 private JComponent target = null; 771 771 /** A list which might have its enabled state changed by this listener. */ 772 772 private JList list = null; 773 773 /** Constructor. 774 774 * @param one A <strong>JButton</strong> whose enabled state is determined by the listener, or <i>null</i> if no button. … … 777 777 * @param list A <strong>JComponent</strong> whose enabled state is determined by the listener, or <i>null</i> if no component. 778 778 */ 779 780 781 782 783 784 779 public EnabledListener(JButton one, JButton two, JList list, JComponent target) { 780 this.list = list; 781 this.one = one; 782 this.target = target; 783 this.two = two; 784 } 785 785 /** Any implementation of ActionListener must include this method so that we can be informed when an action has been performed on or registered check box, prompting us to change the state of the other controls as per the users request. 786 786 * @param event An <strong>ActionEvent</strong> containing information about the click. 787 787 */ 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 788 public void actionPerformed(ActionEvent event) { 789 JCheckBox source = (JCheckBox)event.getSource(); 790 if(source.isSelected()) { 791 target.setBackground(Color.white); 792 target.setEnabled(true); 793 if(one != null && two != null && list != null) { 794 one.setEnabled(true); 795 two.setEnabled(true); 796 list.setBackground(Color.white); 797 list.setEnabled(true); 798 } 799 } 800 else { 801 target.setBackground(Color.lightGray); 802 target.setEnabled(false); 803 if(one != null && two != null && list != null) { 804 one.setEnabled(false); 805 two.setEnabled(false); 806 list.setBackground(Color.lightGray); 807 list.setEnabled(false); 808 } 809 } 810 } 811 } 812 /** If a metadata element is selected that requires an hfile, then this listener defaults that hfile. */ 813 private class HierarchyListener 814 implements ItemListener { 815 815 /** Any implementation of ItemListener must include this method so that we can be informed when an item from the list is selected, and generate a predetermined hfile for that selection. 816 816 * @param event An <strong>ItemEvent</strong> containing information about the selection. … … 818 818 * @see org.greenstone.gatherer.valuetree.GValueModel 819 819 */ 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 820 public void itemStateChanged(ItemEvent event) { 821 // Determine if the selected element represents a hierarchy. 822 Object temp = ((JComboBox)value).getSelectedItem(); 823 String filename = temp.toString(); 824 // Search for a argument control called hfile and enable and set value. 825 for(int i = 0; i < central_pane.getComponentCount(); i++) { 826 Object object = central_pane.getComponent(i); 827 if(object instanceof ArgumentControl) { 828 ArgumentControl control = (ArgumentControl) object; 829 if(control.toString().equals("hfile")) { 830 control.setValue(filename + ".txt"); 831 control.setEnabled(true); 832 } 833 } 834 } 835 } 836 } 837 /** A ListOption is a compound item which is constructed from several Strings. That magic part is that the length of screen real-estate used by the text version of this item is limited. */ 838 private class ListOption 839 implements Comparable { 840 840 /** The maximum length of this String version of this item. */ 841 841 private int MAX_DESC = 35; 842 842 /** The description of the value for this item. */ 843 843 private String description = null; 844 844 /** A cached value for the text value of this option, as it never changes after the first call to toString(). */ 845 845 private String text = null; 846 846 /** The value for this item. */ 847 847 private String value = null; 848 848 /** Constructor. 849 849 * @param value The value for this item as a <strong>String</strong>. 850 850 * @param description The description of the value as a <strong>String</strong>. 851 851 */ 852 853 854 855 852 public ListOption(String value, String description) { 853 this.description = description; 854 this.value = value; 855 } 856 856 /** Compare two possible ListOption objects for ordering. 857 857 * @param object The <strong>Object</strong> to compare to. … … 859 859 * @see java.lang.String#compareTo 860 860 */ 861 862 863 861 public int compareTo(Object object) { 862 return toString().compareTo(object.toString()); 863 } 864 864 /** Tests two possible ListOption objects for equality. Uses the result from compareTo(). 865 865 * @param The <strong>Object</strong> which may be equal. 866 866 * @return <i>true</i> if the objects are equal, <i>false</i> otherwise. 867 867 */ 868 869 870 868 public boolean equals(Object object) { 869 return (compareTo(object) == 0); 870 } 871 871 /** Retrieve the description of this list item. 872 872 * @return The description as a <strong>String</strong>. 873 873 */ 874 875 876 874 public String getDesc() { 875 return description; 876 } 877 877 /** Retrieve the value of this list item. 878 878 * @return The value as a <strong>String</strong>. 879 879 */ 880 881 882 880 public String getValue() { 881 return value; 882 } 883 883 /** Convert this object into a nice readable String. 884 884 * @return A <strong>String</strong> representing this object. 885 885 */ 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 886 public String toString() { 887 if(text == null) { 888 if(description.length() >= MAX_DESC) { 889 text = value + " - " + description.substring(0, MAX_DESC); 890 } 891 else { 892 text = value + " - " + description; 893 } 894 } 895 return text; 896 } 897 } 898 /** Listener which removes entries from a list from a combobox when fired. */ 899 private class RemoveListener 900 implements ActionListener { 901 901 /** The model behind the target list. */ 902 902 private DefaultListModel model = null; 903 903 /** The list to remove data from. */ 904 904 private JList target = null; 905 905 /** Constructor. 906 906 * @param target A <strong>JList</strong>. 907 907 */ 908 909 910 911 908 public RemoveListener(JList target) { 909 this.model = (DefaultListModel) target.getModel(); 910 this.target = target; 911 } 912 912 /** When the remove button is clicked, we attempt to remove the selected metadata from the target. 913 913 * @param event An <strong>ActionEvent</strong> containing information about the event. 914 914 */ 915 916 917 918 919 920 921 922 923 924 915 public void actionPerformed(ActionEvent event) { 916 if(!target.isSelectionEmpty()) { 917 int index = target.getSelectedIndex(); 918 model.remove(index); 919 } 920 } 921 } 922 /** Listener that sets the tooltip associated to a combobox to the tooltip relevant to the selected item. */ 923 private class ToolTipUpdater 924 implements ActionListener { 925 925 /** Any implementation of an ActionListener must include this method so that we can be informed when the selection in a combobox has changed and update the tooltip accordingly. 926 926 * @param event An <strong>ActionEvent</strong> containing information about the action that fired this call. 927 927 */ 928 929 930 931 932 933 934 935 928 public void actionPerformed(ActionEvent event) { 929 JComboBox source = (JComboBox)event.getSource(); 930 ListOption lo = (ListOption)source.getSelectedItem(); 931 String description = Utility.formatHTMLWidth(lo.getDesc(), 60); 932 source.setToolTipText(description); 933 } 934 } 935 } 936 936 } -
trunk/gli/src/org/greenstone/gatherer/cdm/ArgumentContainer.java
r4293 r4366 56 56 */ 57 57 public interface ArgumentContainer { 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 58 /** Method to retrieve the list of arguments from this container. Note that this method returns both the containers arguments plus its 'supers' arguments if any, and alphabetically orders them. 59 * @return The arguments within a <strong>ArrayList</strong>. 60 */ 61 public ArrayList getArguments(); 62 /** Method to retrieve this containers custom argument string. 63 * @return The custom arguments as a <strong>String</strong>. 64 */ 65 public String getCustom(); 66 /** Method to retrieve the name associated with this argument container. 67 * @return The name as a <strong>String</strong>. 68 */ 69 public String getName(); 70 /** Method to set the custom arguments string. 71 * @param custom The new custom argument <strong>String</strong>. 72 */ 73 public void setCustom(String custom); 74 74 } 75 75 -
trunk/gli/src/org/greenstone/gatherer/cdm/Classifier.java
r4293 r4366 66 66 // #################################################################################### 67 67 public class Classifier 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 68 extends ArrayList 69 implements ArgumentContainer, Comparable, Serializable { 70 /** A reference to the classifier that this one inherits from. */ 71 private Classifier super_classifier = null; 72 /** A reference to the manager of this classifier. Only available once the classifiers been assigned, always <i>null</i> for classifiers in reserve. */ 73 private ClassifierManager manager = null; 74 /** Custom arguments (ie those unparsable from classinfo.pl) provided to this class. */ 75 private String custom = null; 76 /** A description of this classifier. */ 77 private String desc = null; 78 /** The name of the classifier as it would appear in the collect.cfg file. */ 79 private String name = null; 80 /** A list of format commands that are dependant on this classifier. */ 81 private ArrayList dependant_formats = null; 82 /** Default Constructor. 83 */ 84 public Classifier() { 85 super(); 86 dependant_formats = new ArrayList(); 87 } 88 /** Constructor. 89 89 * @param name The name of this classifier as a <strong>String</strong>. 90 90 * @param desc A description of this classifier as a <strong>String</strong>. 91 91 * @param super_classifier The super class of this classifier, as a <strong>Classifier</strong>. 92 92 */ 93 94 95 96 97 98 99 93 public Classifier(String name, String desc, Classifier super_classifier) { 94 this(); 95 this.desc = desc; 96 this.name = name; 97 this.super_classifier = super_classifier; 98 } 99 /** Method to add an argument to this classifier. Only adds the argument if it isn't already present. 100 100 * @param argument The <strong>Argument</strong> to add. 101 101 */ 102 103 104 105 106 107 108 102 public void addArgument(Argument argument) { 103 if(!contains(argument)) { 104 add(argument); 105 argument.setOwner(name); 106 } 107 } 108 /** Method to register a dependant format with this classifier. If the classifier changes, this format also needs to be updated. 109 109 * @param format A <strong>Format</strong> which is dependant on this classifier. 110 110 */ 111 112 113 114 111 public void addDependantFormat(Format format) { 112 dependant_formats.add(format); 113 } 114 /** Method to compare two classifiers for ordering. 115 115 * @param object The classifier we are comparing to, as an <strong>Object</strong>. 116 116 * @return An <i>int</i> specifying the classifier order, using values as set out in String. 117 117 * @see java.lang.String#compareTo 118 118 */ 119 120 121 122 123 124 125 126 119 public int compareTo(Object object) { 120 if(object instanceof Classifier) { 121 Classifier classifier = (Classifier) object; 122 return name.compareTo(classifier.getName()); 123 } 124 return name.compareTo(object.toString()); 125 } 126 /** This method produces a deep copy of this classifier. Note that this also creates a new copy of each of the super classes of classifiers as well. This is the way it should be, as each assigned classifier may have different values for the higher classifiers (such as BasPlug). 127 127 * @return A newly created <strong>Classifier</strong> with the same details and Arguments as this one. 128 128 * @see org.greenstone.gatherer.cdm.Argument 129 129 */ 130 131 132 133 134 135 136 137 138 139 140 141 142 143 130 public Classifier copy() { 131 Classifier copy = null; 132 if(super_classifier == null) { 133 copy = new Classifier(name, desc, null); 134 } 135 else { 136 copy = new Classifier(name, desc, super_classifier.copy()); 137 } 138 for(int i = 0; i < size(); i++) { 139 copy.addArgument(((Argument)get(i)).copy()); 140 } 141 return copy; 142 } 143 /** Method to determine if two classifiers are equal. 144 144 * @param object The classifier to test against, as an <strong>Object</strong>. 145 145 * @return <i>true</i> if the classifier names match, <i>false</i> otherwise. 146 146 * @see org.greenstone.gatherer.cdm.CustomClassifier 147 147 */ 148 149 150 151 152 153 154 155 156 157 148 public boolean equals(Object object) { 149 if(object instanceof CustomClassifier) { 150 CustomClassifier classifier = (CustomClassifier) object; 151 return (toString().equalsIgnoreCase(classifier.getCommand())); 152 } 153 else { 154 return(toString().equalsIgnoreCase(object.toString())); 155 } 156 } 157 /** Method to retrieve an argument by its name. 158 158 * @param name The name of the argument as a <strong>String</strong>. 159 159 * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument. 160 160 */ 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 161 public Argument getArgument(String name) { 162 // The name given may still include the '-' 163 if(name.startsWith("-")) { 164 name = name.substring(1); 165 } 166 ArrayList arguments = getArguments(); 167 for(int i = 0; i < arguments.size(); i++) { 168 Argument argument = (Argument)arguments.get(i); 169 if(argument.getName().equals(name)) { 170 return argument; 171 } 172 } 173 return null; 174 } 175 /** Method to retrieve all of the arguments available to a classifier, including both specific and general ones. 176 176 * @return A <strong>Hashtable</strong> of arguments, with <name> -> <argument> entries. 177 177 */ 178 179 180 181 182 183 184 185 186 187 188 189 190 191 178 public ArrayList getArguments() { 179 ArrayList all_arguments = new ArrayList(this); 180 if(super_classifier != null) { 181 ArrayList super_arguments = super_classifier.getArguments(); 182 for(int i = 0; i < super_arguments.size(); i++) { 183 Object argument = super_arguments.get(i); 184 if(!all_arguments.contains(argument)) { 185 all_arguments.add(argument); 186 } 187 } 188 } 189 return all_arguments; 190 } 191 /** Method to retrieve a classifiers custom argument information. 192 192 * @return The custom arguments as a <strong>String</strong>. 193 193 */ 194 195 196 197 194 public String getCustom() { 195 return custom; 196 } 197 /** Method to retrieve a classifiers name. 198 198 * @return A <strong>String</strong> containing the classifiers name. 199 199 */ 200 201 202 203 200 public String getName() { 201 return name; 202 } 203 /** Method to retrieve the position of this classifier as a special keyword or the form "CL#" where # is the classifiers order in the set of classifiers. Note that if this is called for a Classifier that has never been assigned a position of 'Search' is returned, as this is the only case where we will try to write a Classifier that does not have a manager. 204 204 * @return A <strong>String</strong> containing the special position keyword. 205 205 * @see org.greenstone.gatherer.cdm.ClassifierManager 206 206 */ 207 208 209 210 211 212 213 207 public String getPositionString() { 208 if(manager == null) { 209 return "Search"; 210 } 211 return "CL" + (manager.indexOf(this) + 1); 212 } 213 /** Method to set the value of custom. 214 214 * @param custom The new value of custom as a <strong>String</strong>. 215 215 */ 216 217 218 219 216 public void setCustom(String custom) { 217 this.custom = custom; 218 } 219 /** Method to set the value of desc. 220 220 * @param desc The new value of desc as a <strong>String</strong>. 221 221 */ 222 223 224 225 222 public void setDesc(String desc) { 223 this.desc = desc; 224 } 225 /** Method to set the value of manager. 226 226 * @param manager The new manager as a <strong>ClassifierManager</strong>. 227 227 */ 228 229 230 231 228 public void setManager(ClassifierManager manager) { 229 this.manager = manager; 230 } 231 /** Method to set the value of name. 232 232 * @param name The new value of name as a <strong>String</strong>. 233 233 */ 234 235 236 237 234 public void setName(String name) { 235 this.name = name; 236 } 237 /** Method to set the value of the super_classifier. 238 238 * @param super_classifier The new value of super_classifier as a <strong>Classifier</strong>, or <i>null</i> if this class has no inheritance. 239 239 */ 240 241 242 243 240 public void setSuper(Classifier super_classifier) { 241 this.super_classifier = super_classifier; 242 } 243 /** Method to print out this classifier as it would appear as a command within the collection configuration file. 244 244 * @return A <strong>String</strong> containing a single classifier command. 245 245 */ 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 246 public String toString() { 247 StringBuffer text = new StringBuffer("classify "); 248 text.append(name); 249 text.append(" "); 250 ArrayList arguments = getArguments(); 251 for(int i = 0; i < arguments.size(); i++) { 252 Argument argument = (Argument)arguments.get(i); 253 if(argument.isAssigned()) { 254 text.append(argument.toString()); 255 text.append(" "); 256 } 257 } 258 if(custom != null) { 259 text.append(custom); 260 } 261 return text.toString(); 262 } 263 263 } 264 264 -
trunk/gli/src/org/greenstone/gatherer/cdm/ClassifierManager.java
r4293 r4366 112 112 // #################################################################################### 113 113 public class ClassifierManager 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 114 implements MSMListener { 115 /** An interface to the Gatherer, the creator of this cdm module, for access to the Greenstone installation directory. */ 116 private Gatherer gatherer = null; 117 /** A reference to the CollectionDesignManager for access to other configuration managers. */ 118 private CollectionDesignManager manager = null; 119 /** The controls for editing the contents of this manager. */ 120 private Control controls = null; 121 /** A list of assigned classifiers. */ 122 private DynamicListModel assigned = null; 123 /** A list of known, but currently unassigned, classifiers. */ 124 private DynamicListModel reserve = null; 125 /** We may have somehow recieved a classifier command that are, in fact, custom classifiers which can refer to classifiers that haven't been parsed yet, so this holds a list of failed commands which are retried after the loading is complete. */ 126 private ArrayList unresolved_commands = null; 127 /** Constructor. 128 * @param gatherer A reference to the <strong>Gatherer</strong> for access to the Dictionary. 129 * @param manager A reference to the <strong>CollectionDesignManager</strong> itself. 130 * @see org.greenstone.gatherer.Gatherer 131 * @see org.greenstone.gatherer.cdm.DynamicListModel 132 * @see org.greenstone.gatherer.collection.CollectionManager 133 * @see org.greenstone.gatherer.msm.MetadataSetManager 134 * @see org.greenstone.gatherer.msm.MSMListener 135 */ 136 public ClassifierManager(Gatherer gatherer, CollectionDesignManager manager) { 137 this.assigned = new DynamicListModel(); 138 this.gatherer = gatherer; 139 this.manager = manager; 140 this.unresolved_commands = new ArrayList(); 141 loadClassifiers(); 142 saveClassifiers(); 143 // Register as a MSMListener. 144 Gatherer.c_man.getCollection().msm.addMSMListener(this); 145 } 146 /** Method to add a new classifier to reserve. 147 147 * @param classifier The new <strong>Classifier</strong>. 148 148 * @see org.greenstone.gatherer.cdm.DynamicListModel 149 149 */ 150 151 152 153 154 155 150 public void addClassifier(Classifier classifier) { 151 if(!reserve.contains(classifier)) { 152 reserve.addElement(classifier); 153 } 154 } 155 /** Method to assign a classifier. 156 156 * @param classifier The reserve <strong>Classifier</strong> to assign. 157 157 * @see org.greenstone.gatherer.cdm.DynamicListModel 158 158 */ 159 160 161 162 163 164 165 166 159 public void assignClassifier(Classifier classifier) { 160 if(!assigned.contains(classifier)) { 161 assigned.addElement(classifier); 162 classifier.setManager(this); 163 gatherer.c_man.configurationChanged(); 164 } 165 } 166 /** Method to assign a classifier. 167 167 * @param classifier The <strong>CustomClassifier</strong> to assign. 168 168 * @see org.greenstone.gatherer.cdm.DynamicListModel 169 169 */ 170 171 172 173 174 175 176 177 170 public void assignClassifier(CustomClassifier classifier) { 171 if(!assigned.contains(classifier)) { 172 assigned.addElement(classifier); 173 classifier.setManager(this); 174 gatherer.c_man.configurationChanged(); 175 } 176 } 177 /** Destructor. 178 178 * @see org.greenstone.gatherer.Gatherer 179 179 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 180 180 * @see org.greenstone.gatherer.cdm.DynamicListModel 181 181 */ 182 183 184 185 186 187 188 189 190 191 192 193 194 195 182 public void destroy() { 183 // Deregister as a listener 184 if(gatherer.c_man != null && gatherer.c_man.msm != null) { 185 gatherer.c_man.msm.removeMSMListener(this); 186 } 187 // Null globals 188 assigned = null; 189 controls = null; 190 gatherer = null; 191 manager = null; 192 reserve = null; 193 unresolved_commands = null; 194 } 195 /** Method to retrieve the classifier with the given index. 196 196 * @param index The index of the desired classifier as an <i>int</i>. 197 197 * @return The requested Classifier as an <strong>Object</strong> or <i>null</i> if no such classifier exists. 198 198 * @see org.greenstone.gatherer.cdm.DynamicListModel 199 199 */ 200 201 202 203 204 205 206 200 public Object getClassifier(int index) { 201 if(0 <= index && index < assigned.size()) { 202 return assigned.get(index); 203 } 204 return null; 205 } 206 /** Method to retrieve the named classifier. 207 207 * @param name The name of the desired classifier as a <strong>String</strong>. 208 208 * @return The requested <strong>Classifier</strong> or <i>null</i> if no such classifier exists. 209 209 * @see org.greenstone.gatherer.cdm.DynamicListModel 210 210 */ 211 212 213 214 215 216 217 218 219 220 221 211 public Classifier getClassifier(String name) { 212 for(int i = 0; i < reserve.size(); i++) { 213 Classifier classifier = (Classifier)reserve.get(i); 214 if(classifier.getName().equals(name)) { 215 return classifier; 216 } 217 } 218 // No success. 219 return null; 220 } 221 /** Method to retrieve the control for this manager. 222 222 * @return A <strong>JPanel</strong> containing the controls. 223 223 */ 224 225 226 227 228 229 230 224 public JPanel getControls() { 225 if(controls == null) { 226 controls = new Control(); 227 } 228 return controls; 229 } 230 /** Called whenever a metadata element changes significantly. 231 231 * @param event A <strong>MSMEvent</strong> choc' full of event informationy goodness. 232 232 */ 233 234 235 236 233 public void elementChanged(MSMEvent event) { 234 // Don't really care, as the elements dealt with here are all live references so changes like identifier change will propagate immediately. 235 } 236 /** Method to find the index of the given classifier within the assigned classifiers. 237 237 * @param classifier The <strong>Classifier</strong> whose index you wish to find. 238 238 * @return The index of the classifier as an <i>int</i>, which has a value of -1 if the classifier was not found. 239 239 * @see org.greenstone.gatherer.cdm.DynamicListModel 240 240 */ 241 242 243 244 245 246 247 248 249 250 251 */ 252 253 254 255 256 257 258 241 public int indexOf(Classifier classifier) { 242 for(int i = 0; i < assigned.size(); i++) { 243 Classifier sibling = (Classifier) assigned.get(i); 244 if(sibling.equals(classifier)) { 245 return i; 246 } 247 } 248 return -1; 249 } 250 /** Method to invalidate controls after a significant change in the system state. 251 */ 252 public void invalidateControls() { 253 if(controls != null) { 254 controls.destroy(); 255 } 256 controls = null; 257 } 258 /** Method to load the details of a single plug-in. 259 259 * @param classifier The classifier <strong>File</strong> you wish to load. 260 260 */ 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 261 public void loadClassifier(File classifier) { 262 ///ystem.err.println("Attempting to parse " + classifier.toString()); 263 Document document = null; 264 long start; 265 long end; 266 // Run classinfo on this classifier, and then send the results for parsing. 267 try { 268 String args[] = null; 269 if(Utility.isWindows()) { 270 args = new String[4]; 271 if(Gatherer.config.perl_path != null) { 272 args[0] = gatherer.config.perl_path + "Perl.exe"; 273 } 274 else { 275 args[0] = "Perl.exe"; 276 } 277 args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "classinfo.pl"; 278 args[2] = "-xml"; 279 args[3] = getClassifierName(classifier); 280 } 281 else { 282 args = new String[3]; 283 args[0] = "classinfo.pl"; 284 args[1] = "-xml"; 285 args[2] = getClassifierName(classifier); 286 } 287 287 288 288 // Create the process. 289 290 291 292 293 294 295 296 297 298 289 Runtime runtime = Runtime.getRuntime(); 290 Process process = runtime.exec(args); 291 InputStream input_stream = process.getErrorStream(); 292 BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream())); 293 String line = ""; 294 StringBuffer xml = new StringBuffer(""); 295 while((line = error_in.readLine()) != null) { 296 xml.append(line); 297 xml.append("\n"); 298 } 299 299 // Then read the xml from the piped input stream. 300 301 302 303 304 305 306 300 InputSource source = new InputSource(new StringReader(xml.toString())); 301 DOMParser parser = new DOMParser(); 302 parser.parse(source); 303 document = parser.getDocument(); 304 } 305 catch (Exception error) { 306 error.printStackTrace(); 307 307 //ystem.err.println("Error: Cannot parse " + getClassifierName(classifier)); 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 308 } 309 if(document != null) { 310 parse(document.getDocumentElement()); 311 } 312 } 313 /** Called whenever the metadata value associated to a certain record changes. */ 314 public void metadataChanged(MSMEvent event) { 315 FileNode record = event.getRecord(); 316 if(record != null) { 317 for(int i = 0; i < assigned.size(); i++) { 318 Object object = assigned.get(i); 319 if(object instanceof CustomClassifier) { 320 CustomClassifier classifier = (CustomClassifier) object; 321 classifier.process(record); 322 } 323 } 324 } 325 } 326 /** This method attempts to parse a classifier command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct classifier be matched but also all of the parameters given must be legal. If such a command is found, the classifier is immediately assigned. 327 327 * @param command The command <strong>String</strong> that may include classifier information. 328 328 * @return <i>true</i> if a classifier command was parsed, <i>false</i> otherwise. … … 331 331 * @see org.greenstone.gatherer.cdm.CommandTokenizer 332 332 */ 333 public boolean parse(String command) { 334 String command_lc = command.toLowerCase(); 335 if(command_lc.startsWith("classify")) { 336 CommandTokenizer tokenizer = new CommandTokenizer(command); 337 if(tokenizer.countTokens() >= 2) { 338 tokenizer.nextToken(); // Throw away 'classifier' 339 String name = tokenizer.nextToken(); 340 // Try to locate the classifier with this name. 341 Classifier classifier = getClassifier(name); 342 // And if successful start to parse the arguments. 343 if(classifier != null) { 344 // Take a copy. 345 classifier = classifier.copy(); 346 String key = null; 347 while((key = tokenizer.nextToken()) != null) { 348 // Try to retrieve a matching argument. 349 Argument argument = classifier.getArgument(key); 350 if(argument != null) { 351 // Set as assigned. 352 argument.setAssigned(true); 353 // And if the argument is of a parameter type, parse a parameter. 354 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) { 355 String value = tokenizer.nextToken(); 356 value = value.replace(':', MSMUtils.NS_SEP); 357 argument.setValue(value); 358 } 359 } 360 // Argument cannot be matched. 361 else { 362 String cur_key = key; 363 String value = tokenizer.nextToken(); 364 if(value.startsWith("-")) { 365 key = value; 366 value = null; 367 } 368 else { 369 key = null; 370 } 371 String custom = classifier.getCustom(); 372 if(custom == null) { 373 if(value == null) { 374 classifier.setCustom(cur_key); 375 } 376 else { 377 classifier.setCustom(cur_key + " " + value); 378 } 379 } 380 else { 381 if(value == null) { 382 classifier.setCustom(custom + " " + cur_key); 383 } 384 else { 385 classifier.setCustom(custom + " " + cur_key + " " + value); 386 } 387 } 388 } 389 } 390 assignClassifier(classifier); 391 return true; 392 } 393 else { 394 ///ystem.err.println("Unknown classifier"); 395 } 333 public boolean parse(String command) { 334 String command_lc = command.toLowerCase(); 335 if(command_lc.startsWith("classify")) { 336 CommandTokenizer tokenizer = new CommandTokenizer(command); 337 if(tokenizer.countTokens() >= 2) { 338 tokenizer.nextToken(); // Throw away 'classifier' 339 String name = tokenizer.nextToken(); 340 // Try to locate the classifier with this name. 341 Classifier classifier = getClassifier(name); 342 // And if successful start to parse the arguments. 343 if(classifier != null) { 344 // Take a copy. 345 classifier = classifier.copy(); 346 String key = null; 347 while((key = tokenizer.nextToken()) != null) { 348 // Try to retrieve a matching argument. 349 Argument argument = classifier.getArgument(key); 350 if(argument != null) { 351 // Set as assigned. 352 argument.setAssigned(true); 353 // And if the argument is of a parameter type, parse a parameter. 354 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) { 355 String value = tokenizer.nextToken(); 356 value = value.replace(':', MSMUtils.NS_SEP); 357 argument.setValue(value); 358 } 359 } 360 // Argument cannot be matched. 361 else { 362 String cur_key = key; 363 String value = tokenizer.nextToken(); 364 if(value.startsWith("-")) { 365 key = value; 366 value = null; 367 } 368 else { 369 key = null; 370 } 371 String custom = classifier.getCustom(); 372 if(custom == null) { 373 if(value == null) { 374 classifier.setCustom(cur_key); 396 375 } 397 } 398 else if(command_lc.startsWith("customclassifier")) { 399 unresolved_commands.add(command); 400 return true; 401 } 402 return false; 403 } 404 /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the reserve. 376 else { 377 classifier.setCustom(cur_key + " " + value); 378 } 379 } 380 else { 381 if(value == null) { 382 classifier.setCustom(custom + " " + cur_key); 383 } 384 else { 385 classifier.setCustom(custom + " " + cur_key + " " + value); 386 } 387 } 388 } 389 } 390 assignClassifier(classifier); 391 return true; 392 } 393 else { 394 ///ystem.err.println("Unknown classifier"); 395 } 396 } 397 } 398 else if(command_lc.startsWith("customclassifier")) { 399 unresolved_commands.add(command); 400 return true; 401 } 402 return false; 403 } 404 /** This method removes an assigned classifier. I was tempted to call it unassign, but remove is more consistant. Note that there is no way to remove a classifier from the reserve. 405 405 * @param classifier The Classifier or CustomClassifier, as an <strong>Object</strong>, to remove. 406 406 * @see org.greenstone.gatherer.cdm.DynamicListModel 407 407 */ 408 409 410 411 412 408 public void removeClassifier(Object classifier) { 409 assigned.removeElement(classifier); 410 gatherer.c_man.configurationChanged(); 411 } 412 /** Method which attempts to reparse obvious classifier commands which previously referenced unresovable Classifiers. 413 413 * @see org.greenstone.gatherer.cdm.Classifier 414 414 * @see org.greenstone.gatherer.cdm.CommandTokenizer 415 415 * @see org.greenstone.gatherer.cdm.CustomClassifier 416 416 */ 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 417 public void reparseUnresolved() { 418 for(int i = 0; i < unresolved_commands.size(); i++) { 419 String command = (String) unresolved_commands.get(i); 420 CommandTokenizer tokenizer = new CommandTokenizer(command); 421 if(tokenizer.countTokens() >= 6) { 422 tokenizer.nextToken();// Loose customclassifier 423 // Get class name. 424 String class_name = tokenizer.nextToken(); 425 // Parse arguments. 426 String replaces = null; 427 String separations = null; 428 while(tokenizer.hasMoreTokens()) { 429 String arg_name = tokenizer.nextToken(); 430 if(arg_name.equalsIgnoreCase("-replaces")) { 431 replaces = tokenizer.nextToken(); 432 } 433 else { 434 separations = tokenizer.nextToken(); 435 } 436 } 437 try { 438 replaces = replaces.substring(2); 439 int index = Integer.parseInt(replaces); 440 Classifier original = (Classifier)getClassifier(index); 441 if(original != null) { 442 Class custom_classifier_class = Class.forName("org.greenstone.gatherer.cdm.custom." + class_name); 443 CustomClassifier custom_classifier = (CustomClassifier) custom_classifier_class.newInstance(); 444 custom_classifier.setGatherer(gatherer); 445 custom_classifier.recreate(original, separations); 446 assigned.add(indexOf(original), custom_classifier); 447 assigned.removeElement(original); 448 } 449 else { 450 ///ystem.err.println("Missing original."); 451 } 452 } 453 catch (Exception error) { 454 error.printStackTrace(); 455 } 456 } 457 } 458 // Regardless of if they work, clear the commands. 459 unresolved_commands.clear(); 460 } 461 /** Method to cache the current contents of reserve (known classifiers) to file. 462 462 * @see org.greenstone.gatherer.util.Utility 463 463 */ 464 465 466 467 468 469 470 471 472 473 474 464 public void saveClassifiers() { 465 try { 466 FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "classifiers.dat"); 467 ObjectOutputStream out = new ObjectOutputStream(file); 468 out.writeObject(reserve); 469 out.close(); 470 } 471 catch (Exception error) { 472 } 473 } 474 /** Called when a metadata set changed significantly. 475 475 * @param event A <strong>MSMEvent</strong> containing information about the set change. 476 476 */ 477 478 479 480 477 public void setChanged(MSMEvent event) { 478 // Again, we would only worry about this if we contained 'inanimate' references to elements or something, but our references are live, and controls are rebuilt everytime a pop-up is needed. 479 } 480 /** Method used to determine the number of classifiers that have been assigned. 481 481 * @return An <i>int</i> which is the number of classifiers. 482 482 */ 483 484 485 486 483 public int size() { 484 return assigned.size(); 485 } 486 /** Method to print out a block of classifier commands, much like you'd find in a collection configuration file. 487 487 * @return A <strong>String</strong> containing a series of classifier commands separated by new lines. 488 488 * @see org.greenstone.gatherer.cdm.Classifier 489 489 * @see org.greenstone.gatherer.cdm.CustomClassifier 490 490 */ 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 491 public String toString() { 492 StringBuffer text = new StringBuffer(); 493 for(int i = 0; i < assigned.size(); i++) { 494 Object object = assigned.get(i); 495 if(object instanceof Classifier) { 496 Classifier classifier = (Classifier) object; 497 text.append(classifier.toString()); 498 } 499 else if(object instanceof CustomClassifier) { 500 CustomClassifier classifier = (CustomClassifier) object; 501 text.append(classifier.getCommand()); 502 text.append("\n"); 503 text.append(classifier.getCustomCommand(i)); 504 } 505 text.append("\n"); 506 } 507 text.append("\n"); 508 return text.toString(); 509 } 510 /** Called when a significant change has occured to a value tree for a certain element, however we take no further action. 511 511 * @param event A <strong>MSMEvent</strong> containing information relevant to the event. 512 512 */ 513 514 515 513 public void valueChanged(MSMEvent event) { 514 } 515 /** Retrieve a phrase from the dictionary based on a certain key. 516 516 * @param key The search <strong>String</strong>. 517 517 * @return The matching phrase from the Dictionary. 518 518 */ 519 520 521 522 519 private String get(String key) { 520 return get(key, null); 521 } 522 /** Retrieve a phrase from the dictionary based on a certain key and certain arguments. 523 523 * @param key The search <strong>String</strong>. 524 524 * @param args A <strong>String[]</strong> used to complete and format the returned phrase. … … 527 527 * @see org.greenstone.gatherer.Gatherer 528 528 */ 529 530 531 532 533 534 535 529 private String get(String key, String args[]) { 530 if(key.indexOf(".") == -1) { 531 key = "CDM.ClassifierManager." + key; 532 } 533 return gatherer.dictionary.get(key, args); 534 } 535 /** Method to extract just the classifiers name from a file object. 536 536 * @param classifier The <strong>File</strong> which references a certain classifier. 537 537 * @return A <strong>String</strong> containing just the classifiers name, without extension. 538 538 */ 539 540 541 542 543 544 545 546 539 private String getClassifierName(File classifier) { 540 String name = classifier.getName(); 541 if(name.indexOf(".") != -1) { 542 name = name.substring(0, name.indexOf(".")); 543 } 544 return name; 545 } 546 /** Method to initially load information from the standard plug-ins within the gsdl Perl library. 547 547 * @see org.greenstone.gatherer.cdm.DynamicListModel 548 548 * @see org.greenstone.gatherer.util.Utility 549 549 */ 550 551 552 553 554 555 556 557 558 559 560 550 private void loadClassifiers() { 551 // Attempt to restore the cached file. 552 try { 553 FileInputStream file = new FileInputStream(Utility.BASE_DIR + "classifiers.dat"); 554 ObjectInputStream input = new ObjectInputStream(file); 555 reserve = (DynamicListModel) input.readObject(); 556 } 557 catch (Exception error) { 558 } 559 if(reserve == null) { 560 reserve = new DynamicListModel(); 561 561 // Retrieve the gsdl home directory... 562 563 564 565 566 567 562 String directory = gatherer.config.gsdl_path; 563 directory = directory + "perllib" + File.separator + "classify" + File.separator; 564 loadClassifiers(new File(directory)); 565 } 566 } 567 /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location. 568 568 * @param directory A <strong>File</strong> indicating the directory to be scanned for plug-ins. 569 569 * @see org.greenstone.gatherer.cdm.ParsingProgress 570 570 */ 571 572 573 571 private void loadClassifiers(File directory) { 572 File files[] = directory.listFiles(); 573 if(files != null) { 574 574 // Create a progress indicator. 575 576 577 578 579 580 581 582 583 584 585 586 587 588 575 ParsingProgress progress = new ParsingProgress(get("CDM.ClassifierManager.Parsing.Title"), get("CDM.ClassifierManager.Parsing.Message"), files.length); 576 for(int i = 0; i < files.length; i++) { 577 // We only want to check Perl Modules. 578 if(files[i].getName().endsWith(".pm")) { 579 loadClassifier(files[i]); 580 } 581 progress.inc(); 582 } 583 progress.dispose(); 584 progress.destroy(); 585 progress = null; 586 } 587 } 588 /** Parses a DOM tree model turning it into a Classifier and its associated arguments. 589 589 * @param root The <strong>Node</strong> at the root of the DOM model. 590 590 * @return A newly created <strong>Classifier</strong> based on the information parsed from the DOM model. 591 591 * @see org.greenstone.gatherer.cdm.Argument 592 592 */ 593 private Classifier parse(Node root) { 594 Classifier classifier = new Classifier(); 595 String node_name = null; 596 for(Node node = root.getFirstChild(); node != null; 597 node = node.getNextSibling()) { 598 node_name = node.getNodeName(); 599 if(node_name.equals("Name")) { 600 String name = MSMUtils.getValue(node); 601 // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it. 602 Classifier existing = getClassifier(name); 603 if(existing != null) { 604 return existing; 605 } 606 classifier.setName(name); 593 private Classifier parse(Node root) { 594 Classifier classifier = new Classifier(); 595 String node_name = null; 596 for(Node node = root.getFirstChild(); node != null; 597 node = node.getNextSibling()) { 598 node_name = node.getNodeName(); 599 if(node_name.equals("Name")) { 600 String name = MSMUtils.getValue(node); 601 // We can save ourselves some processing time if a classifier with this name already exists in our manager. If so retrieve it and return it. 602 Classifier existing = getClassifier(name); 603 if(existing != null) { 604 return existing; 605 } 606 classifier.setName(name); 607 } 608 else if(node_name.equals("Desc")) { 609 classifier.setDesc(MSMUtils.getValue(node)); 610 } 611 // Parse the multitude of arguments. 612 else if(node_name.equals("Arguments")) { 613 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) { 614 node_name = arg.getNodeName(); 615 // An option. 616 if(node_name.equals("Option")) { 617 Argument argument = new Argument(); 618 // If its an option we parse the multitude of details an options might have. 619 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) { 620 node_name = det.getNodeName(); 621 if(node_name.equals("Name")) { 622 argument.setName(MSMUtils.getValue(det)); 623 } 624 else if(node_name.equals("Desc")) { 625 argument.setDesc(MSMUtils.getValue(det)); 626 } 627 else if(node_name.equals("Type")) { 628 argument.setType(MSMUtils.getValue(det)); 629 } 630 else if(node_name.equals("Default")) { 631 argument.setDefault(MSMUtils.getValue(det)); 632 } 633 else if(node_name.equals("List")) { 634 // Two final loops are required to parse lists. 635 for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) { 636 if(value.getNodeName().equals("Value")) { 637 String key = null; 638 String desc = ""; 639 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { 640 node_name = subvalue.getNodeName(); 641 if(node_name.equals("Name")) { 642 key = MSMUtils.getValue(subvalue); 643 } 644 else if(node_name.equals("Desc")) { 645 desc = MSMUtils.getValue(subvalue); 646 } 647 } 648 if(key != null) { 649 argument.addOption(key, desc); 650 } 651 } 607 652 } 608 else if(node_name.equals("Desc")) { 609 classifier.setDesc(MSMUtils.getValue(node)); 653 } 654 else if(node_name.equals("Required")) { 655 String v = MSMUtils.getValue(det); 656 ///ystem.err.println("Required = " + v); 657 if(v.equalsIgnoreCase("yes")) { 658 ///ystem.err.println("Setting required to true."); 659 argument.setRequired(true); 610 660 } 611 // Parse the multitude of arguments. 612 else if(node_name.equals("Arguments")) { 613 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) { 614 node_name = arg.getNodeName(); 615 // An option. 616 if(node_name.equals("Option")) { 617 Argument argument = new Argument(); 618 // If its an option we parse the multitude of details an options might have. 619 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) { 620 node_name = det.getNodeName(); 621 if(node_name.equals("Name")) { 622 argument.setName(MSMUtils.getValue(det)); 623 } 624 else if(node_name.equals("Desc")) { 625 argument.setDesc(MSMUtils.getValue(det)); 626 } 627 else if(node_name.equals("Type")) { 628 argument.setType(MSMUtils.getValue(det)); 629 } 630 else if(node_name.equals("Default")) { 631 argument.setDefault(MSMUtils.getValue(det)); 632 } 633 else if(node_name.equals("List")) { 634 // Two final loops are required to parse lists. 635 for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) { 636 if(value.getNodeName().equals("Value")) { 637 String key = null; 638 String desc = ""; 639 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { 640 node_name = subvalue.getNodeName(); 641 if(node_name.equals("Name")) { 642 key = MSMUtils.getValue(subvalue); 643 } 644 else if(node_name.equals("Desc")) { 645 desc = MSMUtils.getValue(subvalue); 646 } 647 } 648 if(key != null) { 649 argument.addOption(key, desc); 650 } 651 } 652 } 653 } 654 else if(node_name.equals("Required")) { 655 String v = MSMUtils.getValue(det); 656 ///ystem.err.println("Required = " + v); 657 if(v.equalsIgnoreCase("yes")) { 658 ///ystem.err.println("Setting required to true."); 659 argument.setRequired(true); 660 } 661 } 662 } 663 classifier.addArgument(argument); 664 } 665 // A super classifier class. 666 else if(node_name.equals("ClasInfo")) { 667 Classifier super_classifier = parse(arg); 668 classifier.setSuper(super_classifier); 669 } 670 } 671 } 672 } 673 if(classifier.getName() != null) { 674 addClassifier(classifier); 675 return classifier; 676 } 677 return null; 678 } 679 /** A class which provides controls for assigned and editing classifiers. */ 680 private class Control 681 extends JPanel { 682 /** Button for adding classifiers. */ 683 private JButton add = null; 684 /** Button for configuring the selected classifier. */ 685 private JButton configure = null; 686 /** Button to remove the selected classifier. */ 687 private JButton remove = null; 688 /** A combobox containing all of the known classifiers, including those that may have already been assigned. */ 689 private JComboBox classifier = null; 690 /** A list of assigned classifiers. */ 691 private JList classifier_list = null; 692 /** The text area containing instructions on the use of this control. */ 693 private JTextArea instructions = null; 694 /** Constructor. 695 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.AddListener 696 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.ConfigureListener 697 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.RemoveListener 661 } 662 } 663 classifier.addArgument(argument); 664 } 665 // A super classifier class. 666 else if(node_name.equals("ClasInfo")) { 667 Classifier super_classifier = parse(arg); 668 classifier.setSuper(super_classifier); 669 } 670 } 671 } 672 } 673 if(classifier.getName() != null) { 674 addClassifier(classifier); 675 return classifier; 676 } 677 return null; 678 } 679 /** A class which provides controls for assigned and editing classifiers. */ 680 private class Control 681 extends JPanel { 682 /** Button for adding classifiers. */ 683 private JButton add = null; 684 /** Button for configuring the selected classifier. */ 685 private JButton configure = null; 686 /** Button to remove the selected classifier. */ 687 private JButton remove = null; 688 /** A combobox containing all of the known classifiers, including those that may have already been assigned. */ 689 private JComboBox classifier = null; 690 /** A list of assigned classifiers. */ 691 private JList classifier_list = null; 692 /** The text area containing instructions on the use of this control. */ 693 private JTextArea instructions = null; 694 /** Constructor. 695 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.AddListener 696 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.ConfigureListener 697 * @see org.greenstone.gatherer.cdm.ClassifierManager.Control.RemoveListener 698 */ 699 public Control() { 700 Object classifiers[] = reserve.toArray(); 701 ArrayList classifier_model = new ArrayList(); 702 for(int i = 0; i < classifiers.length; i++) { 703 classifier_model.add(((Classifier)classifiers[i]).getName()); 704 } 705 // Now we add custom classifiers. 706 addCustomClassifiers(classifier_model); 707 Collections.sort(classifier_model); 708 // Create 709 add = new JButton(get("Add")); 710 JPanel button_pane = new JPanel(); 711 JPanel central_pane = new JPanel(); 712 configure = new JButton(get("Configure")); 713 JPanel header_pane = new JPanel(); 714 instructions = new JTextArea(get("Instructions")); 715 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 716 instructions.setEditable(false); 717 instructions.setLineWrap(true); 718 instructions.setRows(5); 719 instructions.setWrapStyleWord(true); 720 classifier = new JComboBox(classifier_model.toArray()); 721 classifier.setEditable(true); 722 JLabel classifier_label = new JLabel(get("Classifier")); 723 classifier_list = new JList(assigned); 724 JLabel classifier_list_label = new JLabel(get("Assigned")); 725 classifier_list_label.setHorizontalAlignment(JLabel.CENTER); 726 classifier_list_label.setOpaque(true); 727 JPanel classifier_list_pane = new JPanel(); 728 JPanel classifier_pane = new JPanel(); 729 remove = new JButton(get("Remove")); 730 JLabel title = new JLabel(get("Title")); 731 title.setHorizontalAlignment(JLabel.CENTER); 732 title.setOpaque(true); 733 JPanel temp = new JPanel(new BorderLayout()); 734 // Listeners 735 add.addActionListener(new AddListener()); 736 configure.addActionListener(new ConfigureListener()); 737 remove.addActionListener(new RemoveListener()); 738 classifier_list.addMouseListener(new ClickListener()); 739 // Layout 740 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0)); 741 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 742 header_pane.setLayout(new BorderLayout()); 743 header_pane.add(title, BorderLayout.NORTH); 744 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 745 classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2)); 746 classifier_list_pane.setLayout(new BorderLayout()); 747 classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH); 748 classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER); 749 classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 750 classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 751 classifier_pane.setLayout(new GridLayout(1,2)); 752 classifier_pane.add(classifier_label); 753 classifier_pane.add(classifier); 754 button_pane.setLayout(new GridLayout(3,1)); 755 button_pane.add(add); 756 button_pane.add(configure); 757 button_pane.add(remove); 758 // Scope these mad bordering skillz. 759 temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Controls")), BorderFactory.createEmptyBorder(2,2,2,2)))); 760 temp.add(classifier_pane, BorderLayout.NORTH); 761 temp.add(button_pane, BorderLayout.SOUTH); 762 central_pane.setLayout(new BorderLayout()); 763 central_pane.add(classifier_list_pane, BorderLayout.CENTER); 764 central_pane.add(temp, BorderLayout.SOUTH); 765 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 766 setLayout(new BorderLayout()); 767 add(header_pane, BorderLayout.NORTH); 768 add(central_pane, BorderLayout.CENTER); 769 } 770 /** Method which acts like a destructor, tidying up references to persistant objects. 698 771 */ 699 public Control() { 700 Object classifiers[] = reserve.toArray(); 701 ArrayList classifier_model = new ArrayList(); 702 for(int i = 0; i < classifiers.length; i++) { 703 classifier_model.add(((Classifier)classifiers[i]).getName()); 704 } 705 // Now we add custom classifiers. 706 addCustomClassifiers(classifier_model); 707 Collections.sort(classifier_model); 708 // Create 709 add = new JButton(get("Add")); 710 JPanel button_pane = new JPanel(); 711 JPanel central_pane = new JPanel(); 712 configure = new JButton(get("Configure")); 713 JPanel header_pane = new JPanel(); 714 instructions = new JTextArea(get("Instructions")); 715 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 716 instructions.setEditable(false); 717 instructions.setLineWrap(true); 718 instructions.setRows(5); 719 instructions.setWrapStyleWord(true); 720 classifier = new JComboBox(classifier_model.toArray()); 721 classifier.setEditable(true); 722 JLabel classifier_label = new JLabel(get("Classifier")); 723 classifier_list = new JList(assigned); 724 JLabel classifier_list_label = new JLabel(get("Assigned")); 725 classifier_list_label.setHorizontalAlignment(JLabel.CENTER); 726 classifier_list_label.setOpaque(true); 727 JPanel classifier_list_pane = new JPanel(); 728 JPanel classifier_pane = new JPanel(); 729 remove = new JButton(get("Remove")); 730 JLabel title = new JLabel(get("Title")); 731 title.setHorizontalAlignment(JLabel.CENTER); 732 title.setOpaque(true); 733 JPanel temp = new JPanel(new BorderLayout()); 734 // Listeners 735 add.addActionListener(new AddListener()); 736 configure.addActionListener(new ConfigureListener()); 737 remove.addActionListener(new RemoveListener()); 738 classifier_list.addMouseListener(new ClickListener()); 739 // Layout 740 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0)); 741 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 742 header_pane.setLayout(new BorderLayout()); 743 header_pane.add(title, BorderLayout.NORTH); 744 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 745 classifier_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2)); 746 classifier_list_pane.setLayout(new BorderLayout()); 747 classifier_list_pane.add(classifier_list_label, BorderLayout.NORTH); 748 classifier_list_pane.add(new JScrollPane(classifier_list), BorderLayout.CENTER); 749 classifier_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 750 classifier_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 751 classifier_pane.setLayout(new GridLayout(1,2)); 752 classifier_pane.add(classifier_label); 753 classifier_pane.add(classifier); 754 button_pane.setLayout(new GridLayout(3,1)); 755 button_pane.add(add); 756 button_pane.add(configure); 757 button_pane.add(remove); 758 // Scope these mad bordering skillz. 759 temp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,0,5,0), BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Controls")), BorderFactory.createEmptyBorder(2,2,2,2)))); 760 temp.add(classifier_pane, BorderLayout.NORTH); 761 temp.add(button_pane, BorderLayout.SOUTH); 762 central_pane.setLayout(new BorderLayout()); 763 central_pane.add(classifier_list_pane, BorderLayout.CENTER); 764 central_pane.add(temp, BorderLayout.SOUTH); 765 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 766 setLayout(new BorderLayout()); 767 add(header_pane, BorderLayout.NORTH); 768 add(central_pane, BorderLayout.CENTER); 769 } 770 /** Method which acts like a destructor, tidying up references to persistant objects. 772 public void destroy() { 773 add = null; 774 classifier = null; 775 classifier_list = null; 776 configure = null; 777 instructions = null; 778 remove = null; 779 } 780 /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called. 771 781 */ 772 public void destroy() { 773 add = null; 774 classifier = null; 775 classifier_list = null; 776 configure = null; 777 instructions = null; 778 remove = null; 779 } 780 /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called. 781 */ 782 public void updateUI() { 783 if(instructions != null) { 784 instructions.setCaretPosition(0); 785 } 786 super.updateUI(); 787 } 788 /** Searches and adds a list of dynamically located CustomClassifiers. Note that the classes must be located under org.greenstone.gatherer.cdm.custom and have accompaning properties files which are used as dictionaries. 782 public void updateUI() { 783 if(instructions != null) { 784 instructions.setCaretPosition(0); 785 } 786 super.updateUI(); 787 } 788 /** Searches and adds a list of dynamically located CustomClassifiers. Note that the classes must be located under org.greenstone.gatherer.cdm.custom and have accompaning properties files which are used as dictionaries. 789 789 * @param classifier_model An <strong>ArrayList</strong> which will be used as the model for the combobox listing all known Classifiers. 790 790 */ 791 791 private void addCustomClassifiers(ArrayList classifier_model) { 792 792 //classifier_model.add("CustomAZList"); 793 793 // Search for classifiers under the org.greenstone.gatherer.cdm.custom directory. 794 795 796 797 798 799 800 801 802 803 804 805 806 807 794 File custom_directory = new File(Utility.BASE_DIR + "classes" + File.separator + "org" + File.separator + "greenstone" + File.separator + "gatherer" + File.separator + "cdm" + File.separator + "custom"); 795 if(custom_directory.exists()) { 796 File children[] = custom_directory.listFiles(); 797 for(int i = 0; i < children.length; i++) { 798 String temp = children[i].getName().toLowerCase(); 799 // There are a whole bunch of conditions about what files are custom classifier main classes. 800 if(temp.endsWith(".class") && temp.indexOf("$") == -1) { 801 // Determine the name of this custom classifier. 802 String name = children[i].getName(); 803 name = name.substring(0, name.indexOf(".")); 804 classifier_model.add(name); 805 } 806 } 807 } 808 808 // Search for any other CustomClassifiers within the jar file (if present) 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 809 File jar_file = new File("Gatherer.jar"); 810 if(jar_file.exists()) { 811 try { 812 JarFile jar = new JarFile(jar_file); 813 for(Enumeration entries = jar.entries(); entries.hasMoreElements(); ) { 814 String name = entries.nextElement().toString(); 815 if(name.startsWith("org/greenstone/gatherer/cdm/custom/") && name.endsWith(".class") && name.indexOf("$") == -1) { 816 name = name.substring(35, name.length() - 6); 817 if(!classifier_model.contains(name)) { 818 classifier_model.add(name); 819 } 820 } 821 name = null; 822 } 823 jar = null; 824 } 825 catch (Exception error) { 826 error.printStackTrace(); 827 } 828 } 829 jar_file = null; 830 } 831 /** This class listens for actions upon the add button in the controls, and if detected calls the assignClassifier() method. 832 832 */ 833 834 833 private class AddListener 834 implements ActionListener { 835 835 /** Any implementation of ActionListener must include this method so that we can be informed when an action has occured on one of our target controls, so that we can add the selected Classifier. 836 836 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. … … 840 840 * @see org.greenstone.gatherer.cdm.CustomClassifier 841 841 */ 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 842 public void actionPerformed(ActionEvent event) { 843 String name = (String)classifier.getSelectedItem(); 844 Classifier target = getClassifier(name); 845 Classifier classifier = null; 846 CustomClassifier custom_classifier = null; 847 if(target != null) { 848 classifier = target.copy(); 849 } 850 else { 851 // Try to retrieve custom classifier for name. 852 try { 853 Class custom_class = Class.forName("org.greenstone.gatherer.cdm.custom." + name); 854 custom_classifier = (CustomClassifier)custom_class.newInstance(); 855 custom_classifier.setGatherer(gatherer); 856 } 857 catch (Exception error) { 858 gatherer.debug(error, "Error in ClassifierManager.AddListener.actionPerformed(): " + error); 859 } 860 // And if all else fails create a new classifier. 861 if(classifier == null && custom_classifier == null) { 862 classifier = new Classifier(name, "", null); 863 } 864 } 865 if(classifier != null) { 866 // Automatically chain to configuration. This ensures required arguments are filled out. 867 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, classifier); 868 if(ac.display()) { 869 assignClassifier(classifier); 870 } 871 ac.destroy(); 872 ac = null; 873 } 874 // Custom classifier 875 else { 876 if(custom_classifier.display(true)) { 877 assignClassifier(custom_classifier); 878 } 879 custom_classifier.destroy(); // Remove gui prompt or else. 880 custom_classifier = null; 881 } 882 } 883 } 884 /** Listens for double clicks apon the list and react as if the configure button was pushed. */ 885 private class ClickListener 886 extends MouseAdapter { 887 887 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt. 888 888 * @param event A <strong>MouseEvent</strong> containing information about the mouse click. 889 889 */ 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 890 public void mouseClicked(MouseEvent event) { 891 if(event.getClickCount() == 2 ) { 892 if(!classifier_list.isSelectionEmpty()) { 893 Object object = classifier_list.getSelectedValue(); 894 if(object instanceof Classifier) { 895 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object); 896 if(ac.display()) { 897 assigned.refresh(); 898 } 899 ac.destroy(); 900 ac = null; 901 } 902 else if(object instanceof CustomClassifier) { 903 CustomClassifier cc = (CustomClassifier)object; 904 if(cc.display(true)) { 905 assigned.refresh(); 906 } 907 cc.destroy(); // Remove gui prompt or else. 908 cc = null; 909 } 910 } 911 } 912 } 913 } 914 /** This class listens for actions upon the configure button in the controls, and if detected creates a new ArgumentConfiguration dialog box to allow for configuration. 915 915 */ 916 917 916 private class ConfigureListener 917 implements ActionListener { 918 918 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 919 919 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. … … 922 922 * @see org.greenstone.gatherer.cdm.CustomClassifier 923 923 */ 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 924 public void actionPerformed(ActionEvent event) { 925 if(!classifier_list.isSelectionEmpty()) { 926 Object object = classifier_list.getSelectedValue(); 927 if(object instanceof Classifier) { 928 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (Classifier)object); 929 if(ac.display()) { 930 assigned.refresh(); 931 } 932 ac.destroy(); 933 ac = null; 934 } 935 else if(object instanceof CustomClassifier) { 936 CustomClassifier cc = (CustomClassifier)object; 937 if(cc.display(true)) { 938 assigned.refresh(); 939 } 940 cc.destroy(); // Remove gui prompt or else. 941 cc = null; 942 } 943 } 944 } 945 } 946 /** This class listens for actions upon the remove button in the controls, and if detected calls the removeClassifier() method. 947 947 */ 948 949 948 private class RemoveListener 949 implements ActionListener { 950 950 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls, so we can remove the selected Classifier. 951 951 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. … … 953 953 * @see org.greenstone.gatherer.cdm.CustomClassifier 954 954 */ 955 956 957 958 959 960 961 962 963 964 955 public void actionPerformed(ActionEvent event) { 956 if(!classifier_list.isSelectionEmpty()) { 957 Object object = classifier_list.getSelectedValue(); 958 if(object instanceof Classifier || object instanceof CustomClassifier) { 959 removeClassifier(object); 960 } 961 } 962 } 963 } 964 } 965 965 } 966 966 -
trunk/gli/src/org/greenstone/gatherer/cdm/CollectionDesignManager.java
r4293 r4366 84 84 // #################################################################################### 85 85 public class CollectionDesignManager { 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 86 /** Whether this collection is to be made public or not. */ 87 public boolean public_col = false; 88 /** Whether this collection is a beta version or not. */ 89 public boolean beta = true; 90 /** A list of classifiers to use at build time. */ 91 public ClassifierManager classifiers = null; 92 /** A manager of collection level metadata. */ 93 public CollectionMetaManager collectionmetadatum = null; 94 /** E-mail address of the collection's creator. */ 95 public EmailAddress creator = null; 96 /** E-mail address of the collection's maintainer. */ 97 public EmailAddress maintainer = null; 98 /** The collection configuration file. */ 99 public File in_file = null; 100 /** A list of formating strings to use at build time. */ 101 public FormatManager formats = null; 102 /** The manager in charge of displaying this manager and the controls for other managers. */ 103 public GUI gui = null; 104 /** List of indexes to be built, and the default index. */ 105 public IndexManager indexes = null; 106 /** Contains instructions dealing with the collection language. */ 107 public LanguageManager languages = null; 108 /** A simple manager for the visual review of metadata sets. */ 109 public MetadataSetManager metadatasets = null; 110 /** A list of plugins to use at build time. */ 111 public PlugInManager plugins = null; 112 /** Contains: A list of subcollections, (defined on metadatadata), a list of which subcollection indexes to build and the default subcollection index. */ 113 public SubcollectionManager subcollections = null; 114 /** A list of whatever commands could not be parsed at all. */ 115 private ArrayList rest = null; 116 /** A reference to the Gatherer. */ 117 private Gatherer gatherer = null; 118 /** Constructor. 119 * @param gatherer The <strong>Gatherer</strong> that created this class. 120 * @see org.greenstone.gatherer.cdm.ClassifierManager 121 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 122 * @see org.greenstone.gatherer.cdm.FormatManager 123 * @see org.greenstone.gatherer.cdm.IndexManager 124 * @see org.greenstone.gatherer.cdm.LanguageManager 125 * @see org.greenstone.gatherer.cdm.MetadataSetManager 126 * @see org.greenstone.gatherer.cdm.PlugInManager 127 * @see org.greenstone.gatherer.cdm.SubcollectionManager 128 */ 129 public CollectionDesignManager() { 130 this.gatherer = Gatherer.self; 131 this.classifiers = new ClassifierManager(gatherer, this); 132 this.collectionmetadatum = new CollectionMetaManager(gatherer, this); 133 this.formats = new FormatManager(gatherer, this); 134 this.indexes = new IndexManager(gatherer, this); 135 this.languages = new LanguageManager(gatherer, this); 136 this.metadatasets = new MetadataSetManager(gatherer); 137 this.plugins = new PlugInManager(gatherer, this); 138 this.rest = new ArrayList(); 139 this.subcollections = new SubcollectionManager(gatherer); 140 } 141 /** In order to prevent Components that have registered themselves wasting memory, this method invalidates each of the sub-managers controls, causing them to unregister listeners. 142 * @see org.greenstone.gatherer.cdm.ClassifierManager 143 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 144 * @see org.greenstone.gatherer.cdm.FormatManager 145 * @see org.greenstone.gatherer.cdm.IndexManager 146 * @see org.greenstone.gatherer.cdm.LanguageManager 147 * @see org.greenstone.gatherer.cdm.MetadataSetManager 148 * @see org.greenstone.gatherer.cdm.PlugInManager 149 * @see org.greenstone.gatherer.cdm.SubcollectionManager 150 */ 151 public void destroy() { 152 // Remove visual the component from its parent. 153 if(gui.getParent() != null) { 154 gui.getParent().remove(gui); 155 } 156 // Remove references from persistant listeners. 157 if(classifiers != null && formats != null && gui != null && indexes != null && languages != null && metadatasets != null && plugins != null && subcollections != null) { 158 classifiers.invalidateControls(); 159 formats.invalidateControls(); 160 gui.invalidateControls(); 161 indexes.invalidateControls(); 162 languages.invalidateControls(); 163 metadatasets.invalidateControls(); 164 plugins.invalidateControls(); 165 subcollections.invalidateControls(); 166 } 167 // Null globals. 168 classifiers = null; 169 collectionmetadatum = null; 170 creator = null; 171 maintainer = null; 172 in_file = null; 173 formats = null; 174 gui = null; 175 indexes = null; 176 languages = null; 177 metadatasets = null; 178 plugins = null; 179 subcollections = null; 180 rest = null; 181 gatherer = null; 182 } 183 184 /** Display the GUI interface for the CollectionDesignManager in the centre of the indicated panel. 185 * @param target The <strong>JPanel</strong> you wish to display the GUI on. 186 * @see org.greenstone.gatherer.cdm.GUI 187 */ 188 public void display(JPanel target) { 189 this.gui = new GUI(gatherer, this); 190 target.add(gui, BorderLayout.CENTER); 191 } 192 /** When the tab on the JTabbedPane that contains the GUI is selected, this method is called to ensure that the controls are all up to date, in terms of references to metadata etc. 193 * @see org.greenstone.gatherer.cdm.GUI 194 */ 195 public void gainFocus() { 196 gui.updateUI(); 197 } 198 /** Retrieve the current set of indexes as defined by the user configuration. 199 * @return An <strong>ArrayList</strong> of indexes. 200 * @see org.greenstone.gatherer.cdm.Index 201 * @see org.greenstone.gatherer.cdm.IndexManager 202 */ 203 public ArrayList getIndexes() { 204 ArrayList result = new ArrayList(); 205 int size = indexes.size(); 206 for(int i = 0; i < size; i++) { 207 result.add(indexes.getIndex(i)); 208 } 209 return result; 210 } 211 /** Retrieve the name of the collection configuration file which is being used as the source of the information in this object. 212 * @return The files absolute path as a <strong>String</strong>. 213 */ 214 public String getFilename() { 215 return in_file.getAbsolutePath(); 216 } 217 /** Used to parse the given file as if it was a collection configuration file, passing any parsed commands to the relevant submanager. Currently ignores any comments, and marks any other lines as being unrecognizable if they can't be parsed. 218 * @param filename The name of the file you wish to attempt to pass as a <strong>String</strong>. 219 * @see org.greenstone.gatherer.cdm.ClassifierManager 220 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 221 * @see org.greenstone.gatherer.cdm.FormatManager 222 * @see org.greenstone.gatherer.cdm.IndexManager 223 * @see org.greenstone.gatherer.cdm.LanguageManager 224 * @see org.greenstone.gatherer.cdm.MetadataSetManager 225 * @see org.greenstone.gatherer.cdm.PlugInManager 226 * @see org.greenstone.gatherer.cdm.SubcollectionManager 227 * @see org.greenstone.gatherer.util.EmailAddress 228 */ 229 public void parse(String filename) { 230 try { 231 in_file = new File(filename); 232 FileReader in_reader = new FileReader(in_file); 233 BufferedReader in = new BufferedReader(in_reader); 234 String command = null; 235 while((command = in.readLine()) != null) { 236 if(command.length() > 0) { 237 // We have to test the end of command for the special character '\'. If found, remove it and append the next line, then repeat. 238 while(command.trim().endsWith("\\")) { 239 command = command.substring(0, command.lastIndexOf("\\")); 240 String next_line = in.readLine(); 241 if(next_line != null) { 242 command = command + next_line; 243 } 244 } 245 // Now we've finished parsing a command line, see what manager wants a piece of it. 246 boolean found = false; 247 String command_lc = command.toLowerCase(); 248 if(command_lc.startsWith("creator")) { 249 creator = new EmailAddress(gatherer, command); 250 found = true; 251 } 252 if(command_lc.startsWith("maintainer")) { 253 maintainer = new EmailAddress(gatherer, command); 254 found = true; 255 } 256 if(command_lc.startsWith("public")) { 257 if(command_lc.endsWith("true")) { 258 public_col = true; 259 } 260 else { 261 public_col = false; 262 } 263 found = true; 264 } 265 if(command_lc.startsWith("beta")) { 266 if(command_lc.endsWith("false")) { 267 beta = false; 268 } 269 else { 270 beta = true; 271 } 272 found = true; 273 } 274 if(!found) { 275 found = indexes.parse(command); 276 } 277 if(!found) { 278 found = subcollections.parse(command, false); 279 } 280 if(!found) { 281 found = languages.parse(command); 282 } 283 if(!found) { 284 found = plugins.parse(command); 285 } 286 if(!found) { 287 found = classifiers.parse(command); 288 } 289 if(!found) { 290 found = formats.parse(command, false); 291 } 292 if(!found) { 293 found = collectionmetadatum.parse(command, false); 294 } 295 // Metadataset commands 296 if(command_lc.startsWith("metadataset")) { 297 // Nothing yet. Eventually used to import metadata. 298 found = true; 299 } 300 // Comments we ignore. 301 if(command_lc.startsWith("# these instructions are not recognized by the gatherer.")) { 302 // Ignore 303 found = true; 304 } 305 // We have been unable to parse this command, add it to rest. 306 if(!found) { 307 rest.add(command); 308 } 309 } 310 } 311 in.close(); 312 312 // Now attempt to finalize any commands that were not immediately parsed as they were waiting for unresolved references. 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 313 subcollections.reparseUnresolved(); 314 classifiers.reparseUnresolved(); 315 formats.reparseUnresolved(); 316 collectionmetadatum.reparseUnresolved(); 317 } 318 catch(Exception error) { 319 error.printStackTrace(); 320 } 321 } 322 /** Cause the current definitions within the Collection Design Manager to be written back out to whatever collect.cfg it is based upon, taking care to change reference pointers into something more sensible within the text file. 323 * @see org.greenstone.gatherer.cdm.ClassifierManager 324 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 325 * @see org.greenstone.gatherer.cdm.FormatManager 326 * @see org.greenstone.gatherer.cdm.IndexManager 327 * @see org.greenstone.gatherer.cdm.LanguageManager 328 * @see org.greenstone.gatherer.cdm.MetadataSetManager 329 * @see org.greenstone.gatherer.cdm.PlugInManager 330 * @see org.greenstone.gatherer.cdm.SubcollectionManager 331 * @see org.greenstone.gatherer.util.EmailAddress 332 */ 333 public void save() { 334 try { 335 335 // If the file already exists (it should) rename it. 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 336 if(in_file.exists()) { 337 String filename = in_file.getAbsolutePath(); 338 File backup = new File(filename + "~"); 339 backup.deleteOnExit(); 340 if(!in_file.renameTo(backup)) { 341 gatherer.debug("Error in CollectionDesignManager.parse(): FileRenamedException"); 342 } 343 in_file = new File(filename); // Just in case we moved it. 344 } 345 FileOutputStream out = new FileOutputStream(in_file); 346 347 StringBuffer text = new StringBuffer(""); 348 if(creator != null) { 349 text.append(creator.toString()); 350 text.append("\n"); 351 } 352 if(maintainer != null) { 353 text.append(maintainer.toString()); 354 text.append("\n"); 355 } 356 if(public_col) { 357 text.append("public true\n"); 358 } 359 else { 360 text.append("public false\n"); 361 } 362 if(beta) { 363 text.append("beta true\n"); 364 } 365 else { 366 text.append("beta false\n"); 367 } 368 if(text.length() > 0) { 369 text.append("\n"); 370 } 371 if(indexes.size() > 0) { 372 text.append(indexes.toString()); 373 } 374 if(subcollections.size() > 0) { 375 text.append(subcollections.toString()); 376 } 377 if(languages.size() > 0) { 378 text.append(languages.toString()); 379 } 380 if(plugins.size() > 0) { 381 text.append(plugins.toString()); 382 } 383 if(classifiers.size() > 0) { 384 text.append(classifiers.toString()); 385 } 386 if(formats.size() > 0) { 387 text.append(formats.toString()); 388 } 389 if(collectionmetadatum.size() > 0) { 390 text.append(collectionmetadatum.toString()); 391 } 392 text.append(metadatasets.toString()); 393 if(rest.size() > 0) { 394 // Write out rest at the bottom. 395 text.append("# These instructions are not recognized by the Gatherer.\n"); 396 for(int i = 0; i < rest.size(); i++) { 397 text.append(rest.get(i)); 398 text.append("\n"); 399 } 400 } 401 out.write(text.toString().getBytes()); 402 out.close(); 403 out = null; 404 } 405 catch(Exception error) { 406 error.printStackTrace(); 407 } 408 } 409 /** Method used during a global search and replace to highlight the appropriate record within the Collection Design Managers version of the Metadata Set Manager (view only). 410 * @param element The name of the desired element as a <strong>String</strong>. 411 * @see org.greenstone.gatherer.cdm.GUI 412 * @see org.greenstone.gatherer.cdm.MetadataSetManager 413 */ 414 public Rectangle setSelectedElement(String element) { 415 // First ensure that the metadata set controls are visible. 416 gui.setSelectedView("CDM.GUI.MetadataSets"); 417 // Then tell them to select the given element. 418 return metadatasets.setSelectedElement(element); 419 } 420 420 } -
trunk/gli/src/org/greenstone/gatherer/cdm/CollectionMeta.java
r4293 r4366 59 59 */ 60 60 public class CollectionMeta 61 62 63 64 65 66 67 68 69 70 71 72 73 61 implements Comparable { 62 /** A reference to the collection design manager for access to the language manager. */ 63 private CollectionDesignManager manager = null; 64 /** The language of this metadata. Should be a two letter code. */ 65 private Language language = null; 66 /** The name of the thing this metadata is assigned to, which may index an Index. */ 67 private Object name = null; 68 /** The value of this metadata. */ 69 private String value = null; 70 /** Constructor. 71 * @param name The object the metadata is assigned to as an <strong>Object</strong>. 72 * @param language The language of the metadata as a <strong>Language</strong>. Should be a two letter code. 73 * @param value The value of this metadata, as a <strong>String</strong>. 74 74 */ 75 76 77 78 79 80 81 75 public CollectionMeta(CollectionDesignManager manager, Object name, Language language, String value) { 76 this.language = language; 77 this.manager = manager; 78 this.name = name; 79 this.value = value; 80 } 81 /** Method to compare two collection metadata objects to calculate their respective ordering. 82 82 * @param object The other metadata to compare to, as an <strong>Object</strong>. 83 83 * @return An <i>int</i> which is less than 0 if this object proceeds the given object, 0 if they are equal and greater than 0 otherwise. 84 84 * @see org.greenstone.gatherer.cdm.Language 85 85 */ 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 86 public int compareTo(Object object) { 87 if(object instanceof CollectionMeta) { 88 CollectionMeta metadata = (CollectionMeta) object; 89 int result = name.toString().compareTo(metadata.getName().toString()); 90 if(result == 0) { 91 Language other_language = metadata.getLanguage(); 92 if(language != null && other_language != null) { 93 result = language.compareTo(metadata.getLanguage()); 94 if(result == 0) { 95 return value.compareTo(metadata.getValue()); 96 } 97 } 98 else if(language != null) { 99 return -1; 100 } 101 else if(other_language != null) { 102 return 1; 103 } 104 } 105 return result; 106 } 107 return toString().compareTo(object.toString()); 108 } 109 /** Method to compare two collection metadata objects for equality. 110 110 * @param object The other metadata to compare to, as an <strong>Object</strong>. 111 111 * @return A <i>boolean</i> value of <i>true</i> if the object are equal, <i>false</i> otherwise. 112 112 */ 113 114 115 116 117 118 119 113 public boolean equals(Object object) { 114 if(compareTo(object) == 0) { 115 return true; 116 } 117 return false; 118 } 119 /** Method to retrieve the value of language. 120 120 * @return The value of language as a <strong>Language</strong>. 121 121 */ 122 123 124 125 122 public Language getLanguage() { 123 return language; 124 } 125 /** Method to retrieve the value of name. 126 126 * @return The value of name as an <strong>Object</strong>. 127 127 */ 128 129 130 131 128 public Object getName() { 129 return name; 130 } 131 /** Method to retrieve the value of value (well great choice of name there). 132 132 * @return The value of value as a <strong>String</strong>. 133 133 */ 134 135 136 137 134 public String getValue() { 135 return value; 136 } 137 /** Method to print out this class as it would appear within the collection configuration file. 138 138 * @return A <strong>String</strong> containing the text value of this class. 139 139 */ 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 140 public String toString() { 141 String text = "collectionmeta "; 142 if(name instanceof Index) { 143 text = text + "."; 144 Index index = (Index)name; 145 text = text + index.toString(false) + " "; 146 } 147 else { 148 text = text + name.toString() + " "; 149 } 150 if(language != null && manager.languages.size() > 0 && !manager.languages.isDefaultLanguage(language)) { 151 text = text + "[l=" + language.getCode() + "] "; 152 } 153 text = text + "\"" + Utility.encodeGreenstone(value) + "\"\n"; 154 return text; 155 } 156 /** Used to update the contents of this collection level metadata to the given 'new' values. 157 157 * @param name The new name of the metadata, as a <strong>Object</strong>. 158 158 * @param language The new <strong>Language</strong> of the metadata. 159 159 * @param value And the value the metadata is assigned, as a <strong>String</strong>. 160 160 */ 161 162 163 164 165 166 161 public void update(Object name, Language language, String value) { 162 this.name = name; 163 this.language = language; 164 this.value = value; 165 } 166 /** Ensure this is a valid metadata entry by checking that the value is non-null and non-zero length (after having removed whitespace). 167 167 * @return <i>true</i> if this metadata has a valid value and should be added to the config, <i>false</i> otherwise. 168 168 */ 169 170 171 169 public boolean valid() { 170 return(value != null && value.trim().length() > 0); 171 } 172 172 } 173 173 -
trunk/gli/src/org/greenstone/gatherer/cdm/CollectionMetaManager.java
r4293 r4366 95 95 // #################################################################################### 96 96 public class CollectionMetaManager 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 97 extends DefaultListModel { 98 /** A reference to the cdm manager so we can access indexes and languages. */ 99 private CollectionDesignManager manager = null; 100 /** A reference to ourself so that inner classes can use us as a model. */ 101 private DefaultListModel model = null; 102 /** A reference to the Gatherer. */ 103 private Gatherer gatherer = null; 104 /** The language the most recent metadata returned was in. */ 105 private Language current_language = null; 106 /** We can't safely parse metadata commands until after all the other commands have been parsed, so we store commands here for now. */ 107 private ArrayList unresolved_commands = null; 108 /** Constructor. 109 * @param gatherer A reference to the <strong>Gatherer</strong>. 110 * @param manager A reference to the <strong>CollectionDesignManager</strong> for access to other configuration managers. 111 */ 112 public CollectionMetaManager(Gatherer gatherer, CollectionDesignManager manager) { 113 super(); 114 this.gatherer = gatherer; 115 this.manager = manager; 116 this.model = this; 117 this.unresolved_commands = new ArrayList(); 118 } 119 /** Method to add a new piece of metadata. 120 120 * @param metadata The new <strong>CollectionMeta</strong>. 121 121 */ 122 123 124 125 126 127 128 129 130 122 public void addMetadata(CollectionMeta metadata) { 123 CollectionMeta existing = getMetadata(metadata.getName().toString(), metadata.getLanguage(), false); 124 if(existing != null) { 125 removeElement(existing); 126 } 127 addElement(metadata); 128 gatherer.c_man.configurationChanged(); 129 } 130 /** Retrieve the collectionextra metadata in the default language, if present. 131 131 * @return A <strong>CollectionMeta</strong> containing the collectionextra in the default language if present, or else the first collectionextra of any language, otherwise <i>null</i>. 132 132 * @see org.greenstone.gatherer.cdm.Language 133 133 */ 134 135 136 137 138 139 140 141 142 134 public CollectionMeta getCollectionExtra() { 135 CollectionMeta result = getMetadata("collectionextra", manager.languages.getDefaultLanguage(), true); 136 if(result == null) { 137 result = new CollectionMeta(manager, "collectionextra", manager.languages.getDefaultLanguage(), ""); 138 addMetadata(result); 139 } 140 return result; 141 } 142 /** Retrieve the collectionname metadata in the default language, if present. 143 143 * @return A <strong>CollectionMeta</strong> containing the collectionname in the default language if present, or else the first collectionname of any language, otherwise <i>null</i>. 144 144 * @see org.greenstone.gatherer.cdm.Language 145 145 */ 146 147 148 149 146 public CollectionMeta getCollectionName() { 147 return getMetadata("collectionname", manager.languages.getDefaultLanguage(), true); 148 } 149 /** Retrieve the iconcollection metadata in the default language, if present. 150 150 * @return A <strong>CollectionMeta</strong> containing the iconcollection in the default language if present, or else the first iconcollection of any language, otherwise <i>null</i>. 151 151 * @see org.greenstone.gatherer.cdm.Language 152 152 */ 153 154 155 156 157 158 159 160 161 153 public CollectionMeta getIconCollection() { 154 CollectionMeta result = getMetadata("iconcollection", manager.languages.getDefaultLanguage(), true); 155 if(result == null) { 156 result = new CollectionMeta(manager, "iconcollection", manager.languages.getDefaultLanguage(), ""); 157 addMetadata(result); 158 } 159 return result; 160 } 161 /** Method to retrieve the list of metadata. 162 162 * @return An <strong>ArrayList</strong> containing the metadata. 163 163 */ 164 165 166 167 168 169 170 171 164 public ArrayList getMetadata() { 165 ArrayList metadata = new ArrayList(); 166 for(int i = 0; i < size(); i++) { 167 metadata.add(get(i)); 168 } 169 Collections.sort(metadata); 170 return metadata; 171 } 172 172 173 174 175 176 177 178 179 180 181 182 183 184 173 /** Retrieve all of the metadata for the given feature, regardless of language. */ 174 public ArrayList getMetadata(String name) { 175 ArrayList result = new ArrayList(); 176 for(int i = 0; i < size(); i++) { 177 CollectionMeta metadata = (CollectionMeta) get(i); 178 if(metadata.getName().equals(name)) { 179 result.add(metadata); 180 } 181 } 182 return result; 183 } 184 /** Method to retrieve a certain piece of metadata based on its name and language. 185 185 * @param name The name of the metadata as a <strong>String</strong>. 186 186 * @param language The <strong>Language</strong> of the metadata. … … 188 188 * @return The <strong>CollectionMeta</strong> requested, or <i>null</i> if no such metadata. 189 189 */ 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 190 public CollectionMeta getMetadata(String name, Language language, boolean partial) { 191 CollectionMeta partial_match = null; 192 for(int i = 0; i < size(); i++) { 193 CollectionMeta metadata = (CollectionMeta) get(i); 194 if(metadata.getName().equals(name)) { 195 if (metadata.getLanguage().equals(language)) { 196 return metadata; 197 } 198 partial_match = metadata; 199 } 200 } 201 if(partial) { 202 return partial_match; 203 } 204 return null; 205 } 206 /** Method that attempts to parse a collection metadata command from the given text. If a command is parsed successfully it is immediately added to the the collections metadata. 207 207 * @param command The command text we wish to parse, as a <strong>String</strong>. 208 208 * @return A <i>boolean</i> which is <i>true</i> if a collection metadata command was successfully parsed, <i>false</i> otherwise. … … 213 213 * @see org.greenstone.gatherer.util.Utility 214 214 */ 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 215 public boolean parse(String command, boolean finished) { 216 String temp = command.toLowerCase(); 217 if(temp.startsWith("collectionmeta")) { 218 if(finished) { 219 CommandTokenizer ct = new CommandTokenizer(command); 220 if(ct.countTokens() >= 3) { 221 ct.nextToken(); // Throw away collectionmeta 222 Object key = ct.nextToken(); 223 Language language = null; 224 String language_code = null; 225 String value = ct.nextToken(); 226 // Arg. Remember a language token will be '[l=<code>]' 227 if(value.startsWith("[") && value.endsWith("]")) { 228 language_code = value.substring(3, value.length() - 1); 229 ///ystem.err.println("Language code = " + language_code); 230 value = ct.nextToken(); 231 } 232 // Check if the key is an index, an if so retrieve it. 233 if(((String)key).startsWith(".")) { 234 String key_str = (String)key; 235 key_str = key_str.substring(1); 236 key = manager.indexes.getIndex(key_str); 237 } 238 // An if we have a language code, retrieve its object too. 239 if(language_code != null) { 240 language = manager.languages.getLanguage(language_code, false); 241 } 242 // Otherwise set language to the default language. 243 else { 244 language = manager.languages.getDefaultLanguage(); 245 } 246 if(key != null) { 247 // Trim any " 248 if(value.equals("\"\"")) { 249 value = ""; 250 } 251 else { 252 if(value.startsWith("\"")) { 253 value = value.substring(1); 254 } 255 if(value.endsWith("\"")) { 256 value = value.substring(0, value.length() - 1); 257 } 258 } 259 CollectionMeta meta = new CollectionMeta(manager, key, language, Utility.decodeGreenstone(value)); 260 addMetadata(meta); 261 } 262 return true; 263 } 264 } 265 else { 266 unresolved_commands.add(command); 267 return true; 268 } 269 } 270 return false; 271 } 272 /** Ensure that the values being showed are the most up to date. */ 273 public void refresh() { 274 fireContentsChanged(this, 0, size()); 275 } 276 277 /** Method to remove a piece of metadata. 278 278 * @param metadata The <strong>CollectionMeta</strong> you wish to remove. 279 279 */ 280 281 282 283 284 285 */ 286 287 288 289 290 291 292 293 280 public void removeMetadata(CollectionMeta metadata) { 281 removeElement(metadata); 282 gatherer.c_man.configurationChanged(); 283 } 284 /** Method which attempts to reparse obvious metadata commands which used unresovable references. 285 */ 286 public void reparseUnresolved() { 287 for(int i = 0; i < unresolved_commands.size(); i++) { 288 parse((String)unresolved_commands.get(i), true); 289 } 290 // Regardless of if they work, clear the commands. 291 unresolved_commands.clear(); 292 } 293 /** Sets the value of a certain metadata. 294 294 * @param name The name of the metadata as a <strong>String</strong>. 295 295 * @param language The <strong>Language</strong> to use. 296 296 * @param value The value of the metadata also as a <strong>String</strong>. 297 297 */ 298 299 300 301 298 public void setMetadata(String name, Language language, String value) { 299 addMetadata(new CollectionMeta(manager, name, language, value)); 300 } 301 /** Method to produce the list of metadata in a string such as you would find in the collection configuration file. 302 302 * @return A <strong>String</strong> containing the list of collection metadata. 303 303 */ 304 305 306 307 308 309 310 311 312 313 314 315 304 public String toString() { 305 StringBuffer text = new StringBuffer(""); 306 for(int i = 0; i < size(); i++) { 307 CollectionMeta data = (CollectionMeta) get(i); 308 if(data.valid()) { 309 text.append(data.toString()); 310 } 311 } 312 text.append("\n"); 313 return text.toString(); 314 } 315 /** Overloaded to call get with both a key and an empty argument array. 316 316 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. 317 317 * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call. 318 318 */ 319 320 321 322 319 private String get(String key) { 320 return get(key, null); 321 } 322 /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR> 323 323 * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>. 324 324 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. … … 328 328 * @see org.greenstone.gatherer.Dictionary 329 329 */ 330 331 332 333 334 335 330 private String get(String key, String args[]) { 331 if(key.indexOf('.') == -1) { 332 key = "CDM.CollectionMetaManager." + key; 333 } 334 return gatherer.dictionary.get(key, args); 335 } 336 336 } -
trunk/gli/src/org/greenstone/gatherer/cdm/CommandTokenizer.java
r4293 r4366 56 56 */ 57 57 public class CommandTokenizer 58 58 extends StringTokenizer { 59 59 60 60 private int last_type = -1; 61 61 62 63 64 65 62 static final public int BRACKET_ENCLOSED = 0; 63 static final public int DOUBLE_QUOTE_ENCLOSED = 1; 64 static final public int NORMAL = 2; 65 static final public int QUOTE_ENCLOSED = 3; 66 66 67 68 69 70 71 72 67 /** Constructor. 68 * @param command The command <strong>String</strong> you wish to tokenize. 69 */ 70 public CommandTokenizer(String command) { 71 super(command); 72 } 73 73 74 75 76 74 public int getLastType() { 75 return last_type; 76 } 77 77 78 79 80 78 public boolean isComment() { 79 return (last_type == DOUBLE_QUOTE_ENCLOSED || last_type == QUOTE_ENCLOSED); 80 } 81 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 82 /** Method to retrieve the next token from the command, taking care to group tokens enclosed in speech marks. 83 * @return A <strong>String</strong> containing the next token from the command. 84 */ 85 public String nextToken() { 86 String result = null; 87 if(hasMoreTokens()) { 88 StringBuffer buffer = new StringBuffer(super.nextToken()); 89 switch(buffer.charAt(0)) { 90 case '\"': 91 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != '\"') && hasMoreTokens()) { 92 buffer.append(" "); 93 buffer.append(super.nextToken()); 94 ///ystem.err.println("Current Buffer = '" + buffer.toString() + "'"); 95 } 96 ///ystem.err.println("Final Buffer = '" + buffer.toString() + "'"); 97 last_type = DOUBLE_QUOTE_ENCLOSED; 98 break; 99 case '\'': 100 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != '\'') && hasMoreTokens()) { 101 buffer.append(" "); 102 buffer.append(super.nextToken()); 103 } 104 last_type = QUOTE_ENCLOSED; 105 break; 106 case '[': 107 while((buffer.length() == 1 || buffer.charAt(buffer.length() - 1) != ']') && hasMoreTokens()) { 108 buffer.append(" "); 109 buffer.append(super.nextToken()); 110 } 111 last_type = BRACKET_ENCLOSED; 112 break; 113 default: 114 last_type = NORMAL; 115 } 116 result = buffer.toString(); 117 } 118 return result; 119 } 120 /** Unfortunately the StringBuffer doesn't have a built in endsWith method, so I'll just have to implement my own. 121 * @param str The <strong>StringBuffer</strong> we are checking the end of. 122 * @param target The <strong>String</strong> fragment we are searching for. 123 * @return <i>true</i> if str ends with target, <i>false</i> otherwise. 124 */ 125 private boolean endsWith(StringBuffer str, String target) { 126 String temp = str.toString(); 127 if(temp.endsWith(target) != (str.lastIndexOf(target) == str.length() - target.length())) { 128 128 ///ystem.err.println("Holy error that'll crash the HFile creator if it happens twice, Batman!"); 129 129 ///ystem.err.println("String = '" + temp + "'"); 130 130 ///ystem.err.println("Target = '" + target + "'"); 131 132 133 131 } 132 return str.lastIndexOf(target) == str.length() - target.length(); 133 } 134 134 } 135 135 -
trunk/gli/src/org/greenstone/gatherer/cdm/CustomClassifier.java
r4293 r4366 44 44 */ 45 45 public interface CustomClassifier 46 47 48 46 extends Comparable { 47 /** Constructor. 48 * public CustomClassifier(Gatherer gatherer); 49 49 */ 50 50 /** Create a blank copy of this pseudo-classifier. 51 51 * @return A newly allocated <strong>CustomClassifier</strong>. 52 52 */ 53 54 55 56 53 public CustomClassifier copy(); 54 /** Destructor. */ 55 public void destroy(); 56 /** Show the controls for configuring this pseudo-classifier. 57 57 * @param show <i>true</i> if the component should immediately show itself, <i>false</i> if you just wish to initialize components. 58 58 */ 59 60 59 public boolean display(boolean show); 60 /** Method to return this pseudo-classifier represented as a String. 61 61 * @return A <strong>String</strong>. 62 62 */ 63 64 63 public String getCommand(); 64 /** Retrieve the custom command, a command line that overrides and replaces some other 'actual' classifier. 65 65 * @param index The number of the classifer this one is replacing. 66 66 */ 67 68 67 public String getCustomCommand(int index); 68 /** Get the name of this custom classifier. 69 69 * @return A <strong>String</strong> representing the name. 70 70 */ 71 72 73 74 75 76 77 78 71 public String getName(); 72 public void process(FileNode record); 73 /** Recreate a CustomAZList given several parameters including the real classifier created during custom design. 74 * @param classifier The real <strong>Classifier</strong>. 75 * @param separations A <strong>String</strong> representing the choosen separations. 76 */ 77 public void recreate(Classifier classifier, String separations); 78 /** Sets the value of Gatherer, for those classes loaded dynamically. 79 79 * @param gatherer A reference to the <strong>Gatherer</strong>. 80 80 */ 81 82 81 public void setGatherer(Gatherer gatherer); 82 /** Sets the Classifier manager in charge of this classifier. 83 83 * @param manager This classifiers <strong>ClassifierManager</strong>. 84 84 */ 85 85 public void setManager(ClassifierManager manager); 86 86 } -
trunk/gli/src/org/greenstone/gatherer/cdm/DefaultSubIndex.java
r4293 r4366 60 60 */ 61 61 public class DefaultSubIndex 62 63 64 62 extends SubIndex { 63 /** Copy constructor. 64 * @param subindex The <strong>SubIndex</strong> we are copying. 65 65 */ 66 67 68 69 70 71 66 public DefaultSubIndex(SubIndex subindex) { 67 for(int i = 0; i < subindex.size(); i++) { 68 add(subindex.get(i)); 69 } 70 } 71 /** Parsed data Constructor. 72 72 * @param raw A <strong>String</strong> containing a comma separated list of subcollection names. 73 73 * @param manager A reference to the <strong>SubcollectionManager</strong> via which we retrieve the required <strong>Subcollection</strong>s. 74 74 */ 75 76 77 78 75 public DefaultSubIndex(String raw, SubcollectionManager manager) { 76 super(raw, manager); 77 } 78 /** Method to extract just the subindex information from this class. 79 79 * @return A <strong>SubIndex</strong> based on the information in this class. 80 80 */ 81 82 83 84 81 public SubIndex getSubIndex() { 82 return new SubIndex(this); 83 } 84 /** Method to produce this class as a string much like you'd find in the collection configuration file. 85 85 * @return A <strong>String</string> with the default index entry. 86 86 */ 87 88 89 90 91 92 93 94 95 96 97 98 99 87 public String toString() { 88 String text = "defaultsubcollection "; 89 for(int i = 0; i < size(); i++) { 90 Object object = get(i); 91 Subcollection sub = (Subcollection) get(i); 92 text = text + sub.getName(); 93 if(i < size() - 1) { 94 text = text + ","; 95 } 96 } 97 text = text + "\n"; 98 return text; 99 } 100 100 } 101 101 -
trunk/gli/src/org/greenstone/gatherer/cdm/DynamicListModel.java
r4293 r4366 57 57 */ 58 58 public class DynamicListModel 59 60 59 extends DefaultListModel 60 implements ComboBoxModel { 61 61 62 62 private boolean auto_order = false; 63 63 64 64 private Object object = null; 65 65 66 67 66 public void addElement(Object element) { 67 if(auto_order) { 68 68 // Insert the object in its alphabetically correct place. 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 69 int position = 0; 70 boolean found = false; 71 while(!found && position < size()) { 72 ///ystem.err.print("Compare " + element.toString() + " to " + get(position).toString() + ": "); 73 int order = element.toString().compareTo(get(position).toString()); 74 if(order < 0) { 75 add(position, element); 76 found = true; 77 ///ystem.err.println("Greater than. Insert"); 78 } 79 else if(order == 0) { 80 found = true; 81 ///ystem.err.println("Equal. End."); 82 } 83 else { 84 position++; 85 ///ystem.err.println("Less than. Carry on."); 86 } 87 } 88 if(!found) { 89 super.addElement(element); 90 ///ystem.err.println("Out of elements. Insert"); 91 } 92 } 93 else { 94 super.addElement(element); 95 } 96 } 97 97 98 99 100 101 102 103 104 105 98 public DynamicListModel shallowCopy() { 99 DynamicListModel copy = new DynamicListModel(); 100 copy.setAutoOrder(auto_order); 101 for(int i = 0; i < size(); i++) { 102 copy.addElement(get(i)); 103 } 104 return copy; 105 } 106 106 107 108 109 110 111 112 113 114 107 public Object getSelectedItem() { 108 ///ystem.err.println("Get item: " + object); 109 return object; 110 } 111 /** Notify all controls that are based on this list model that its contents have changed, and they should repaint themselves. */ 112 public void refresh() { 113 fireContentsChanged(this, 0, size()); 114 } 115 115 116 117 118 116 public void setAutoOrder(boolean auto_order) { 117 this.auto_order = auto_order; 118 } 119 119 120 121 122 123 120 public void setSelectedItem(Object object) { 121 ///ystem.err.println("Set item: " + object); 122 this.object = object; 123 } 124 124 } -
trunk/gli/src/org/greenstone/gatherer/cdm/ElementWrapper.java
r4293 r4366 6 6 */ 7 7 public class ElementWrapper 8 9 10 11 12 8 implements Comparable { 9 /** The element as the data from this object. */ 10 private Node element = null; 11 /** Constructor. 12 * @param element The <strong>Node</strong> this object is wrapped around. 13 13 */ 14 15 16 17 14 public ElementWrapper(Node element) { 15 this.element = element; 16 } 17 /** Compare two objects for ordering. 18 18 * @param object The other <strong>Object</strong> to compare to. 19 19 * @return An <i>int</i> indicating the ordering as is String.compareTo 20 20 */ 21 22 23 24 25 26 27 21 public int compareTo(Object object) { 22 if(object == null) { 23 return 1; 24 } 25 return toString().compareTo(object.toString()); 26 } 27 /** Compare two objects for equality. 28 28 * @param object The <strong>Object</strong> to compare to. 29 29 * @return <i>true</i> if the objects are equal, <i>false</i> otherwise. 30 30 */ 31 32 33 34 35 36 37 31 public boolean equals(Object object) { 32 if(compareTo(object) == 0) { 33 return true; 34 } 35 return false; 36 } 37 /** Retrieve the name of the element. 38 38 * @return The fully qualified name as a <strong>String</strong>. 39 39 * @see org.greenstone.gatherer.msm.MSMUtils 40 40 */ 41 42 43 44 41 public String name() { 42 return MSMUtils.getFullName((Element)element); 43 } 44 /** Retrieve a textual representation of this object. 45 45 * @return A <strong>String</strong>. 46 46 * @see org.greenstone.gatherer.msm.MSMUtils 47 47 */ 48 49 50 48 public String toString() { 49 return MSMUtils.getIdentifier(element) + ": " + MSMUtils.getDescription(element); 50 } 51 51 } -
trunk/gli/src/org/greenstone/gatherer/cdm/Format.java
r4293 r4366 56 56 */ 57 57 public class Format { 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 58 /** If this format is of a true/false type, the current state. */ 59 private boolean state = false; 60 /** The type of this format command, either FLAG, FORMAT or PARAM. */ 61 private int type = -1; 62 /** The feature this format command affects. */ 63 private Object feature = null; 64 /** If this format refers to a specific part of a feature, this indicates the part. */ 65 private String part = null; 66 /** A command string, which may include a specific HTML chunk used to format a control. */ 67 private String value = null; 68 /** An element of the format type enumeration. A true/false option. */ 69 static final public int FLAG = 0; 70 /** An element of the format type enumeration. A string parameter. */ 71 static final public int VALUE = 1; 72 /** The default features as specified by the Greenstone Developers manual. */ 73 static final public String DEFAULT_FEATURES[] = {"", "DocumentArrowsBottom","DocumentButtons","DocumentContents","DocumentHeading","DocumentImages","DocumentText","DocumentUseHTML","Search"}; 74 /** The list of known feature parts. */ 75 static final public String DEFAULT_PARTS[] = {"","DateList","HList","Invisible","VList"}; 76 /** Constructor for a flag format command. 77 * @param feature The <Strong>Object</strong> this format affects. 78 * @param part The specific part of the control to format as a <strong>String</strong>. 79 * @param state A <i>boolean</i> indicating this formats state. 80 */ 81 public Format(Object feature, String part, boolean state) { 82 this.feature = feature; 83 this.part = part; 84 this.state = state; 85 this.type = FLAG; 86 } 87 /** Constructor for a format-string format command. 88 * @param feature The <Strong>Object</strong> this format affects. 89 * @param part The specific part of the control to format as a <strong>String</strong>. 90 * @param value The format <strong>String</strong> which may be a label name, or a piece of HTML formatting. 91 */ 92 public Format(Object feature, String part, String value) { 93 this.feature = feature; 94 this.part = part; 95 this.type = VALUE; 96 this.value = value; 97 } 98 /** Method to retrieve the value of feature, which may either be a String or a Classifier. 99 * @return The value of feature as an <strong>Object</strong>. 100 */ 101 public Object getFeature() { 102 return feature; 103 } 104 /** Method to retrieve the value of part. 105 * @return The value of part as a <Strong>String</strong>. 106 */ 107 public String getPart() { 108 return part; 109 } 110 /** Method to retrieve this formats special Greenstone position code. 111 * @return A <strong>String</strong> which distinctly indicates this classifiers position. 112 * @see org.greenstone.gatherer.cdm.Classifier 113 */ 114 public String getPosition() { 115 ///ystem.err.println("Retrieving the name of feature " + feature); 116 String position = null; 117 if(feature instanceof Classifier) { 118 position = ((Classifier)feature).getPositionString(); 119 } 120 else { 121 position = feature.toString(); 122 } 123 ///ystem.err.println("Result: " + position + part); 124 return position + part; 125 } 126 /** Method to retrieve the value of state. 127 * @param The value of state as a <i>boolean</i>. 128 */ 129 public boolean getState() { 130 return state; 131 } 132 /** Method to retrieve the value of type. 133 * @param The value of type as an <i>int</i>. 134 */ 135 public int getType() { 136 return type; 137 } 138 /** Retrieve the value of value. 139 * @return A <strong>String</strong> which is the value of value. 140 */ 141 public String getValue() { 142 return value; 143 } 144 /** Set the value of state. 145 * @param state The new value for state as a <i>boolean</i>. 146 */ 147 public void setState(boolean state) { 148 this.state = state; 149 } 150 /** Set the value of type. 151 * @param type The new value for type as an <i>int</i>. 152 */ 153 public void setType(int type) { 154 this.type = type; 155 } 156 /** Set the value of value. Hmmm. 157 * @param value The new value from value as a <strong>String</strong>. 158 */ 159 public void setValue(String value) { 160 this.value = value; 161 } 162 /** Method to translate this classes information into a line of text as you would expect in the collection configuration file. 163 * @return A <strong>String</strong> containing the format command. 164 */ 165 public String toString() { 166 String text = "format "; 167 text = text + getPosition() + " "; 168 switch(type) { 169 case FLAG: 170 if(state) { 171 text = text + "true"; 172 } 173 else { 174 text = text + "false"; 175 } 176 break; 177 default: 178 text = text + "\"" + value + "\""; 179 } 180 return text; 181 } 182 /** Retrieve the type of a certain named feature. 183 * @param name The name of the feature as a <strong>String</strong>. 184 * @return An <i>int</i> indicating the type, and hence the controls needed to edit this type. 185 */ 186 static public int getType(String name) { 187 int index = -1; 188 for(int i = 1; i < DEFAULT_FEATURES.length; i++) { 189 if(name.equalsIgnoreCase(DEFAULT_FEATURES[i])) { 190 index = i; 191 } 192 } 193 if(index == 1 || index == 3 || index == 5 || index == 7) { 194 return FLAG; 195 } 196 return VALUE; 197 } 198 198 } -
trunk/gli/src/org/greenstone/gatherer/cdm/FormatManager.java
r4293 r4366 94 94 */ 95 95 public class FormatManager 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 96 extends DynamicListModel { 97 /** The main manager so we can get to ClassifierManager which is needed to turn position reference such as "CL1" into the appropriate Classifier. */ 98 private CollectionDesignManager manager = null; 99 /** The controls used to edit the format commands. */ 100 private Control controls = null; 101 /** A reference to ourselves so inner classes can get at the model. */ 102 private DynamicListModel model = null; 103 /** A reference to the Gatherer. */ 104 private Gatherer gatherer = null; 105 /** We may have somehow recieved a format command which references a classifier that hasn't been parsed yet, so this variable holds a list of failed commands which are retried after the loading is complete. */ 106 private Vector unresolved_commands = null; 107 /** Constructor. 108 * @param gatherer A reference to the <strong>Gatherer</strong>. 109 * @param manager A reference to the <strong>CollectionDesignManager</strong> that created this manager. 110 */ 111 public FormatManager(Gatherer gatherer, CollectionDesignManager manager) { 112 super(); 113 this.gatherer = gatherer; 114 this.manager = manager; 115 this.model = this; 116 this.unresolved_commands = new Vector(); 117 } 118 /** Method to add a new format to this manager. 119 119 * @param format The <strong>Format</strong> to add. 120 120 */ 121 122 123 124 125 126 127 121 public void addFormat(Format format) { 122 if(formatExists(format) == null) { 123 addElement(format); 124 gatherer.c_man.configurationChanged(); 125 } 126 } 127 /** Method which determines if a certain format exists, in which case it must be removed before a new format of the same component is added. For general formatting statements this compares types, for 'custom' ones it compares list and part. 128 128 * @param format The <strong>Format</strong> whose uniqueness we want to check. 129 129 * @return The <strong>Format</strong> that matches the one given, or <i>null</i> if no such format exists. 130 130 */ 131 132 133 134 135 136 137 138 139 140 131 public Format formatExists(Format format) { 132 for(int i = 0; i < size(); i++) { 133 Format current = (Format) get(i); 134 if(format.getPosition().equals(current.getPosition())) { 135 return current; 136 } 137 } 138 return null; 139 } 140 /** Gets the format indicated by the index. 141 141 * @param index The location of the desired format, as an <i>int</i>. 142 142 */ 143 144 145 146 143 public Format getFormat(int index) { 144 return (Format)get(index); 145 } 146 /** Method to retrieve this managers controls. 147 147 * @return The <strong>Control</strong> for this collection. 148 148 */ 149 150 151 152 153 154 155 156 157 158 159 160 161 162 149 public Control getControls() { 150 if(controls == null) { 151 controls = new Control(); 152 } 153 return controls; 154 } 155 /** Method to invalidate controls when some significant change has occured within the collection. */ 156 public void invalidateControls() { 157 if(controls != null) { 158 controls.destroy(); 159 } 160 controls = null; 161 } 162 /** This method attempts to parse a format command from the given string. If a format is parsed, it is immediately added to this managers list of format commands. 163 163 * @param command The <strong>String</strong> we are trying to parse a command from. 164 164 * @param finished A <i>boolean</i> which is <i>true</i> if we are calling this after the the input has been completely parsed (i.e all legal Classifiers are know to exist), or <i>false</i> otherwise. … … 168 168 * @see org.greenstone.gatherer.cdm.Format 169 169 */ 170 public boolean parse(String command, boolean finished) { 171 String temp = command.toLowerCase(); 172 if(temp.startsWith("format")) { 173 if(finished) { 174 CommandTokenizer ct = new CommandTokenizer(command); 175 ct.nextToken(); // Throw away 'format' 176 String position = ct.nextToken(); 177 String value = ct.nextToken(); 178 // String speech marks. 179 if(value.startsWith("\"") && value.endsWith("\"")) { 180 if(value.equals("\"\"")) { 181 value = ""; 182 } 183 else { 184 value = value.substring(1, value.length() - 1); 185 } 186 } 187 // Ensure we parsed a good command. 188 if(position != null && value != null) { 189 // The trickiest bit of parsing format commands is figuring out how much of the position is feature, and how much part. Since the parts are far less likely to change or be customized in any way, we'll try to match them first (except "" of course). 190 String feature_name = null; 191 String part = null; 192 // If this works, then we're all finished. Yay. 193 for(int i = 1; i < Format.DEFAULT_PARTS.length; i++) { 194 if(position.endsWith(Format.DEFAULT_PARTS[i])) { 195 part = Format.DEFAULT_PARTS[i]; 196 feature_name = position.substring(0, position.length() - part.length()); 197 } 198 } 199 // Otherwise we can attempt to find the default features, but we have less chance of success. 200 if(feature_name == null || part == null) { 201 for(int i = 1; i < Format.DEFAULT_FEATURES.length; i++) { 202 if(position.startsWith(Format.DEFAULT_FEATURES[i])) { 203 feature_name = Format.DEFAULT_FEATURES[i]; 204 if(position.length() > feature_name.length()) { 205 part = position.substring(feature_name.length()); 206 } 207 else { 208 part = ""; 209 } 210 } 211 } 212 } 213 // Otherwise we can assume we are dealing with a classifier and split the position using... 214 // position ::= <classifier_position><part> 215 // classifier_position ::= <alphanum>[0-9]$ 216 // part ::= ^![0-9]<alpha> 217 // But I don't like my chances of this working if someone does a scary like CL4Part8B. I just have 218 // to hope no-one uses numbers, and no-one expects CustomFeatureCustomPart to parse properly. 219 if(feature_name == null || part == null) { 220 part = ""; 221 boolean found = false; 222 int index = position.length() - 1; 223 while(index >= 0 && !found) { 224 if(Character.isDigit(position.charAt(index))) { 225 found = true; 226 } 227 else { 228 part = position.charAt(index) + part; 229 index--; 230 } 231 } 232 if(found) { 233 feature_name = position.substring(0, index + 1); 234 } 235 // We ran out of string. No digits. Arg! 236 else { 237 part = null; 238 } 239 } 240 // And if all else fails, stick it all in feature. 241 if(feature_name == null || part == null) { 242 feature_name = position; 243 part = ""; 244 } 245 // Now try to retrieve a classifier with the feature name. 246 Object feature = null; 247 String feature_name_lc = feature_name.toLowerCase(); 248 if(feature_name_lc.startsWith("cl") && feature_name.length() >= 3) { 249 String raw_index = feature_name.substring(2); // Lose the 'CL' 250 int index = -1; 251 try { 252 index = Integer.parseInt(raw_index); 253 } 254 catch(NumberFormatException nfe) { 255 nfe.printStackTrace(); 256 } 257 feature = manager.classifiers.getClassifier(index - 1); 258 } 259 else { 260 ///ystem.err.println("name to short for classifier."); 261 } 262 if(feature == null) { 263 feature = feature_name; 264 } 265 ///ystem.err.println("Feature name = " + feature_name + "\nPart = " + part); 266 if(feature instanceof Classifier) { 267 ///ystem.err.println("Feature is a classifier."); 268 } 269 else { 270 ///ystem.err.println("Feature is a String."); 271 } 272 // Now we have a quick look at value. If its true or false we create a FLAG type 273 if(value.equalsIgnoreCase("true")) { 274 addFormat(new Format(feature, part, true)); 275 } 276 else if(value.equalsIgnoreCase("false")) { 277 addFormat(new Format(feature, part, false)); 278 } 279 // Otherwise add a plain old value based format 280 else { 281 addFormat(new Format(feature, part, value)); 282 } 283 return true; 284 } 285 // Somethings gone terribly, terribly wrong. 286 return false; 170 public boolean parse(String command, boolean finished) { 171 String temp = command.toLowerCase(); 172 if(temp.startsWith("format")) { 173 if(finished) { 174 CommandTokenizer ct = new CommandTokenizer(command); 175 ct.nextToken(); // Throw away 'format' 176 String position = ct.nextToken(); 177 String value = ct.nextToken(); 178 // String speech marks. 179 if(value.startsWith("\"") && value.endsWith("\"")) { 180 if(value.equals("\"\"")) { 181 value = ""; 182 } 183 else { 184 value = value.substring(1, value.length() - 1); 185 } 186 } 187 // Ensure we parsed a good command. 188 if(position != null && value != null) { 189 // The trickiest bit of parsing format commands is figuring out how much of the position is feature, and how much part. Since the parts are far less likely to change or be customized in any way, we'll try to match them first (except "" of course). 190 String feature_name = null; 191 String part = null; 192 // If this works, then we're all finished. Yay. 193 for(int i = 1; i < Format.DEFAULT_PARTS.length; i++) { 194 if(position.endsWith(Format.DEFAULT_PARTS[i])) { 195 part = Format.DEFAULT_PARTS[i]; 196 feature_name = position.substring(0, position.length() - part.length()); 197 } 198 } 199 // Otherwise we can attempt to find the default features, but we have less chance of success. 200 if(feature_name == null || part == null) { 201 for(int i = 1; i < Format.DEFAULT_FEATURES.length; i++) { 202 if(position.startsWith(Format.DEFAULT_FEATURES[i])) { 203 feature_name = Format.DEFAULT_FEATURES[i]; 204 if(position.length() > feature_name.length()) { 205 part = position.substring(feature_name.length()); 287 206 } 288 207 else { 289 unresolved_commands.add(command);208 part = ""; 290 209 } 291 return true; 292 } 293 return false; 294 } 295 /** Method to remove a format. 210 } 211 } 212 } 213 // Otherwise we can assume we are dealing with a classifier and split the position using... 214 // position ::= <classifier_position><part> 215 // classifier_position ::= <alphanum>[0-9]$ 216 // part ::= ^![0-9]<alpha> 217 // But I don't like my chances of this working if someone does a scary like CL4Part8B. I just have 218 // to hope no-one uses numbers, and no-one expects CustomFeatureCustomPart to parse properly. 219 if(feature_name == null || part == null) { 220 part = ""; 221 boolean found = false; 222 int index = position.length() - 1; 223 while(index >= 0 && !found) { 224 if(Character.isDigit(position.charAt(index))) { 225 found = true; 226 } 227 else { 228 part = position.charAt(index) + part; 229 index--; 230 } 231 } 232 if(found) { 233 feature_name = position.substring(0, index + 1); 234 } 235 // We ran out of string. No digits. Arg! 236 else { 237 part = null; 238 } 239 } 240 // And if all else fails, stick it all in feature. 241 if(feature_name == null || part == null) { 242 feature_name = position; 243 part = ""; 244 } 245 // Now try to retrieve a classifier with the feature name. 246 Object feature = null; 247 String feature_name_lc = feature_name.toLowerCase(); 248 if(feature_name_lc.startsWith("cl") && feature_name.length() >= 3) { 249 String raw_index = feature_name.substring(2); // Lose the 'CL' 250 int index = -1; 251 try { 252 index = Integer.parseInt(raw_index); 253 } 254 catch(NumberFormatException nfe) { 255 nfe.printStackTrace(); 256 } 257 feature = manager.classifiers.getClassifier(index - 1); 258 } 259 else { 260 ///ystem.err.println("name to short for classifier."); 261 } 262 if(feature == null) { 263 feature = feature_name; 264 } 265 ///ystem.err.println("Feature name = " + feature_name + "\nPart = " + part); 266 if(feature instanceof Classifier) { 267 ///ystem.err.println("Feature is a classifier."); 268 } 269 else { 270 ///ystem.err.println("Feature is a String."); 271 } 272 // Now we have a quick look at value. If its true or false we create a FLAG type 273 if(value.equalsIgnoreCase("true")) { 274 addFormat(new Format(feature, part, true)); 275 } 276 else if(value.equalsIgnoreCase("false")) { 277 addFormat(new Format(feature, part, false)); 278 } 279 // Otherwise add a plain old value based format 280 else { 281 addFormat(new Format(feature, part, value)); 282 } 283 return true; 284 } 285 // Somethings gone terribly, terribly wrong. 286 return false; 287 } 288 else { 289 unresolved_commands.add(command); 290 } 291 return true; 292 } 293 return false; 294 } 295 /** Method to remove a format. 296 296 * @param format The <strong>Format</strong> to remove. 297 297 */ 298 299 300 301 302 298 public void removeFormat(Format format) { 299 removeElement(format); 300 gatherer.c_man.configurationChanged(); 301 } 302 /** Method which attempts to reparse obvious format commands which previously referenced unresovable Classifiers. 303 303 */ 304 305 306 307 308 309 310 311 312 313 304 public void reparseUnresolved() { 305 for(int i = 0; i < unresolved_commands.size(); i++) { 306 if(!parse((String)unresolved_commands.get(i), true)) { 307 ///ystem.err.println("*** Error: Command " + unresolved_commands.get(i)); 308 } 309 } 310 // Regardless of if they work, clear the commands. 311 unresolved_commands.clear(); 312 } 313 /** Method to produce a block of text representing the format commands in this manager, ready to be used in the collection configuration file. 314 314 * @return A <strong>String</strong> containing a series of format commands. 315 315 */ 316 317 318 319 320 321 322 323 324 325 326 316 public String toString() { 317 StringBuffer text = new StringBuffer(""); 318 for(int i = 0; i < size(); i++) { 319 Format format = (Format) get(i); 320 text.append(format.toString()); 321 text.append("\n"); 322 } 323 text.append("\n"); 324 return text.toString(); 325 } 326 /** Overloaded to call get with both a key and an empty argument array. 327 327 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. 328 328 * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call. 329 329 */ 330 331 332 333 330 private String get(String key) { 331 return get(key, null); 332 } 333 /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR> 334 334 * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>. 335 335 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. … … 339 339 * @see org.greenstone.gatherer.Dictionary 340 340 */ 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 341 private String get(String key, String args[]) { 342 if(key.indexOf('.') == -1) { 343 key = "CDM.FormatManager." + key; 344 } 345 return gatherer.dictionary.get(key, args); 346 } 347 private class Control 348 extends JPanel { 349 /** Do we ignore selection changing events (mainly because we're generating them!) */ 350 private boolean ignore = false; 351 private boolean new_entry = true; 352 private boolean ready = false; 353 private ButtonGroup button_group = null; 354 private CardLayout card_layout = null; 355 private Dimension LABEL_SIZE = new Dimension(175,25); 356 private Format current_format = null; 357 private String view_type = "custom"; 358 private JButton add = null; 359 private JButton insert = null; 360 private JButton preview = null; 361 private JButton remove = null; 362 private JComboBox feature = null; 363 private JComboBox part = null; 364 private JComboBox special = null; 365 private JLabel editor_label = null; 366 private JLabel feature_label = null; 367 private JLabel format_list_label = null; 368 private JLabel part_label = null; 369 private JLabel special_label = null; 370 private JLabel title = null; 371 private JLabel value_label = null; 372 private JList format_list = null; 373 private JPanel blank_pane = null; 374 private JPanel control_pane = null; 375 private JPanel editor_pane = null; 376 private JPanel feature_pane = null; 377 private JPanel format_list_pane = null; 378 private JPanel header_pane = null; 379 private JPanel inner_button_pane = null; 380 private JPanel inner_state_pane = null; 381 private JPanel inner_value_pane = null; 382 private JPanel options_pane = null; 383 private JPanel outer_button_pane = null; 384 private JPanel part_pane = null; 385 private JPanel special_pane = null; 386 private JPanel state_pane = null; 387 private JPanel value_pane = null; 388 private JPanel view_pane = null; 389 private JTextArea editor = null; 390 private JTextArea instructions = null; 391 private JTextField value = null; 392 private JToggleButton off = null; 393 private JToggleButton on = null; 394 private String BLANK = "blank"; 395 private String CUSTOM = "custom"; 396 private String FLAG = "flag"; 397 private String PARAM = "param"; 398 private Vector part_model = null; 399 private Vector special_model = null; 400 public Control() { 401 ArrayList feature_model = new ArrayList(); 402 402 // Add the set options 403 404 405 403 for(int i = 0; i < Format.DEFAULT_FEATURES.length; i++) { 404 feature_model.add(new Entry(Format.DEFAULT_FEATURES[i])); 405 } 406 406 // Now the classifiers. 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 407 for(int j = 0; j < manager.classifiers.size(); j++) { 408 feature_model.add(new Entry(manager.classifiers.getClassifier(j))); 409 } 410 Collections.sort(feature_model); 411 part_model = new Vector(); 412 part_model.add("");//get("Custom")); 413 part_model.add("DateList"); 414 part_model.add("HList"); 415 part_model.add("Invisible"); 416 part_model.add("VList"); 417 special_model = new Vector(); 418 special_model.add("[Text]"); 419 special_model.add("[link]"); 420 special_model.add("[/link]"); 421 special_model.add("[icon]"); 422 special_model.add("[num]"); 423 special_model.add("[parent():_]"); 424 special_model.add("[parent(Top):_]"); 425 special_model.add("[parent(All'_'):_]"); 426 Vector elements = gatherer.c_man.msm.getAssignedElements(); 427 for(int i = 0; i < elements.size(); i++) { 428 special_model.add("[" + ((ElementWrapper)elements.get(i)).toString() + "]"); 429 } 430 Collections.sort(special_model); 431 431 // Create 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 432 add = new JButton(get("Add")); 433 add.setEnabled(false); 434 blank_pane = new JPanel(); 435 button_group = new ButtonGroup(); 436 card_layout = new CardLayout(); 437 control_pane = new JPanel(); 438 editor = new JTextArea(); 439 editor.setCaretPosition(0); 440 editor.setLineWrap(true); 441 editor.setWrapStyleWord(true); 442 editor_label = new JLabel(get("Editor")); 443 editor_label.setHorizontalAlignment(JLabel.CENTER); 444 editor_pane = new JPanel(); 445 feature = new JComboBox(feature_model.toArray()); 446 feature.setEditable(true); 447 feature_label = new JLabel(get("Feature")); 448 feature_label.setPreferredSize(LABEL_SIZE); 449 format_list = new JList(model); 450 format_list_label = new JLabel(get("Assigned_Formats")); 451 format_list_pane = new JPanel(); 452 feature_pane = new JPanel(); 453 header_pane = new JPanel(); 454 inner_button_pane = new JPanel(); 455 inner_state_pane = new JPanel(); 456 inner_value_pane = new JPanel(); 457 insert = new JButton(get("Insert")); 458 instructions = new JTextArea(get("Instructions")); 459 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 460 instructions.setEditable(false); 461 instructions.setLineWrap(true); 462 instructions.setRows(4); 463 instructions.setWrapStyleWord(true); 464 off = new JToggleButton(get("Off")); 465 off.setSelected(false); 466 on = new JToggleButton(get("On")); 467 on.setSelected(true); 468 options_pane = new JPanel(); 469 outer_button_pane = new JPanel(); 470 part = new JComboBox(part_model); 471 part.setEditable(true); 472 part_label = new JLabel(get("Part")); 473 part_label.setPreferredSize(LABEL_SIZE); 474 part_pane = new JPanel(); 475 preview = new JButton(get("Preview")); 476 preview.setEnabled(false); 477 remove = new JButton(get("Remove")); 478 remove.setEnabled(false); 479 special = new JComboBox(special_model); 480 special_label = new JLabel(get("Special")); 481 special_label.setHorizontalAlignment(JLabel.CENTER); 482 special_pane = new JPanel(); 483 state_pane = new JPanel(); 484 title = new JLabel(get("Title")); 485 title.setHorizontalAlignment(JLabel.CENTER); 486 title.setOpaque(true); 487 value = new JTextField(); 488 value_label = new JLabel(get("Value")); 489 value_pane = new JPanel(); 490 view_pane = new JPanel(); 491 491 // Connect 492 493 494 495 496 497 498 499 500 501 502 503 504 492 add.addActionListener(new AddListener()); 493 button_group.add(on); 494 button_group.add(off); 495 editor.addKeyListener(new EditorListener()); 496 feature.addActionListener(new FeatureListener()); 497 format_list.addListSelectionListener(new FormatListListener()); 498 insert.addActionListener(new InsertListener()); 499 off.addActionListener(new StateListener()); 500 on.addActionListener(new StateListener()); 501 part.addActionListener(new PartListener()); 502 preview.addActionListener(new PreviewListener()); 503 remove.addActionListener(new RemoveListener()); 504 value.addKeyListener(new ValueListener()); 505 505 // Layout 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 506 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 507 508 header_pane.setLayout(new BorderLayout()); 509 header_pane.add(title, BorderLayout.NORTH); 510 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 511 512 format_list_label.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 513 514 format_list_pane.setLayout(new BorderLayout()); 515 format_list_pane.add(format_list_label, BorderLayout.NORTH); 516 format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER); 517 518 feature_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 519 520 feature_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 521 feature_pane.setLayout(new BorderLayout()); 522 feature_pane.add(feature_label, BorderLayout.WEST); 523 feature_pane.add(feature, BorderLayout.CENTER); 524 525 part_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 526 527 part_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 528 part_pane.setLayout(new BorderLayout()); 529 part_pane.add(part_label, BorderLayout.WEST); 530 part_pane.add(part, BorderLayout.CENTER); 531 532 options_pane.setLayout(new GridLayout(2,1)); 533 options_pane.add(feature_pane); 534 options_pane.add(part_pane); 535 536 inner_state_pane = new JPanel(new GridLayout(1,2)); 537 inner_state_pane.add(on); 538 inner_state_pane.add(off); 539 540 state_pane.setLayout(new BorderLayout()); 541 state_pane.add(inner_state_pane, BorderLayout.NORTH); 542 state_pane.add(new JPanel(), BorderLayout.CENTER); 543 544 value_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 545 546 inner_value_pane.setLayout(new BorderLayout()); 547 inner_value_pane.add(value_label, BorderLayout.WEST); 548 inner_value_pane.add(value, BorderLayout.CENTER); 549 550 value_pane.setLayout(new BorderLayout()); 551 value_pane.add(inner_value_pane, BorderLayout.NORTH); 552 value_pane.add(new JPanel(), BorderLayout.CENTER); 553 554 special_pane.setLayout(new GridLayout(3,1)); 555 special_pane.add(special_label); 556 special_pane.add(special); 557 special_pane.add(insert); 558 559 editor_pane.setLayout(new BorderLayout()); 560 editor_pane.add(editor_label, BorderLayout.NORTH); 561 editor_pane.add(new JScrollPane(editor), BorderLayout.CENTER); 562 editor_pane.add(special_pane, BorderLayout.EAST); 563 563 564 564 // Magic for view_pane card layout. 565 566 567 565 view_pane.setLayout(card_layout); 566 view_pane.add(editor_pane, CUSTOM); 567 view_pane.add(state_pane, FLAG); 568 568 //view_pane.add(value_pane, PARAM); 569 569 570 571 572 573 574 575 576 570 inner_button_pane.setLayout(new GridLayout(1,2)); 571 inner_button_pane.add(add); 572 inner_button_pane.add(remove); 573 574 outer_button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); 575 outer_button_pane.setLayout(new GridLayout(1,1)); 576 outer_button_pane.add(inner_button_pane); 577 577 //outer_button_pane.add(preview); 578 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 579 control_pane.setLayout(new BorderLayout()); 580 control_pane.add(options_pane, BorderLayout.NORTH); 581 control_pane.add(view_pane, BorderLayout.CENTER); 582 control_pane.add(outer_button_pane, BorderLayout.SOUTH); 583 584 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 585 setLayout(new BorderLayout()); 586 add(header_pane, BorderLayout.NORTH); 587 add(format_list_pane, BorderLayout.CENTER); 588 add(control_pane, BorderLayout.SOUTH); 589 ready = true; 590 } 591 public void destroy() { 592 } 593 /** Overriden to ensure that the instructions pane is scrolled to the top. 594 594 */ 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 595 public void updateUI() { 596 if(ready) { 597 // Rebuild feature model. 598 ArrayList feature_model = new ArrayList(); 599 // Add the set options 600 for(int i = 0; i < Format.DEFAULT_FEATURES.length; i++) { 601 feature_model.add(new Entry(Format.DEFAULT_FEATURES[i])); 602 } 603 // Now the classifiers. 604 for(int j = 0; j < manager.classifiers.size(); j++) { 605 feature_model.add(new Entry(manager.classifiers.getClassifier(j))); 606 } 607 feature.setModel(new DefaultComboBoxModel(feature_model.toArray())); 608 if(instructions != null) { 609 instructions.setCaretPosition(0); 610 } 611 } 612 super.updateUI(); 613 } 614 615 616 617 /** Formats the formatting string so that it contains safe characters and isn't enclosed in speech marks etc. (Ironic eh?) 618 618 * @see java.lang.StringBuffer 619 619 */ 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 620 private String format(String raw) { 621 String safe = null; 622 if(raw != null && raw.length() > 0) { 623 StringBuffer temp = new StringBuffer(raw); 624 // Remove quotes at start and end. Look at my wiggly save three lines of code skills. 625 char start = ' '; 626 while(temp.length() > 0 && (start = temp.charAt(0)) == '\"' || start == '\'') { 627 temp.delete(0, 1); 628 } 629 int length = 0; 630 char end = ' '; 631 while((length = temp.length()) > 0 && (end = temp.charAt(length - 1)) == '\"' || end == '\'') { 632 temp.delete(length - 1, length); 633 } 634 // Now escape quotes within the format string 635 int quote_index = -1; 636 while((quote_index = temp.indexOf("\"", quote_index + 1)) != -1) { 637 temp.replace(quote_index, quote_index + 1, "\\\""); 638 quote_index = quote_index + 1; 639 } 640 // Done. 641 safe = temp.toString(); 642 } 643 return safe; 644 } 645 /** Remove safe characters from string replacing them with unsafe ones. 646 646 * @see java.lang.StringBuffer 647 647 */ 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 648 private String unformat(String safe) { 649 String raw = null; 650 if(safe != null && safe.length() > 0) { 651 StringBuffer temp = new StringBuffer(safe); 652 int quote_index = -1; 653 while((quote_index = temp.indexOf("\\\"")) != -1) { 654 temp.replace(quote_index, quote_index + 2, "\""); 655 } 656 raw = temp.toString(); 657 } 658 return raw; 659 } 660 /** Listens for clicks on the add button, and if the relevant details are provided adds a new format. */ 661 private class AddListener 662 implements ActionListener { 663 public void actionPerformed(ActionEvent event) { 664 ignore = true; 665 Entry entry = (Entry)feature.getSelectedItem(); 666 Object f = entry.getFeature(); 667 String p = (String)part.getSelectedItem(); 668 if(view_type.equals(FLAG)) { 669 current_format = new Format(f, p, on.isSelected()); 670 } 671 else { 672 current_format = new Format(f, p, format(Utility.stripNL(editor.getText()))); 673 } 674 addFormat(current_format); 675 add.setEnabled(false); 676 remove.setEnabled(true); 677 // Update list selection 678 format_list.setSelectedValue(current_format, true); 679 new_entry = false; 680 ignore = false; 681 } 682 } 683 private class EditorListener 684 extends KeyAdapter { 685 public void keyReleased(KeyEvent event) { 686 String safe = format(editor.getText()); 687 if(!ignore && current_format != null) { 688 // We have just performed an edit. Immediately update the format and model. 689 if(safe != null) { 690 current_format.setValue(safe); 691 } 692 else { 693 current_format.setValue(""); 694 } 695 gatherer.c_man.configurationChanged(); 696 model.refresh(); 697 } 698 Entry entry = (Entry) feature.getSelectedItem(); 699 String name = entry.toString(); 700 if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && safe != null && safe.length() != 0 && new_entry) { 701 add.setEnabled(true); 702 } 703 else { 704 add.setEnabled(false); 705 } 706 } 707 } 708 /** This object provides a wrapping around an entry in the format target control, which is tranparent as to whether it is backed by a String or a Classifier. */ 709 private class Entry 710 implements Comparable { 711 private Classifier classifier = null; 712 private CustomClassifier custom_classifier = null; 713 private String text = null; 714 public Entry(Object object) { 715 if(object instanceof Classifier) { 716 classifier = (Classifier)object; 717 } 718 if(object instanceof CustomClassifier) { 719 custom_classifier = (CustomClassifier)object; 720 } 721 else if(object instanceof String) { 722 text = (String)object; 723 } 724 else { 725 text = ""; 726 } 727 } 728 public Entry(String text) { 729 this.text = text; 730 } 731 public int compareTo(Object object) { 732 if(object == null) { 733 return 1; 734 } 735 if(toString() == null) { 736 return -1; 737 } 738 else { 739 String object_str = object.toString(); 740 if(object_str == null) { 741 return 1; 742 } 743 return toString().compareTo(object_str); 744 } 745 } 746 public boolean equals(Object object) { 747 if(compareTo(object) == 0) { 748 return true; 749 } 750 return false; 751 } 752 public Classifier getClassifier() { 753 return classifier; 754 } 755 public CustomClassifier getCustomClassifier() { 756 return custom_classifier; 757 } 758 public Object getFeature() { 759 if(classifier != null) { 760 return classifier; 761 } 762 return text; 763 } 764 public String toString() { 765 if(classifier != null) { 766 String name = classifier.toString(); 767 return name.substring(9); 768 } 769 if(custom_classifier != null) { 770 String name = custom_classifier.toString(); 771 return name;//.substring(17); 772 } 773 return text; 774 } 775 } 776 private class FeatureListener 777 implements ActionListener { 778 public void actionPerformed(ActionEvent event) { 779 if(!ignore) { 780 current_format = null; 781 Entry entry = (Entry) feature.getSelectedItem(); 782 String name = entry.toString(); 783 int type = Format.getType(name); 784 switch(type) { 785 case Format.FLAG: 786 // Flags first. 787 part.setEnabled(false); 788 part_pane.remove(part); 789 card_layout.show(view_pane, FLAG); 790 view_type = FLAG; 791 add.setEnabled(true); // One of the options must be selected. 792 break; 793 default: 794 part.setEnabled(true); 795 part_pane.add(part, BorderLayout.CENTER); 796 card_layout.show(view_pane, CUSTOM); 797 view_type = CUSTOM; 798 if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && editor.getText().length() != 0) { 799 add.setEnabled(true); 800 } 801 else { 802 add.setEnabled(false); 803 } 804 } 805 control_pane.updateUI(); 806 new_entry = true; 807 } 808 } 809 } 810 private class FormatListListener 811 implements ListSelectionListener { 812 public void valueChanged(ListSelectionEvent event) { 813 if(!ignore) { 814 if(!format_list.isSelectionEmpty()) { 815 ignore = true; 816 current_format = (Format)format_list.getSelectedValue(); 817 // Try to match the target, remembering the entries within are Entry's 818 Entry an_entry = new Entry(current_format.getFeature()); 819 feature.setSelectedItem(an_entry); 820 // Try to match the part. 821 part.setSelectedItem(current_format.getPart()); 822 // Now use type to determine what controls are visible, and what have initial values. 823 switch(current_format.getType()) { 824 case Format.FLAG: 825 // Flags first. 826 part.setEnabled(false); 827 part_pane.remove(part); 828 card_layout.show(view_pane, FLAG); 829 view_type = FLAG; 830 // Initial value 831 on.setSelected(current_format.getState()); 832 off.setSelected(!current_format.getState()); 833 add.setEnabled(false); // Can only update 834 break; 835 default: 836 part.setEnabled(true); 837 part_pane.add(part, BorderLayout.CENTER); 838 card_layout.show(view_pane, CUSTOM); 839 view_type = CUSTOM; 840 // Initial value 841 editor.setText(unformat(current_format.getValue())); 842 add.setEnabled(false); 843 } 844 control_pane.updateUI(); 845 ignore = false; 846 preview.setEnabled(true); 847 remove.setEnabled(true); 848 new_entry = false; 849 } 850 else { 851 preview.setEnabled(false); 852 remove.setEnabled(false); 853 } 854 } 855 } 856 } 857 private class InsertListener 858 implements ActionListener { 859 public void actionPerformed(ActionEvent event) { 860 editor.insert((String)special.getSelectedItem(), editor.getCaretPosition()); 861 } 862 } 863 private class PartListener 864 implements ActionListener { 865 public void actionPerformed(ActionEvent event) { 866 if(!ignore) { 867 current_format = null; 868 Entry entry = (Entry) feature.getSelectedItem(); 869 String name = entry.toString(); 870 if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && editor.getText().length() != 0) { 871 add.setEnabled(true); 872 } 873 else { 874 add.setEnabled(false); 875 } 876 new_entry = true; 877 } 878 } 879 } 880 private class PreviewListener 881 implements ActionListener { 882 public void actionPerformed(ActionEvent event) { 883 } 884 } 885 private class RemoveListener 886 implements ActionListener { 887 public void actionPerformed(ActionEvent event) { 888 if(!format_list.isSelectionEmpty()) { 889 removeFormat((Format)format_list.getSelectedValue()); 890 // Change buttons 891 add.setEnabled(true); 892 remove.setEnabled(false); 893 } 894 } 895 } 896 private class StateListener 897 implements ActionListener { 898 public void actionPerformed(ActionEvent event) { 899 if(!ignore && current_format != null) { 900 // We have just performed an edit. Immediately update the format and model. 901 current_format.setState(on.isSelected()); 902 model.refresh(); 903 } 904 } 905 } 906 private class ValueListener 907 extends KeyAdapter { 908 public void keyReleased(KeyEvent event) { 909 if(!ignore && current_format != null) { 910 // We have just performed an edit. Immediately update the format and model. 911 current_format.setValue(value.getText()); 912 model.refresh(); 913 } 914 } 915 } 916 } 917 917 } -
trunk/gli/src/org/greenstone/gatherer/cdm/GUI.java
r4293 r4366 86 86 */ 87 87 public class GUI 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 88 extends JPanel { 89 /** A reference to the collection manager, as it is here that all of the other data members and managers reside. */ 90 private CollectionDesignManager manager = null; 91 /** The controls used to modify the general options. */ 92 private Control controls = null; 93 /** A tree to serve as a 'table of contents' for this design tool. We decided on a tree rather than a list, as it allows us to break sections into subsections if they become to complicated. */ 94 private DesignTree tree = null; 95 /** A reference to the Gatherer. */ 96 private Gatherer gatherer = null; 97 /** The title located just above the content tree. */ 98 private JLabel title = null; 99 /** The panel containing both the title and the tree. */ 100 private JPanel tree_pane = null; 101 /** The panel apon which is rendered the currently selected section screen. */ 102 private JPanel view = null; 103 /** The available subscreens. */ 104 static final public String CONTENTS[] = {"General", "Indexes", "Subcollections", "Languages", "Plugins", "Classifiers", "Formats", "MetadataSets"}; 105 /** The preferred size of the collection design module screen real-estate. */ 106 static final private Dimension SIZE = new Dimension(760, 500); 107 /** Constructor. 108 * @see DesignTree 109 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 110 */ 111 public GUI(Gatherer gatherer, CollectionDesignManager manager) { 112 super(); 113 // Assignments 114 this.gatherer = gatherer; 115 this.manager = manager; 116 // Creation 117 this.title = new JLabel(get("Design_Topics")); 118 this.tree = new DesignTree(); 119 this.tree_pane = new JPanel(); 120 this.view = getControls(); 121 // Connect 122 tree.addTreeSelectionListener(new TreeListener()); 123 tree_pane.setLayout(new BorderLayout()); 124 tree_pane.add(title, BorderLayout.NORTH); 125 tree_pane.add(new JScrollPane(tree), BorderLayout.CENTER); 126 // Layout 127 setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); 128 setLayout(new BorderLayout()); 129 add(tree_pane, BorderLayout.WEST); 130 add(view, BorderLayout.CENTER); 131 } 132 /** Mark the current set of controls as invalid. If they are needed again in the future new controls will be generate. 133 133 * @see org.greenstone.gatherer.cdm.GUI.Control 134 134 */ 135 136 137 138 139 140 141 135 public void invalidateControls() { 136 if(controls != null) { 137 controls.destroy(); 138 } 139 controls = null; 140 } 141 /** Force the display to show a certain pane of controls. 142 142 * @param type A <strong>String</strong> giving the name of the submanager view we wish to display. 143 143 */ 144 145 146 147 144 public void setSelectedView(String type) { 145 tree.setSelectedView(type); 146 } 147 /** Overrides the normal updateUI to ensure that the current view also recieves an update message. 148 148 */ 149 150 151 152 153 154 155 149 public void updateUI() { 150 if(view != null) { 151 view.updateUI(); 152 } 153 super.updateUI(); 154 } 155 /**Overridden so we can exit when window is closed 156 156 * @param event A <strong>WindowsEvent</strong> that encapsulates all the information gathered about the event that called this method. 157 157 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 158 158 */ 159 160 161 162 163 164 165 159 protected void processWindowEvent(WindowEvent event) { 160 if(event.getID() == WindowEvent.WINDOW_CLOSING) { 161 manager.save(); 162 System.exit(0); 163 } 164 } 165 /** Overloaded to call get with both a key and an empty argument array. 166 166 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. 167 167 * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call. 168 168 */ 169 170 171 172 169 private String get(String key) { 170 return get(key, null); 171 } 172 /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR> 173 173 * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>. 174 174 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. … … 178 178 * @see org.greenstone.gatherer.Dictionary 179 179 */ 180 181 182 183 184 185 186 180 private String get(String key, String args[]) { 181 if(key.indexOf('.') == -1) { 182 key = "CDM.GUI." + key; 183 } 184 return gatherer.dictionary.get(key, args); 185 } 186 /** Because the CollectionDesignManager has enough to do, this class is resposible for generating the controls for the general options, all of which are stored in the aforementioned manager. 187 187 * @return A <strong>JPanel</strong> containing controls for editing the general options. 188 188 */ 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 189 private JPanel getControls() { 190 if(controls == null) { 191 controls = new Control(); 192 } 193 return controls; 194 } 195 /** This class represents the visual component of the general options stored in the CollectionDesignManager. */ 196 private class Control 197 extends JPanel { 198 /** The collection metadata representing the extra or description of the collection. */ 199 private CollectionMeta collection_extra_data = null; 200 /** The collection metadata representing the name of the collection. */ 201 private CollectionMeta collection_name_data = null; 202 /** The collection metadata representing the icon file location of the collection. */ 203 private CollectionMeta icon_collection_data = null; 204 /** The default size of label on this control. */ 205 private Dimension LABEL_SIZE = new Dimension(200,25); 206 /** The checkbox controlling public access to the collection. */ 207 private JCheckBox access = null; 208 /** The checkbox controlling the state of the collection. */ 209 private JCheckBox beta = null; 210 /** The label denoting the collection extra area. */ 211 private JLabel collection_extra_label = null; 212 /** The label denoting the collection extra language (Default). */ 213 private JLabel collection_extra_language = null; 214 /** The label denoting the collection name area. */ 215 private JLabel collection_name_label = null; 216 /** The label denoting the name language (Default). */ 217 private JLabel collection_name_language = null; 218 /** The label denoting the collection icon area. */ 219 private JLabel icon_collection_label = null; 220 /** The label denoting the icon language (Default). */ 221 private JLabel icon_collection_language = null; 222 /** The label which serves as the title of this view. */ 223 private JLabel title = null; 224 /** The panel containing the access controls. */ 225 private JPanel access_pane = null; 226 /** The panel containing the state controls. */ 227 private JPanel beta_pane = null; 228 /** The central pane that will contain the view. */ 229 private JPanel central_pane = null; 230 /** A panel used to affect internal layout of the collection extra area. */ 231 private JPanel collection_extra_inner_pane = null; 232 /** The panel containing the collection extra area. */ 233 private JPanel collection_extra_pane = null; 234 /** A panel used to affect internal layout of the collection name area. */ 235 private JPanel collection_name_inner_pane = null; 236 /** The panel containing the collection name area. */ 237 private JPanel collection_name_pane = null; 238 /** A panel used to affect internal layout of the collection icon area. */ 239 private JPanel icon_collection_inner_pane = null; 240 /** The panel containing the icon area. */ 241 private JPanel icon_collection_pane = null; 242 /** A text area used to display the inline help for this manager. */ 243 private JTextArea instructions = null; 244 /** The text field used to edit the collections title. */ 245 private JTextField collection_name = null; 246 /** The text field used to edit the file name of the collections icon. */ 247 private JTextField icon_collection = null; 248 /** A text area used to modify the collection description. */ 249 private JTextArea collection_extra = null; 250 /** Constructor. 251 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 252 * @see org.greenstone.gatherer.cdm.CollectionMeta 253 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 254 * @see org.greenstone.gatherer.cdm.Language 255 * @see org.greenstone.gatherer.cdm.LanguageManager 256 */ 257 public Control() { 258 super(); 259 collection_extra_data = manager.collectionmetadatum.getCollectionExtra(); 260 collection_name_data = manager.collectionmetadatum.getCollectionName(); 261 icon_collection_data = manager.collectionmetadatum.getIconCollection(); 262 262 // Creation. 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 263 access = new JCheckBox(get("CDM.General.Access")); 264 access.setSelected(manager.public_col); 265 access_pane = new JPanel(); 266 beta = new JCheckBox(get("CDM.General.Beta")); 267 beta.setSelected(manager.beta); 268 beta_pane = new JPanel(); 269 central_pane = new JPanel(); 270 collection_extra = new JTextArea(); 271 collection_extra_inner_pane = new JPanel(); 272 collection_extra_label = new JLabel(get("CDM.General.Collection_Extra")); 273 collection_extra_label.setHorizontalAlignment(JLabel.CENTER); 274 collection_extra_language = new JLabel(); 275 collection_extra_pane = new JPanel(); 276 if(collection_extra_data != null) { 277 collection_extra.setText(collection_extra_data.getValue()); 278 Language language = null; 279 if((language = collection_extra_data.getLanguage()) != null) { 280 collection_extra_language.setText(language.toString()); 281 } 282 else { 283 collection_extra_language.setText(manager.languages.getDefaultLanguage().toString()); 284 } 285 } 286 collection_name = new JTextField(); 287 collection_name_inner_pane = new JPanel(); 288 collection_name_label = new JLabel(get("CDM.General.Collection_Name")); 289 collection_name_label.setPreferredSize(LABEL_SIZE); 290 collection_name_language = new JLabel(); 291 collection_name_pane = new JPanel(); 292 if(collection_name_data != null) { 293 collection_name.setText(collection_name_data.getValue()); 294 Language language = null; 295 if((language = collection_name_data.getLanguage()) != null) { 296 collection_name_language.setText(language.toString()); 297 } 298 else { 299 collection_name_language.setText(manager.languages.getDefaultLanguage().toString()); 300 } 301 } 302 icon_collection = new JTextField(); 303 icon_collection_inner_pane = new JPanel(); 304 icon_collection_label = new JLabel(get("CDM.General.Icon_Collection")); 305 icon_collection_label.setPreferredSize(LABEL_SIZE); 306 icon_collection_language = new JLabel(); 307 icon_collection_pane = new JPanel(); 308 if(icon_collection_data != null) { 309 icon_collection.setText(icon_collection_data.getValue()); 310 Language language = null; 311 if((language = icon_collection_data.getLanguage()) != null) { 312 icon_collection_language.setText(language.toString()); 313 } 314 else { 315 icon_collection_language.setText(manager.languages.getDefaultLanguage().toString()); 316 } 317 } 318 instructions = new JTextArea(get("CDM.General.Instructions")); 319 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 320 instructions.setEditable(false); 321 instructions.setLineWrap(true); 322 instructions.setRows(4); 323 instructions.setWrapStyleWord(true); 324 JPanel lower = new JPanel(); 325 title = new JLabel(get("CDM.General.Title")); 326 title.setHorizontalAlignment(JLabel.CENTER); 327 title.setOpaque(true); 328 JPanel upper = new JPanel(); 329 329 // Add listeners. 330 331 332 333 334 335 330 access.addActionListener(new AccessListener()); 331 beta.addActionListener(new BetaListener()); 332 collection_extra.addKeyListener(new ChangeListener(collection_extra_data, collection_extra, "collectionextra")); 333 collection_name.addKeyListener(new ChangeListener(collection_name_data, collection_name, "collectionname")); 334 collection_name.addKeyListener(new CollectionTitleListener()); 335 icon_collection.addKeyListener(new ChangeListener(icon_collection_data, icon_collection, "iconcollection")); 336 336 // Layout 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 337 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 338 339 upper.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 340 upper.setLayout(new BorderLayout()); 341 upper.add(title, BorderLayout.NORTH); 342 upper.add(new JScrollPane(instructions), BorderLayout.CENTER); 343 344 collection_name_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 345 collection_name_language.setBorder(BorderFactory.createEmptyBorder(0,5,0,0)); 346 347 collection_name_inner_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 348 collection_name_inner_pane.setLayout(new BorderLayout()); 349 collection_name_inner_pane.add(collection_name); 350 351 collection_name_pane.setLayout(new BorderLayout()); 352 collection_name_pane.add(collection_name_label, BorderLayout.WEST); 353 collection_name_pane.add(collection_name_inner_pane, BorderLayout.CENTER); 354 collection_name_pane.add(collection_name_language, BorderLayout.EAST); 355 356 icon_collection_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 357 icon_collection_language.setBorder(BorderFactory.createEmptyBorder(0,5,0,0)); 358 359 icon_collection_inner_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 360 icon_collection_inner_pane.setLayout(new BorderLayout()); 361 icon_collection_inner_pane.add(icon_collection, BorderLayout.CENTER); 362 363 icon_collection_pane.setLayout(new BorderLayout()); 364 icon_collection_pane.add(icon_collection_label, BorderLayout.WEST); 365 icon_collection_pane.add(icon_collection_inner_pane, BorderLayout.CENTER); 366 icon_collection_pane.add(icon_collection_language, BorderLayout.EAST); 367 368 access_pane.add(access); 369 370 beta_pane.add(beta); 371 372 lower.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); 373 lower.setLayout(new GridLayout(6,1)); 374 lower.add(manager.creator.getControls()); 375 lower.add(manager.maintainer.getControls()); 376 lower.add(access_pane); 377 lower.add(beta_pane); 378 lower.add(collection_name_pane); 379 lower.add(icon_collection_pane); 380 381 collection_extra_inner_pane.setLayout(new BorderLayout()); 382 collection_extra_inner_pane.add(collection_extra_label, BorderLayout.WEST); 383 collection_extra_inner_pane.add(collection_extra_language, BorderLayout.EAST); 384 385 collection_extra.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 386 387 collection_extra_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); 388 collection_extra_pane.setLayout(new BorderLayout()); 389 collection_extra_pane.add(collection_extra_inner_pane, BorderLayout.NORTH); 390 collection_extra_pane.add(new JScrollPane(collection_extra), BorderLayout.CENTER); 391 392 central_pane.setLayout(new BorderLayout()); 393 central_pane.add(lower, BorderLayout.NORTH); 394 central_pane.add(collection_extra_pane, BorderLayout.CENTER); 395 396 setLayout(new BorderLayout()); 397 add(upper, BorderLayout.NORTH); 398 add(central_pane, BorderLayout.CENTER); 399 } 400 /** Destructor. 401 401 */ 402 403 404 402 public void destroy() { 403 } 404 /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first. 405 405 */ 406 407 408 409 410 411 412 413 414 415 406 public void updateUI() { 407 if(instructions != null) { 408 instructions.setCaretPosition(0); 409 } 410 if(collection_extra != null) { 411 collection_extra.setCaretPosition(0); 412 } 413 super.updateUI(); 414 } 415 /** Detect when the collection access changes, and update the configuration as necessary. 416 416 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 417 417 */ 418 419 420 421 422 423 424 418 private class AccessListener 419 implements ActionListener { 420 public void actionPerformed(ActionEvent event) { 421 manager.public_col = access.isSelected(); 422 } 423 } 424 /** Detect when the collection state changes and update the configuration as necessary. 425 425 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 426 426 */ 427 428 429 430 431 432 433 434 435 427 private class BetaListener 428 implements ActionListener { 429 public void actionPerformed(ActionEvent event) { 430 manager.beta = beta.isSelected(); 431 } 432 } 433 /** This class listens for any changes its registered controls, including enter actions and keys typed, and updates the fields stored in CollectionDesignManager as necessary. */ 434 private class ChangeListener 435 extends KeyAdapter { 436 436 /** The collection metadata to alter. */ 437 437 private CollectionMeta metadata = null; 438 438 /** The control we are watching for changes. */ 439 439 private JTextComponent component = null; 440 440 /** The name of the metadata to monitor. */ 441 441 private String name = null; 442 442 /** Construstor. 443 * @param metadata The <strong>CollectionMeta</strong> to alter.444 * @param component The <strong>JTextComponent</strong> we are monitoring for changes.445 * @param name The name of the metadata as a <strong>String</strong>.443 * @param metadata The <strong>CollectionMeta</strong> to alter. 444 * @param component The <strong>JTextComponent</strong> we are monitoring for changes. 445 * @param name The name of the metadata as a <strong>String</strong>. 446 446 */ 447 448 449 450 451 452 453 454 455 456 447 public ChangeListener(CollectionMeta metadata, JTextComponent component, String name) { 448 this.component = component; 449 this.metadata = metadata; 450 if(metadata != null) { 451 this.name = metadata.getName().toString(); 452 } 453 else { 454 this.name = name; 455 } 456 } 457 457 /** Any extension of a KeyAdapter may override this method so we can be informed when a key has been released (ie after the character etc has been added). In this case we want to update the appropriate metadata, however there are three distinct cases to consider:<br> 1. A simple update of the value field is all that is necessary,<br> 2. The metadata exists but it currently has no language, so we must set the language to default and update the value, or<br> 3. The metadata doesn't exist so we'll create a new one with the specified name, default language and new value.<br>This final case is highly unlikely but still possible. 458 458 * @param event An <strong>Event</strong> containing information about the key release. … … 465 465 * @see org.greenstone.gatherer.collection.CollectionManager 466 466 */ 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 467 public void keyReleased(KeyEvent event) { 468 if(metadata != null) { 469 Language language = metadata.getLanguage(); 470 if(language == null) { 471 metadata.update(metadata.getName(), manager.languages.getDefaultLanguage(), component.getText()); 472 } 473 else { 474 metadata.update(metadata.getName(), metadata.getLanguage(), component.getText()); 475 } 476 } 477 else { 478 metadata = new CollectionMeta(manager, name, manager.languages.getDefaultLanguage(), component.getText()); 479 manager.collectionmetadatum.addMetadata(metadata); 480 } 481 gatherer.c_man.configurationChanged(); 482 } 483 } 484 /** Listens for changes to the collection name and updates the windows title bar appropriately and collection file. */ 485 private class CollectionTitleListener 486 extends KeyAdapter { 487 487 /** Any extension of a KeyAdapter may override this method so we can be informed when a key has been released (ie after the character etc has been added). When such a change occurs update the main guis title bar to reflect the change and fix the collection name. 488 488 * @param event An <strong>Event</strong> containing information about the key release. 489 489 */ 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 490 public void keyReleased(KeyEvent event) { 491 String name = collection_name.getText(); 492 if(name != null && name.length() > 0) { 493 gatherer.g_man.setTitle(Utility.PROGRAM_NAME + ":\"" + name + "\""); 494 gatherer.c_man.getCollection().setTitle(name); 495 } 496 } 497 } 498 } 499 /** This tree provides a 'table of contents' for the various components of the design process (collection configuration in more technical terms). */ 500 private class DesignTree 501 extends JTree { 502 private DesignNode root = null; 503 /** Constructor. Automatically generates all of the nodes, in the order of CONTENTS. 504 */ 505 public DesignTree() { 506 super(); 507 root = new DesignNode("Root"); 508 this.setModel(new DefaultTreeModel(root)); 509 509 // Now add the design categories. 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 510 for(int i = 0; i < CONTENTS.length; i++) { 511 root.add(new DesignNode(CONTENTS[i])); 512 } 513 expandRow(0); 514 setRootVisible(false); 515 setSelectionRow(0); 516 } 517 /** Set the current view to the one specified. 518 * @param type The name of the desired view as a <strong>String</strong>. 519 * @see org.greenstone.gatherer.Gatherer 520 * @see org.greenstone.gatherer.cdm.GUI.DesignNode 521 */ 522 public void setSelectedView(String type) { 523 type = gatherer.get(type); 524 for(int i = 0; i < root.getChildCount(); i++) { 525 DesignNode child = (DesignNode) root.getChildAt(i); 526 if(child.toString().equals(type)) { 527 TreePath path = new TreePath(child.getPath()); 528 setSelectionPath(path); 529 } 530 } 531 } 532 } 533 /** A tree node that retains a reference to one of the possible design sub-views relating to the different sub-managers. */ 534 private class DesignNode 535 extends DefaultMutableTreeNode { 536 /** Constructor. 537 * @param object The <strong>Object</strong> assigned to this node. 538 538 */ 539 540 541 542 539 public DesignNode(String object) { 540 super(object); 541 } 542 /** Retrieve a textual representation of the object. 543 543 * @return A <strong>String</strong>. 544 544 */ 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 545 public String toString() { 546 return get((String)getUserObject()); 547 } 548 } 549 /** Listens for selection changes in the 'contents' tree, and switches to the appropriate view. */ 550 private class TreeListener 551 implements TreeSelectionListener { 552 /** Called whenever the selection changes, we must update the view so it matches the node selected. 553 * @param event A <strong>TreeSelectionEvent</strong> containing more information about the tree selection. 554 * @see org.greenstone.gatherer.cdm.ClassifierManager 555 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 556 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 557 * @see org.greenstone.gatherer.cdm.FormatManager 558 * @see org.greenstone.gatherer.cdm.LanguageManager 559 * @see org.greenstone.gatherer.cdm.MetadataSetManager 560 * @see org.greenstone.gatherer.cdm.SubcollectionManager 561 * @see org.greenstone.gatherer.cdm.PlugInManager 562 */ 563 public void valueChanged(TreeSelectionEvent event) { 564 if(!tree.isSelectionEmpty()) { 565 TreePath path = tree.getSelectionPath(); 566 DesignNode node = (DesignNode)path.getLastPathComponent(); 567 String type = (String)node.getUserObject(); 568 // Assure user 569 // Build and change panes. 570 remove(view); 571 view.hasFocus(); // Trigger pending information update events. 572 if(type.equals("General")) { 573 view = getControls(); 574 } 575 else if(type.equals("Indexes")) { 576 view = manager.indexes.getControls(); 577 } 578 else if(type.equals("Subcollections")) { 579 view = manager.subcollections.getControls(); 580 } 581 else if(type.equals("Languages")) { 582 view = manager.languages.getControls(); 583 } 584 else if(type.equals("Plugins")) { 585 view = manager.plugins.getControls(); 586 } 587 else if(type.equals("Classifiers")) { 588 view = manager.classifiers.getControls(); 589 } 590 else if(type.equals("Formats")) { 591 view = manager.formats.getControls(); 592 } 593 else if(type.equals("MetadataSets")) { 594 view = manager.metadatasets.getControls(); 595 } 596 add(view, BorderLayout.CENTER); 597 view.updateUI(); 598 // Ready 599 } 600 } 601 } 602 602 } -
trunk/gli/src/org/greenstone/gatherer/cdm/Index.java
r4293 r4366 57 57 import org.w3c.dom.Element; 58 58 /** This class encapsulates a single indexing pair. 59 * @author John Thompson, Greenstone Digital Library, University of Waikato60 * @version 2.261 */59 * @author John Thompson, Greenstone Digital Library, University of Waikato 60 * @version 2.2 61 */ 62 62 public class Index 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 63 implements Comparable { 64 /** A refernce to the main manager for access to other sub-managers. */ 65 private CollectionDesignManager manager = null; 66 /** The level of this index. */ 67 private int level = 0; 68 /** The sources for data this index is built apon, which are either fully qualified metadata element names or 'text'. */ 69 private Vector sources = null; 70 /** An element in the index level enumeration. */ 71 static public final int DOCUMENT = 0; 72 /** An element in the index level enumeration. */ 73 static public final int PARAGRAPH = 1; 74 /** An element in the index level enumeration. */ 75 static public final int SECTION = 2; 76 /** An values of items in the index level enumeration. */ 77 static public final String LEVEL[] = {"document","paragraph","section"}; 78 /** Constructor. 79 * @param level The level of this index as a <strong>String</string>. 80 * @param metadata The fully qualified name of the metadata this index is built on as a <strong>String</strong>, or <i>null</i> in which case the data defaults to "text". 81 */ 82 public Index(int level, Vector sources, CollectionDesignManager manager) { 83 this.level = level; 84 this.manager = manager; 85 this.sources = sources; 86 if(this.sources == null) { 87 this.sources = new Vector(); 88 this.sources.add("text"); 89 } 90 } 91 /** Method to compare two indexes. 92 92 * @param object The other index as an <strong>Object</strong>. 93 93 * @return An <i>int</i> which indicates how the indexes compare. 94 94 * @see java.lang.String 95 95 */ 96 97 98 99 100 101 102 103 96 public int compareTo(Object object) { 97 if(object instanceof Index) { 98 Index index = (Index) object; 99 return toString(false).compareTo(index.toString(false)); 100 } 101 return toString(false).compareTo(object.toString()); 102 } 103 /** Method to test for the equality of two indexes. 104 104 * @param object The other index as an <strong>Object</strong>. 105 105 * @return A <i>boolean</i> which is <i>true</i> if the two indexes are equal, <i>false</i> otherwise. 106 106 */ 107 108 109 110 111 112 113 107 public boolean equals(Object object) { 108 if(compareTo(object) == 0) { 109 return true; 110 } 111 return false; 112 } 113 /** Method to get the data source of this index. 114 114 * @return A <strong>String</string> which is a comma separated list of either fully qualified names of an assigned metadata elements, or "text". 115 115 */ 116 117 118 119 120 121 122 123 124 125 126 127 116 public String getData() { 117 String result = ""; 118 Collections.sort(sources, new IndexComparator()); 119 for(int i = 0; i < sources.size(); i++) { 120 result = result + sources.get(i).toString(); 121 if(i < sources.size() - 1) { 122 result = result + ","; 123 } 124 } 125 return result; 126 } 127 /** Method to get the value of level. 128 128 * @return The value of level as a <strong>String</strong>. 129 129 */ 130 131 132 133 130 public int getLevel() { 131 return level; 132 } 133 /** Method to get the value of metadata. 134 134 * @return The value of metadata as an <strong>Vector</strong>. 135 135 */ 136 137 138 139 136 public Vector getMetadata() { 137 return sources; 138 } 139 /** Method to retrieve this indexes name. 140 140 * @return A <strong>String</strong>. 141 141 */ 142 143 144 145 146 147 148 149 150 151 152 153 142 public String getName() { 143 if(manager != null) { 144 String name = LEVEL[level] + ":" + getData(); 145 Language language = manager.languages.getDefaultLanguage(); 146 CollectionMeta metadata = manager.collectionmetadatum.getMetadata(name, language, true); 147 if(metadata != null) { 148 return metadata.getValue(); 149 } 150 } 151 return ""; 152 } 153 /** Method to turn this object into a string representation ready to be placed in the collection configuration file. 154 154 * @return A <strong>String</strong> containing the information of this class. 155 155 */ 156 157 158 159 156 public String toString() { 157 return LEVEL[level] + ":" + getData() + " \"" + getName() + "\""; 158 } 159 /** Retrieve a textual representation of this index. 160 160 * @param show_name <i>true</i> if you want the name of this index, <i>false</i> for the gsdl index reference. 161 161 */ 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 162 public String toString(boolean show_name) { 163 if(show_name) { 164 return getName(); 165 } 166 return LEVEL[level] + ":" + getData(); 167 } 168 /** A custom comparator for comparing Indexes. */ 169 private class IndexComparator 170 implements Comparator { 171 /** Method to compare two objects, which may be either indexes or strings. 172 * @param object1 One object as an <strong>Object</strong>. 173 * @param object2 Another object as an <strong>Object</strong>. 174 * @return An <i>int</i> which indicates how they compare. 175 * @see java.lang.String 176 */ 177 public int compare(Object object1, Object object2) { 178 if(object1 instanceof Index && object2 instanceof Index) { 179 Index index1 = (Index)object1; 180 Index index2 = (Index)object2; 181 return index1.toString(false).compareTo(index2.toString(false)); 182 } 183 else if(object1 instanceof Index) { 184 Index index = (Index) object1; 185 return index.toString(false).compareTo(object2.toString()); 186 } 187 else if(object2 instanceof Index) { 188 Index index = (Index) object2; 189 return object1.toString().compareTo(index.toString(false)); 190 } 191 return object1.toString().compareTo(object2.toString()); 192 } 193 /** Method to test for the equality of two objects, which may be indexes or strings. 194 194 * @param object Another object as an <strong>Object</strong>. 195 195 * @return A <i>boolean</i> which is <i>true</i> if the two objects are equal, <i>false</i> otherwise. 196 196 */ 197 198 199 200 201 202 203 197 public boolean equals(Object object) { 198 if(compareTo(object) == 0) { 199 return true; 200 } 201 return false; 202 } 203 } 204 204 } -
trunk/gli/src/org/greenstone/gatherer/cdm/IndexManager.java
r4293 r4366 83 83 import org.w3c.dom.Element; 84 84 /** This class is resposible for storing the indexes which have been assigned to this collection and the default index, and providing methods for interacting with both these data pools. It also knows how to turn itself into a String as it would be displayed in the collection configuration file. 85 * @author John Thompson, Greenstone Digital Library, University of Waikato86 * @version 2.387 */85 * @author John Thompson, Greenstone Digital Library, University of Waikato 86 * @version 2.3 87 */ 88 88 public class IndexManager 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 89 extends DefaultListModel { 90 /** A reference to our creator, the collection design manager. */ 91 private CollectionDesignManager manager = null; 92 /** The controls for editing the indexes. */ 93 private Control controls = null; 94 /** A reference to ourselves so our inner methods have access. */ 95 private DefaultListModel model = null; 96 /** A reference to the Gatherer, for access to the Dictionary and messaging purposes. */ 97 private Gatherer gatherer = null; 98 /** The default index. */ 99 private Index default_index = null; 100 /** Constructor. 101 * @param gatherer A reference to the <strong>Gatherer</strong>. 102 * @param manager A reference to the <strong>CollectionDesignManager</strong>. 103 */ 104 public IndexManager(Gatherer gatherer, CollectionDesignManager manager) { 105 super(); 106 this.gatherer = gatherer; 107 this.manager = manager; 108 this.model = this; 109 } 110 /** Method to add a new index. 111 111 * @param index The <strong>Index</strong> to add. 112 112 * @see org.greenstone.gatherer.Gatherer 113 113 * @see org.greenstone.gatherer.collection.CollectionManager 114 114 */ 115 116 117 115 public void addIndex(Index index) { 116 if(!contains(index)) { 117 String index_str = index.toString(false).toLowerCase(); 118 118 // Add alphabetically. 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 119 for(int i = 0; i < size(); i++) { 120 Index sibling = (Index) get(i); 121 String sibling_str = sibling.toString(false).toLowerCase(); 122 int position = index_str.compareTo(sibling_str); 123 // Sibling is before index. 124 if(position > 0) { 125 // Carry on. 126 } 127 // Index is equal to, or before sibling. Insert it. 128 else if(position == 0 || position < 0) { 129 add(i, index); 130 gatherer.c_man.configurationChanged(); 131 return; 132 } 133 } 134 134 // If we got this far, we haven't inserted index, and we are out of model so. 135 136 137 138 139 140 141 142 135 addElement(index); 136 gatherer.c_man.configurationChanged(); 137 } 138 else { 139 JOptionPane.showMessageDialog(manager.gui, get("CDM.IndexManager.Index_Exists"), get("General.Warning"), JOptionPane.WARNING_MESSAGE); 140 } 141 } 142 /** Method to acquire the controls for editing the indexes. 143 143 * @return A <strong>JPanel</strong> containing the controls. 144 144 * @see org.greenstone.gatherer.cdm.IndexManager.Control 145 145 */ 146 147 148 149 150 151 152 146 public JPanel getControls() { 147 if(controls == null) { 148 controls = new Control(); 149 } 150 return controls; 151 } 152 /** Method to get the default index. 153 153 * @return The default <strong>Index</strong>. 154 154 */ 155 156 157 158 155 public Index getDefault() { 156 return default_index; 157 } 158 /** Method to retrieve a certain index, as referenced by an index number. 159 159 * @param index An <i>int</i> which indicates the position of the desired index. 160 160 * @return The <strong>Index</strong> at the given index, or <i>null</i> if no such index exists. 161 161 */ 162 163 164 165 166 167 168 162 public Index getIndex(int index) { 163 if(0 <= index && index < size()) { 164 return (Index)get(index); 165 } 166 return null; 167 } 168 /** Method to retrieve a certain index, given its name. 169 169 * @param name The name of the index as a <Strong>String</strong>. 170 170 * @return The <strong>Index</strong> that matches name, or <i>null</i> if no such index exists. 171 171 */ 172 173 174 175 176 177 178 179 180 181 182 183 184 172 public Index getIndex(String name) { 173 ///ystem.err.println("Searching for index " + name); 174 for(int i = 0; i < size(); i++) { 175 Index index = (Index) get(i); 176 if(index.toString(false).equals(name)) { 177 ///ystem.err.println("Found."); 178 return (Index)get(i); 179 } 180 } 181 ///ystem.err.println("No such index."); 182 return null; 183 } 184 /** A method to retrieve all of the indexes associated with this manager. 185 185 * @return A <strong>Vector</strong> of <strong>Index</strong>es. 186 186 */ 187 188 189 190 191 192 193 194 195 187 public Vector getIndexes() { 188 Vector indexes = new Vector(); 189 for(int i = 0; i < size(); i++) { 190 indexes.add(get(i)); 191 } 192 Collections.sort(indexes); 193 return indexes; 194 } 195 /** Mark the current set of controls, if any, as obsolete and deallocate them. If further need of the controls will cause new controls to be created. 196 196 * @see org.greenstone.gatherer.cdm.IndexManager.Control 197 197 */ 198 199 200 201 202 203 204 198 public void invalidateControls() { 199 if(controls != null) { 200 controls.destroy(); 201 } 202 controls = null; 203 } 204 /** Method that attempts to parse an index related command from the given command. If such a command is parsed, it is immediately registered with this manager. 205 205 * @param command The <strong>String</strong> to parse. 206 206 * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise. … … 208 208 * @see org.greenstone.gatherer.cdm.Index 209 209 */ 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 210 public boolean parse(String command) { 211 String temp = command.toLowerCase(); 212 if(temp.startsWith("indexes")) { 213 CommandTokenizer ct = new CommandTokenizer(command); 214 ct.nextToken(); // Throw away indexes. 215 while(ct.hasMoreTokens()) { 216 String entry = ct.nextToken(); 217 if(entry.indexOf(":") != -1) { 218 String level_str = entry.substring(0, entry.indexOf(":")); 219 String sources_raw = entry.substring(entry.indexOf(":") + 1); 220 Vector sources = new Vector(); 221 StringTokenizer st = new StringTokenizer(sources_raw, ","); 222 while(st.hasMoreTokens()) { 223 String token = st.nextToken(); 224 // We may have to replace old : with whatever namespace separator we are using. 225 token = token.replace(':', MSMUtils.NS_SEP); 226 sources.add(token); 227 } 228 for(int i = 0; i < Index.LEVEL.length; i++) { 229 if(level_str.equals(Index.LEVEL[i])) { 230 addIndex(new Index(i, sources, manager)); 231 } 232 } 233 } 234 else { 235 return false; 236 } 237 } 238 return true; 239 } 240 else if(temp.startsWith("defaultindex")) { 241 CommandTokenizer ct = new CommandTokenizer(command); 242 ct.nextToken(); 243 String entry = ct.nextToken(); 244 if(entry.indexOf(":") != -1) { 245 String level_str = entry.substring(0, entry.indexOf(":")); 246 String sources_raw = entry.substring(entry.indexOf(":") + 1); 247 Vector sources = new Vector(); 248 StringTokenizer st = new StringTokenizer(sources_raw, ","); 249 while(st.hasMoreTokens()) { 250 sources.add(st.nextToken()); 251 } 252 for(int i = 0; i < Index.LEVEL.length; i++) { 253 if(level_str.equals(Index.LEVEL[i])) { 254 setDefault(new Index(i, sources, manager)); 255 } 256 } 257 } 258 else { 259 return false; 260 } 261 return true; 262 } 263 return false; 264 } 265 266 public void removeAll() { 267 removeAllElements(); 268 default_index = null; 269 gatherer.c_man.configurationChanged(); 270 } 271 272 /** Method to remove a certain index. 273 273 * @param index The <Strong>Index</strong> to remove. 274 274 * @see org.greenstone.gatherer.Gatherer … … 277 277 * @see org.greenstone.gatherer.collection.CollectionManager 278 278 */ 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 279 public void removeIndex(Index index) { 280 if(index != null) { 281 String name = index.getName(); 282 if(name != null) { 283 Language default_language = manager.languages.getDefaultLanguage(); 284 CollectionMeta metadata = new CollectionMeta(manager, index, default_language, name); 285 manager.collectionmetadatum.removeMetadata(metadata); 286 } 287 removeElement(index); 288 if(default_index != null && default_index.equals(index)) { 289 default_index = null; 290 } 291 gatherer.c_man.configurationChanged(); 292 } 293 } 294 /** Method to set the default index. 295 295 * @param index The new default <strong>Index</strong>. 296 296 * @see org.greenstone.gatherer.Gatherer 297 297 * @see org.greenstone.gatherer.collection.CollectionManager 298 298 */ 299 300 301 302 303 304 305 306 299 public void setDefault(Index index) { 300 default_index = index; 301 if(index != null && !contains(index)) { 302 addElement(index); 303 } 304 gatherer.c_man.configurationChanged(); 305 } 306 /** Method to print out the contents of this class as a string. 307 307 * @return A <strong>String</strong> just as it would appear in the colleciton configuration file. 308 308 */ 309 310 311 312 313 314 315 316 317 318 319 320 309 public String toString() { 310 String text = ""; 311 // First the indexes. 312 if(size() > 0) { 313 text = "indexes "; 314 for(int i = 0; i < size(); i++) { 315 Index index = (Index) get(i); 316 text = text + index.toString(false); 317 if(i < size() - 1) { 318 text = text + " "; 319 } 320 } 321 321 // Now the default index if there is one, or just the first index 322 322 // if there isn't 323 324 325 326 327 328 329 330 323 if(default_index != null) { 324 text = text + "\ndefaultindex " + default_index.toString(false) + "\n"; 325 } 326 text = text + "\n"; 327 } 328 return text; 329 } 330 /** Overloaded to call get with both a key and an empty argument array. 331 331 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. 332 332 * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call. 333 333 */ 334 335 336 337 334 private String get(String key) { 335 return get(key, null); 336 } 337 /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR> 338 338 * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>. 339 339 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. … … 343 343 * @see org.greenstone.gatherer.Dictionary 344 344 */ 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 345 private String get(String key, String args[]) { 346 if(key.indexOf('.') == -1) { 347 key = "CDM.IndexManager." + key; 348 } 349 return gatherer.dictionary.get(key, args); 350 } 351 /** This class creates a set of controls for editing the indexes. */ 352 private class Control 353 extends JPanel { 354 /** The default size of a label on this control. */ 355 private Dimension LABEL_SIZE = new Dimension(120,25); 356 /** The button used to add a new index. */ 357 private JButton add = null; 358 /** The button used to clear the default index. */ 359 private JButton clear_default = null; 360 /** The button used to remove an index. */ 361 private JButton remove = null; 362 /** The button used to set the default index. */ 363 private JButton set_default = null; 364 /** The combobox used to adjust what level the new index will built on. */ 365 private JComboBox level = null; 366 /** The label denoting the default index to be built for this collection. */ 367 private JLabel default_label = null; 368 /** The label denoting the list of assigned indexes. */ 369 private JLabel index_label = null; 370 /** The label denoting the control for choosing index level. */ 371 private JLabel level_label = null; 372 /** The label denoting the name of the index. */ 373 private JLabel name_label = null; 374 /** The label denoting the list of possible sources for the index. */ 375 private JLabel source_label = null; 376 /** The title shown at the top of the index controls. */ 377 private JLabel title = null; 378 /** The list of assigned indexes. */ 379 private JList index_list = null; 380 /** The list of possible sources on which the index could be built. */ 381 private JList source_list = null; 382 /** The panel used to display the list of assigned indexes. */ 383 private JPanel assigned_pane = null; 384 /** The panel which contains the buttons used to edit indexes. */ 385 private JPanel button_pane = null; 386 /** The panel on which all other panels are displayed. */ 387 private JPanel central_pane = null; 388 /** The control pane showing the editable controls. */ 389 private JPanel control_pane = null; 390 /** The edit pane contains the list of possible sources. */ 391 private JPanel edit_pane = null; 392 /** A panel used to correctly lay out the default index label. */ 393 private JPanel default_pane = null; 394 /** The panel containing the title label and instructions. */ 395 private JPanel header_pane = null; 396 /** The lvel panel contains the control for adjusting index level. */ 397 private JPanel level_pane = null; 398 /** The pane in which the name control is set. */ 399 private JPanel name_pane = null; 400 /** The scrollpane containing the instructions text area. */ 401 private JScrollPane instructions_scroll = null; 402 /** A text area containing inline instructions. */ 403 private JTextArea instructions = null; 404 /** A text field naming the default index. Non-editable. */ 405 private JTextField default_value = null; 406 /** A text field for controlling the name of the new index. */ 407 private JTextField name = null; 408 /** A model containing all of the available index sources. */ 409 private Vector source_model = null; 410 /** Constructor. 411 * @see org.greenstone.gatherer.Configuration 412 * @see org.greenstone.gatherer.Gatherer 413 * @see org.greenstone.gatherer.cdm.IndexManager.Control.AddListener 414 * @see org.greenstone.gatherer.cdm.IndexManager.Control.ClearDefaultListener 415 * @see org.greenstone.gatherer.cdm.IndexManager.Control.NameListener 416 * @see org.greenstone.gatherer.cdm.IndexManager.Control.RemoveListener 417 * @see org.greenstone.gatherer.cdm.IndexManager.Control.SetDefaultListener 418 * @see org.greenstone.gatherer.collection.CollectionManager 419 * @see org.greenstone.gatherer.gui.Coloring 420 * @see org.greenstone.gatherer.msm.MetadataSetManager 421 * @see org.greenstone.gatherer.util.ExclusiveListSelectionListener 422 */ 423 public Control() { 424 super(); 425 source_model = new Vector(); 426 source_model.add("text"); 427 source_model.addAll(gatherer.c_man.msm.getAssignedElements()); 428 428 //source_model.addAll(gatherer.c_man.msm.getElements()); 429 429 // Creation 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 430 add = new JButton(get("Add")); 431 add.setEnabled(false); 432 add.setMnemonic(KeyEvent.VK_A); 433 assigned_pane = new JPanel(); 434 button_pane = new JPanel(); 435 central_pane = new JPanel(); 436 control_pane = new JPanel(); 437 clear_default = new JButton(get("Clear_Default")); 438 clear_default.setMnemonic(KeyEvent.VK_C); 439 if(default_index == null) { 440 clear_default.setEnabled(false); 441 } 442 default_label = new JLabel(get("Default_Index")); 443 default_pane = new JPanel(); 444 if(default_index != null) { 445 default_value = new JTextField(default_index.toString(true)); 446 default_value.setCaretPosition(0); 447 } 448 else { 449 default_value = new JTextField(); 450 } 451 edit_pane = new JPanel(); 452 header_pane = new JPanel(); 453 index_label = new JLabel(get("Indexes")); 454 index_list = new JList(model); 455 instructions = new JTextArea(get("Instructions")); 456 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 457 instructions.setEditable(false); 458 instructions.setLineWrap(true); 459 instructions.setRows(5); 460 instructions.setWrapStyleWord(true); 461 level = new JComboBox(); 462 level.addItem(get("Document")); 463 level.addItem(get("Paragraph")); 464 level.addItem(get("Section")); 465 level.setEditable(false); 466 level_label = new JLabel(get("Level")); 467 level_label.setPreferredSize(LABEL_SIZE); 468 level_pane = new JPanel(); 469 name = new JTextField(); 470 name_label = new JLabel(get("Name")); 471 name_label.setPreferredSize(LABEL_SIZE); 472 name_pane = new JPanel(); 473 remove = new JButton(get("Remove")); 474 remove.setEnabled(false); 475 remove.setMnemonic(KeyEvent.VK_R); 476 set_default = new JButton(get("Set_Default")); 477 set_default.setEnabled(false); 478 set_default.setMnemonic(KeyEvent.VK_S); 479 source_label = new JLabel(get("Source")); 480 source_list = new JList(source_model); 481 title = new JLabel(get("Title")); 482 title.setHorizontalAlignment(JLabel.CENTER); 483 483 484 484 // Listeners 485 486 487 488 489 490 491 492 493 494 495 485 add.addActionListener(new AddListener()); 486 clear_default.addActionListener(new ClearDefaultListener()); 487 remove.addActionListener(new RemoveListener()); 488 set_default.addActionListener(new SetDefaultListener()); 489 name.addKeyListener(new NameListener()); 490 ListListener ll = new ListListener(); 491 index_list.addListSelectionListener(ll); 492 source_list.addListSelectionListener(ll); 493 ExclusiveListSelectionListener elsl = new ExclusiveListSelectionListener(); 494 elsl.add(index_list); 495 elsl.add(source_list); 496 496 497 497 // Layout 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 498 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0)); 499 500 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 501 502 header_pane.setLayout(new BorderLayout()); 503 header_pane.add(title, BorderLayout.NORTH); 504 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 505 506 name_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 507 508 name_pane.setBorder(BorderFactory.createEmptyBorder(4,2,4,2)); 509 name_pane.setLayout(new BorderLayout()); 510 name_pane.add(name_label, BorderLayout.WEST); 511 name_pane.add(name, BorderLayout.CENTER); 512 513 control_pane.setLayout(new BorderLayout()); 514 control_pane.add(source_label, BorderLayout.NORTH); 515 control_pane.add(new JScrollPane(source_list), BorderLayout.CENTER); 516 517 level_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 518 519 level_pane.setBorder(BorderFactory.createEmptyBorder(4,2,4,2)); 520 level_pane.setLayout(new BorderLayout()); 521 level_pane.add(level_label, BorderLayout.WEST); 522 level_pane.add(level, BorderLayout.CENTER); 523 524 edit_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 525 edit_pane.setLayout(new BorderLayout()); 526 edit_pane.add(name_pane, BorderLayout.NORTH); 527 edit_pane.add(control_pane, BorderLayout.CENTER); 528 edit_pane.add(level_pane, BorderLayout.SOUTH); 529 530 default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 531 532 default_pane.setBorder 533 (BorderFactory.createCompoundBorder 534 (BorderFactory.createCompoundBorder 535 (BorderFactory.createEmptyBorder(2,2,2,2), 536 BorderFactory.createRaisedBevelBorder()), 537 BorderFactory.createEmptyBorder(2,2,2,2))); 538 default_pane.setLayout(new BorderLayout()); 539 default_pane.add(default_label, BorderLayout.WEST); 540 default_pane.add(default_value, BorderLayout.CENTER); 541 542 assigned_pane.setLayout(new BorderLayout()); 543 assigned_pane.add(index_label, BorderLayout.NORTH); 544 assigned_pane.add(new JScrollPane(index_list), BorderLayout.CENTER); 545 assigned_pane.add(default_pane, BorderLayout.SOUTH); 546 547 central_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0)); 548 central_pane.setLayout(new GridLayout(1,2)); 549 central_pane.add(edit_pane); 550 central_pane.add(assigned_pane); 551 552 button_pane.setLayout(new GridLayout(2,2)); 553 button_pane.add(add); 554 button_pane.add(remove); 555 button_pane.add(clear_default); 556 button_pane.add(set_default); 557 558 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 559 setLayout(new BorderLayout()); 560 add(header_pane, BorderLayout.NORTH); 561 add(central_pane, BorderLayout.CENTER); 562 add(button_pane, BorderLayout.SOUTH); 563 } 564 /* Destructor, removes persistant listeners from the Dictionary. 565 565 */ 566 567 568 566 public void destroy() { 567 } 568 /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first. 569 569 * @see org.greenstone.gatherer.Gatherer 570 570 * @see org.greenstone.gatherer.collection.CollectionManager 571 571 * @see org.greenstone.gatherer.msm.MetadataSetManager 572 572 */ 573 574 575 576 573 public void updateUI() { 574 if(instructions != null) { 575 instructions.setCaretPosition(0); 576 } 577 577 // Reload the assigned indexes list. 578 579 580 581 582 578 if(source_model != null) { 579 source_model.clear(); 580 source_model.add("text"); 581 source_model.addAll(gatherer.c_man.msm.getAssignedElements()); 582 } 583 583 // Faster than a NPE its the - 'Super class'. 584 585 586 587 588 584 super.updateUI(); 585 } 586 /** Listens for actions apon the 'add' button in the IndexManager controls, and if detected calls the add method of the manager with a newly created index. */ 587 private class AddListener 588 implements ActionListener { 589 589 /** Method called when an action is performed on a registered component, and when it does we check if we have enough data to create a new index, and if so we create one. 590 * @param event An <strong>ActionEvent</strong> providing extra information about the event. 591 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 592 * @see org.greenstone.gatherer.cdm.CollectionMeta 593 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 594 * @see org.greenstone.gatherer.cdm.Index 595 * @see org.greenstone.gatherer.cdm.Language 596 * @see org.greenstone.gatherer.cdm.LanguageManager 590 * @param event An <strong>ActionEvent</strong> providing extra information about the event. 591 * @see org.greenstone.gatherer.cdm.CollectionDesignManager 592 * @see org.greenstone.gatherer.cdm.CollectionMeta 593 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 594 * @see org.greenstone.gatherer.cdm.Index 595 * @see org.greenstone.gatherer.cdm.Language 596 * @see org.greenstone.gatherer.cdm.LanguageManager 597 */ 598 public void actionPerformed(ActionEvent event) { 599 if(!source_list.isSelectionEmpty() && name.getText().length() != 0) { 600 Object object[] = source_list.getSelectedValues(); 601 Vector sources = new Vector(); 602 for(int i = 0; i < object.length; i++) { 603 sources.add(object[i]); 604 } 605 Index index = new Index(level.getSelectedIndex(), sources, manager); 606 // Before we add the index to the model, we have to add the collection metadata for this. 607 Language language = manager.languages.getDefaultLanguage(); 608 CollectionMeta metadata = new CollectionMeta(manager, index, language, name.getText()); 609 manager.collectionmetadatum.addMetadata(metadata); 610 // Finally add index. 611 addIndex(index); 612 } 613 } 614 } 615 /** Listens for actions apon the 'clear default' button in the IndexManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */ 616 private class ClearDefaultListener 617 implements ActionListener { 618 /** If called when an action occurs on a registered component, we clear the default index. 619 * @param event An <strong>ActionEvent</strong> containing extra information about the action that occured. 597 620 */ 598 public void actionPerformed(ActionEvent event) { 599 if(!source_list.isSelectionEmpty() && name.getText().length() != 0) { 600 Object object[] = source_list.getSelectedValues(); 601 Vector sources = new Vector(); 602 for(int i = 0; i < object.length; i++) { 603 sources.add(object[i]); 604 } 605 Index index = new Index(level.getSelectedIndex(), sources, manager); 606 // Before we add the index to the model, we have to add the collection metadata for this. 607 Language language = manager.languages.getDefaultLanguage(); 608 CollectionMeta metadata = new CollectionMeta(manager, index, language, name.getText()); 609 manager.collectionmetadatum.addMetadata(metadata); 610 // Finally add index. 611 addIndex(index); 612 } 613 } 614 } 615 /** Listens for actions apon the 'clear default' button in the IndexManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */ 616 private class ClearDefaultListener 617 implements ActionListener { 618 /** If called when an action occurs on a registered component, we clear the default index. 619 * @param event An <strong>ActionEvent</strong> containing extra information about the action that occured. 621 public void actionPerformed(ActionEvent event) { 622 setDefault(null); 623 clear_default.setEnabled(false); 624 default_value.setText(""); 625 } 626 } 627 /** Listens for actions apon the 'remove' button in the IndexManager controls, and if detected calls the remove method of the manager with the index selected for removal. */ 628 private class RemoveListener 629 implements ActionListener { 630 /** If called when an action occurs on a registered component, we remove the currently selected index, if there is one. 631 * @param event An <strong>ActionEvent</strong> containing extra information about the action that occured. 632 * @see org.greenstone.gatherer.cdm.Index 633 */ 634 public void actionPerformed(ActionEvent event) { 635 if(!index_list.isSelectionEmpty()) { 636 removeIndex((Index)index_list.getSelectedValue()); 637 if(default_index == null) { 638 clear_default.setEnabled(false); 639 default_value.setText(""); 640 } 641 } 642 } 643 } 644 /** Listens for actions apon the 'set default' button in the IndexManager controls, and if detected calls the setDefault method of the manager with the index selected for default. */ 645 private class SetDefaultListener 646 implements ActionListener { 647 /** If called when an action occurs on a registered component, we set the default index to the index currently selected. 648 * @param event An <strong>ActionEvent</strong> containing extra information about the action that occured. 649 * @see org.greenstone.gatherer.cdm.Index 650 */ 651 public void actionPerformed(ActionEvent event) { 652 setDefault((Index)index_list.getSelectedValue()); 653 if(default_index != null) { 654 clear_default.setEnabled(true); 655 default_value.setText(default_index.toString(true)); 656 default_value.setCaretPosition(0); 657 } 658 else { 659 clear_default.setEnabled(false); 660 default_value.setText(""); 661 } 662 } 663 } 664 /** Listens for key presses within the name field, and enabled or disables controls as appropriate. */ 665 private class NameListener 666 extends KeyAdapter { 667 /** Called when a key is released, this is the perfect time to enable the add button if the fields are appropriately set. 668 * @param event A <strong>KeyEvent</strong> containing information about the key released. 620 669 */ 621 public void actionPerformed(ActionEvent event) { 622 setDefault(null); 623 clear_default.setEnabled(false); 624 default_value.setText(""); 625 } 626 } 627 /** Listens for actions apon the 'remove' button in the IndexManager controls, and if detected calls the remove method of the manager with the index selected for removal. */ 628 private class RemoveListener 629 implements ActionListener { 630 /** If called when an action occurs on a registered component, we remove the currently selected index, if there is one. 631 * @param event An <strong>ActionEvent</strong> containing extra information about the action that occured. 632 * @see org.greenstone.gatherer.cdm.Index 670 public void keyReleased(KeyEvent event) { 671 if(source_list.isSelectionEmpty() || name.getText().length() == 0) { 672 add.setEnabled(false); 673 } 674 else { 675 add.setEnabled(true); 676 } 677 if(index_list.isSelectionEmpty()) { 678 remove.setEnabled(false); 679 set_default.setEnabled(false); 680 } 681 else { 682 remove.setEnabled(true); 683 set_default.setEnabled(true); 684 } 685 } 686 } 687 /** Listens for selections within the list on the IndexManager controls, and if a change is detected enables, or disables, controls appropriately. */ 688 private class ListListener 689 implements ListSelectionListener { 690 /** This method is called whenever the source list selection changes. When it does we need to check if the add button should now be enabled. 691 * @param event A <strong>ListSelectionEvent</strong> containing further information about the list selection. 633 692 */ 634 public void actionPerformed(ActionEvent event) { 635 if(!index_list.isSelectionEmpty()) { 636 removeIndex((Index)index_list.getSelectedValue()); 637 if(default_index == null) { 638 clear_default.setEnabled(false); 639 default_value.setText(""); 640 } 641 } 642 } 643 } 644 /** Listens for actions apon the 'set default' button in the IndexManager controls, and if detected calls the setDefault method of the manager with the index selected for default. */ 645 private class SetDefaultListener 646 implements ActionListener { 647 /** If called when an action occurs on a registered component, we set the default index to the index currently selected. 648 * @param event An <strong>ActionEvent</strong> containing extra information about the action that occured. 649 * @see org.greenstone.gatherer.cdm.Index 650 */ 651 public void actionPerformed(ActionEvent event) { 652 setDefault((Index)index_list.getSelectedValue()); 653 if(default_index != null) { 654 clear_default.setEnabled(true); 655 default_value.setText(default_index.toString(true)); 656 default_value.setCaretPosition(0); 657 } 658 else { 659 clear_default.setEnabled(false); 660 default_value.setText(""); 661 } 662 } 663 } 664 /** Listens for key presses within the name field, and enabled or disables controls as appropriate. */ 665 private class NameListener 666 extends KeyAdapter { 667 /** Called when a key is released, this is the perfect time to enable the add button if the fields are appropriately set. 668 * @param event A <strong>KeyEvent</strong> containing information about the key released. 669 */ 670 public void keyReleased(KeyEvent event) { 671 if(source_list.isSelectionEmpty() || name.getText().length() == 0) { 672 add.setEnabled(false); 673 } 674 else { 675 add.setEnabled(true); 676 } 677 if(index_list.isSelectionEmpty()) { 678 remove.setEnabled(false); 679 set_default.setEnabled(false); 680 } 681 else { 682 remove.setEnabled(true); 683 set_default.setEnabled(true); 684 } 685 } 686 } 687 /** Listens for selections within the list on the IndexManager controls, and if a change is detected enables, or disables, controls appropriately. */ 688 private class ListListener 689 implements ListSelectionListener { 690 /** This method is called whenever the source list selection changes. When it does we need to check if the add button should now be enabled. 691 * @param event A <strong>ListSelectionEvent</strong> containing further information about the list selection. 692 */ 693 public void valueChanged(ListSelectionEvent event) { 694 if(source_list.isSelectionEmpty() || name.getText().length() == 0) { 695 add.setEnabled(false); 696 } 697 else { 698 add.setEnabled(true); 699 } 700 if(index_list.isSelectionEmpty()) { 701 remove.setEnabled(false); 702 set_default.setEnabled(false); 703 } 704 else { 705 remove.setEnabled(true); 706 set_default.setEnabled(true); 707 } 708 } 709 } 710 } 693 public void valueChanged(ListSelectionEvent event) { 694 if(source_list.isSelectionEmpty() || name.getText().length() == 0) { 695 add.setEnabled(false); 696 } 697 else { 698 add.setEnabled(true); 699 } 700 if(index_list.isSelectionEmpty()) { 701 remove.setEnabled(false); 702 set_default.setEnabled(false); 703 } 704 else { 705 remove.setEnabled(true); 706 set_default.setEnabled(true); 707 } 708 } 709 } 710 } 711 711 } 712 712 -
trunk/gli/src/org/greenstone/gatherer/cdm/Language.java
r4293 r4366 56 56 */ 57 57 public class Language 58 59 60 61 62 63 64 65 66 67 68 58 implements Comparable { 59 /** Is this language the default one. */ 60 private boolean default_language = false; 61 /** The name of this language. */ 62 private String name = null; 63 /** The two character code for this language. */ 64 private String value = null; 65 /** Constructor. 66 * @param value A <strong>String</strong> representing the code for this language. 67 * @param name A <strong>String</strong> representing the name of this language. 68 * @param default_language A <i>boolean</i> which is <i>true</i> if this language is the default one. 69 69 */ 70 71 72 73 74 75 70 public Language(String value, String name, boolean default_language) { 71 this.default_language = default_language; 72 this.name = name; 73 this.value = value.substring(0, 2); 74 } 75 /** Copy constructor. 76 76 * @param language The <strong>Language</strong> we want to copy. 77 77 */ 78 79 80 81 82 83 78 public Language(Language language) { 79 this.default_language = language.isDefault(); 80 this.name = language.toString(); 81 this.value = language.getCode(); 82 } 83 /** Method to compare two languages for ordering purposes. 84 84 * @param object The other language as an <strong>Object</strong>. 85 85 * @return An <i>int</i> which indicates order using the same values as in String.compareTo(). 86 86 * @see java.lang.String#compareTo 87 87 */ 88 89 90 91 88 public int compareTo(Object object) { 89 return toString().compareTo(object.toString()); 90 } 91 /** Method to test for the equality of two languages. 92 92 * @param object The other language as an <strong>Object</strong>. 93 93 * @return <i>true</i> if the languages are equal, <i>false</i> otherwise. 94 94 */ 95 96 97 98 99 100 101 95 public boolean equals(Object object) { 96 if(compareTo(object) == 0) { 97 return true; 98 } 99 return false; 100 } 101 /** Method to retrieve the code of this language. 102 102 * @return A <strong>String</strong> representing the two letter code. 103 103 */ 104 105 106 107 104 public String getCode() { 105 return value; 106 } 107 /** Method to determine if this language is the default one. 108 108 * @return A <i>boolean</i> which is <i>true</i> if this language is the default one. 109 109 */ 110 111 112 113 110 public boolean isDefault() { 111 return default_language; 112 } 113 /** Method to set the value of default. 114 114 * @param value The new value of default as a <i>boolean</i>. 115 115 */ 116 117 118 119 116 public void setDefault(boolean value) { 117 this.default_language = default_language; 118 } 119 /** Method to display the language code. 120 120 * @return A <strong>String</strong> representing the language code. 121 121 */ 122 123 124 122 public String toString() { 123 return name; 124 } 125 125 } 126 126 -
trunk/gli/src/org/greenstone/gatherer/cdm/LanguageManager.java
r4293 r4366 85 85 import org.greenstone.gatherer.cdm.Language; 86 86 /** This class manages the language commands, remembering both a list of languages to build indexes in, plus the default language. 87 * @author John Thompson, Greenstone Digital Library, University of Waikato88 * @version 2.389 */87 * @author John Thompson, Greenstone Digital Library, University of Waikato 88 * @version 2.3 89 */ 90 90 public class LanguageManager 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 91 extends DefaultListModel { 92 /** A reference to the collection design manager. */ 93 private CollectionDesignManager manager = null; 94 /** The visual controls for this manager. */ 95 private Control controls = null; 96 /** A reference to the Gatherer. */ 97 private Gatherer gatherer = null; 98 /** A reference to this class as a model, for the inner controls class. */ 99 private ListModel model = null; 100 /** A hashtable of code->name mappings of known languages. */ 101 private LinkedHashMap known_languages = null; 102 /** The default language object. */ 103 private Language default_language = null; 104 /** Constructor. 105 * @param gatherer A reference to the <strong>Gatherer</strong>. 106 * @param manager A reference to the <strong>CollectionDesignManager</strong>. 107 */ 108 public LanguageManager(Gatherer gatherer, CollectionDesignManager manager) { 109 super(); 110 this.gatherer = gatherer; 111 this.known_languages = new LinkedHashMap(); 112 this.manager = manager; 113 this.model = this; 114 loadLanguages(); 115 } 116 /** Method to add a new language. 117 117 * @param language The <strong>Language</strong> to add. 118 118 * @see org.greenstone.gatherer.Gatherer 119 119 * @see org.greenstone.gatherer.collection.CollectionManager 120 120 */ 121 122 121 public void addLanguage(Language language) { 122 if(!contains(language)) { 123 123 // Add alphabetically. 124 125 126 127 128 129 130 131 132 133 134 135 136 137 124 for(int index = 0; index < size(); index++) { 125 Language sibling = (Language) get(index); 126 int position = language.compareTo(sibling); 127 // Sibling is before language. 128 if(position > 0) { 129 // Carry on. 130 } 131 // Language is equal to, or before sibling. Insert it. 132 else if(position == 0 || position < 0) { 133 add(index, language); 134 gatherer.c_man.configurationChanged(); 135 return; 136 } 137 } 138 138 // If we got this far, we haven't inserted language, and we are out of model so. 139 140 141 142 143 139 addElement(language); 140 gatherer.c_man.configurationChanged(); 141 } 142 } 143 /** Method to retrieve the control for this manager. 144 144 * @return A <strong>JPanel</strong> containing the controls. 145 145 */ 146 147 148 149 150 151 152 146 public JPanel getControls() { 147 if(controls == null) { 148 controls = new Control(); 149 } 150 return controls; 151 } 152 /** Method to retrieve the default language code. 153 153 * @return A <strong>Language</strong> containing a two letter code. 154 154 */ 155 156 157 155 public Language getDefaultLanguage() { 156 // If no default is set... 157 if(default_language == null) { 158 158 // And we have other assigned languages, use the first one of them. 159 160 161 159 if(size() >= 1) { 160 default_language = (Language) get(0); 161 } 162 162 // And we have nothing else, use English. 163 164 165 166 167 168 169 170 171 163 else { 164 default_language = getLanguage("en", false); 165 // Remember to add it. 166 addLanguage(default_language); 167 } 168 } 169 return default_language; 170 } 171 /** Method to retrieve a certain language object by its code. 172 172 * @param code The two letter code of a language, as a <strong>String</strong>. 173 173 * @param assigned_only If <i>true</i> only those languages currently having indexes built for them are checked, otherwise the known languages buffer is checked. 174 174 * @return The <strong>Language</strong> that matches the given code, or <i>null</i> if no such language exists. 175 175 */ 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 176 public Language getLanguage(String code, boolean assigned_only) { 177 if(assigned_only) { 178 for(int i = 0; i < size(); i++) { 179 Language pos = (Language)get(i); 180 ///ystem.err.println("Comparing " + pos.getCode() + " and " + code); 181 if(pos.getCode().equals(code)) { 182 return pos; 183 } 184 } 185 } 186 else { 187 if(known_languages.containsKey(code)) { 188 return new Language((Language)known_languages.get(code)); 189 } 190 } 191 return null; 192 } 193 /** Method to return a list of the known language codes. 194 194 * @return An <strong>ArrayList</strong> containing a series of alphabetically sorted two letter codes. 195 195 */ 196 197 198 199 200 201 202 203 204 205 206 207 208 196 public ArrayList getLanguageCodes() { 197 ArrayList result = new ArrayList(); 198 Iterator key_iter = known_languages.keySet().iterator(); 199 while(key_iter.hasNext()) { 200 result.add(known_languages.get(key_iter.next())); 201 } 202 //for(Enumeration keys = known_languages.keys(); keys.hasMoreElements(); ) { 203 // result.add(known_languages.get(keys.nextElement())); 204 //} 205 //Collections.sort(result); 206 return result; 207 } 208 /** Mark the current set of controls, if any, as obsolete and deallocate them. If further need of the controls will cause new controls to be created. 209 209 * @see org.greenstone.gatherer.cdm.IndexManager.Control 210 210 */ 211 212 213 214 215 216 217 218 211 public void invalidateControls() { 212 if(controls != null) { 213 controls.destroy(); 214 } 215 controls = null; 216 } 217 218 /** Determine if the given language is the current default language. 219 219 * @param language The <strong>Language</strong> to test. 220 220 * @return <i>true</i> if the language is the default one, <i>false</i> otherwise. 221 221 */ 222 223 224 225 222 public boolean isDefaultLanguage(Language language) { 223 return (language.equals(default_language)); 224 } 225 /** This method attempts to parse a language command from the given string. If such a command is parsed, it is immediately added to the list of languages. 226 226 * @param command The <strong>String</strong> containing a possible language command. 227 227 * @return A <i>boolean</i> which is <i>true</i> if a command was parsed, <i>false</i> otherwise. 228 228 * @see org.greenstone.gatherer.cdm.Language 229 229 */ 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 230 public boolean parse(String command) { 231 String command_lc = command.toLowerCase(); 232 if(command_lc.startsWith("languages")) { 233 StringTokenizer tokenizer = new StringTokenizer(command); 234 tokenizer.nextToken(); 235 while(tokenizer.hasMoreTokens()) { 236 String code = tokenizer.nextToken(); 237 if(known_languages.containsKey(code)) { 238 Language language = (Language)known_languages.get(code); 239 addElement(new Language(language)); 240 } 241 else { 242 addElement(new Language(code, code, false)); 243 } 244 } 245 return true; 246 } 247 if(command_lc.startsWith("defaultlanguage")) { 248 StringTokenizer tokenizer = new StringTokenizer(command); 249 tokenizer.nextToken(); 250 if(tokenizer.hasMoreTokens()) { 251 String code = tokenizer.nextToken(); 252 Language language = getLanguage(code, true); 253 if(language == null) { 254 language = new Language(code, (String)known_languages.get(code), true); 255 addElement(language); 256 } 257 else { 258 language.setDefault(true); 259 } 260 setDefault(language); 261 } 262 return true; 263 } 264 return false; 265 } 266 /** Method to cause the list appearance to update if the selection changes. */ 267 public void refreshAppearance() { 268 fireContentsChanged(this, 0, size()); 269 } 270 /** Method to remove a certain language. 271 271 * @param language The <strong>Language</strong> to remove. 272 272 * @see org.greenstone.gatherer.Gatherer 273 273 * @see org.greenstone.gatherer.collection.CollectionManager 274 274 */ 275 276 277 278 279 280 281 282 275 public void removeLanguage(Language language) { 276 removeElement(language); 277 if(default_language != null && default_language.equals(language)) { 278 default_language = null; 279 } 280 gatherer.c_man.configurationChanged(); 281 } 282 /** Method to set the default language. 283 283 * @param language The <strong>Language</strong> to use as a default, or <i>null</i> for no default. 284 284 * @see org.greenstone.gatherer.Gatherer 285 285 * @see org.greenstone.gatherer.collection.CollectionManager 286 286 */ 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 287 public void setDefault(Language language) { 288 // Unset existing. 289 Language old = null; 290 if(default_language != null) { 291 old = default_language; 292 default_language.setDefault(false); 293 default_language = null; 294 } 295 // Now set the new if its not null. 296 if(language != null) { 297 default_language = language; 298 default_language.setDefault(true); 299 } 300 // Now cause the model to refresh any lists that are listening. 301 int start = 0; 302 int end = size() - 1; 303 if(default_language != null && old != null) { 304 int index_default = indexOf(default_language); 305 int index_old = indexOf(old); 306 if(index_default < index_old) { 307 start = index_default; 308 end = index_old; 309 } 310 else { 311 start = index_old; 312 end = index_default; 313 } 314 } 315 else if(default_language != null) { 316 start = end = indexOf(default_language); 317 } 318 else { 319 start = end = indexOf(old); 320 } 321 fireContentsChanged(this, 0, size()); 322 gatherer.c_man.configurationChanged(); 323 } 324 /** Method to translate this object into a block of commands as you you expect to find in the collection configuration file. 325 325 * @return A <strong>String</string> containing a series of commands. 326 326 */ 327 328 329 330 331 332 333 334 335 336 337 338 339 340 327 public String toString() { 328 StringBuffer text = new StringBuffer(); 329 if(size() > 1) { 330 text.append("languages "); 331 for(int i = 0; i < size(); i++) { 332 Language language = (Language) get(i); 333 text.append(language.getCode()); 334 if(i < size() - 1) { 335 text.append(" "); 336 } 337 else { 338 text.append("\n"); 339 } 340 } 341 341 // Only bother with default language if there is more than one language. 342 343 344 345 346 347 348 349 350 351 342 if(default_language != null) { 343 text.append("defaultlanguage "); 344 text.append(default_language.getCode()); 345 text.append("\n"); 346 } 347 text.append("\n"); 348 } 349 return text.toString(); 350 } 351 /** Overloaded to call get with both a key and an empty argument array. 352 352 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. 353 353 * @return A <strong>String</strong> which has been referenced by the key String and that either contains no argument fields, or has had the argument fields automatiically populated with formatting Strings of with argument String provided in the get call. 354 354 */ 355 356 357 358 355 private String get(String key) { 356 return get(key, null); 357 } 358 /** Used to retrieve a property value from the Locale specific ResourceBundle, based upon the key and arguments supplied. If the key cannot be found or if some other part of the call fails a default (English) error message is returned. <BR> 359 359 * Here the get recieves a second argument which is an array of Strings used to populate argument fields, denoted {<I>n</I>}, within the value String returned. Note that argument numbers greater than or equal to 32 are automatically mapped to the formatting String named Farg<I>n</I>. 360 360 * @param key A <strong>String</strong> which is mapped to a initial String within the ResourceBundle. … … 364 364 * @see org.greenstone.gatherer.Dictionary 365 365 */ 366 367 368 369 370 371 372 366 private String get(String key, String args[]) { 367 if(key.indexOf('.') == -1) { 368 key = "CDM.LanguageManager." + key; 369 } 370 return gatherer.dictionary.get(key, args); 371 } 372 /** This method loads a series of code->language mappings into known_languages, by reading from the 'languages.dat' file, which is essentially a verbatim copy of the ISO 639 Standard. 373 373 * @see org.greenstone.gatherer.cdm.Language 374 374 */ 375 private void loadLanguages() { 376 try { 377 File in_file = new File("languages.dat"); 378 FileReader in_reader = new FileReader(in_file); 379 BufferedReader in = new BufferedReader(in_reader); 380 String entry = null; 381 while((entry = in.readLine()) != null) { 382 if(!entry.startsWith("#")) { 383 StringTokenizer tokenizer = new StringTokenizer(entry); 384 String name = tokenizer.nextToken(); 385 String code = tokenizer.nextToken().toLowerCase(); 386 Language language = new Language(code, name, false); 387 known_languages.put(code, language); 388 } 389 } 390 in.close(); 391 } 392 catch (Exception error) { 393 error.printStackTrace(); 394 } 395 } 396 397 /** This class represents the visual component of the Language Manager. */ 398 private class Control 399 extends JPanel { 400 /** The button to add a new language support. */ 401 private JButton add = null; 402 /** The button to clear the current default language. */ 403 private JButton clear_default = null; 404 /** The button to remove a supported language. */ 405 private JButton remove = null; 406 /** The button to set the current language as the default one. */ 407 private JButton set_default = null; 408 /** A button to active the translation manager prompt. */ 409 private JButton translate = null; 410 /** A combobox listing the available supported languages. */ 411 private JComboBox selector = null; 412 /** The label denoting the default language. */ 413 private JLabel default_language_label = null; 414 /** The label denoting the language selector. */ 415 private JLabel selector_label = null; 416 /** The title label of this control view. */ 417 private JLabel title = null; 418 /** A list of currently supported languages. */ 419 private JList list = null; 420 /** The pane in which the control buttons are placed. */ 421 private JPanel button_pane = null; 422 /** The pane onto which all other panes are placed. */ 423 private JPanel central_pane = null; 424 /** The pane to the left containing editing controls. */ 425 private JPanel control_pane = null; 426 /** A panel used to correctly layout the default language box. */ 427 private JPanel default_language_pane = null; 428 /** The display pane contains the title and instruction controls. */ 429 private JPanel display_pane = null; 430 /** The pane which holds everything the display pane doesn't! */ 431 private JPanel lower_pane = null; 432 /** The pane containing the selector combobox. */ 433 private JPanel selector_pane = null; 434 /** A text area displaying inline instructions. */ 435 private JTextArea instructions = null; 436 /** A description of the language currently selected. */ 437 private JTextArea description = null; 438 /** The text field showing the currently name of the default language. Non-editable. */ 439 private JTextField default_language_value = null; 440 /** Constructor. 441 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.AddListener 442 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.ClearDefaultListener 443 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.ListListener 444 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.RemoveListener 445 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.SelectorListener 446 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.SetDefaultListener 447 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.TranslateListener 375 private void loadLanguages() { 376 try { 377 File in_file = new File("languages.dat"); 378 FileReader in_reader = new FileReader(in_file); 379 BufferedReader in = new BufferedReader(in_reader); 380 String entry = null; 381 while((entry = in.readLine()) != null) { 382 if(!entry.startsWith("#")) { 383 StringTokenizer tokenizer = new StringTokenizer(entry); 384 String name = tokenizer.nextToken(); 385 String code = tokenizer.nextToken().toLowerCase(); 386 Language language = new Language(code, name, false); 387 known_languages.put(code, language); 388 } 389 } 390 in.close(); 391 } 392 catch (Exception error) { 393 error.printStackTrace(); 394 } 395 } 396 397 /** This class represents the visual component of the Language Manager. */ 398 private class Control 399 extends JPanel { 400 /** The button to add a new language support. */ 401 private JButton add = null; 402 /** The button to clear the current default language. */ 403 private JButton clear_default = null; 404 /** The button to remove a supported language. */ 405 private JButton remove = null; 406 /** The button to set the current language as the default one. */ 407 private JButton set_default = null; 408 /** A button to active the translation manager prompt. */ 409 private JButton translate = null; 410 /** A combobox listing the available supported languages. */ 411 private JComboBox selector = null; 412 /** The label denoting the default language. */ 413 private JLabel default_language_label = null; 414 /** The label denoting the language selector. */ 415 private JLabel selector_label = null; 416 /** The title label of this control view. */ 417 private JLabel title = null; 418 /** A list of currently supported languages. */ 419 private JList list = null; 420 /** The pane in which the control buttons are placed. */ 421 private JPanel button_pane = null; 422 /** The pane onto which all other panes are placed. */ 423 private JPanel central_pane = null; 424 /** The pane to the left containing editing controls. */ 425 private JPanel control_pane = null; 426 /** A panel used to correctly layout the default language box. */ 427 private JPanel default_language_pane = null; 428 /** The display pane contains the title and instruction controls. */ 429 private JPanel display_pane = null; 430 /** The pane which holds everything the display pane doesn't! */ 431 private JPanel lower_pane = null; 432 /** The pane containing the selector combobox. */ 433 private JPanel selector_pane = null; 434 /** A text area displaying inline instructions. */ 435 private JTextArea instructions = null; 436 /** A description of the language currently selected. */ 437 private JTextArea description = null; 438 /** The text field showing the currently name of the default language. Non-editable. */ 439 private JTextField default_language_value = null; 440 /** Constructor. 441 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.AddListener 442 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.ClearDefaultListener 443 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.ListListener 444 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.RemoveListener 445 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.SelectorListener 446 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.SetDefaultListener 447 * @see org.greenstone.gatherer.cdm.LanguageManager.Control.TranslateListener 448 */ 449 public Control() { 450 super(); 451 // Creation. 452 title = new JLabel(get("Title")); 453 title.setHorizontalAlignment(JLabel.CENTER); 454 title.setOpaque(true); 455 456 central_pane = new JPanel(); 457 458 control_pane = new JPanel(); 459 460 instructions = new JTextArea(get("Instructions")); 461 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 462 instructions.setEditable(false); 463 instructions.setLineWrap(true); 464 instructions.setWrapStyleWord(true); 465 466 selector_pane = new JPanel(); 467 468 selector_label = new JLabel(get("Selector")); 469 selector = new JComboBox(getLanguageCodes().toArray()); 470 471 display_pane = new JPanel(); 472 473 list = new JList(model); 474 list.setCellRenderer(new ListRenderer()); 475 476 default_language_pane = new JPanel(); 477 478 default_language_label = new JLabel(get("Default_Language")); 479 default_language_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 480 if(default_language == null) { 481 default_language_value = new JTextField(); 482 } 483 else { 484 default_language_value = new JTextField(default_language.toString()); 485 } 486 default_language_value.setBackground(Color.white); 487 default_language_value.setEditable(false); 488 489 button_pane = new JPanel(); 490 491 add = new JButton(get("Add")); 492 add.setMnemonic(KeyEvent.VK_A); 493 if(selector.getSelectedItem() != null) { 494 add.setEnabled(true); 495 } 496 else { 497 add.setEnabled(false); 498 } 499 500 remove = new JButton(get("Remove")); 501 remove.setMnemonic(KeyEvent.VK_R); 502 remove.setEnabled(false); 503 504 clear_default = new JButton(get("Clear_Default")); 505 clear_default.setMnemonic(KeyEvent.VK_C); 506 clear_default.setEnabled(false); 507 508 set_default = new JButton(get("Set_Default")); 509 set_default.setMnemonic(KeyEvent.VK_S); 510 set_default.setEnabled(false); 511 512 lower_pane = new JPanel(); 513 translate = new JButton(get("Translate")); 514 translate.setMnemonic(KeyEvent.VK_T); 515 516 // Set up and connect listeners. 517 add.addActionListener(new AddListener()); 518 clear_default.addActionListener(new ClearDefaultListener()); 519 remove.addActionListener(new RemoveListener()); 520 selector.addActionListener(new SelectorListener()); 521 set_default.addActionListener(new SetDefaultListener()); 522 translate.addActionListener(new TranslateListener()); 523 list.addListSelectionListener(new ListListener()); 524 // Layout components. 525 selector_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2)); 526 selector_pane.setLayout(new BorderLayout()); 527 selector_pane.add(selector_label, BorderLayout.WEST); 528 selector_pane.add(selector, BorderLayout.CENTER); 529 530 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 531 532 control_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 533 control_pane.setLayout(new BorderLayout()); 534 control_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 535 control_pane.add(selector_pane, BorderLayout.SOUTH); 536 537 default_language_pane.setBorder 538 (BorderFactory.createCompoundBorder 539 (BorderFactory.createCompoundBorder 540 (BorderFactory.createEmptyBorder(5,5,5,5), 541 BorderFactory.createRaisedBevelBorder()), 542 BorderFactory.createEmptyBorder(2,2,2,2))); 543 default_language_pane.setLayout(new BorderLayout()); 544 default_language_pane.add(default_language_label, BorderLayout.WEST); 545 default_language_pane.add(default_language_value, BorderLayout.CENTER); 546 547 display_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,5)); 548 display_pane.setLayout(new BorderLayout()); 549 display_pane.add(new JScrollPane(list), BorderLayout.CENTER); 550 display_pane.add(default_language_pane, BorderLayout.SOUTH); 551 552 central_pane.setLayout(new GridLayout(1,2)); 553 central_pane.add(control_pane); 554 central_pane.add(display_pane); 555 556 button_pane.setLayout(new GridLayout(2,2)); 557 button_pane.add(add); 558 button_pane.add(remove); 559 button_pane.add(clear_default); 560 button_pane.add(set_default); 561 562 lower_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); 563 lower_pane = new JPanel(new BorderLayout()); 564 lower_pane.add(button_pane, BorderLayout.NORTH); 565 lower_pane.add(translate, BorderLayout.CENTER); 566 567 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 568 setLayout(new BorderLayout()); 569 add(title, BorderLayout.NORTH); 570 add(central_pane, BorderLayout.CENTER); 571 add(lower_pane, BorderLayout.SOUTH); 572 } 573 /** Destructor. 448 574 */ 449 public Control() { 450 super(); 451 // Creation. 452 title = new JLabel(get("Title")); 453 title.setHorizontalAlignment(JLabel.CENTER); 454 title.setOpaque(true); 455 456 central_pane = new JPanel(); 457 458 control_pane = new JPanel(); 459 460 instructions = new JTextArea(get("Instructions")); 461 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 462 instructions.setEditable(false); 463 instructions.setLineWrap(true); 464 instructions.setWrapStyleWord(true); 465 466 selector_pane = new JPanel(); 467 468 selector_label = new JLabel(get("Selector")); 469 selector = new JComboBox(getLanguageCodes().toArray()); 470 471 display_pane = new JPanel(); 472 473 list = new JList(model); 474 list.setCellRenderer(new ListRenderer()); 475 476 default_language_pane = new JPanel(); 477 478 default_language_label = new JLabel(get("Default_Language")); 479 default_language_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 480 if(default_language == null) { 481 default_language_value = new JTextField(); 482 } 483 else { 484 default_language_value = new JTextField(default_language.toString()); 485 } 486 default_language_value.setBackground(Color.white); 487 default_language_value.setEditable(false); 488 489 button_pane = new JPanel(); 490 491 add = new JButton(get("Add")); 492 add.setMnemonic(KeyEvent.VK_A); 493 if(selector.getSelectedItem() != null) { 494 add.setEnabled(true); 495 } 496 else { 497 add.setEnabled(false); 498 } 499 500 remove = new JButton(get("Remove")); 501 remove.setMnemonic(KeyEvent.VK_R); 502 remove.setEnabled(false); 503 504 clear_default = new JButton(get("Clear_Default")); 505 clear_default.setMnemonic(KeyEvent.VK_C); 506 clear_default.setEnabled(false); 507 508 set_default = new JButton(get("Set_Default")); 509 set_default.setMnemonic(KeyEvent.VK_S); 510 set_default.setEnabled(false); 511 512 lower_pane = new JPanel(); 513 translate = new JButton(get("Translate")); 514 translate.setMnemonic(KeyEvent.VK_T); 515 516 // Set up and connect listeners. 517 add.addActionListener(new AddListener()); 518 clear_default.addActionListener(new ClearDefaultListener()); 519 remove.addActionListener(new RemoveListener()); 520 selector.addActionListener(new SelectorListener()); 521 set_default.addActionListener(new SetDefaultListener()); 522 translate.addActionListener(new TranslateListener()); 523 list.addListSelectionListener(new ListListener()); 524 // Layout components. 525 selector_pane.setBorder(BorderFactory.createEmptyBorder(2,2,2,2)); 526 selector_pane.setLayout(new BorderLayout()); 527 selector_pane.add(selector_label, BorderLayout.WEST); 528 selector_pane.add(selector, BorderLayout.CENTER); 529 530 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 531 532 control_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 533 control_pane.setLayout(new BorderLayout()); 534 control_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 535 control_pane.add(selector_pane, BorderLayout.SOUTH); 536 537 default_language_pane.setBorder 538 (BorderFactory.createCompoundBorder 539 (BorderFactory.createCompoundBorder 540 (BorderFactory.createEmptyBorder(5,5,5,5), 541 BorderFactory.createRaisedBevelBorder()), 542 BorderFactory.createEmptyBorder(2,2,2,2))); 543 default_language_pane.setLayout(new BorderLayout()); 544 default_language_pane.add(default_language_label, BorderLayout.WEST); 545 default_language_pane.add(default_language_value, BorderLayout.CENTER); 546 547 display_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,5)); 548 display_pane.setLayout(new BorderLayout()); 549 display_pane.add(new JScrollPane(list), BorderLayout.CENTER); 550 display_pane.add(default_language_pane, BorderLayout.SOUTH); 551 552 central_pane.setLayout(new GridLayout(1,2)); 553 central_pane.add(control_pane); 554 central_pane.add(display_pane); 555 556 button_pane.setLayout(new GridLayout(2,2)); 557 button_pane.add(add); 558 button_pane.add(remove); 559 button_pane.add(clear_default); 560 button_pane.add(set_default); 561 562 lower_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); 563 lower_pane = new JPanel(new BorderLayout()); 564 lower_pane.add(button_pane, BorderLayout.NORTH); 565 lower_pane.add(translate, BorderLayout.CENTER); 566 567 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 568 setLayout(new BorderLayout()); 569 add(title, BorderLayout.NORTH); 570 add(central_pane, BorderLayout.CENTER); 571 add(lower_pane, BorderLayout.SOUTH); 572 } 573 /** Destructor. 575 public void destroy() { 576 } 577 /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first. 574 578 */ 575 public void destroy() { 576 } 577 /** We override the updateUI method so that we can ensure we are scrolled to the top of the instructions box first. 578 */ 579 public void updateUI() { 580 if(instructions != null) { 581 instructions.setCaretPosition(0); 582 } 583 super.updateUI(); 584 } 585 /** Listens for actions apon the 'add' button in the LanguageManager controls, and if detected calls the add method of the manager with a newly created language. */ 586 private class AddListener 587 implements ActionListener { 579 public void updateUI() { 580 if(instructions != null) { 581 instructions.setCaretPosition(0); 582 } 583 super.updateUI(); 584 } 585 /** Listens for actions apon the 'add' button in the LanguageManager controls, and if detected calls the add method of the manager with a newly created language. */ 586 private class AddListener 587 implements ActionListener { 588 588 /** Add a new language support. 589 * @param event An <strong>ActionEvent</strong>. 590 * @see org.greenstone.gatherer.cdm.Language 589 * @param event An <strong>ActionEvent</strong>. 590 * @see org.greenstone.gatherer.cdm.Language 591 */ 592 public void actionPerformed(ActionEvent event) { 593 Language language = (Language)selector.getSelectedItem(); 594 if(language != null) { 595 addLanguage(new Language(language)); 596 } 597 } 598 } 599 /** Listens for actions apon the 'clear default' button in the LanguageManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */ 600 private class ClearDefaultListener 601 implements ActionListener { 602 /** Clear the default index. 603 * @param event An <strong>ActionEvent</strong>. 591 604 */ 592 public void actionPerformed(ActionEvent event) { 593 Language language = (Language)selector.getSelectedItem(); 594 if(language != null) { 595 addLanguage(new Language(language)); 596 } 597 } 598 } 599 /** Listens for actions apon the 'clear default' button in the LanguageManager controls, and if detected calls the setDefault method of the manager with <i>null</i>. */ 600 private class ClearDefaultListener 601 implements ActionListener { 602 /** Clear the default index. 603 * @param event An <strong>ActionEvent</strong>. 605 public void actionPerformed(ActionEvent event) { 606 setDefault(null); 607 clear_default.setEnabled(false); 608 default_language_value.setText(""); 609 } 610 } 611 /** Listens for actions apon the 'remove' button in the LanguageManager controls, and if detected calls the remove method of the manager with the language selected for removal. */ 612 private class RemoveListener 613 implements ActionListener { 614 /** Remove the currently selected language, if any. 615 * @param event An <strong>ActionEvent</strong>. 616 * @see org.greenstone.gatherer.cdm.Language 617 */ 618 public void actionPerformed(ActionEvent event) { 619 if(!list.isSelectionEmpty()) { 620 removeLanguage((Language)list.getSelectedValue()); 621 if(default_language == null) { 622 clear_default.setEnabled(false); 623 default_language_value.setText(""); 624 } 625 } 626 } 627 } 628 /** Listens for selections wihtin the combobox on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */ 629 private class SelectorListener 630 implements ActionListener { 631 /** Enable or disable controls depeding on selection. 632 * @param event An <strong>ActionEvent</strong>. 604 633 */ 605 public void actionPerformed(ActionEvent event) { 606 setDefault(null); 607 clear_default.setEnabled(false); 608 default_language_value.setText(""); 609 } 610 } 611 /** Listens for actions apon the 'remove' button in the LanguageManager controls, and if detected calls the remove method of the manager with the language selected for removal. */ 612 private class RemoveListener 613 implements ActionListener { 614 /** Remove the currently selected language, if any. 615 * @param event An <strong>ActionEvent</strong>. 616 * @see org.greenstone.gatherer.cdm.Language 634 public void actionPerformed(ActionEvent event) { 635 if(selector.getSelectedItem() != null) { 636 add.setEnabled(true); 637 //description.setText((String)known_languages.get(code)); 638 } 639 else { 640 add.setEnabled(false); 641 //description.setText(""); 642 } 643 } 644 } 645 /** Listens for actions apon the 'set default' button in the LanguageManager controls, and if detected calls the <i>setDefault()</i> method of the manager with the language selected for default. */ 646 private class SetDefaultListener 647 implements ActionListener { 648 /** Set the default index to the one currently selected, if any. 649 * @param event An <strong>ActionEvent</strong>. 650 * @see org.greenstone.gatherer.cdm.Language 651 */ 652 public void actionPerformed(ActionEvent event) { 653 if(!list.isSelectionEmpty()) { 654 setDefault((Language)list.getSelectedValue()); 655 clear_default.setEnabled(true); 656 default_language_value.setText(default_language.toString()); 657 } 658 } 659 } 660 /** Listens for actions apon the 'translate' button in the LanguageManager controls, and if detected creates a new <strong>TranslationManager</strong> to allow the user to tranlate. */ 661 private class TranslateListener 662 implements ActionListener { 663 /** Create a new translation manager, but remember to clean up after it disposes. 664 * @param event An <strong>ActionEvent</strong>. 665 * @see org.greenstone.gatherer.cdm.TranslationManager 666 */ 667 public void actionPerformed(ActionEvent event) { 668 TranslationManager tm = new TranslationManager(gatherer, manager); 669 tm.destroy(); 670 } 671 } 672 /** Listens for selections within the list on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */ 673 private class ListListener 674 implements ListSelectionListener { 675 /** Enable or disable controls depending on the current list selection. 676 * @param event A <strong>ListSelectionEvent</strong>. 617 677 */ 618 public void actionPerformed(ActionEvent event) { 619 if(!list.isSelectionEmpty()) { 620 removeLanguage((Language)list.getSelectedValue()); 621 if(default_language == null) { 622 clear_default.setEnabled(false); 623 default_language_value.setText(""); 624 } 625 } 626 } 627 } 628 /** Listens for selections wihtin the combobox on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */ 629 private class SelectorListener 630 implements ActionListener { 631 /** Enable or disable controls depeding on selection. 632 * @param event An <strong>ActionEvent</strong>. 633 */ 634 public void actionPerformed(ActionEvent event) { 635 if(selector.getSelectedItem() != null) { 636 add.setEnabled(true); 637 //description.setText((String)known_languages.get(code)); 638 } 639 else { 640 add.setEnabled(false); 641 //description.setText(""); 642 } 643 } 644 } 645 /** Listens for actions apon the 'set default' button in the LanguageManager controls, and if detected calls the <i>setDefault()</i> method of the manager with the language selected for default. */ 646 private class SetDefaultListener 647 implements ActionListener { 648 /** Set the default index to the one currently selected, if any. 649 * @param event An <strong>ActionEvent</strong>. 650 * @see org.greenstone.gatherer.cdm.Language 651 */ 652 public void actionPerformed(ActionEvent event) { 653 if(!list.isSelectionEmpty()) { 654 setDefault((Language)list.getSelectedValue()); 655 clear_default.setEnabled(true); 656 default_language_value.setText(default_language.toString()); 657 } 658 } 659 } 660 /** Listens for actions apon the 'translate' button in the LanguageManager controls, and if detected creates a new <strong>TranslationManager</strong> to allow the user to tranlate. */ 661 private class TranslateListener 662 implements ActionListener { 663 /** Create a new translation manager, but remember to clean up after it disposes. 664 * @param event An <strong>ActionEvent</strong>. 665 * @see org.greenstone.gatherer.cdm.TranslationManager 666 */ 667 public void actionPerformed(ActionEvent event) { 668 TranslationManager tm = new TranslationManager(gatherer, manager); 669 tm.destroy(); 670 } 671 } 672 /** Listens for selections within the list on the LanguageManager controls, and if a change is detected enables, or disables, controls appropriately. */ 673 private class ListListener 674 implements ListSelectionListener { 675 /** Enable or disable controls depending on the current list selection. 676 * @param event A <strong>ListSelectionEvent</strong>. 677 */ 678 public void valueChanged(ListSelectionEvent event) { 679 if(list.isSelectionEmpty()) { 680 remove.setEnabled(false); 681 set_default.setEnabled(false); 682 } 683 else { 684 remove.setEnabled(true); 685 set_default.setEnabled(true); 686 } 687 refreshAppearance(); 688 } 689 } 690 /** Our list cel renderer which renders the default cell just a little different. */ 691 private class ListRenderer 692 extends DefaultListCellRenderer { 678 public void valueChanged(ListSelectionEvent event) { 679 if(list.isSelectionEmpty()) { 680 remove.setEnabled(false); 681 set_default.setEnabled(false); 682 } 683 else { 684 remove.setEnabled(true); 685 set_default.setEnabled(true); 686 } 687 refreshAppearance(); 688 } 689 } 690 /** Our list cel renderer which renders the default cell just a little different. */ 691 private class ListRenderer 692 extends DefaultListCellRenderer { 693 693 /** Method to produce the component used to display an entry in the list. 694 694 * @param list The <strong>JList</strong> the component will be placed in. … … 700 700 * @see org.greenstone.gatherer.cdm.Language 701 701 */ 702 703 704 705 706 707 708 709 710 711 712 713 714 702 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 703 Component component = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 704 Language language = (Language) value; 705 if(language.isDefault() && !isSelected) { 706 component.setBackground(Gatherer.config.getColor("coloring.workspace_selection_background", false)); 707 } 708 if(component instanceof JLabel) { 709 ((JLabel)component).setOpaque(true); 710 } 711 return component; 712 } 713 } 714 } 715 715 } 716 716 -
trunk/gli/src/org/greenstone/gatherer/cdm/MetadataSetManager.java
r4293 r4366 78 78 import org.w3c.dom.NodeList; 79 79 /** Unlike its namesake in the msm package, this class really only knows how to produce a simple visual representation of the currently imported metadata sets. It is also read-only, so should be fairly straight forward. 80 * @author John Thompson, Greenstone Digital Library, University of Waikato81 * @version 2.382 * @see org.greenstone.gatherer.msm.MetadataSetManager83 */80 * @author John Thompson, Greenstone Digital Library, University of Waikato 81 * @version 2.3 82 * @see org.greenstone.gatherer.msm.MetadataSetManager 83 */ 84 84 public class MetadataSetManager 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 85 extends DynamicListModel 86 implements MSMListener { 87 /** The visual contols used to review the metadata sets. */ 88 private Control controls = null; 89 /** A reference to the Gatherer. */ 90 private Gatherer gatherer = null; 91 /** A reference to ourselves so our inner classes can refer to us. */ 92 private DynamicListModel model = null; 93 /** Constructor. 94 * @param gatherer A reference to the <strong>Gatherer</strong>. 95 * @see org.greenstone.gatherer.collection.CollectionManager 96 * @see org.greenstone.gatherer.msm.MetadataSetManager 97 */ 98 public MetadataSetManager(Gatherer gatherer) { 99 this.gatherer = gatherer; 100 this.model = this; 101 Gatherer.c_man.getCollection().msm.addMSMListener(this); 102 loadMetadataSets(); 103 } 104 /** Destructor. Remove any references of this class from persistant objects. 105 105 * @see org.greenstone.gatherer.Gatherer 106 106 * @see org.greenstone.gatherer.collection.CollectionManager 107 107 * @see org.greenstone.gatherer.msm.MetadataSetManager 108 108 */ 109 110 111 112 109 public void destroy() { 110 gatherer.c_man.msm.removeMSMListener(this); 111 } 112 /** Called when an element is changed within a set in the MSM, prompting us to refresh our list of elements being shown. 113 113 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change. 114 114 * @see org.greenstone.gatherer.cdm.MetadataSetManager.Control 115 115 */ 116 117 118 119 120 121 122 116 public void elementChanged(MSMEvent event) { 117 // Get the controls to refresh element list. 118 if(controls != null) { 119 controls.refreshElementList(); 120 } 121 } 122 /** A method for retrieve the controls for this manager. 123 123 * @see org.greenstone.gatherer.Dictionary 124 124 * @see org.greenstone.gatherer.gui.Coloring 125 125 * @see org.greenstone.gatherer.msm.MetadataSetManager 126 126 */ 127 128 129 130 131 132 133 127 public Control getControls() { 128 if(controls == null) { 129 controls = new Control(); 130 } 131 return controls; 132 } 133 /** A method to invalidate the current set of controls, as they become obselete. 134 134 * @see org.greenstone.gatherer.cdm.MetadataSetManager.Control 135 135 */ 136 137 138 139 140 141 142 136 public void invalidateControls() { 137 if(controls != null) { 138 controls.destroy(); 139 } 140 controls = null; 141 } 142 /** Called when a metadata value has undergone significant change. 143 143 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change. 144 144 */ 145 146 147 148 145 public void metadataChanged(MSMEvent event) { 146 // Couldn't care less. 147 } 148 /** Called when a set is added or removed from the MSM. 149 149 * @param event A <strong>MSMEvent</strong> which encapsulates relevant data about the change. 150 150 */ 151 152 153 154 155 156 151 public void setChanged(MSMEvent event) { 152 // Reload model. 153 clear(); 154 loadMetadataSets(); 155 } 156 /** Select the selected element, given its name, and return the bounds of the selection. Used during search and replace. 157 157 * @param element The elements fully qualified name as a <strong>String</strong>. 158 158 * @return The bounds of the selection as a <strong>Rectangle</strong>. 159 159 * @see org.greenstone.gatherer.cdm.MetadataSetManager.Control 160 160 */ 161 162 163 164 165 166 167 161 public Rectangle setSelectedElement(String element) { 162 if(controls != null) { 163 return controls.setSelectedElement(element); 164 } 165 return null; 166 } 167 /** Prints out the contents of this manager, as they would appear in the collection configuration file. 168 168 * @return A <strong>String</strong> containing a block of commands. 169 169 * @see org.greenstone.gatherer.cdm.MetadataSetManager.SetWrapper 170 170 */ 171 172 173 174 175 176 177 178 179 180 171 public String toString() { 172 String text = ""; 173 for(int i = 0; i < size(); i++) { 174 SetWrapper set = (SetWrapper)get(i); 175 text = text + set.toString() + "\n"; 176 } 177 text = text + "\n"; 178 return text; 179 } 180 /** Called when a significant change has occured to a value tree for a certain element, however we take no further action. 181 181 * @param event A <strong>MSMEvent</strong> containing information relevant to the event. 182 182 */ 183 184 185 183 public void valueChanged(MSMEvent event) { 184 } 185 /** Method to retrieve a phrase from the dictionary based on a key. 186 186 * @param key A <strong>String</strong> used to find the correct phrase. 187 187 * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase. 188 188 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. 189 189 */ 190 191 192 193 190 private String get(String key) { 191 return get(key, null); 192 } 193 /** Method to retrieve a phrase from the dictionary based on a key. 194 194 * @param key A <strong>String</strong> used to find the correct phrase. 195 195 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. … … 197 197 * @see org.greenstone.gatherer.Gatherer 198 198 */ 199 200 201 202 203 204 205 199 private String get(String key, String args[]) { 200 if(key.indexOf(".") == -1) { 201 key = "CDM.MetadataSetManager." + key; 202 } 203 return gatherer.dictionary.get(key, args); 204 } 205 /** Retrieves the current list of loaded metadata sets, and builds a list model around them. 206 206 * @see org.greenstone.gatherer.Gatherer 207 207 * @see org.greenstone.gatherer.cdm.MetadataSetManager.SetWrapper … … 210 210 * @see org.greenstone.gatherer.msm.MetadataSetManager 211 211 */ 212 private void loadMetadataSets() { 213 // We initialize the set_model with wrapped metadata sets. Note that when we call getSets() we also end up adding ourselves as a listener to the metadata set manager. 214 Vector sets = gatherer.c_man.getCollection().msm.getSets(); 215 for(int i = 0; i < sets.size(); i++) { 216 addElement(new SetWrapper((MetadataSet)sets.get(i))); 217 } 218 } 219 /** This class creates and lays-out the various controls for reviewing the metadata sets, and their commands as they would appear in the collection configuration file. */ 220 private class Control 221 extends JPanel { 222 /** The label denoting the element list. */ 223 private JLabel element_label = null; 224 /** The label denoting the set list. */ 225 private JLabel set_label = null; 226 /** The title of these controls. */ 227 private JLabel title = null; 228 /** The list of elements for the choosen set. */ 229 private JList element_list = null; 230 /** The list of sets in this collection. */ 231 private JList set_list = null; 232 /** The panel onto which all other panels will be placed. */ 233 private JPanel central_pane = null; 234 /** The panel onto which the element list will be placed. */ 235 private JPanel element_pane = null; 236 /** The panel containing the title and instructions. */ 237 private JPanel header_pane = null; 238 /** The panel containing the set list. */ 239 private JPanel set_pane = null; 240 /** The text area of inline instructions. */ 241 private JTextArea instructions = null; 242 /** The element model for the currently selected set. */ 243 private Vector element_model = null; 244 /* Constructor. 245 * @see org.greenstone.gatherer.Coloring; 246 * @see org.greenstone.gatherer.Dictionary 247 * @see org.greenstone.gatherer.cdm.MetadataSetManager.ListListener 248 * @see org.greenstone.gatherer.msm.MetadataSetManager 212 private void loadMetadataSets() { 213 // We initialize the set_model with wrapped metadata sets. Note that when we call getSets() we also end up adding ourselves as a listener to the metadata set manager. 214 Vector sets = gatherer.c_man.getCollection().msm.getSets(); 215 for(int i = 0; i < sets.size(); i++) { 216 addElement(new SetWrapper((MetadataSet)sets.get(i))); 217 } 218 } 219 /** This class creates and lays-out the various controls for reviewing the metadata sets, and their commands as they would appear in the collection configuration file. */ 220 private class Control 221 extends JPanel { 222 /** The label denoting the element list. */ 223 private JLabel element_label = null; 224 /** The label denoting the set list. */ 225 private JLabel set_label = null; 226 /** The title of these controls. */ 227 private JLabel title = null; 228 /** The list of elements for the choosen set. */ 229 private JList element_list = null; 230 /** The list of sets in this collection. */ 231 private JList set_list = null; 232 /** The panel onto which all other panels will be placed. */ 233 private JPanel central_pane = null; 234 /** The panel onto which the element list will be placed. */ 235 private JPanel element_pane = null; 236 /** The panel containing the title and instructions. */ 237 private JPanel header_pane = null; 238 /** The panel containing the set list. */ 239 private JPanel set_pane = null; 240 /** The text area of inline instructions. */ 241 private JTextArea instructions = null; 242 /** The element model for the currently selected set. */ 243 private Vector element_model = null; 244 /* Constructor. 245 * @see org.greenstone.gatherer.Coloring; 246 * @see org.greenstone.gatherer.Dictionary 247 * @see org.greenstone.gatherer.cdm.MetadataSetManager.ListListener 248 * @see org.greenstone.gatherer.msm.MetadataSetManager 249 */ 250 public Control() { 251 // Create visual components 252 central_pane = new JPanel(); 253 element_label = new JLabel(get("Elements")); 254 element_label.setHorizontalAlignment(JLabel.CENTER); 255 element_label.setOpaque(true); 256 element_list = new JList(); 257 element_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 258 element_pane = new JPanel(); 259 header_pane = new JPanel(); 260 instructions = new JTextArea(get("Instructions")); 261 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 262 instructions.setEditable(false); 263 instructions.setLineWrap(true); 264 instructions.setRows(5); 265 instructions.setWrapStyleWord(true); 266 set_label = new JLabel(get("Sets")); 267 set_label.setHorizontalAlignment(JLabel.CENTER); 268 set_label.setOpaque(true); 269 set_list = new JList(model); 270 set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 271 set_pane = new JPanel(); 272 title = new JLabel(get("Title")); 273 title.setHorizontalAlignment(JLabel.CENTER); 274 title.setOpaque(true); 275 // Add listeners 276 set_list.addListSelectionListener(new ListListener()); 277 // Layout 278 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 279 280 header_pane.setLayout(new BorderLayout()); 281 header_pane.add(title, BorderLayout.NORTH); 282 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 283 284 set_pane.setLayout(new BorderLayout()); 285 set_pane.add(set_label, BorderLayout.NORTH); 286 set_pane.add(new JScrollPane(set_list), BorderLayout.CENTER); 287 288 element_pane.setLayout(new BorderLayout()); 289 element_pane.add(element_label, BorderLayout.NORTH); 290 element_pane.add(new JScrollPane(element_list), BorderLayout.CENTER); 291 292 central_pane.setLayout(new GridLayout(2,1)); 293 central_pane.add(set_pane); 294 central_pane.add(element_pane); 295 296 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 297 setLayout(new BorderLayout()); 298 add(header_pane, BorderLayout.NORTH); 299 add(central_pane, BorderLayout.CENTER); 300 } 301 /** Destructor. 249 302 */ 250 public Control() { 251 // Create visual components 252 central_pane = new JPanel(); 253 element_label = new JLabel(get("Elements")); 254 element_label.setHorizontalAlignment(JLabel.CENTER); 255 element_label.setOpaque(true); 256 element_list = new JList(); 257 element_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 258 element_pane = new JPanel(); 259 header_pane = new JPanel(); 260 instructions = new JTextArea(get("Instructions")); 261 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 262 instructions.setEditable(false); 263 instructions.setLineWrap(true); 264 instructions.setRows(5); 265 instructions.setWrapStyleWord(true); 266 set_label = new JLabel(get("Sets")); 267 set_label.setHorizontalAlignment(JLabel.CENTER); 268 set_label.setOpaque(true); 269 set_list = new JList(model); 270 set_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 271 set_pane = new JPanel(); 272 title = new JLabel(get("Title")); 273 title.setHorizontalAlignment(JLabel.CENTER); 274 title.setOpaque(true); 275 // Add listeners 276 set_list.addListSelectionListener(new ListListener()); 277 // Layout 278 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 279 280 header_pane.setLayout(new BorderLayout()); 281 header_pane.add(title, BorderLayout.NORTH); 282 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 283 284 set_pane.setLayout(new BorderLayout()); 285 set_pane.add(set_label, BorderLayout.NORTH); 286 set_pane.add(new JScrollPane(set_list), BorderLayout.CENTER); 287 288 element_pane.setLayout(new BorderLayout()); 289 element_pane.add(element_label, BorderLayout.NORTH); 290 element_pane.add(new JScrollPane(element_list), BorderLayout.CENTER); 291 292 central_pane.setLayout(new GridLayout(2,1)); 293 central_pane.add(set_pane); 294 central_pane.add(element_pane); 295 296 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 297 setLayout(new BorderLayout()); 298 add(header_pane, BorderLayout.NORTH); 299 add(central_pane, BorderLayout.CENTER); 300 } 301 /** Destructor. 302 */ 303 public void destroy() { 304 } 305 /** Update the element list. */ 306 public void refreshElementList() { 307 element_list.updateUI(); 308 } 309 /** Select the selected element, given its name, and return the bounds of the selection. Used during search and replace. 303 public void destroy() { 304 } 305 /** Update the element list. */ 306 public void refreshElementList() { 307 element_list.updateUI(); 308 } 309 /** Select the selected element, given its name, and return the bounds of the selection. Used during search and replace. 310 310 * @param element The elements fully qualified name as a <strong>String</strong>. 311 311 * @return The bounds of the selection as a <strong>Rectangle</strong>. … … 313 313 * @see org.greenstone.gatherer.cdm.MetadataSetManager.Control.ElementWrapper 314 314 */ 315 316 315 public Rectangle setSelectedElement(String element) { 316 Rectangle bounds = null; 317 317 // Parse off namespace 318 318 String namespace = element.substring(0, element.indexOf(".")); 319 319 // Force the set list to show the correct entry. 320 321 322 323 324 325 326 320 ListModel s_model = set_list.getModel(); 321 for(int i = 0; i < s_model.getSize(); i++) { 322 SetWrapper sw = (SetWrapper) s_model.getElementAt(i); 323 if(sw.getSet().getNamespace().equals(namespace)) { 324 set_list.setSelectedValue(sw, true); 325 } 326 } 327 327 // Force the element list to show that name. 328 329 330 331 332 333 334 335 328 ListModel e_model = element_list.getModel(); 329 for(int i = 0; i < e_model.getSize(); i++) { 330 ElementWrapper ew = (ElementWrapper) e_model.getElementAt(i); 331 if(ew.name().equals(element)) { 332 element_list.setSelectedValue(ew, true); 333 bounds = element_list.getCellBounds(i, i); 334 } 335 } 336 336 // Return the bounds of the selected row. 337 338 339 337 return bounds; 338 } 339 /** Overriden to ensure the instruction area is scrolled to top. 340 340 */ 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 341 public void updateUI() { 342 if(instructions != null) { 343 instructions.setCaretPosition(0); 344 } 345 super.updateUI(); 346 } 347 348 private class ListListener 349 implements ListSelectionListener { 350 public void valueChanged(ListSelectionEvent event) { 351 if(!set_list.isSelectionEmpty()) { 352 MetadataSet set = ((SetWrapper)set_list.getSelectedValue()).getSet(); 353 NodeList elements = set.getElements(); 354 element_model = new Vector(); 355 for(int i = 0; i < elements.getLength(); i++) { 356 element_model.add(new ElementWrapper(elements.item(i))); 357 } 358 Collections.sort(element_model); 359 element_list.setListData(element_model); 360 } 361 } 362 } 363 } 364 /** Provides a convience wrapper around a metadata set, that allows it to appear in the <strong>JList</strong> the same way it would in the collection configuration file. */ 365 private class SetWrapper { 366 private MetadataSet set = null; 367 public SetWrapper(MetadataSet set) { 368 this.set = set; 369 } 370 public MetadataSet getSet() { 371 return set; 372 } 373 public String toString() { 374 String namespace = set.getNamespace(); 375 375 // Watch out for the greenstone set, with its namespace of "" 376 377 378 379 380 381 376 if(namespace == null || namespace.length() == 0) { 377 namespace = "greenstone"; 378 } 379 return "metadataset " + namespace + " \"" + set.getFile().getName() + "\""; 380 } 381 } 382 382 } -
trunk/gli/src/org/greenstone/gatherer/cdm/ParsingProgress.java
r4293 r4366 60 60 import javax.swing.JProgressBar; 61 61 /** This class provides a progress bar to be displayed whenever the module must reload the plugin and classifier information, either automatically or if the user indicates a reload is needed. 62 * @author John Thompson, Greenstone Digital Library, University of Waikato63 * @version 2.364 */62 * @author John Thompson, Greenstone Digital Library, University of Waikato 63 * @version 2.3 64 */ 65 65 public class ParsingProgress 66 67 68 69 70 71 72 73 74 75 76 66 extends JDialog { 67 /** The content pane within the dialog box. */ 68 private JPanel content_pane = null; 69 /** The progress bar itself. */ 70 private JProgressBar progress = null; 71 /** The default size of the progress dialog. */ 72 static final Dimension SIZE = new Dimension(400,75); 73 /** Constructor. 74 * @param title The title to show on the dialog, as a <strong>String</strong>. 75 * @param message The message to show on the dialog, as a <strong>String</strong>. 76 * @param max The total number of plugins/classifiers that have to be parsed before the progress bar can be disposed of, as an <i>int</i>. 77 77 */ 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 78 public ParsingProgress(String title, String message, int max) { 79 super(); 80 this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 81 this.setSize(SIZE); 82 this.setTitle(title); 83 // Creation 84 this.content_pane = (JPanel) getContentPane(); 85 this.progress = new JProgressBar(); 86 this.progress.setMaximum(max); 87 // Layout 88 this.content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 89 this.content_pane.setLayout(new BorderLayout()); 90 this.content_pane.add(new JLabel(message), BorderLayout.NORTH); 91 this.content_pane.add(progress, BorderLayout.CENTER); 92 // Center and display 93 Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize(); 94 setLocation((screen_size.width - SIZE.width) / 2, 95 (screen_size.height - SIZE.height) / 2); 96 show(); 97 } 98 public void destroy() { 99 } 100 /** Method which increments the progress count by one, which should be called after every successful parsing of a classifier or plugin. 101 101 */ 102 103 104 102 public void inc() { 103 progress.setValue(progress.getValue() + 1); 104 } 105 105 } -
trunk/gli/src/org/greenstone/gatherer/cdm/PlugIn.java
r4293 r4366 63 63 // #################################################################################### 64 64 public class PlugIn 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 65 extends ArrayList 66 implements ArgumentContainer, Comparable, Serializable { 67 /** A reference to the plugin that this one inherits from. */ 68 private PlugIn super_plugin = null; 69 /** A string of custom arguments to pass to the plugin. */ 70 private String custom = null; 71 /** A description of this plugin. */ 72 private String desc = null; 73 /** The name of the plugin as it would appear in the collect.cfg file. */ 74 private String name = null; 75 /** Default Constructor. 76 */ 77 public PlugIn() { 78 super(); 79 } 80 /** Constructor. 81 81 * @param name The name of this plugin as a <strong>String</strong>. 82 82 * @param desc A description of this plugin as a <strong>String</strong>. 83 83 * @param super_plugin The super class of this plugin, as a <strong>PlugIn</strong>. 84 84 */ 85 86 87 88 89 90 91 85 public PlugIn(String name, String desc, PlugIn super_plugin) { 86 super(); 87 this.desc = desc; 88 this.name = name; 89 this.super_plugin = super_plugin; 90 } 91 /** Method to add an argument to this plugin. Only adds the argument if it isn't already present. 92 92 * @param argument The <strong>Argument</strong> to add. 93 93 */ 94 95 96 97 98 99 100 94 public void addArgument(Argument argument) { 95 if(!contains(argument)) { 96 add(argument); 97 argument.setOwner(name); 98 } 99 } 100 /** Method to compare two plugins for ordering. 101 101 * @param object The plugin we are comparing to, as an <strong>Object</strong>. 102 102 * @return An <i>int</i> specifying the plugin order, using values as set out in <strong>String</strong>. 103 103 * @see java.lang.String#compareTo 104 104 */ 105 106 107 108 109 110 111 112 105 public int compareTo(Object object) { 106 if(object != null && object instanceof PlugIn) { 107 PlugIn plugin = (PlugIn) object; 108 return name.compareTo(plugin.getName()); 109 } 110 return -1; 111 } 112 /** This method produces a deep copy of this plugin. Note that this also creates a new copy of each of the super classes of plugins as well. This is the way it should be, as each assigned plugin may have different values for the higher plugins (such as BasPlug). 113 113 * @return A newly created <strong>PlugIn</strong> with the same details and <strong>Argument</strong>s as this one. 114 114 */ 115 116 117 118 119 120 121 122 123 124 125 126 127 128 115 public PlugIn copy() { 116 PlugIn copy = null; 117 if(super_plugin == null) { 118 copy = new PlugIn(name, desc, null); 119 } 120 else { 121 copy = new PlugIn(name, desc, super_plugin.copy()); 122 } 123 for(int i = 0; i < size(); i++) { 124 copy.addArgument(((Argument)get(i)).copy()); 125 } 126 return copy; 127 } 128 /** Method to determine if two plugins are equal. 129 129 * @param object The plugin to test against, as an <strong>Object</strong>. 130 130 * @return <i>true</i> if the plugin names match, <i>false</i> otherwise. 131 131 */ 132 133 134 135 136 137 138 132 public boolean equals(Object object) { 133 if(object != null && compareTo(object) == 0) { 134 return true; 135 } 136 return false; 137 } 138 /** Method to retrieve an argument by its name. 139 139 * @param name The name of the argument as a <strong>String</strong>. 140 140 * @return The <strong>Argument</strong> requested, or <i>null</i> if no such argument. 141 141 */ 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 142 public Argument getArgument(String name) { 143 // The name given may still include the '-' 144 if(name.startsWith("-")) { 145 name = name.substring(1); 146 } 147 ArrayList arguments = getArguments(); 148 for(int i = 0; i < arguments.size(); i++) { 149 Argument argument = (Argument)arguments.get(i); 150 if(argument.getName().equals(name)) { 151 return argument; 152 } 153 } 154 return null; 155 } 156 /** Method to retrieve all of the arguments available to a plugin, including both specific and general ones. 157 157 * @return A <strong>Hashtable</strong> of arguments, with <name> -> <argument> entries. 158 158 */ 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 159 public ArrayList getArguments() { 160 ArrayList all_arguments = new ArrayList(this); 161 Collections.sort(all_arguments); 162 if(super_plugin != null) { 163 ArrayList super_arguments = super_plugin.getArguments(); 164 for(int i = 0; i < super_arguments.size(); i++) { 165 Object argument = super_arguments.get(i); 166 if(!all_arguments.contains(argument)) { 167 all_arguments.add(argument); 168 } 169 } 170 } 171 return all_arguments; 172 } 173 /** Method to retrieve a plugins custom argument information. 174 174 * @return The custom arguments as a <strong>String</strong>. 175 175 */ 176 177 178 179 176 public String getCustom() { 177 return custom; 178 } 179 /** Method to retrieve a plugins name. 180 180 * @return A <strong>String</strong> containing the plugins name. 181 181 */ 182 183 184 185 186 187 188 182 public String getName() { 183 return name; 184 } 185 public void setCustom(String custom) { 186 this.custom = custom; 187 } 188 /** Method to set the value of desc. 189 189 * @param desc The new value of desc as a <strong>String</strong>. 190 190 */ 191 192 193 194 191 public void setDesc(String desc) { 192 this.desc = desc; 193 } 194 /** Method to set the value of name. 195 195 * @param name The new value of name as a <strong>String</strong>. 196 196 */ 197 198 199 200 197 public void setName(String name) { 198 this.name = name; 199 } 200 /** Method to set the value of the super_plugin. 201 201 * @param super_plugin The new value of super_plugin as a <strong>PlugIn</strong>, or <i>null</i> if this class has no inheritance. 202 202 */ 203 204 205 206 203 public void setSuper(PlugIn super_plugin) { 204 this.super_plugin = super_plugin; 205 } 206 /** Method to print out this plugin as it would appear as a command within the collection configuration file. 207 207 * @return A <strong>String</strong> containing a single plugin command. 208 208 */ 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 209 public String toString() { 210 String text = "plugin " + name + " "; 211 ArrayList arguments = getArguments(); 212 for(int i = 0; i < arguments.size(); i++) { 213 Argument argument = (Argument)arguments.get(i); 214 if(argument.isAssigned()) { 215 text = text + argument.toString(); 216 if(i < arguments.size() - 1) { 217 text = text + " "; 218 } 219 } 220 } 221 // Now print custom arguments if any. 222 if(custom != null) { 223 text = text + " " + custom; 224 } 225 return text; 226 } 227 227 } 228 228 -
trunk/gli/src/org/greenstone/gatherer/cdm/PlugInManager.java
r4293 r4366 103 103 /** This class is resposible for maintaining a list of known plug-ins, and importing new plugins using the parser. */ 104 104 public class PlugInManager { 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 105 /** A reference to the main manager for this module. */ 106 private CollectionDesignManager manager = null; 107 /** The controls for editing the contents of this manager. */ 108 private Control controls = null; 109 /** A list of assigned plugins. */ 110 private DynamicListModel assigned = null; 111 /** A list of those plugins that have not yet been assigned. Begins as a copy of reserve. */ 112 private DynamicListModel available = null; 113 /** A list of known, but currently unassigned, plug-ins. */ 114 private DynamicListModel reserve = null; 115 /** A reference to the Gatherer. */ 116 private Gatherer gatherer = null; 117 /** The current index of the separator. */ 118 private JPanel separator = null; 119 /** The default size for a label. */ 120 static final private Dimension LABEL_SIZE = new Dimension(140, 20); 121 /** Constructor. 122 */ 123 public PlugInManager(Gatherer gatherer, CollectionDesignManager manager) { 124 this.assigned = new DynamicListModel(); 125 this.gatherer = gatherer; 126 this.manager = manager; 127 this.separator = getSeparator(); 128 // Add the movement separator 129 assigned.addElement(separator); 130 loadPlugIns(); 131 savePlugIns(); 132 } 133 /** Method to add a new plugin to reserve. 134 134 * @param plugin The new <strong>PlugIn</strong>. 135 135 */ 136 137 138 139 140 141 142 136 public void addPlugIn(PlugIn plugin) { 137 if(!reserve.contains(plugin)) { 138 reserve.addElement(plugin); 139 available.addElement(plugin); 140 } 141 } 142 /** Method to assign a plugin. 143 143 * @param plugin The reserve <strong>PlugIn</strong> to assign. 144 144 */ 145 146 147 148 149 150 151 152 153 145 public void assignPlugIn(PlugIn plugin) { 146 if(!assigned.contains(plugin)) { 147 if(plugin.getName().equals("RecPlug") || plugin.getName().equals("ArcPlug")) { 148 assigned.addElement(plugin); // Adds after separator 149 } 150 else { 151 int index = assigned.indexOf(separator); 152 assigned.add(index, plugin); 153 } 154 154 // Remove from available 155 156 157 158 159 155 available.removeElement(plugin); 156 gatherer.c_man.configurationChanged(); 157 } 158 } 159 /** Method to retrieve the control for this manager. 160 160 * @return A <strong>JPanel</strong> containing the controls. 161 161 */ 162 163 164 165 166 167 168 162 public JPanel getControls() { 163 if(controls == null) { 164 controls = new Control(); 165 } 166 return controls; 167 } 168 /** Method to retrieve the named plugin. 169 169 * @param name The name of the desired plugin as a <strong>String</strong>. 170 170 * @return The requested <strong>PlugIn</strong> or <i>null</i> if no such plugin exists. 171 171 */ 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 */ 187 188 189 190 191 192 193 172 public PlugIn getPlugIn(String name) { 173 for(int i = 0; i < reserve.size(); i++) { 174 Object object = reserve.get(i); 175 if(object instanceof PlugIn) { 176 PlugIn plugin = (PlugIn) object; 177 if(plugin.getName().equals(name)) { 178 return plugin; 179 } 180 } 181 } 182 // No success. 183 return null; 184 } 185 /** Method to invalidate controls after a significant change in the system state. 186 */ 187 public void invalidateControls() { 188 if(controls != null) { 189 controls.destroy(); 190 } 191 controls = null; 192 } 193 /** Method to load the details of a single plug-in. 194 194 * @param plugin The plugin <strong>File</strong> you wish to load. 195 195 */ 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 196 public void loadPlugIn(File plugin) { 197 Document document = null; 198 // Run pluginfo on this plugin, and then send the results for parsing. 199 try { 200 String args[] = null; 201 if(Utility.isWindows()) { 202 args = new String[4]; 203 if(gatherer.config.perl_path != null) { 204 args[0] = gatherer.config.perl_path + "Perl.exe"; 205 } 206 else { 207 args[0] = "Perl.exe"; 208 } 209 args[1] = gatherer.config.gsdl_path + "bin" + File.separator + "script" + File.separator + "pluginfo.pl"; 210 args[2] = "-xml"; 211 args[3] = getPlugInName(plugin); 212 } 213 else { 214 args = new String[3]; 215 args[0] = "pluginfo.pl"; 216 args[1] = "-xml"; 217 args[2] = getPlugInName(plugin); 218 } 219 for(int i = 0; i < args.length; i++) { 220 ///ystem.out.print(args[i] + " "); 221 } 222 222 ///ystem.out.print("\n"); 223 223 // Create the process. 224 225 224 Runtime runtime = Runtime.getRuntime(); 225 Process process = runtime.exec(args); 226 226 //InputStream input_stream = process.getErrorStream(); 227 228 229 230 231 232 233 234 235 227 BufferedReader error_in = new BufferedReader(new InputStreamReader(process.getErrorStream())); 228 String line = ""; 229 StringBuffer xml = new StringBuffer(""); 230 while((line = error_in.readLine()) != null) { 231 xml.append(line); 232 xml.append("\n"); 233 } 234 line = null; 235 error_in = null; 236 236 ///ystem.out.println("\n"); 237 237 // Then read the xml from the piped input stream. 238 239 240 241 242 243 244 245 246 247 248 249 250 238 InputSource source = new InputSource(new StringReader(xml.toString())); 239 DOMParser parser = new DOMParser(); 240 parser.parse(source); 241 document = parser.getDocument(); 242 } 243 catch (Exception error) { 244 error.printStackTrace(); 245 } 246 if(document != null) { 247 parse(document.getDocumentElement()); 248 } 249 } 250 /** Method to move a plugin higher in the list order. 251 251 * @param plugin The <strong>PlugIn</strong> you want to move. 252 252 * @param direction <i>true</i> to move the plugin up, <i>false</i> to move it down. 253 253 * @param all <i>true</i> to move to move all the way, <i>false</i> for a single step. 254 254 */ 255 public void movePlugIn(PlugIn plugin, boolean direction, boolean all) { 256 // Can't ever move RecPlug or ArcPlug. 257 if(plugin.getName().equals("ArcPlug") || plugin.getName().equals("RecPlug")) { 258 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Fixed"), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 259 return; 260 } 261 if(all) { 262 if(direction) { 263 assigned.removeElement(plugin); 264 assigned.add(0, plugin); 265 gatherer.c_man.configurationChanged(); 255 public void movePlugIn(PlugIn plugin, boolean direction, boolean all) { 256 // Can't ever move RecPlug or ArcPlug. 257 if(plugin.getName().equals("ArcPlug") || plugin.getName().equals("RecPlug")) { 258 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Fixed"), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 259 return; 260 } 261 if(all) { 262 if(direction) { 263 assigned.removeElement(plugin); 264 assigned.add(0, plugin); 265 gatherer.c_man.configurationChanged(); 266 } 267 else { 268 assigned.removeElement(plugin); 269 int index = assigned.size() - 1; 270 boolean found = false; 271 while(!found) { 272 Object temp = assigned.get(index); 273 if(temp instanceof PlugIn) { 274 PlugIn current = (PlugIn) temp; 275 if(current.getName().equals("ArcPlug") || current.getName().equals("RecPlug")) { 276 index--; 277 } 278 else { 279 found = true; 280 } 281 } 282 else { 283 found = true; 284 } 285 } 286 assigned.add(index, plugin); 287 gatherer.c_man.configurationChanged(); 288 } 289 } 290 else { 291 // Try to move the plugin one step in the desired direction. 292 int index = assigned.indexOf(plugin); 293 ///ystem.err.println("Index of " + plugin + " = " + index); 294 if(direction) { 295 index--; 296 if(index < 0) { 297 String args[] = new String[1]; 298 args[0] = plugin.getName(); 299 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Top", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 300 return; 301 } 302 assigned.removeElement(plugin); 303 assigned.add(index, plugin); 304 gatherer.c_man.configurationChanged(); 305 } 306 else { 307 index++; 308 Object object = assigned.get(index); 309 if(index == assigned.size()) { 310 String args[] = new String[1]; 311 args[0] = plugin.getName(); 312 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Bottom", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 313 // Still not going to move RecPlug or ArcPlug. 314 return; 315 } 316 else if(!(object instanceof PlugIn) || ((PlugIn)object).getName().equals("ArcPlug") || ((PlugIn)object).getName().equals("RecPlug")) { 317 String args[] = new String[1]; 318 args[0] = plugin.getName(); 319 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Cannot", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 320 // Still not going to move RecPlug or ArcPlug. 321 return; 322 } 323 assigned.removeElement(plugin); 324 assigned.add(index, plugin); 325 gatherer.c_man.configurationChanged(); 326 } 327 } 328 } 329 330 /** This method attempts to parse a plugin command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct plugin be matched by also all of the parameters given must be legal. If such a command is found, the plugin is immediately assigned. 331 * @param command The coomand <strong>String</strong> that may include plugin information. 332 * @return <i>true</i> if a plugin command was parsed, <i>false</i> otherwise. 333 */ 334 public boolean parse(String command) { 335 String command_lc = command.toLowerCase(); 336 if(command_lc.startsWith("plugin")) { 337 CommandTokenizer tokenizer = new CommandTokenizer(command); 338 if(tokenizer.countTokens() >= 2) { 339 tokenizer.nextToken(); // Throw away 'plugin' 340 String name = tokenizer.nextToken(); 341 // Try to locate the plugin with this name. 342 PlugIn plugin = getPlugIn(name); 343 // And if successful start to parse the arguments. 344 if(plugin != null) { 345 // Take a copy. 346 plugin = plugin.copy(); 347 String key = null; 348 while(tokenizer.hasMoreTokens()) { 349 if(key == null) { 350 key = tokenizer.nextToken(); 351 } 352 // Try to retrieve a matching argument. 353 Argument argument = plugin.getArgument(key); 354 if(argument != null) { 355 // Set as assigned. 356 argument.setAssigned(true); 357 // And if the argument is of a parameter type, parse a parameter. 358 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) { 359 argument.setValue(tokenizer.nextToken()); 360 } 361 key = null; 362 } 363 // Argument cannot be matched. 364 else { 365 String cur_key = key; 366 String value = tokenizer.nextToken(); 367 if(value.startsWith("-")) { 368 key = value; 369 value = null; 370 } 371 else { 372 key = null; 373 } 374 String custom = plugin.getCustom(); 375 if(custom == null) { 376 if(value == null) { 377 plugin.setCustom(cur_key); 266 378 } 267 379 else { 268 assigned.removeElement(plugin); 269 int index = assigned.size() - 1; 270 boolean found = false; 271 while(!found) { 272 Object temp = assigned.get(index); 273 if(temp instanceof PlugIn) { 274 PlugIn current = (PlugIn) temp; 275 if(current.getName().equals("ArcPlug") || current.getName().equals("RecPlug")) { 276 index--; 277 } 278 else { 279 found = true; 280 } 281 } 282 else { 283 found = true; 284 } 285 } 286 assigned.add(index, plugin); 287 gatherer.c_man.configurationChanged(); 380 plugin.setCustom(cur_key + " " + value); 288 381 } 289 } 290 else { 291 // Try to move the plugin one step in the desired direction. 292 int index = assigned.indexOf(plugin); 293 ///ystem.err.println("Index of " + plugin + " = " + index); 294 if(direction) { 295 index--; 296 if(index < 0) { 297 String args[] = new String[1]; 298 args[0] = plugin.getName(); 299 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Top", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 300 return; 301 } 302 assigned.removeElement(plugin); 303 assigned.add(index, plugin); 304 gatherer.c_man.configurationChanged(); 382 } 383 else { 384 if(value == null) { 385 plugin.setCustom(custom + " " + cur_key); 305 386 } 306 387 else { 307 index++; 308 Object object = assigned.get(index); 309 if(index == assigned.size()) { 310 String args[] = new String[1]; 311 args[0] = plugin.getName(); 312 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.At_Bottom", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 313 // Still not going to move RecPlug or ArcPlug. 314 return; 315 } 316 else if(!(object instanceof PlugIn) || ((PlugIn)object).getName().equals("ArcPlug") || ((PlugIn)object).getName().equals("RecPlug")) { 317 String args[] = new String[1]; 318 args[0] = plugin.getName(); 319 JOptionPane.showMessageDialog(manager.gui, get("CDM.Move.Cannot", args), get("CDM.Move.Title"), JOptionPane.ERROR_MESSAGE); 320 // Still not going to move RecPlug or ArcPlug. 321 return; 322 } 323 assigned.removeElement(plugin); 324 assigned.add(index, plugin); 325 gatherer.c_man.configurationChanged(); 388 plugin.setCustom(custom + " " + cur_key + " " + value); 326 389 } 327 } 328 } 329 330 /** This method attempts to parse a plugin command from a command string taken from the collection configuration file. This process is quite complex as not only must the correct plugin be matched by also all of the parameters given must be legal. If such a command is found, the plugin is immediately assigned. 331 * @param command The coomand <strong>String</strong> that may include plugin information. 332 * @return <i>true</i> if a plugin command was parsed, <i>false</i> otherwise. 333 */ 334 public boolean parse(String command) { 335 String command_lc = command.toLowerCase(); 336 if(command_lc.startsWith("plugin")) { 337 CommandTokenizer tokenizer = new CommandTokenizer(command); 338 if(tokenizer.countTokens() >= 2) { 339 tokenizer.nextToken(); // Throw away 'plugin' 340 String name = tokenizer.nextToken(); 341 // Try to locate the plugin with this name. 342 PlugIn plugin = getPlugIn(name); 343 // And if successful start to parse the arguments. 344 if(plugin != null) { 345 // Take a copy. 346 plugin = plugin.copy(); 347 String key = null; 348 while(tokenizer.hasMoreTokens()) { 349 if(key == null) { 350 key = tokenizer.nextToken(); 351 } 352 // Try to retrieve a matching argument. 353 Argument argument = plugin.getArgument(key); 354 if(argument != null) { 355 // Set as assigned. 356 argument.setAssigned(true); 357 // And if the argument is of a parameter type, parse a parameter. 358 if(argument.getType() != Argument.FLAG && tokenizer.hasMoreTokens()) { 359 argument.setValue(tokenizer.nextToken()); 360 } 361 key = null; 362 } 363 // Argument cannot be matched. 364 else { 365 String cur_key = key; 366 String value = tokenizer.nextToken(); 367 if(value.startsWith("-")) { 368 key = value; 369 value = null; 370 } 371 else { 372 key = null; 373 } 374 String custom = plugin.getCustom(); 375 if(custom == null) { 376 if(value == null) { 377 plugin.setCustom(cur_key); 378 } 379 else { 380 plugin.setCustom(cur_key + " " + value); 381 } 382 } 383 else { 384 if(value == null) { 385 plugin.setCustom(custom + " " + cur_key); 386 } 387 else { 388 plugin.setCustom(custom + " " + cur_key + " " + value); 389 } 390 } 391 } 392 } 393 // Slight tweak. If the plugin is the RecPlug we want to set use_metadata_files by default. 394 if(plugin.getName().equalsIgnoreCase("RecPlug")) { 395 Argument argument = plugin.getArgument("-use_metadata_files"); 396 if(argument != null) { 397 argument.setAssigned(true); 398 } 399 } 400 // Second tweak. If the plugin is the HTMLPlug we want to modify the block expression so our backup files are ignored. 401 if(plugin.getName().equalsIgnoreCase("HTMLPlug")) { 402 Argument argument = plugin.getArgument("-block_exp"); 403 if(argument != null) { 404 argument.setValue(argument.getDefaultValue() + "|(~$)"); 405 } 406 } 407 // Add the plugin to our reserve 408 assignPlugIn(plugin); 409 return true; 410 } 411 else { 412 //ystem.err.println("Unknown plugin"); 413 } 414 } 415 } 416 return false; 417 } 418 /** This method removes an assigned plugin. I was tempted to call it unassign, by remove is more consistant. Note that there is no way to remove a plugin from the reserve. 390 } 391 } 392 } 393 // Slight tweak. If the plugin is the RecPlug we want to set use_metadata_files by default. 394 if(plugin.getName().equalsIgnoreCase("RecPlug")) { 395 Argument argument = plugin.getArgument("-use_metadata_files"); 396 if(argument != null) { 397 argument.setAssigned(true); 398 } 399 } 400 // Second tweak. If the plugin is the HTMLPlug we want to modify the block expression so our backup files are ignored. 401 if(plugin.getName().equalsIgnoreCase("HTMLPlug")) { 402 Argument argument = plugin.getArgument("-block_exp"); 403 if(argument != null) { 404 argument.setValue(argument.getDefaultValue() + "|(~$)"); 405 } 406 } 407 // Add the plugin to our reserve 408 assignPlugIn(plugin); 409 return true; 410 } 411 else { 412 //ystem.err.println("Unknown plugin"); 413 } 414 } 415 } 416 return false; 417 } 418 /** This method removes an assigned plugin. I was tempted to call it unassign, by remove is more consistant. Note that there is no way to remove a plugin from the reserve. 419 419 * @param plugin The <strong>PlugIn</strong> to remove. 420 420 */ 421 422 423 424 425 426 427 */ 428 429 430 431 432 433 434 435 436 437 438 421 public void removePlugIn(PlugIn plugin) { 422 assigned.removeElement(plugin); 423 available.addElement(plugin); 424 gatherer.c_man.configurationChanged(); 425 } 426 /** Method to cache the current contents of reserve (known plugins) to file. 427 */ 428 public void savePlugIns() { 429 try { 430 FileOutputStream file = new FileOutputStream(Utility.BASE_DIR + "plugins.dat"); 431 ObjectOutputStream out = new ObjectOutputStream(file); 432 out.writeObject(reserve); 433 out.close(); 434 } 435 catch (Exception error) { 436 } 437 } 438 /** Method used to determine the number of plugins that have been assigned. 439 439 * @return An <i>int</i> which is the number of plugins. 440 440 */ 441 442 443 444 441 public int size() { 442 return assigned.size(); 443 } 444 /** Method to print out a block of plugin commands, much like you'd find in a collection configuration file. 445 445 * @return A <strong>String</strong> containing a series of plugin commands separated by new lines. 446 446 */ 447 448 449 450 451 452 453 454 455 456 457 458 459 447 public String toString() { 448 String text = ""; 449 for(int i = 0; i < assigned.size(); i++) { 450 Object object = assigned.get(i); 451 if(object instanceof PlugIn) { 452 PlugIn plugin = (PlugIn) object; 453 text = text + plugin.toString() + "\n"; 454 } 455 } 456 text = text + "\n"; 457 return text; 458 } 459 /* Retrieve a phrase from the dictionary based on a certain key. 460 460 * @param key The search <strong>String</strong>. 461 461 * @return The matching phrase from the Dictionary. 462 462 */ 463 464 465 466 463 private String get(String key) { 464 return get(key, null); 465 } 466 /* Retrieve a phrase from the dictionary based on a certain key and arguments. 467 467 * @param key The search <strong>String</strong>. 468 468 * @param args A <strong>String[]</strong> of arguments used to complete and format the choosen phrase. 469 469 * @return The matching phrase from the Dictionary. 470 470 */ 471 472 473 474 475 476 477 471 private String get(String key, String args[]) { 472 if(key.indexOf(".") == -1) { 473 key = "CDM.PlugInManager." + key; 474 } 475 return gatherer.dictionary.get(key, args); 476 } 477 /** Method to extract just the plugins name from a file object. 478 478 * @param plugin The <strong>File</strong> which references a certain plugin. 479 479 * @return A <strong>String</strong> containing just the plugins name, without extension. 480 480 */ 481 482 483 484 485 486 487 488 481 private String getPlugInName(File plugin) { 482 String name = plugin.getName(); 483 if(name.indexOf(".") != -1) { 484 name = name.substring(0, name.indexOf(".")); 485 } 486 return name; 487 } 488 /** Method to retrieve the CData value from a node. Requires a search for the #text node. 489 489 * @param node The <strong>Node</strong> whose value we wish to find. 490 490 * @return The value of node as a <strong>String</strong>, or <i>null</i> if no value exists. 491 491 */ 492 493 494 492 private String getValue(Node node) { 493 if(node.hasChildNodes()) { 494 Node text = node.getFirstChild(); 495 495 //ystem.err.println("Value of " + node.getNodeName() + " = " + text.getNodeValue()); 496 497 498 499 500 501 */ 502 503 504 505 506 507 508 509 510 511 512 513 514 515 496 return text.getNodeValue(); 497 } 498 return node.getNodeValue(); 499 } 500 /** Method to initially load information from the standard plug-ins within the gsdl Perl library. 501 */ 502 private void loadPlugIns() { 503 // Attempt to restore the cached file. 504 try { 505 FileInputStream file = new FileInputStream(Utility.BASE_DIR + "plugins.dat"); 506 ObjectInputStream input = new ObjectInputStream(file); 507 reserve = (DynamicListModel) input.readObject(); 508 available = reserve.shallowCopy(); 509 } 510 catch (Exception error) { 511 } 512 if(reserve == null) { 513 available = new DynamicListModel(); 514 reserve = new DynamicListModel(); 515 reserve.setAutoOrder(true); 516 516 // Retrieve the gsdl home directory... 517 518 519 520 521 522 517 String directory = gatherer.config.gsdl_path; 518 directory = directory + "perllib" + File.separator + "plugins" + File.separator; 519 loadPlugIns(new File(directory)); 520 } 521 } 522 /** Method to load plug-in information from a specified directory. Of course no plug-ins may be found at this location. 523 523 * @param directory A <strong>File</strong> indicating the directory to be scanned for plug-ins. 524 524 */ 525 526 527 525 private void loadPlugIns(File directory) { 526 File files[] = directory.listFiles(); 527 if(files != null) { 528 528 // Create a progress indicator. 529 ParsingProgress progress = new ParsingProgress(get("CDM.PlugInManager.Parsing.Title"), get("CDM.PlugInManager.Parsing.Message"), files.length); 530 for(int i = 0; i < files.length; i++) { 531 // We only want to check Perl Modules. 532 if(files[i].getName().endsWith(".pm")) { 533 loadPlugIn(files[i]); 534 } 535 progress.inc(); 529 ParsingProgress progress = new ParsingProgress(get("CDM.PlugInManager.Parsing.Title"), get("CDM.PlugInManager.Parsing.Message"), files.length); 530 for(int i = 0; i < files.length; i++) { 531 // We only want to check Perl Modules. 532 if(files[i].getName().endsWith(".pm")) { 533 loadPlugIn(files[i]); 534 } 535 progress.inc(); 536 } 537 progress.dispose(); 538 } 539 } 540 541 private PlugIn parse(Node root) { 542 PlugIn plugin = new PlugIn(); 543 String node_name = null; 544 for(Node node = root.getFirstChild(); node != null; 545 node = node.getNextSibling()) { 546 node_name = node.getNodeName(); 547 if(node_name.equals("Name")) { 548 String name = getValue(node); 549 // We can save ourselves some processing time if a plugin with this name already exists in our manager. If so retrieve it and return it. 550 PlugIn existing = getPlugIn(name); 551 if(existing != null) { 552 return existing; 553 } 554 plugin.setName(name); 555 } 556 else if(node_name.equals("Desc")) { 557 plugin.setDesc(getValue(node)); 558 } 559 // Parse the multitude of arguments. 560 else if(node_name.equals("Arguments")) { 561 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) { 562 node_name = arg.getNodeName(); 563 // An option. 564 if(node_name.equals("Option")) { 565 Argument argument = new Argument(); 566 // If its an option we parse the multitude of details an options might have. 567 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) { 568 node_name = det.getNodeName(); 569 if(node_name.equals("Name")) { 570 argument.setName(getValue(det)); 571 } 572 else if(node_name.equals("Desc")) { 573 argument.setDesc(getValue(det)); 574 } 575 else if(node_name.equals("Type")) { 576 argument.setType(getValue(det)); 577 } 578 else if(node_name.equals("Default")) { 579 argument.setDefault(getValue(det)); 580 } 581 else if(node_name.equals("List")) { 582 // Two final loops are required to parse lists. 583 for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) { 584 if(value.getNodeName().equals("Value")) { 585 String key = null; 586 String desc = ""; 587 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { 588 node_name = subvalue.getNodeName(); 589 if(node_name.equals("Name")) { 590 key = getValue(subvalue); 591 } 592 else if(node_name.equals("Desc")) { 593 desc = getValue(subvalue); 594 } 595 } 596 if(key != null) { 597 argument.addOption(key, desc); 598 } 599 } 536 600 } 537 progress.dispose(); 538 } 539 } 540 541 private PlugIn parse(Node root) { 542 PlugIn plugin = new PlugIn(); 543 String node_name = null; 544 for(Node node = root.getFirstChild(); node != null; 545 node = node.getNextSibling()) { 546 node_name = node.getNodeName(); 547 if(node_name.equals("Name")) { 548 String name = getValue(node); 549 // We can save ourselves some processing time if a plugin with this name already exists in our manager. If so retrieve it and return it. 550 PlugIn existing = getPlugIn(name); 551 if(existing != null) { 552 return existing; 553 } 554 plugin.setName(name); 601 } 602 else if(node_name.equals("Required")) { 603 String v = getValue(det); 604 if(v != null && v.equals("yes")) { 605 argument.setRequired(true); 555 606 } 556 else if(node_name.equals("Desc")) { 557 plugin.setDesc(getValue(node)); 558 } 559 // Parse the multitude of arguments. 560 else if(node_name.equals("Arguments")) { 561 for(Node arg = node.getFirstChild(); arg != null; arg = arg.getNextSibling()) { 562 node_name = arg.getNodeName(); 563 // An option. 564 if(node_name.equals("Option")) { 565 Argument argument = new Argument(); 566 // If its an option we parse the multitude of details an options might have. 567 for(Node det = arg.getFirstChild(); det != null; det = det.getNextSibling()) { 568 node_name = det.getNodeName(); 569 if(node_name.equals("Name")) { 570 argument.setName(getValue(det)); 571 } 572 else if(node_name.equals("Desc")) { 573 argument.setDesc(getValue(det)); 574 } 575 else if(node_name.equals("Type")) { 576 argument.setType(getValue(det)); 577 } 578 else if(node_name.equals("Default")) { 579 argument.setDefault(getValue(det)); 580 } 581 else if(node_name.equals("List")) { 582 // Two final loops are required to parse lists. 583 for(Node value = det.getFirstChild(); value != null; value = value.getNextSibling()) { 584 if(value.getNodeName().equals("Value")) { 585 String key = null; 586 String desc = ""; 587 for(Node subvalue = value.getFirstChild(); subvalue != null; subvalue = subvalue.getNextSibling()) { 588 node_name = subvalue.getNodeName(); 589 if(node_name.equals("Name")) { 590 key = getValue(subvalue); 591 } 592 else if(node_name.equals("Desc")) { 593 desc = getValue(subvalue); 594 } 595 } 596 if(key != null) { 597 argument.addOption(key, desc); 598 } 599 } 600 } 601 } 602 else if(node_name.equals("Required")) { 603 String v = getValue(det); 604 if(v != null && v.equals("yes")) { 605 argument.setRequired(true); 606 } 607 } 608 } 609 plugin.addArgument(argument); 610 } 611 // A super plugin class. 612 else if(node_name.equals("PlugInfo")) { 613 PlugIn super_plugin = parse(arg); 614 plugin.setSuper(super_plugin); 615 } 616 } 617 } 618 } 619 if(plugin.getName() != null) { 620 addPlugIn(plugin); 621 return plugin; 622 } 623 return null; 624 } 625 626 /** A class which provodes controls for assigned and editing plugins. */ 627 private class Control 628 extends JPanel { 629 /** Button for adding plugins. */ 630 private JButton add = null; 631 /** Button for configuring the selected plugin. */ 632 private JButton configure = null; 633 /** Buttom to move an assinged plugin as low in the order as possible. */ 634 private JButton move_bottom = null; 635 /** Button to move an assigned plugin one position lower in the order. */ 636 private JButton move_down = null; 637 /** Button to move an assigned plugin as high in the order as possible. */ 638 private JButton move_top = null; 639 /** Button to move an assigned plugin one position higher in the order. */ 640 private JButton move_up = null; 641 /** Button to remove the selected plugin. */ 642 private JButton remove = null; 643 /** A combobox containing all of the known plugins, including those that may have already been assigned. */ 644 private JComboBox plugin = null; 645 /** The label next to the plugin combobox. */ 646 private JLabel plugin_label = null; 647 /** The label above the assigned plugin list. */ 648 private JLabel plugin_list_label = null; 649 /** The title of this view. */ 650 private JLabel title = null; 651 /** A list of assigned plugins. */ 652 private JList plugin_list = null; 653 /** The area where the add, configure and remove buttons are placed. */ 654 private JPanel button_pane = null; 655 /** The region which divides the central portion of the view into list and controls. */ 656 private JPanel central_pane = null; 657 /** The area where title label and instructions sit. */ 658 private JPanel header_pane = null; 659 /** The area where movement buttons are placed. */ 660 private JPanel movement_pane = null; 661 /** The small region containing the plugin combobox and its label. */ 662 private JPanel plugin_pane = null; 663 /** The pane containing the assigned plugin list and its label. */ 664 private JPanel plugin_list_pane = null; 665 /** The text area containing instructions on the use of this control. */ 666 private JTextArea instructions = null; 667 /** Constructor. 607 } 608 } 609 plugin.addArgument(argument); 610 } 611 // A super plugin class. 612 else if(node_name.equals("PlugInfo")) { 613 PlugIn super_plugin = parse(arg); 614 plugin.setSuper(super_plugin); 615 } 616 } 617 } 618 } 619 if(plugin.getName() != null) { 620 addPlugIn(plugin); 621 return plugin; 622 } 623 return null; 624 } 625 626 /** A class which provodes controls for assigned and editing plugins. */ 627 private class Control 628 extends JPanel { 629 /** Button for adding plugins. */ 630 private JButton add = null; 631 /** Button for configuring the selected plugin. */ 632 private JButton configure = null; 633 /** Buttom to move an assinged plugin as low in the order as possible. */ 634 private JButton move_bottom = null; 635 /** Button to move an assigned plugin one position lower in the order. */ 636 private JButton move_down = null; 637 /** Button to move an assigned plugin as high in the order as possible. */ 638 private JButton move_top = null; 639 /** Button to move an assigned plugin one position higher in the order. */ 640 private JButton move_up = null; 641 /** Button to remove the selected plugin. */ 642 private JButton remove = null; 643 /** A combobox containing all of the known plugins, including those that may have already been assigned. */ 644 private JComboBox plugin = null; 645 /** The label next to the plugin combobox. */ 646 private JLabel plugin_label = null; 647 /** The label above the assigned plugin list. */ 648 private JLabel plugin_list_label = null; 649 /** The title of this view. */ 650 private JLabel title = null; 651 /** A list of assigned plugins. */ 652 private JList plugin_list = null; 653 /** The area where the add, configure and remove buttons are placed. */ 654 private JPanel button_pane = null; 655 /** The region which divides the central portion of the view into list and controls. */ 656 private JPanel central_pane = null; 657 /** The area where title label and instructions sit. */ 658 private JPanel header_pane = null; 659 /** The area where movement buttons are placed. */ 660 private JPanel movement_pane = null; 661 /** The small region containing the plugin combobox and its label. */ 662 private JPanel plugin_pane = null; 663 /** The pane containing the assigned plugin list and its label. */ 664 private JPanel plugin_list_pane = null; 665 /** The text area containing instructions on the use of this control. */ 666 private JTextArea instructions = null; 667 /** Constructor. 668 */ 669 public Control() { 670 Object plugins[] = reserve.toArray(); 671 Vector plugin_model = new Vector(); 672 for(int i = 0; i < plugins.length; i++) { 673 plugin_model.add(((PlugIn)plugins[i]).getName()); 674 } 675 Collections.sort(plugin_model); 676 // Create 677 add = new JButton(get("Add")); 678 add.setMnemonic(KeyEvent.VK_A); 679 button_pane = new JPanel(); 680 central_pane = new JPanel(); 681 configure = new JButton(get("Configure")); 682 configure.setMnemonic(KeyEvent.VK_C); 683 header_pane = new JPanel(); 684 instructions = new JTextArea(get("Instructions")); 685 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 686 instructions.setEditable(false); 687 instructions.setLineWrap(true); 688 instructions.setRows(5); 689 instructions.setWrapStyleWord(true); 690 move_bottom = new JButton(); 691 JLabel move_bottom_label = new JLabel(get("Move_Bottom")); 692 move_bottom_label.setHorizontalAlignment(JLabel.CENTER); 693 move_bottom_label.setPreferredSize(LABEL_SIZE); 694 move_bottom.setLayout(new BorderLayout()); 695 move_bottom.add(new JLabel(Utility.getImage("arrow-bottom.gif")), BorderLayout.WEST); 696 move_bottom.add(move_bottom_label, BorderLayout.CENTER); 697 move_bottom.add(new JLabel(Utility.getImage("arrow-bottom.gif")), BorderLayout.EAST); 698 move_bottom.setMnemonic(KeyEvent.VK_B); 699 move_down = new JButton(); 700 JLabel move_down_label = new JLabel(get("Move_Down")); 701 move_down_label.setHorizontalAlignment(JLabel.CENTER); 702 move_down_label.setPreferredSize(LABEL_SIZE); 703 move_down.setLayout(new BorderLayout()); 704 move_down.add(new JLabel(Utility.getImage("arrow-down.gif")), BorderLayout.WEST); 705 move_down.add(move_down_label, BorderLayout.CENTER); 706 move_down.add(new JLabel(Utility.getImage("arrow-down.gif")), BorderLayout.EAST); 707 move_down.setMnemonic(KeyEvent.VK_D); 708 move_top = new JButton(); 709 JLabel move_top_label = new JLabel(get("Move_Top")); 710 move_top_label.setHorizontalAlignment(JLabel.CENTER); 711 move_top_label.setPreferredSize(LABEL_SIZE); 712 move_top.setLayout(new BorderLayout()); 713 move_top.add(new JLabel(Utility.getImage("arrow-top.gif")), BorderLayout.WEST); 714 move_top.add(move_top_label, BorderLayout.CENTER); 715 move_top.add(new JLabel(Utility.getImage("arrow-top.gif")), BorderLayout.EAST); 716 move_top.setMnemonic(KeyEvent.VK_T); 717 move_up = new JButton(); 718 JLabel move_up_label = new JLabel(get("Move_Up")); 719 move_up_label.setHorizontalAlignment(JLabel.CENTER); 720 move_up_label.setPreferredSize(LABEL_SIZE); 721 move_up.setLayout(new BorderLayout()); 722 move_up.add(new JLabel(Utility.getImage("arrow-up.gif")), BorderLayout.WEST); 723 move_up.add(move_up_label, BorderLayout.CENTER); 724 move_up.add(new JLabel(Utility.getImage("arrow-up.gif")), BorderLayout.EAST); 725 move_up.setMnemonic(KeyEvent.VK_U); 726 movement_pane = new JPanel(); 727 plugin = new JComboBox(available); 728 //plugin.setEditable(true); 729 plugin.setSelectedIndex(0); 730 plugin_label = new JLabel(get("PlugIn")); 731 plugin_list = new JList(assigned); 732 plugin_list.setCellRenderer(new ListRenderer()); 733 plugin_list_label = new JLabel(get("Assigned")); 734 plugin_list_label.setHorizontalAlignment(JLabel.CENTER); 735 plugin_list_label.setOpaque(true); 736 plugin_list_pane = new JPanel(); 737 plugin_pane = new JPanel(); 738 remove = new JButton(get("Remove")); 739 remove.setMnemonic(KeyEvent.VK_R); 740 title = new JLabel(get("Title")); 741 title.setHorizontalAlignment(JLabel.CENTER); 742 title.setOpaque(true); 743 // Listeners 744 add.addActionListener(new AddListener()); 745 configure.addActionListener(new ConfigureListener()); 746 MoveListener ml = new MoveListener(); 747 move_bottom.addActionListener(ml); 748 move_down.addActionListener(ml); 749 move_top.addActionListener(ml); 750 move_up.addActionListener(ml); 751 remove.addActionListener(new RemoveListener()); 752 plugin_list.addMouseListener(new ClickListener()); 753 // Layout 754 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0)); 755 756 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 757 758 header_pane.setLayout(new BorderLayout()); 759 header_pane.add(title, BorderLayout.NORTH); 760 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 761 762 plugin_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2)); 763 764 movement_pane.setLayout(new GridLayout(4,1)); 765 movement_pane.add(move_top); 766 movement_pane.add(move_up); 767 movement_pane.add(move_down); 768 movement_pane.add(move_bottom); 769 770 plugin_list_pane.setLayout(new BorderLayout()); 771 plugin_list_pane.add(plugin_list_label, BorderLayout.NORTH); 772 plugin_list_pane.add(new JScrollPane(plugin_list), BorderLayout.CENTER); 773 plugin_list_pane.add(movement_pane, BorderLayout.EAST); 774 775 plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 776 777 plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 778 plugin_pane.setLayout(new GridLayout(1,2)); 779 plugin_pane.add(plugin_label); 780 plugin_pane.add(plugin); 781 782 // Scope these mad bordering skillz. 783 JPanel temp = new JPanel(new BorderLayout()); 784 temp.setBorder 785 (BorderFactory.createCompoundBorder 786 (BorderFactory.createEmptyBorder(5,0,5,0), 787 BorderFactory.createCompoundBorder 788 (BorderFactory.createTitledBorder(get("Controls")), 789 BorderFactory.createEmptyBorder(2,2,2,2)))); 790 791 temp.add(plugin_pane, BorderLayout.NORTH); 792 temp.add(button_pane, BorderLayout.SOUTH); 793 794 central_pane.setLayout(new BorderLayout()); 795 central_pane.add(plugin_list_pane, BorderLayout.CENTER); 796 central_pane.add(temp, BorderLayout.SOUTH); 797 798 button_pane.setLayout(new GridLayout(3,1)); 799 button_pane.add(add); 800 button_pane.add(configure); 801 button_pane.add(remove); 802 803 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 804 setLayout(new BorderLayout()); 805 add(header_pane, BorderLayout.NORTH); 806 add(central_pane, BorderLayout.CENTER); 807 //add(button_pane, BorderLayout.SOUTH); 808 } 809 /** Method which acts like a destructor, tidying up references to persistant objects. 668 810 */ 669 public Control() { 670 Object plugins[] = reserve.toArray(); 671 Vector plugin_model = new Vector(); 672 for(int i = 0; i < plugins.length; i++) { 673 plugin_model.add(((PlugIn)plugins[i]).getName()); 674 } 675 Collections.sort(plugin_model); 676 // Create 677 add = new JButton(get("Add")); 678 add.setMnemonic(KeyEvent.VK_A); 679 button_pane = new JPanel(); 680 central_pane = new JPanel(); 681 configure = new JButton(get("Configure")); 682 configure.setMnemonic(KeyEvent.VK_C); 683 header_pane = new JPanel(); 684 instructions = new JTextArea(get("Instructions")); 685 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 686 instructions.setEditable(false); 687 instructions.setLineWrap(true); 688 instructions.setRows(5); 689 instructions.setWrapStyleWord(true); 690 move_bottom = new JButton(); 691 JLabel move_bottom_label = new JLabel(get("Move_Bottom")); 692 move_bottom_label.setHorizontalAlignment(JLabel.CENTER); 693 move_bottom_label.setPreferredSize(LABEL_SIZE); 694 move_bottom.setLayout(new BorderLayout()); 695 move_bottom.add(new JLabel(Utility.getImage("arrow-bottom.gif")), BorderLayout.WEST); 696 move_bottom.add(move_bottom_label, BorderLayout.CENTER); 697 move_bottom.add(new JLabel(Utility.getImage("arrow-bottom.gif")), BorderLayout.EAST); 698 move_bottom.setMnemonic(KeyEvent.VK_B); 699 move_down = new JButton(); 700 JLabel move_down_label = new JLabel(get("Move_Down")); 701 move_down_label.setHorizontalAlignment(JLabel.CENTER); 702 move_down_label.setPreferredSize(LABEL_SIZE); 703 move_down.setLayout(new BorderLayout()); 704 move_down.add(new JLabel(Utility.getImage("arrow-down.gif")), BorderLayout.WEST); 705 move_down.add(move_down_label, BorderLayout.CENTER); 706 move_down.add(new JLabel(Utility.getImage("arrow-down.gif")), BorderLayout.EAST); 707 move_down.setMnemonic(KeyEvent.VK_D); 708 move_top = new JButton(); 709 JLabel move_top_label = new JLabel(get("Move_Top")); 710 move_top_label.setHorizontalAlignment(JLabel.CENTER); 711 move_top_label.setPreferredSize(LABEL_SIZE); 712 move_top.setLayout(new BorderLayout()); 713 move_top.add(new JLabel(Utility.getImage("arrow-top.gif")), BorderLayout.WEST); 714 move_top.add(move_top_label, BorderLayout.CENTER); 715 move_top.add(new JLabel(Utility.getImage("arrow-top.gif")), BorderLayout.EAST); 716 move_top.setMnemonic(KeyEvent.VK_T); 717 move_up = new JButton(); 718 JLabel move_up_label = new JLabel(get("Move_Up")); 719 move_up_label.setHorizontalAlignment(JLabel.CENTER); 720 move_up_label.setPreferredSize(LABEL_SIZE); 721 move_up.setLayout(new BorderLayout()); 722 move_up.add(new JLabel(Utility.getImage("arrow-up.gif")), BorderLayout.WEST); 723 move_up.add(move_up_label, BorderLayout.CENTER); 724 move_up.add(new JLabel(Utility.getImage("arrow-up.gif")), BorderLayout.EAST); 725 move_up.setMnemonic(KeyEvent.VK_U); 726 movement_pane = new JPanel(); 727 plugin = new JComboBox(available); 728 //plugin.setEditable(true); 729 plugin.setSelectedIndex(0); 730 plugin_label = new JLabel(get("PlugIn")); 731 plugin_list = new JList(assigned); 732 plugin_list.setCellRenderer(new ListRenderer()); 733 plugin_list_label = new JLabel(get("Assigned")); 734 plugin_list_label.setHorizontalAlignment(JLabel.CENTER); 735 plugin_list_label.setOpaque(true); 736 plugin_list_pane = new JPanel(); 737 plugin_pane = new JPanel(); 738 remove = new JButton(get("Remove")); 739 remove.setMnemonic(KeyEvent.VK_R); 740 title = new JLabel(get("Title")); 741 title.setHorizontalAlignment(JLabel.CENTER); 742 title.setOpaque(true); 743 // Listeners 744 add.addActionListener(new AddListener()); 745 configure.addActionListener(new ConfigureListener()); 746 MoveListener ml = new MoveListener(); 747 move_bottom.addActionListener(ml); 748 move_down.addActionListener(ml); 749 move_top.addActionListener(ml); 750 move_up.addActionListener(ml); 751 remove.addActionListener(new RemoveListener()); 752 plugin_list.addMouseListener(new ClickListener()); 753 // Layout 754 title.setBorder(BorderFactory.createEmptyBorder(0,0,2,0)); 755 756 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 757 758 header_pane.setLayout(new BorderLayout()); 759 header_pane.add(title, BorderLayout.NORTH); 760 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 761 762 plugin_list_label.setBorder(BorderFactory.createEmptyBorder(0,2,0,2)); 763 764 movement_pane.setLayout(new GridLayout(4,1)); 765 movement_pane.add(move_top); 766 movement_pane.add(move_up); 767 movement_pane.add(move_down); 768 movement_pane.add(move_bottom); 769 770 plugin_list_pane.setLayout(new BorderLayout()); 771 plugin_list_pane.add(plugin_list_label, BorderLayout.NORTH); 772 plugin_list_pane.add(new JScrollPane(plugin_list), BorderLayout.CENTER); 773 plugin_list_pane.add(movement_pane, BorderLayout.EAST); 774 775 plugin_label.setBorder(BorderFactory.createEmptyBorder(0,0,5,0)); 776 777 plugin_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 778 plugin_pane.setLayout(new GridLayout(1,2)); 779 plugin_pane.add(plugin_label); 780 plugin_pane.add(plugin); 781 782 // Scope these mad bordering skillz. 783 JPanel temp = new JPanel(new BorderLayout()); 784 temp.setBorder 785 (BorderFactory.createCompoundBorder 786 (BorderFactory.createEmptyBorder(5,0,5,0), 787 BorderFactory.createCompoundBorder 788 (BorderFactory.createTitledBorder(get("Controls")), 789 BorderFactory.createEmptyBorder(2,2,2,2)))); 790 791 temp.add(plugin_pane, BorderLayout.NORTH); 792 temp.add(button_pane, BorderLayout.SOUTH); 793 794 central_pane.setLayout(new BorderLayout()); 795 central_pane.add(plugin_list_pane, BorderLayout.CENTER); 796 central_pane.add(temp, BorderLayout.SOUTH); 797 798 button_pane.setLayout(new GridLayout(3,1)); 799 button_pane.add(add); 800 button_pane.add(configure); 801 button_pane.add(remove); 802 803 setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 804 setLayout(new BorderLayout()); 805 add(header_pane, BorderLayout.NORTH); 806 add(central_pane, BorderLayout.CENTER); 807 //add(button_pane, BorderLayout.SOUTH); 808 } 809 /** Method which acts like a destructor, tidying up references to persistant objects. 810 */ 811 public void destroy() { 812 } 813 /** This method is overridden in some control classes to allow for the updating of collection configuration when the focus is lost to another view. In this case however the updates are asynchronous and so no 'has the configuration changed without the user updating' check is needed. 811 public void destroy() { 812 } 813 /** This method is overridden in some control classes to allow for the updating of collection configuration when the focus is lost to another view. In this case however the updates are asynchronous and so no 'has the configuration changed without the user updating' check is needed. 814 814 * @return <i>true</i> if this control has focus, <i>false</i> otherwise. 815 815 */ 816 817 818 819 816 public boolean hasFocus() { 817 return super.hasFocus(); 818 } 819 /** This method is overridden to ensure the instructions are scrolled to top, before the super classes updateUI() is called. 820 820 */ 821 822 823 824 825 826 827 821 public void updateUI() { 822 if(instructions != null) { 823 instructions.setCaretPosition(0); 824 } 825 super.updateUI(); 826 } 827 /** This class listens for actions upon the add button in the controls, and if detected calls the <i>assignPlugIn()</i> method. 828 828 */ 829 830 829 private class AddListener 830 implements ActionListener { 831 831 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 832 832 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. 833 833 */ 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 834 public void actionPerformed(ActionEvent event) { 835 PlugIn new_plugin = null; 836 Object object = plugin.getSelectedItem(); 837 if(object instanceof PlugIn) { 838 PlugIn target = (PlugIn)object; 839 new_plugin = target.copy(); 840 } 841 else { 842 new_plugin = new PlugIn(object.toString(), "", null); 843 } 844 object = null; 845 // Automatically chain to configuration. This ensures required arguments are filled out. 846 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, new_plugin); 847 if(ac.display()) { 848 assignPlugIn(new_plugin); 849 plugin_list.setSelectedValue(new_plugin, true); 850 } 851 ac = null; 852 new_plugin = null; 853 plugin.setSelectedIndex(0); 854 } 855 } 856 /** This class listens for actions upon the configure button in the controls, and if detected creates a new <strong>ArgumentConfiguration</strong> dialog box to allow for configuration. 857 857 * @see org.greenstone.gatherer.cdm.ArgumentConfiguration 858 858 */ 859 860 859 private class ConfigureListener 860 implements ActionListener { 861 861 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 862 862 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. 863 863 */ 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 864 public void actionPerformed(ActionEvent event) { 865 if(!plugin_list.isSelectionEmpty()) { 866 Object object = plugin_list.getSelectedValue(); 867 if(object instanceof PlugIn) { 868 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (PlugIn)object); 869 if(ac.display()) { 870 assigned.refresh(); 871 } 872 } 873 } 874 } 875 } 876 /** A special list renderer which is able to render separating lines as well. */ 877 private class ListRenderer 878 extends DefaultListCellRenderer { 879 879 /** Return a component that has been configured to display the specified value. That component's paint method is then called to "render" the cell. If it is necessary to compute the dimensions of a list because the list cells do not have a fixed size, this method is called to generate a component on which getPreferredSize can be invoked. 880 880 * @param list - The <strong>JList</strong> we're painting. … … 889 889 * @see javax.swing.ListSelectionModel 890 890 */ 891 892 893 894 895 896 897 898 899 900 901 902 891 public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { 892 if(value instanceof JPanel) { 893 return (JPanel) value; 894 } 895 else { 896 return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); 897 } 898 } 899 } 900 /** Listens for double clicks apon the list and react as if the configure button was pushed. */ 901 private class ClickListener 902 extends MouseAdapter { 903 903 /** Called whenever the mouse is clicked over a registered component, we use this to chain through to the configure prompt. 904 904 * @param event A <strong>MouseEvent</strong> containing information about the mouse click. 905 905 */ 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 906 public void mouseClicked(MouseEvent event) { 907 if(event.getClickCount() == 2 ) { 908 if(!plugin_list.isSelectionEmpty()) { 909 Object object = plugin_list.getSelectedValue(); 910 if(object instanceof PlugIn) { 911 ArgumentConfiguration ac = new ArgumentConfiguration(gatherer, manager, (PlugIn)object); 912 if(ac.display()) { 913 assigned.refresh(); 914 } 915 } 916 } 917 } 918 } 919 } 920 /** Listens for actions apon the move buttons in the manager controls, and if detected calls the <i>movePlugIn()</i> method of the manager with the appropriate details. */ 921 private class MoveListener 922 implements ActionListener { 923 923 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 924 924 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. 925 925 */ 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 926 public void actionPerformed(ActionEvent event) { 927 if(!plugin_list.isSelectionEmpty()) { 928 Object object = plugin_list.getSelectedValue(); 929 if(object instanceof PlugIn) { 930 PlugIn plugin = (PlugIn) object; 931 if(event.getSource() == move_top) { 932 movePlugIn(plugin, true, true); 933 } 934 else if(event.getSource() == move_up) { 935 movePlugIn(plugin, true, false); 936 } 937 else if(event.getSource() == move_down) { 938 movePlugIn(plugin, false, false); 939 } 940 else { 941 movePlugIn(plugin, false, true); 942 } 943 plugin_list.setSelectedValue(plugin, true); 944 } 945 } 946 } 947 } 948 /** This class listens for actions upon the remove button in the controls, and if detected calls the <i>removePlugIn()</i> method. 949 949 */ 950 951 950 private class RemoveListener 951 implements ActionListener { 952 952 /** Any implementation of <i>ActionListener</i> must include this method so that we can be informed when an action has occured on one of our target controls. 953 953 * @param event An <strong>ActionEvent</strong> containing information garnered from the control action. 954 954 */ 955 956 957 958 959 960 961 962 963 964 965 955 public void actionPerformed(ActionEvent event) { 956 if(!plugin_list.isSelectionEmpty()) { 957 Object object = plugin_list.getSelectedValue(); 958 if(object instanceof PlugIn) { 959 removePlugIn((PlugIn)object); 960 } 961 } 962 } 963 } 964 } 965 /** Creates a list separator. 966 966 * Code courtesy of Farwell, Paul. Contact <a href="mailto:[email protected]">[email protected]</a> 967 967 */ 968 969 970 971 972 973 974 975 976 977 978 979 968 static private JPanel getSeparator() { 969 // we put the separator inside a panel to control 970 // its appearance 971 JPanel _sepPanel = new JPanel(); 972 _sepPanel.setOpaque(false); 973 _sepPanel.setBorder(BorderFactory.createEmptyBorder(1, 3, 1, 3)); 974 _sepPanel.setLayout(new BoxLayout(_sepPanel, BoxLayout.Y_AXIS)); 975 _sepPanel.add(Box.createRigidArea(new Dimension(0, 4))); 976 _sepPanel.add(new JPopupMenu.Separator()); 977 _sepPanel.add(Box.createRigidArea(new Dimension(0, 4))); 978 return _sepPanel; 979 } 980 980 } 981 981 -
trunk/gli/src/org/greenstone/gatherer/cdm/SubIndex.java
r4293 r4366 60 60 */ 61 61 public class SubIndex 62 63 64 65 66 67 68 69 62 extends Vector 63 implements Comparable { 64 /** Default Constructor. 65 */ 66 public SubIndex() { 67 super(); 68 } 69 /** Copy Constructor. 70 70 * @param original The <strong>Vector</strong> used to initially fill the SubIndex. 71 71 */ 72 73 74 75 72 public SubIndex(Vector original) { 73 super(original); 74 } 75 /** Parsed data Constructor. 76 76 * @param raw A <strong>String</strong> containing a comma separated list of subcollection names. 77 77 * @param manager A reference to the <strong>SubcollectionManager</strong> via which we retrieve the required Subcollections. 78 78 */ 79 80 81 82 83 84 85 86 87 88 89 90 79 public SubIndex(String raw, SubcollectionManager manager) { 80 super(); 81 StringTokenizer tokenizer = new StringTokenizer(raw, ","); 82 while(tokenizer.hasMoreTokens()) { 83 String name = tokenizer.nextToken(); 84 Subcollection sub = manager.getSubcollection(name); 85 if(sub != null) { 86 add(sub); 87 } 88 } 89 } 90 /** Method to compare two subindexes. 91 91 * @param object The other subindex to compare to, as an <strong>Object</strong>. 92 92 * @return An <i>int</i> which is greater than, equal to or less than zero if the this object is before, equal to, or after the target object respectively. 93 93 */ 94 95 96 97 98 94 public int compareTo(Object object) { 95 SubIndex index = (SubIndex) object; 96 return toString().compareTo(index.toString()); 97 } 98 /** Method to determine if this subindex contains a certain subcollection. 99 99 * @param name The name, as a <strong>String</strong>, of the subcollection you are checking for. 100 100 * @return A <i>boolean</i> which is <i>true</i> if this index contains the named subcollection, <i>false</i> otherwise. 101 101 */ 102 103 104 105 106 107 108 109 110 111 102 public boolean containsSubcollection(String name) { 103 for(int i = 0; i < size(); i++) { 104 Subcollection sub = (Subcollection) get(i); 105 if(sub.getName().equals(name)) { 106 return true; 107 } 108 } 109 return false; 110 } 111 /** Method to check two subindexes for equality. 112 112 * @param object The other subindex to compare to, as an <strong>Object</strong>. 113 113 * @return A <i>boolean</i> which is <i>true</i> if the subindexes are equal, <i>false</i> otherwise. 114 114 */ 115 116 117 118 119 120 121 115 public boolean equals(Object object) { 116 if(compareTo(object) == 0) { 117 return true; 118 } 119 return false; 120 } 121 /** Method to generate a comma separated list from a subindex vector. 122 122 * @return A <strong>String</strong> representing this subindex. 123 123 */ 124 125 126 127 128 129 130 131 132 133 134 135 124 public String toString() { 125 String text = ""; 126 for(int i = 0; i < size(); i++) { 127 Object object = get(i); 128 Subcollection sub = (Subcollection) get(i); 129 text = text + sub.getName(); 130 if(i < size() - 1) { 131 text = text + ","; 132 } 133 } 134 return text; 135 } 136 136 } -
trunk/gli/src/org/greenstone/gatherer/cdm/SubIndexes.java
r4293 r4366 58 58 */ 59 59 public class SubIndexes 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 60 extends DefaultListModel { 61 public void changed() { 62 fireContentsChanged(this, 0, getSize() - 1); 63 } 64 /** Method to display the contents of this class as an entry in the collection configuration file. The line contains the key word, then a space separated series of index entries. 65 * @return A <strong>String</strong> representing this collection of indexes. 66 */ 67 public String toString() { 68 String text = "indexsubcollections "; 69 for(int i = 0; i < size(); i++) { 70 text = text + ((SubIndex)get(i)).toString(); 71 if(i < size() - 1) { 72 text = text + " "; 73 } 74 } 75 text = text + "\n"; 76 return text; 77 } 78 78 } -
trunk/gli/src/org/greenstone/gatherer/cdm/Subcollection.java
r4293 r4366 53 53 import org.w3c.dom.Element; 54 54 /** This class encapsulates one subcollection entry in the collection configuration file. 55 * @author John Thompson, Greenstone Digital Library, University of Waikato56 * @version 2.357 */55 * @author John Thompson, Greenstone Digital Library, University of Waikato 56 * @version 2.3 57 */ 58 58 public class Subcollection 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 59 implements Comparable { 60 /** A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise. */ 61 private boolean include = true; 62 /** Either the fully qualified name of the metadata whose value should be matched against the given expression, or <i>null</i> if you wish to match against the file name. */ 63 private String element = null; 64 /** A String containing a Perl expression which is used as the filter for this subcollection. */ 65 private String exp = null; 66 /** A series of flags to be used when matching the expression. */ 67 private String flags = null; 68 /** A String which is a unique identifier of a subcollection. */ 69 private String name = null; 70 /** Constructor. 71 * @param name A <strong>String</strong> which is a unique identifier of a subcollection. 72 * @param pattern A <strong>String</strong> containing the inclusion, the element to filter, a Perl expression which is used as the filter for this subcollection, and a series of argument flags. 73 */ 74 public Subcollection(String name, String pattern) { 75 this.name = name; 76 // Have to do some work on pattern. 77 // Remove quote marks. 78 if(pattern.startsWith("\"") || pattern.startsWith("'")) { 79 pattern = pattern.substring(1, pattern.length() - 1); 80 } 81 // Test for exclusion 82 if(pattern.startsWith("!")) { 83 this.include = false; 84 pattern = pattern.substring(1, pattern.length()); 85 } 86 else { 87 this.include = true; 88 } 89 if(pattern.indexOf("/") != -1) { 90 90 // Now element (which may be Filename) 91 92 93 94 91 this.element = pattern.substring(0, pattern.indexOf("/")); 92 if(this.element.toLowerCase().equals("filename")) { 93 this.element = null; 94 } 95 95 // Extract Perl expression 96 97 98 99 100 101 102 103 104 105 96 if(pattern.indexOf("/") != pattern.lastIndexOf("/")) { 97 this.exp = pattern.substring(pattern.indexOf("/") + 1, 98 pattern.lastIndexOf("/")); 99 this.flags = pattern.substring(pattern.lastIndexOf("/") + 1); 100 } 101 else { 102 this.exp = pattern.substring(pattern.indexOf("/") + 1); 103 } 104 } 105 else { 106 106 // Hmmm. Well I don't know what this is but it isn't a proper subcollection definition. Can't really 'return null' or something. So I'll just not set include, element, exp and flag expressions. 107 108 109 107 } 108 } 109 /** Constructor. 110 110 * @param name A <strong>String</strong> which is a unique identifier of a subcollection. 111 111 * @param include A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise. 112 112 * @param exp A <strong>String</strong> containing a Perl expression which is used as the filter for this subcollection. 113 113 */ 114 115 116 117 118 119 120 121 114 public Subcollection(String name, boolean include, String exp, String flags) { 115 this.element = null; 116 this.exp = exp; 117 this.flags = flags; 118 this.include = include; 119 this.name = name; 120 } 121 /** Constructor. 122 122 * @param name A <strong>String</strong> which is a unique identifier of a subcollection. 123 123 * @param include A <i>boolean</i> which is <i>true</i> if the condition is an include one, <i>false</i> otherwise. … … 126 126 * @param flags A <strong>String</strong> of flags to be taken into account when matching the expression. 127 127 */ 128 129 130 131 132 133 134 135 128 public Subcollection(String name, boolean include, String element, String exp, String flags) { 129 this.element = element; 130 this.exp = exp; 131 this.flags = flags; 132 this.include = include; 133 this.name = name; 134 } 135 /** Method to compare two subcollections. 136 136 * @param object The other subcollection to compare to, as an <strong>Object</strong>. 137 137 * @return An <i>int</i> which is greater than, equal to or less than zero if the this object is before, equal to, or after the target object respectively. 138 138 */ 139 140 141 142 143 139 public int compareTo(Object object) { 140 Subcollection sub = (Subcollection) object; 141 return getName().compareTo(sub.getName()); 142 } 143 /** Method to check two subcollections for equality. 144 144 * @param object The other subcollection to compare to, as an <strong>Object</strong>. 145 145 * @return A <i>boolean</i> which is <i>true</i> if the subcollections are equal, <i>false</i> otherwise. 146 146 */ 147 148 149 150 151 152 153 147 public boolean equals(Object object) { 148 if(compareTo(object) == 0) { 149 return true; 150 } 151 return false; 152 } 153 /** Method to get the value of element. 154 154 * @return The value of element as an <strong>String</strong>. 155 155 */ 156 157 158 159 156 public String getElement() { 157 return element; 158 } 159 /** Method to get the value of expression. 160 160 * @return The value of exp as a <strong>String</strong>. 161 161 */ 162 163 164 165 162 public String getExpression() { 163 return exp; 164 } 165 /** Method to get the value of flags. 166 166 * @return The value of flags as a <strong>String</strong>. 167 167 */ 168 169 170 171 168 public String getFlags() { 169 return flags; 170 } 171 /** Method to get the value of include. 172 172 * @param boolean The value of include as a <i>boolean</i>. 173 173 */ 174 175 176 177 174 public boolean getInclude() { 175 return include; 176 } 177 /** Method to get the value of name. 178 178 * @param String The value of name as a <strong>String</string>. 179 179 */ 180 181 182 183 180 public String getName() { 181 return name; 182 } 183 /** Method to get the name of the source of the strings used in pattern matching. 184 184 * @return A <strong>String</strong> which is either the fully qualified name of a metadata element, or "Filename". 185 185 */ 186 187 188 189 190 191 192 186 public String getSource() { 187 if(element != null) { 188 return element; 189 } 190 return "Filename"; 191 } 192 /** Method to display the contents of this class as it would appear in the collection configuration file. 193 193 * @return A <strong>String</strong> which could be used as a subcollection entry in collect.cfg. 194 194 */ 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 195 public String toString() { 196 String text = "subcollection "; 197 text = text + name + " "; 198 text = text + "\""; 199 if(!include) { 200 text = text + "!"; 201 } 202 if(element != null) { 203 text = text + element; 204 } 205 else { 206 text = text + "Filename"; 207 } 208 text = text + "/"; 209 text = text + exp; 210 text = text + "/"; 211 if(flags != null) { 212 text = text + flags; 213 } 214 text = text + "\"\n"; 215 return text; 216 } 217 218 /** Update certain fields of this subcollection. 219 219 * @param name A <strong>String</strong> which is a unique identifier of a subcollection. 220 220 * @param source Either the fully qualified name of the metadata whose value should be matched against the given expression, or <i>null</i> if you wish to match against the file name. … … 223 223 * @param flags A <strong>String</strong> of flags to be taken into account when matching the expression. 224 224 */ 225 226 227 228 229 230 231 232 233 225 public void update(String name, String source, String exp, boolean include, String flags) { 226 this.name = name; 227 this.element = source; 228 this.exp = exp; 229 this.include = include; 230 this.flags = flags; 231 } 232 233 /** Method to update the name of a metadata element, if it changes. 234 234 * @param old_name The current name of the element as a <strong>String</strong>. 235 235 * @param new_name The new name of the element as a <strong>String</strong>. 236 236 */ 237 238 239 240 241 237 public void updateElement(String old_name, String new_name) { 238 if(element.equals(old_name)) { 239 element = new_name; 240 } 241 } 242 242 } 243 243 -
trunk/gli/src/org/greenstone/gatherer/cdm/SubcollectionManager.java
r4293 r4366 87 87 import org.w3c.dom.Element; 88 88 /** This class maintains a list of subcollections within our collection, and also records which of these subcollections we are building indexes for. 89 * @author John Thompson, Greenstone Digital Library, University of Waikato90 * @version 2.191 */89 * @author John Thompson, Greenstone Digital Library, University of Waikato 90 * @version 2.1 91 */ 92 92 public class SubcollectionManager 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 93 extends DefaultListModel { 94 /** The controls used to edit the settings of this manager. */ 95 private Control controls = null; 96 /** A reference to this class so we can use it as a model in our inner classes. */ 97 private DefaultListModel model = null; 98 /** The default index for the subcollections. */ 99 private DefaultSubIndex default_index = null; 100 /** A reference to the Gatherer. */ 101 private Gatherer gatherer = null; 102 /** A hashtable of subcollections, with mappings from name to subcollection. */ 103 private Hashtable subcollections = null; 104 /** A vector-type structure of subcollection indexes. */ 105 private SubIndexes subindexes = null; 106 /** A vector containing all of the subcollection commands that are unresolved, or in other words require that all 'subcollection <name> "<exp>"' to have been previously parsed before we can be certain their references will make sense. */ 107 private ArrayList unresolved = null; 108 /** Constructor. 109 * @param gatherer A reference to the <Strong>Gatherer</strong>. 110 * @see org.greenstone.gatherer.cdm.SubIndexes 111 */ 112 public SubcollectionManager(Gatherer gatherer) { 113 super(); 114 this.gatherer = gatherer; 115 this.model = this; 116 this.subcollections = new Hashtable(); 117 this.subindexes = new SubIndexes(); 118 this.unresolved = new ArrayList(); 119 } 120 /** Method to add a subindex. 121 121 * @param subindex A <strong>SubIndex</strong>. 122 122 * @see org.greenstone.gatherer.Gatherer 123 123 * @see org.greenstone.gatherer.collection.CollectionManager 124 124 */ 125 126 127 128 129 130 131 125 public void addSubIndex(SubIndex subindex) { 126 if(!subindexes.contains(subindex)) { 127 subindexes.addElement(subindex); 128 gatherer.c_man.configurationChanged(); 129 } 130 } 131 /** Method to add a new subcollection. Adds it to both the underlying list model and the hashtable mapping names to subcollections. 132 132 * @param sub The <strong>Subcollection</strong> to add. 133 133 * @return A <i>boolean</i> indicating if the addition was successful (<i>true</i>) or not (<i>false</i>). … … 135 135 * @see org.greenstone.gatherer.collection.CollectionManager 136 136 */ 137 138 139 140 141 142 143 144 145 146 137 public boolean addSubcollection(Subcollection sub) { 138 if(!contains(sub)) { 139 addElement(sub); 140 subcollections.put(sub.getName(), sub); 141 gatherer.c_man.configurationChanged(); 142 return true; 143 } 144 return false; 145 } 146 /** A method to add a new subcollection, by specifying its name, metadata element if applicable and Perl expression to filter pages into or out of this collection. 147 147 * @param name A <>>String</>> which is a unique identifier of a subcollection. 148 148 * @param include A <i>boolean</i> indicating whether this is an inclusion filter (<i>true</i>) or an exclusion one (<i>false</i>). … … 153 153 * @see org.greenstone.gatherer.cdm.Subcollection 154 154 */ 155 156 157 158 159 160 161 162 163 164 165 155 public boolean addSubcollection(String name, boolean include, String element, String exp, String flags) { 156 Subcollection sub = null; 157 if(element != null) { 158 sub = new Subcollection(name, include, element, exp, flags); 159 } 160 else { 161 sub = new Subcollection(name, include, exp, flags); 162 } 163 return addSubcollection(sub); 164 } 165 /** Refresh all derived components using this manager as a model. 166 166 */ 167 168 169 170 167 public void changed() { 168 fireContentsChanged(this, 0, getSize() - 1); 169 } 170 /** Method to retrieve the controls for this manager. 171 171 * @return A <Strong>Control</strong> object which contains the controls used to edit the subcollection data. 172 172 */ 173 174 175 176 177 178 179 173 public Control getControls() { 174 if(controls == null) { 175 controls = new Control(); 176 } 177 return controls; 178 } 179 /** Method to retrieve the default index. 180 180 * @return A <strong>DefaultSubIndex</strong> object. 181 181 */ 182 183 184 185 182 public DefaultSubIndex getDefaultSubIndex() { 183 return default_index; 184 } 185 /** Method to retrieve a certain subcollection by its name. 186 186 * @param name A <strong>String</strong> which is used as the key for finding the matching subcollection. 187 187 * @return The requested <strong>Subcollection</strong> or <i>null</i> if no such subcollection exists. 188 188 */ 189 190 191 192 189 public Subcollection getSubcollection(String name) { 190 return (Subcollection) subcollections.get(name); 191 } 192 /** Method to get all of the subindexes set. 193 193 * @return A <strong>SubIndexes</strong> object containing all the defined indexes. 194 194 */ 195 196 197 198 195 public SubIndexes getSubIndexes() { 196 return subindexes; 197 } 198 /** Method to get all of the subcollections defined. 199 199 * @return A <strong>Vector</strong> of subcollections. 200 200 */ 201 202 203 204 205 206 207 208 201 public Vector getSubcollections() { 202 Vector subcollections = new Vector(); 203 for(int i = 0; i < size(); i++) { 204 subcollections.add(get(i)); 205 } 206 return subcollections; 207 } 208 /** Mark the current controls, if any, as invalid and deallocate them. Any further use of the controls will requires them being rebuilt. 209 209 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control 210 210 */ 211 212 213 214 215 216 217 211 public void invalidateControls() { 212 if(controls != null) { 213 controls.destroy(); 214 controls = null; 215 } 216 } 217 /** This method attempts to parse a subcollection related command from the given command string. If such a string is successfully parsed, it is immediately added to the data within this collection. 218 218 * @param command The <strong>String</strong> to be parsed. 219 219 * @param finished This <i>boolean</i> is usually <i>false</i> when called, unless this parse call is being made -after- the entire collection configuration file has been read in in which case it is <i>true</i>. … … 224 224 * @see org.greenstone.gatherer.cdm.SubIndex 225 225 */ 226 227 228 229 230 231 232 233 234 235 236 237 238 226 public boolean parse(String command, boolean finished) { 227 String temp = command.toLowerCase(); 228 CommandTokenizer tokenizer = new CommandTokenizer(command); 229 tokenizer.nextToken(); // Throw away head. 230 if(temp.startsWith("subcollection")) { 231 if(tokenizer.countTokens() >= 2) { 232 String name = tokenizer.nextToken(); 233 String pattern = tokenizer.nextToken(); 234 addSubcollection(new Subcollection(name, pattern)); 235 return true; 236 } 237 } 238 else if(temp.startsWith("indexsubcollections")) { 239 239 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete. 240 241 242 243 244 245 246 247 248 249 250 240 if(!finished) { 241 unresolved.add(command); 242 } 243 else { 244 while(tokenizer.hasMoreTokens()) { 245 addSubIndex(new SubIndex(tokenizer.nextToken(), this)); 246 } 247 } 248 return true; 249 } 250 else if(temp.startsWith("defaultsubcollection")) { 251 251 // These entries depend on what subcollections have previously been set, so we cannot safely parse them until after the file is complete. 252 253 254 255 256 257 258 259 260 261 262 263 264 252 if(!finished) { 253 unresolved.add(command); 254 } 255 else { 256 if(tokenizer.hasMoreTokens()) { 257 setDefaultSubIndex(new DefaultSubIndex(tokenizer.nextToken(), this)); 258 } 259 } 260 return true; 261 } 262 return false; 263 } 264 /** Method to remove a certain subindex. 265 265 * @param subindex The <strong>SubIndex</strong> you wish to remove. 266 266 * @see org.greenstone.gatherer.Gatherer 267 267 * @see org.greenstone.gatherer.collection.CollectionManager 268 268 */ 269 270 271 272 273 269 public void removeSubIndex(SubIndex subindex) { 270 subindexes.removeElement(subindex); 271 gatherer.c_man.configurationChanged(); 272 } 273 /** Method to remove all of the subindexes that contain a certain subcollection. 274 274 * @param sub The <strong>Subcollection</strong> that you wish to remove. 275 275 * @see org.greenstone.gatherer.Gatherer … … 277 277 * @see org.greenstone.gatherer.collection.CollectionManager 278 278 */ 279 280 281 282 283 284 285 286 287 288 279 public void removeSubIndexes(Subcollection sub) { 280 for(int i = subindexes.size() - 1; i >= 0; i--) { 281 SubIndex subindex = (SubIndex)subindexes.get(i); 282 if(subindex.containsSubcollection(sub.getName())) { 283 subindexes.removeElement(subindex); 284 } 285 } 286 gatherer.c_man.configurationChanged(); 287 } 288 /** Method to remove the given subcollection. 289 289 * @param sub The <strong>Subcollection</strong> you want to remove. 290 290 * @see org.greenstone.gatherer.Gatherer 291 291 * @see org.greenstone.gatherer.collection.CollectionManager 292 292 */ 293 294 295 296 297 298 299 */ 300 301 302 303 304 305 306 293 public void removeSubcollection(Subcollection sub) { 294 removeElement(sub); 295 subcollections.remove(sub); 296 gatherer.c_man.configurationChanged(); 297 } 298 /** Method to retry the parsing of commands that were previously unable to be parsed as they referenced subcollections that may not have been instantiated. 299 */ 300 public void reparseUnresolved() { 301 for(int i = 0; i < unresolved.size(); i++) { 302 parse((String)unresolved.get(i), true); 303 } 304 unresolved.clear(); 305 } 306 /** Method to set the default subcollection index. 307 307 * @param subcollection The <strong>Subcollection</strong> to use as the default index. 308 308 * @see org.greenstone.gatherer.Gatherer 309 309 * @see org.greenstone.gatherer.collection.CollectionManager 310 310 */ 311 312 313 314 315 316 317 318 311 public void setDefaultSubIndex(DefaultSubIndex subindex) { 312 this.default_index = subindex; 313 if(subindex != null) { 314 addSubIndex(subindex.getSubIndex()); 315 } 316 gatherer.c_man.configurationChanged(); 317 } 318 /** This method causes the contents of this manager to be converted to a string, which is accomplished by calling <i>toString()</i> on each subcollection, then printing out the contents of the index vector. 319 319 * @return A <strong>String</strong> containing a block of configuration commands. 320 320 * @see org.greenstone.gatherer.cdm.SubIndex 321 321 * @see org.greenstone.gatherer.cdm.Subcollection 322 322 */ 323 324 325 326 327 328 329 330 331 332 333 323 public String toString() { 324 String text = ""; 325 // Retrieve the subcollection names and sort them. 326 if(subcollections.size() > 0) { 327 Vector names = new Vector(subcollections.keySet()); 328 Collections.sort(names); 329 for(int i = 0; i < names.size(); i++) { 330 Subcollection sub = 331 (Subcollection) subcollections.get(names.get(i)); 332 text = text + sub.toString(); 333 } 334 334 // Now add a entry, separated by spaces for each subcollection 335 335 // index. 336 337 338 336 if(subindexes.size() > 0) { 337 text = text + subindexes.toString(); 338 } 339 339 // Finally add the default subcollection index if necessary. 340 341 342 343 344 345 346 347 348 349 340 if(default_index != null) { 341 text = text + default_index.toString(); 342 } 343 text = text + "\n"; 344 } 345 // Otherwise if there were no subcollections, there aren't going to be 346 // subcollection indexes, nor a default subcollection index are there. 347 return text; 348 } 349 /** Method to retrieve a phrase from the dictionary based on a key. 350 350 * @param key A <strong>String</strong> used to find the correct phrase. 351 351 * @param args A <strong>String[]</strong> of arguments used in formatting and filling out the phrase. 352 352 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. 353 353 */ 354 355 356 357 354 private String get(String key) { 355 return get(key, null); 356 } 357 /** Method to retrieve a phrase from the dictionary based on a key. 358 358 * @param key A <strong>String</strong> used to find the correct phrase. 359 359 * @return A <strong>String</strong> containing the correct phrase with the correct formatting. … … 361 361 * @see org.greenstone.gatherer.Gatherer 362 362 */ 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 363 private String get(String key, String args[]) { 364 if(key.indexOf(".") == -1) { 365 key = "CDM.SubcollectionManager." + key; 366 } 367 return gatherer.dictionary.get(key, args); 368 } 369 /** This class creates a JPanel containing serveral more controls used for editing subcollection information. */ 370 private class Control 371 extends JPanel { 372 /** <i>true</i> if the current selection has changed. */ 373 private boolean changed = false; 374 /** Button to add a subcollection. */ 375 private JButton add = null; 376 /** Button to add a subindex. */ 377 private JButton add_index = null; 378 /** Button to clear the default subindex. */ 379 private JButton clear_default = null; 380 /** Button to remove a subcollection. */ 381 private JButton remove = null; 382 /** Button to remove a subindex. */ 383 private JButton remove_index = null; 384 /** Button to set the default subindex. */ 385 private JButton set_default = null; 386 /** Button to cause an update of the subcollections. */ 387 private JButton update = null; 388 /** A combobox allowing you to choose which field the data for matching should be taken from. Includes text body and filename, as well as all assigned metadata elements. */ 389 private JComboBox source = null; 390 /** The list of assigned subcollections. */ 391 private JList subcollection_list = null; 392 /** The list of subcollections available for the creation of subindexes. */ 393 private JList subcollection_list_2 = null; 394 /** The list of assigned subindexes. */ 395 private JList subindexes_list = null; 396 /** The label denoting the list of subindexes. */ 397 private JLabel subindexes_label = null; 398 /** The panel containing the subcollection controls. */ 399 private JPanel subcollection_pane = null; 400 /** The panel containing the subindex controls. */ 401 private JPanel subindex_pane = null; 402 /** The tabbed pane used to store the subcollection and subindex controls. */ 403 private JTabbedPane tabbed_pane = null; 404 /** The area used to display inline instructions. */ 405 private JTextArea instructions = null; 406 /** The field displaying the name of the default subindex. */ 407 private JTextField default_value = null; 408 /** A field used for specifying flags for the PERL expression matching, such as 'i' for case insensitive. */ 409 private JTextField flags = null; 410 /** The pattern the source text must match. */ 411 private JTextField match = null; 412 /** The name of this subcollection. */ 413 private JTextField name = null; 414 /** When this button is selected the filter matching files are excluded. */ 415 private JToggleButton exclude = null; 416 /** When this button is selected the filter matching files are included. */ 417 private JToggleButton include = null; 418 /** The existing subcollection whose details you are reviewing, if any. */ 419 private Subcollection current = null; 420 /** Constructor, creates the outer parts of the view, then calls two methods in turn to create the subcollection controls and subindex controls. 421 */ 422 public Control() { 423 423 // Create 424 425 426 427 428 429 430 431 432 433 434 435 436 424 JPanel border_pane = new JPanel(); 425 JPanel header_pane = new JPanel(); 426 instructions = new JTextArea(get("Instructions")); 427 instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 428 instructions.setEditable(false); 429 instructions.setLineWrap(true); 430 instructions.setRows(5); 431 instructions.setWrapStyleWord(true); 432 tabbed_pane = new JTabbedPane(); 433 JLabel title = new JLabel(get("Title")); 434 title.setHorizontalAlignment(JLabel.CENTER); 435 createSubcollection(); 436 createSubindex(); 437 437 // Add listeners 438 438 // Layout 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 439 instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5)); 440 header_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 441 header_pane.setLayout(new BorderLayout()); 442 header_pane.add(title, BorderLayout.NORTH); 443 header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER); 444 tabbed_pane.addTab(get("Subcollection_Controls"), subcollection_pane); 445 tabbed_pane.addTab(get("Subindex_Controls"), subindex_pane); 446 border_pane.setBorder(BorderFactory.createEmptyBorder(0,5,5,5)); 447 border_pane.setLayout(new BorderLayout()); 448 border_pane.add(tabbed_pane, BorderLayout.CENTER); 449 setLayout(new BorderLayout()); 450 add(header_pane, BorderLayout.NORTH); 451 add(border_pane, BorderLayout.CENTER); 452 } 453 /** Create the subcollection controls. 454 454 * @see org.greenstone.gatherer.Gatherer 455 455 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddListener … … 459 459 * @see org.greenstone.gatherer.msm.MetadataSetManager 460 460 */ 461 461 public void createSubcollection() { 462 462 // Create 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 463 add = new JButton(get("Add")); 464 add.setMnemonic(KeyEvent.VK_A); 465 JPanel button_pane = new JPanel(); 466 JPanel button_pane_1 = new JPanel(); 467 JPanel button_pane_3 = new JPanel(); 468 exclude = new JToggleButton(get("Exclude")); 469 exclude.setMnemonic(KeyEvent.VK_X); 470 flags = new JTextField(); 471 JLabel flags_label = new JLabel(get("Flags")); 472 include = new JToggleButton(get("Include")); 473 include.setMnemonic(KeyEvent.VK_I); 474 JLabel inclusive_label = new JLabel(get("Inclusive")); 475 JPanel inclusive_pane = new JPanel(); 476 match = new JTextField(); 477 JLabel match_label = new JLabel(get("Match")); 478 name = new JTextField(); 479 JLabel name_label = new JLabel(get("Name")); 480 remove = new JButton(get("Remove")); 481 remove.setMnemonic(KeyEvent.VK_R); 482 Vector source_model = gatherer.c_man.msm.getAssignedElements(); 483 source_model.add(0, "Filename"); 484 source = new JComboBox(source_model); 485 JLabel source_label = new JLabel(get("Source")); 486 subcollection_list = new JList(model); 487 subcollection_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 488 subcollection_pane = new JPanel(); 489 ButtonGroup bg = new ButtonGroup(); 490 bg.add(include); 491 bg.add(exclude); 492 include.setSelected(true); 493 JPanel subcollection_list_pane = new JPanel(); 494 JLabel subcollection_list_label = new JLabel(get("Assigned")); 495 495 496 496 // Add listeners 497 498 499 497 add.addActionListener(new AddListener()); 498 remove.addActionListener(new RemoveListener()); 499 subcollection_list.addListSelectionListener(new ListListener()); 500 500 501 501 // Layout 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 502 inclusive_pane.setLayout(new GridLayout()); 503 inclusive_pane.add(include); 504 inclusive_pane.add(exclude); 505 button_pane_1.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); 506 button_pane_1.setLayout(new GridLayout(5, 2)); 507 button_pane_1.add(name_label); 508 button_pane_1.add(name); 509 button_pane_1.add(source_label); 510 button_pane_1.add(source); 511 button_pane_1.add(match_label); 512 button_pane_1.add(match); 513 button_pane_1.add(inclusive_label); 514 button_pane_1.add(inclusive_pane); 515 button_pane_1.add(flags_label); 516 button_pane_1.add(flags); 517 button_pane_3.setBorder(BorderFactory.createEmptyBorder(5,0,0,0)); 518 button_pane_3.setLayout(new GridLayout(1,2)); 519 button_pane_3.add(add); 520 button_pane_3.add(remove); 521 button_pane.setLayout(new BorderLayout()); 522 button_pane.add(button_pane_1, BorderLayout.CENTER); 523 button_pane.add(button_pane_3, BorderLayout.SOUTH); 524 subcollection_list_pane.setLayout(new BorderLayout()); 525 subcollection_list_pane.add(subcollection_list_label, BorderLayout.NORTH); 526 subcollection_list_pane.add(new JScrollPane(subcollection_list), BorderLayout.CENTER); 527 subcollection_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 528 subcollection_pane.setLayout(new BorderLayout()); 529 subcollection_pane.add(subcollection_list_pane, BorderLayout.CENTER); 530 subcollection_pane.add(button_pane, BorderLayout.SOUTH); 531 } 532 /** Create the subindex controls. 533 533 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.AddSubIndexListener 534 534 * @see org.greenstone.gatherer.cdm.SubcollectionManager.Control.ClearDefaultListener … … 538 538 * @see org.greenstone.gatherer.util.ExclusiveListListener 539 539 */ 540 540 public void createSubindex() { 541 541 // Creation 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 542 add_index = new JButton(get("Add_Subindex")); 543 add_index.setMnemonic(KeyEvent.VK_A); 544 JPanel button_pane_2 = new JPanel(); 545 clear_default = new JButton(get("Clear_Default_Subindex")); 546 clear_default.setMnemonic(KeyEvent.VK_C); 547 if(default_index == null) { 548 clear_default.setEnabled(false); 549 } 550 JLabel default_label = new JLabel(get("Default_Subindex")); 551 JPanel default_pane = new JPanel(); 552 if(default_index == null) { 553 default_value = new JTextField(); 554 } 555 else { 556 default_value = new JTextField(default_index.getSubIndex().toString()); 557 } 558 JPanel subindex_inner_pane_1 = new JPanel(); 559 JPanel subindex_inner_pane_2 = new JPanel(); 560 remove_index = new JButton(get("Remove_Subindex")); 561 remove_index.setMnemonic(KeyEvent.VK_R); 562 set_default = new JButton(get("Set_Default_Subindex")); 563 set_default.setMnemonic(KeyEvent.VK_S); 564 JLabel subcollection_label = new JLabel(get("Subcollection")); 565 subcollection_list_2 = new JList(model); 566 JPanel list_2_pane = new JPanel(); 567 subindex_pane = new JPanel(); 568 JLabel subindexes_label = new JLabel(get("Subindexes")); 569 subindexes_list = new JList(subindexes); 570 subindexes_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 571 JPanel subindexes_pane = new JPanel(); 572 572 573 573 // Add listeners 574 575 576 577 578 579 580 581 582 583 584 585 586 587 574 ChangeListener cl = new ChangeListener(); 575 ExclusiveListSelectionListener ell = new ExclusiveListSelectionListener(); 576 ell.add(subcollection_list_2); 577 ell.add(subindexes_list); 578 add_index.addActionListener(new AddSubIndexListener()); 579 clear_default.addActionListener(new ClearDefaultListener()); 580 exclude.addActionListener(cl); 581 include.addActionListener(cl); 582 remove_index.addActionListener(new RemoveSubIndexListener()); 583 set_default.addActionListener(new SetDefaultListener()); 584 source.addActionListener(cl); 585 flags.addKeyListener(cl); 586 match.addKeyListener(cl); 587 name.addKeyListener(cl); 588 588 589 589 // Layout 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 590 list_2_pane.setLayout(new BorderLayout()); 591 list_2_pane.add(subcollection_label, BorderLayout.NORTH); 592 list_2_pane.add(new JScrollPane(subcollection_list_2), BorderLayout.CENTER); 593 subindexes_pane.setLayout(new BorderLayout()); 594 subindexes_pane.add(subindexes_label, BorderLayout.NORTH); 595 subindexes_pane.add(new JScrollPane(subindexes_list), BorderLayout.CENTER); 596 subindex_inner_pane_2.setLayout(new GridLayout(2,1)); 597 subindex_inner_pane_2.add(list_2_pane); 598 subindex_inner_pane_2.add(subindexes_pane); 599 default_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 600 default_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), BorderFactory.createRaisedBevelBorder()), BorderFactory.createEmptyBorder(2,2,2,2))); 601 default_pane.setLayout(new BorderLayout()); 602 default_pane.add(default_label, BorderLayout.WEST); 603 default_pane.add(default_value, BorderLayout.CENTER); 604 subindex_inner_pane_1.setLayout(new BorderLayout()); 605 subindex_inner_pane_1.add(subindex_inner_pane_2, BorderLayout.CENTER); 606 subindex_inner_pane_1.add(default_pane, BorderLayout.SOUTH); 607 button_pane_2.setLayout(new GridLayout(2,2)); 608 button_pane_2.add(add_index); 609 button_pane_2.add(remove_index); 610 button_pane_2.add(clear_default); 611 button_pane_2.add(set_default); 612 subindex_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 613 subindex_pane.setLayout(new BorderLayout()); 614 subindex_pane.add(subindex_inner_pane_1, BorderLayout.CENTER); 615 subindex_pane.add(button_pane_2, BorderLayout.SOUTH); 616 } 617 /** Method to unregister any listeners to avoid memory leaks. 618 618 */ 619 620 621 619 public void destroy() { 620 } 621 /** We have overriden this method to provide completely different functionality, given that our JPanel will never actually have focus. We call this method in GUI on the view we are about to replace, and this method checks if a change has occured and if so updates the current object. 622 622 * @return A <i>boolean</i> which is always <i>false</i>. 623 623 * @see org.greenstone.gatherer.msm.ElementWrapper 624 624 */ 625 625 public boolean hasFocus() { 626 626 // If we have a current metadata open, and something has changed then save the change. 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 627 if(changed && current != null) { 628 String n = name.getText(); 629 String s = null; 630 Object o = source.getSelectedItem(); 631 if(o instanceof ElementWrapper) { 632 ElementWrapper e = (ElementWrapper)o; 633 s = e.toString(); 634 } 635 String e = match.getText(); 636 String f = flags.getText(); 637 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) { 638 current.update(n, s, e, include.isSelected(), f); 639 int index = model.indexOf(current); 640 changed(); 641 subindexes.changed(); 642 if(default_index != null) { 643 default_value.setText(default_index.getSubIndex().toString()); 644 } 645 } 646 changed = false; 647 } 648 return false; 649 } 650 /** Overriden to ensure the instructions are scrolled to top. 651 651 */ 652 653 654 655 656 657 658 659 660 652 public void updateUI() { 653 if(instructions != null) { 654 instructions.setCaretPosition(0); 655 } 656 super.updateUI(); 657 } 658 /** Listens for actions apon the 'add' button in the SubcollectionManager controls, and if detected calls the addSubcollection method of the manager with a newly created subcollection. */ 659 private class AddListener 660 implements ActionListener { 661 661 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we wish to retrieve information from the various edit controls, and if we have sufficient data to build a new subcollection do so. 662 662 * @param event An <strong>ActionEvent</strong> containing information about the event. … … 664 664 * @see org.greenstone.gatherer.msm.ElementWrapper 665 665 */ 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 666 public void actionPerformed(ActionEvent event) { 667 String n = name.getText(); 668 String s = null; 669 Object o = source.getSelectedItem(); 670 if(o instanceof ElementWrapper) { 671 ElementWrapper e = (ElementWrapper)o; 672 s = e.toString(); 673 } 674 String e = match.getText(); 675 String f = flags.getText(); 676 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) { 677 Subcollection sub = new Subcollection(n, include.isSelected(), s, e, f); 678 addSubcollection(sub); 679 } 680 changed = false; 681 } 682 } 683 /** Listens for actions apon the 'add subindex' button in the SubcollectionManager controls, and if detected calls the addSubindex method of the manager with a newly created subindex. */ 684 private class AddSubIndexListener 685 implements ActionListener { 686 686 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a series of subcollections selected, and if so build an new subindex based apon them. 687 687 * @param event An <strong>ActionEvent</strong> containing information about the event. 688 688 * @see org.greenstone.gatherer.cdm.SubIndex 689 689 */ 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 690 public void actionPerformed(ActionEvent event) { 691 if(!subcollection_list_2.isSelectionEmpty()) { 692 Vector selected = new Vector(); 693 Object raw[] = subcollection_list_2.getSelectedValues(); 694 for(int i = 0; i < raw.length; i++) { 695 selected.add(raw[i]); 696 } 697 addSubIndex(new SubIndex(selected)); 698 } 699 } 700 } 701 /** This class listens for any key entry in a text field, selection change in a combobox or button click, and when detected sets the changed flag to true. Its also convenient to use this class to test if the add button should be active yet. */ 702 public class ChangeListener 703 extends KeyAdapter 704 implements ActionListener { 705 705 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to record that somethings changed, then validate the controls. 706 706 * @param event An <strong>ActionEvent</strong> containing information about the event. 707 707 */ 708 709 710 711 708 public void actionPerformed(ActionEvent event) { 709 changed = true; 710 validate(); 711 } 712 712 /** Any inheritor of KeyAdapter can override this method so we can be informed when an key has been type in one of our target controls. In this case we want to record that somethings changed, then validate the controls. 713 713 * @param event An <strong>KeyEvent</strong> containing information about the event. 714 714 */ 715 716 717 718 715 public void keyPressed(KeyEvent event) { 716 changed = true; 717 validate(); 718 } 719 719 /** Method to validate the current editor values, and enable or disable controls based on said values. */ 720 721 722 723 724 725 726 727 728 729 730 731 720 private void validate() { 721 if(changed && name.getText().length() > 0 && match.getText().length() > 0) { 722 add.setEnabled(true); 723 } 724 else { 725 add.setEnabled(false); 726 } 727 } 728 } 729 /** Listens for actions apon the 'clear default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex() method of the manager with <i>null</i>. */ 730 private class ClearDefaultListener 731 implements ActionListener { 732 732 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to clear the default subindex. 733 733 * @param event An <strong>ActionEvent</strong> containing information about the event. 734 734 */ 735 736 737 738 739 740 741 742 743 735 public void actionPerformed(ActionEvent event) { 736 setDefaultSubIndex(null); 737 clear_default.setEnabled(false); 738 default_value.setText(""); 739 } 740 } 741 /** This class listens for selections in the list on the subcollections pane of the SubcollectionManager, and updates the controls as necessary to reflect selection. */ 742 private class ListListener 743 implements ListSelectionListener { 744 744 /** Any implementation of ListSelectionListener must include this method so we can be informed when the selection changes. In this case we want to execute any changes the users made to the entry, then update the controls with details of the new selection. 745 745 * @param event A <strong>ListSelectionEvent</strong> containing information related to this event. … … 747 747 * @see org.greenstone.gatherer.msm.ElementWrapper 748 748 */ 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 749 public void valueChanged(ListSelectionEvent event) { 750 // If we have a previous collection and the users changed something, but not added, then update subcollection. 751 if(changed && current != null) { 752 String n = name.getText(); 753 String s = null; 754 Object o = source.getSelectedItem(); 755 if(o instanceof ElementWrapper) { 756 ElementWrapper e = (ElementWrapper)o; 757 s = e.toString(); 758 } 759 String e = match.getText(); 760 String f = flags.getText(); 761 if(n != null && n.length() > 0 && (s == null || s.length() > 0) && e != null && e.length() > 0) { 762 current.update(n, s, e, include.isSelected(), f); 763 int index = model.indexOf(current); 764 changed(); 765 subindexes.changed(); 766 if(default_index != null) { 767 default_value.setText(default_index.getSubIndex().toString()); 768 } 769 } 770 } 771 // Now load the new entry. 772 if(!subcollection_list.isSelectionEmpty()) { 773 current = (Subcollection) subcollection_list.getSelectedValue(); 774 flags.setText(current.getFlags()); 775 include.setSelected(current.getInclude()); 776 exclude.setSelected(!current.getInclude()); 777 match.setText(current.getExpression()); 778 name.setText(current.getName()); 779 String s = current.getSource(); 780 int pos = 0; 781 Object value = source.getItemAt(pos); 782 while(value != null) { 783 if(value instanceof ElementWrapper) { 784 ElementWrapper e = (ElementWrapper) value; 785 if(e.toString().equals(s)) { 786 source.setSelectedIndex(pos); 787 value = null; 788 } 789 else { 790 pos++; 791 value = source.getItemAt(pos); 792 } 793 } 794 else if(value.toString().equals(s)) { 795 source.setSelectedIndex(pos); 796 value = null; 797 } 798 else { 799 pos++; 800 value = source.getItemAt(pos); 801 } 802 } 803 // Can't add one thats already there. 804 add.setEnabled(false); 805 // You can remove it though... 806 remove.setEnabled(true); 807 } 808 else { 809 flags.setText(""); 810 include.setSelected(true); 811 match.setText(""); 812 name.setText(""); 813 source.setSelectedIndex(0); 814 remove.setEnabled(false); 815 } 816 // Have to do this after so we don't get called when nothings actually changed. 817 changed = false; 818 } 819 } 820 /** Listens for actions apon the 'remove' button in the SubcollectionManager controls, and if detected calls the remove method of the manager with the SubIndex selected for removal. */ 821 private class RemoveListener 822 implements ActionListener { 823 823 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subcolleciton selected, and if so remove both it and any subindexes based on it. 824 824 * @param event An <strong>ActionEvent</strong> containing information about the event. 825 825 * @see org.greenstone.gatherer.cdm.Subcollection 826 826 */ 827 828 829 830 831 832 833 834 835 836 837 827 public void actionPerformed(ActionEvent event) { 828 if(!subcollection_list.isSelectionEmpty()) { 829 Subcollection sub_col = (Subcollection)subcollection_list.getSelectedValue(); 830 removeSubIndexes(sub_col); 831 removeSubcollection(sub_col); 832 } 833 } 834 } 835 /** Listens for actions apon the 'remove subindex' button in the SubcollectionManager controls, and if detected calls the removeSubIndex method of the manager with the SubIndex selected for removal. */ 836 private class RemoveSubIndexListener 837 implements ActionListener { 838 838 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subindex selected, and if so remove it. 839 839 * @param event An <strong>ActionEvent</strong> containing information about the event. 840 840 * @see org.greenstone.gatherer.cdm.SubIndex 841 841 */ 842 843 844 845 846 847 848 849 850 842 public void actionPerformed(ActionEvent event) { 843 if(!subindexes_list.isSelectionEmpty()) { 844 removeSubIndex((SubIndex)subindexes_list.getSelectedValue()); 845 } 846 } 847 } 848 /** Listens for actions apon the 'set default subindex' button in the SubcollectionManager controls, and if detected calls the setDefaultSubIndex method of the manager with the SubIndex selected for default. */ 849 private class SetDefaultListener 850 implements ActionListener { 851 851 /** Any implementation of ActionListener must include this method so we can be informed when an action has been performed on one of our target controls. In this case we want to check if they have a subindex selected, and if so set it as default. 852 852 * @param event An <strong>ActionEvent</strong> containing information about the event. … … 854 854 * @see org.greenstone.gatherer.cdm.SubIndex 855 855 */ 856 857 858 859 860 861 862 863 864 856 public void actionPerformed(ActionEvent event) { 857 if(!subindexes_list.isSelectionEmpty()) { 858 setDefaultSubIndex(new DefaultSubIndex((SubIndex)subindexes_list.getSelectedValue())); 859 clear_default.setEnabled(true); 860 default_value.setText(default_index.getSubIndex().toString()); 861 } 862 } 863 } 864 } 865 865 } 866 866 -
trunk/gli/src/org/greenstone/gatherer/cdm/TranslationManager.java
r4293 r4366 87 87 import org.greenstone.gatherer.cdm.LanguageManager; 88 88 /** This class provides a graphical interface to allow a user to quickly and conviently (ie all in one place) translate the text fragments associated with general metadata and indexes into each of the assigned languages in the collection. It should provide clear controls for the editing of these text fragments, plus clear indicate what languages still need further translation, which it will do through a combination of coloring and other visual indicators. 89 * @author John Thompson, Greenstone Digital Library, University of Waikato90 * @version 2.391 */89 * @author John Thompson, Greenstone Digital Library, University of Waikato 90 * @version 2.3 91 */ 92 92 public class TranslationManager 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 93 extends JDialog { 94 /** A reference to our creator, the CollectionDesignManager. */ 95 private CollectionDesignManager manager = null; 96 /** The currently selected collection metadata. */ 97 private CollectionMeta current = null; 98 /** A listener for selection changes in the feature list. */ 99 private FeatureListener features_listener = null; 100 /** A reference to the Gatherer, for access to the Dictionary and messaging purposes. */ 101 private Gatherer gatherer = null; 102 /** The button used to close the translation dialog. */ 103 private JButton close_button = null; 104 /** A reference to the dialog so that our inner classes can interact with it. */ 105 private JDialog dialog = null; 106 /** The label denoting the features list. */ 107 private JLabel features_label = null; 108 /** The label denoting the language table. */ 109 private JLabel languages_label = null; 110 /** The label denoting the original text area. */ 111 private JLabel original_label = null; 112 /** The label denoting the original language field */ 113 private JLabel original_language_label = null; 114 /** The label denoting the translated text area. */ 115 private JLabel translation_label = null; 116 /** The label denoting the translated language field. */ 117 private JLabel translation_language_label = null; 118 /** A list of the various features that have collection metadata associated with them. */ 119 private JList features_list = null; 120 /** The base panel. */ 121 private JPanel content_pane = null; 122 /** The right panel. */ 123 private JPanel control_pane = null; 124 /** The panel the features list is shown in. */ 125 private JPanel features_pane = null; 126 /** The panel the languages table is shown in. */ 127 private JPanel languages_pane = null; 128 /** The panel the original text is shown in. */ 129 private JPanel original_pane = null; 130 /** The panel the original language field is shown in. */ 131 private JPanel original_header_pane = null; 132 /** The panel the translation text is shown in. */ 133 private JPanel translation_pane = null; 134 /** The panel the translation language field is shown in. */ 135 private JPanel translation_header_pane = null; 136 /** The table used to show the languages supported by the collection. */ 137 private JTable languages_table = null; 138 /** The text area displaying the original text (in the default language). */ 139 private JTextArea original = null; 140 /** The text area displaying the translated text (in the selected language). */ 141 private JTextArea translation = null; 142 /** The language currently selected. */ 143 private Language current_language = null; 144 /** The proxy model to the language manager which serves as the basis for the table. */ 145 private TableProxy languages_model = null; 146 /** The default size of the features list. */ 147 static final private Dimension FEATURE_SIZE = new Dimension(200, 400); 148 /** The default size of the translation dialog. */ 149 static final private Dimension SIZE = new Dimension(800, 450); 150 /** Constructor. 151 * @param gatherer A reference to the <strong>Gatherer</strong>. 152 * @param manager A reference to the <strong>CollectionDesignManager</strong>. 153 * @see org.greenstone.gatherer.Configuration 154 * @see org.greenstone.gatherer.cdm.CollectionMeta 155 * @see org.greenstone.gatherer.cdm.TranslationManager.TableProxy 156 */ 157 public TranslationManager(Gatherer gatherer, CollectionDesignManager manager) { 158 super(); 159 this.dialog = this; 160 this.gatherer = gatherer; 161 this.manager = manager; 162 this.languages_model = new TableProxy(); 163 // Create the features model. Basically we want one string entry for each unique name in the metadata. 164 ArrayList features_model = new ArrayList(); 165 for(int i = 0; i < manager.collectionmetadatum.size(); i++) { 166 CollectionMeta metadata = (CollectionMeta) manager.collectionmetadatum.get(i); 167 Object object = metadata.getName(); 168 String name = null; 169 if(object instanceof Index) { 170 name = ((Index)object).toString(false); 171 } 172 else { 173 name = object.toString(); 174 } 175 if(!features_model.contains(name)) { 176 features_model.add(name); 177 } 178 } 179 Collections.sort(features_model); 180 // Create components... 181 setModal(true); 182 setSize(SIZE); 183 close_button = new JButton(get("General.Close")); 184 content_pane = (JPanel) getContentPane(); 185 control_pane = new JPanel(); 186 features_label = new JLabel(get("Affected_Features")); 187 features_label.setHorizontalAlignment(JLabel.CENTER); 188 features_list = new JList(features_model.toArray()); 189 features_listener = new FeatureListener(); 190 features_pane = new JPanel(); 191 features_pane.setPreferredSize(FEATURE_SIZE); 192 languages_table = new JTable(languages_model); 193 languages_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); 194 languages_label = new JLabel(get("Assigned_Languages")); 195 languages_label.setHorizontalAlignment(JLabel.CENTER); 196 languages_pane = new JPanel(); 197 original = new JTextArea(); 198 original.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 199 original.setEditable(false); 200 original.setFont(new Font("Arial Unicode MS", Font.PLAIN, 10)); 201 original_header_pane = new JPanel(); 202 original_label = new JLabel(get("Default_Text")); 203 original_label.setHorizontalAlignment(JLabel.CENTER); 204 original_language_label = new JLabel(""); 205 original_pane = new JPanel(); 206 translation = new JTextArea(); 207 translation.setEnabled(false); 208 translation.setFont(new Font("Arial Unicode MS", Font.PLAIN, 10)); 209 translation_header_pane = new JPanel(); 210 translation_label = new JLabel(get("Translation")); 211 translation_label.setHorizontalAlignment(JLabel.CENTER); 212 translation_language_label = new JLabel(""); 213 translation_pane = new JPanel(); 214 // Add listeners... 215 close_button.addActionListener(new CloseListener()); 216 translation.addKeyListener(new TranslationListener()); 217 features_list.addListSelectionListener(features_listener); 218 features_list.addListSelectionListener(languages_model); 219 ListSelectionModel languages_selection_model = languages_table.getSelectionModel(); 220 languages_selection_model.addListSelectionListener(new TableListener()); 221 // Layout... 222 features_pane.setBorder(BorderFactory.createEmptyBorder(0,0,0,5)); 223 features_pane.setLayout(new BorderLayout()); 224 features_pane.add(features_label, BorderLayout.NORTH); 225 features_pane.add(new JScrollPane(features_list), BorderLayout.CENTER); 226 languages_label.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 227 languages_pane.setLayout(new BorderLayout()); 228 languages_pane.add(languages_label, BorderLayout.NORTH); 229 languages_pane.add(new JScrollPane(languages_table), BorderLayout.CENTER); 230 original_header_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 231 original_header_pane.setLayout(new BorderLayout()); 232 original_header_pane.add(original_label, BorderLayout.WEST); 233 original_header_pane.add(original_language_label, BorderLayout.EAST); 234 original_pane.setLayout(new BorderLayout()); 235 original_pane.add(original_header_pane, BorderLayout.NORTH); 236 original_pane.add(new JScrollPane(original), BorderLayout.CENTER); 237 translation_header_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0)); 238 translation_header_pane.setLayout(new BorderLayout()); 239 translation_header_pane.add(translation_label, BorderLayout.WEST); 240 translation_header_pane.add(translation_language_label, BorderLayout.EAST); 241 translation_pane.setLayout(new BorderLayout()); 242 translation_pane.add(translation_header_pane, BorderLayout.NORTH); 243 translation_pane.add(new JScrollPane(translation), BorderLayout.CENTER); 244 control_pane.setLayout(new GridLayout(3,1)); 245 control_pane.add(languages_pane); 246 control_pane.add(original_pane); 247 control_pane.add(translation_pane); 248 content_pane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 249 content_pane.setLayout(new BorderLayout()); 250 content_pane.add(features_pane, BorderLayout.WEST); 251 content_pane.add(control_pane, BorderLayout.CENTER); 252 content_pane.add(close_button, BorderLayout.SOUTH); 253 // Display... 254 Dimension screen_size = Toolkit.getDefaultToolkit().getScreenSize(); 255 for (int i = 0; i < languages_model.getColumnCount() - 1; i++) { 256 TableColumn column = languages_table.getColumnModel().getColumn(i); 257 column.setMinWidth(0); 258 column.setMaxWidth(screen_size.width); 259 column.setPreferredWidth((SIZE.width - FEATURE_SIZE.width) / 6); 260 } 261 setLocation((screen_size.width - SIZE.width) / 2, (screen_size.height - SIZE.height) / 2); 262 show(); 263 } 264 /** Destructor 265 265 */ 266 267 268 269 266 public void destroy() { 267 dialog = null; 268 } 269 /** Retrieve a phrase from the dictionary based on a certain key. 270 270 * @param key The search <strong>String</strong>. 271 271 * @return The matching phrase from the Dictionary as a <strong>String</strong>. 272 272 */ 273 274 275 276 273 private String get(String key) { 274 return get(key, null); 275 } 276 /** Retrieve a phrase from the dictionary based on a certain key and certain arguments. 277 277 * @param key The search <strong>String</strong>. 278 278 * @param args A <strong>String[]</strong> used to complete and format the returned phrase. … … 281 281 * @see org.greenstone.gatherer.Gatherer 282 282 */ 283 284 285 286 287 288 289 290 291 292 293 294 */ 295 296 297 298 299 300 301 302 303 304 305 306 307 283 private String get(String key, String args[]) { 284 if(key.indexOf(".") == -1) { 285 key = "CDM.TranslationManager." + key; 286 } 287 return gatherer.dictionary.get(key, args); 288 } 289 /** Listens for actions apon the close button. */ 290 private class CloseListener 291 implements ActionListener { 292 /** Closes the dialog. Any implementation of an ActionListener must include this method so we can be informed when an action has occured. 293 * @param event An <Strong>ActionEvent</strong> containing details about the action. 294 */ 295 public void actionPerformed(ActionEvent event) { 296 dialog.dispose(); 297 } 298 } 299 /** Listens to selections within the feature list. */ 300 private class FeatureListener 301 implements ListSelectionListener { 302 /** Called whenever the selection changes in the registered list, which requires us to create a new TableProxy. 303 * @param event A <strong>ListSelectionEvent</strong> containing more information about the list selection change. 304 * @see org.greenstone.gatherer.cdm.CollectionMeta 305 * @see org.greenstone.gatherer.cdm.Language 306 */ 307 public void valueChanged(ListSelectionEvent event) { 308 308 // Try to find the default language value for this feature. 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 309 String name = (String) features_list.getSelectedValue(); 310 Language language = manager.languages.getDefaultLanguage(); 311 CollectionMeta metadata = manager.collectionmetadatum.getMetadata(name, language, true); 312 if(metadata != null && metadata.getValue() != null && metadata.getValue().length() != 0) { 313 if(!metadata.getLanguage().equals(language)) { 314 original_label.setText(get("Existing_Text")); 315 } 316 else { 317 original_label.setText(get("Default_Text")); 318 } 319 original.setText(metadata.getValue()); 320 original_language_label.setText(metadata.getLanguage().toString()); 321 } 322 else { 323 original_label.setText(get("No_Text")); 324 original.setText(""); 325 } 326 } 327 } 328 /** Listens for selections within the languages table. */ 329 private class TableListener 330 implements ListSelectionListener { 331 /** Called whenever the selection changes in the registered list, which requires us to update several parts of the dialog. 332 * @param event A <strong>ListSelectionEvent</strong> containing more information about the list selection change. 333 * @see org.greenstone.gatherer.cdm.CollectionMeta 334 * @see org.greenstone.gatherer.cdm.Language 335 */ 336 public void valueChanged(ListSelectionEvent event) { 337 if (event.getValueIsAdjusting()) return; 338 ListSelectionModel lsm = (ListSelectionModel)event.getSource(); 339 if (!lsm.isSelectionEmpty()) { 340 int row = lsm.getMinSelectionIndex(); 341 current = languages_model.getMetadata(row); 342 if(current != null) { 343 if (current.getValue() != null) { 344 translation.setText(current.getValue()); 345 } 346 else { 347 translation.setText(""); 348 } 349 current_language = current.getLanguage(); 350 } 351 else { 352 current_language = (Language) languages_model.getValueAt(row, 1); 353 translation.setText(""); 354 } 355 features_listener.valueChanged(null); 356 translation_language_label.setText(current_language.toString()); 357 translation.setEnabled(true); 358 } 359 } 360 } 361 /** A AbstractTableModel extension based upon a vector of CollectionMeta, which can also listen to a list for selection changes. */ 362 private class TableProxy 363 extends AbstractTableModel 364 implements ListSelectionListener { 365 /** Called when the contents of a cell changes. 366 */ 367 public void cellChanged() { 368 fireTableDataChanged(); 369 } 370 /** Returns the most specific superclass for all the cell values in the column. 371 371 * @param column An <i>int</i> specifying which columns class to be determined. 372 372 * @return The columns <strong>Class</strong>. 373 373 */ 374 374 public Class getColumnClass(int column) { 375 376 377 375 return String.class; 376 } 377 /** Returns the number of columns in the model. 378 378 * @return An <i>int</i> specifying the number of columns. 379 379 */ 380 381 382 383 384 385 380 public int getColumnCount() { 381 if(!features_list.isSelectionEmpty()) { 382 return 2; 383 } 384 return 0; 385 } 386 386 /** Returns the name of the column at columnIndex. 387 387 * @param column An <i>int</i> specifying the column whose name you are interesting in. 388 388 * @return The name of the column as a <strong>String</strong>. 389 389 */ 390 391 392 393 394 395 396 397 398 399 400 401 402 390 public String getColumnName(int column) { 391 String name = null; 392 switch(column) { 393 case 0: 394 name = get("Language"); 395 break; 396 case 1: 397 name = get("Text"); 398 break; 399 } 400 return name; 401 } 402 /** Retrieve the collection metadata from the specified row. 403 403 * @param row An <i>int</i> indicating the row in question. 404 404 * @see org.greenstone.gatherer.cdm.Language 405 405 * @see org.greenstone.gatherer.cdm.LanguageManager 406 406 */ 407 408 409 410 411 407 public CollectionMeta getMetadata(int row) { 408 String name = (String) features_list.getSelectedValue(); 409 Language language = (Language) getValueAt(row, 0); 410 return manager.collectionmetadatum.getMetadata(name, language, false); 411 } 412 412 /** Returns the number of rows in the model. 413 413 * @return An <i>int</i> specifying the number of rows in the table, which is exactly the number of languages assigned to this collection. 414 414 * @see org.greenstone.gatherer.cdm.LanguageManager 415 415 */ 416 417 418 419 416 public int getRowCount() { 417 return manager.languages.size(); 418 } 419 /** Returns the value for the cell at column and row. 420 420 * @param row The desired row as an <i>int</i>. 421 421 * @param column The desired column as an <i>int</i>. … … 425 425 * @see org.greenstone.gatherer.cdm.LanguageManager 426 426 */ 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 427 public Object getValueAt(int row, int column) { 428 if(!features_list.isSelectionEmpty()) { 429 // First of all find the Language that matches the row and the current feature name, because in any case you'll need them. 430 Language language = (Language)manager.languages.get(row); 431 String feature_name = (String)features_list.getSelectedValue(); 432 // Also try to locate the collection level metadata that matches. 433 CollectionMeta metadata = manager.collectionmetadatum.getMetadata(feature_name, language, false); 434 // Now we do subtly different things depending on the column. 435 switch(column) { 436 case 0: // The Language. Easiest case. 437 return language; 438 case 1: // The value of the metadata. Needs us to retrieve the value for a certain feature and language. 439 if(metadata != null) { 440 return metadata.getValue(); 441 } 442 } 443 // If all else fails, return an empty string and hope the class caster doesn't explode. 444 } 445 return ""; 446 } 447 447 /** Returns true if the cell at row and column is editable. 448 448 * @param row The row of the cell as an <i>int</i>. 449 449 * @param column The column of the cell also as an <i>int</i>. 450 450 */ 451 452 453 451 public boolean isCellEditable(int rowIndex, int columnIndex) { 452 return false; 453 } 454 454 /** Sets the value in the cell at columnIndex and rowIndex to aValue. 455 455 */ 456 457 458 456 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 457 } 458 /** Any implementation of <i>ListSelectionListener</i> must include this method so we can be informed when the list selection has changed. 459 459 * @param event A <strong>ListSelectionEvent</strong> containing information about the selection change. 460 460 */ 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 461 public void valueChanged(ListSelectionEvent event) { 462 fireTableStructureChanged(); 463 } 464 } 465 /** This provides a custom renderer that colours the background of the default language cell green, and the foreground of currently unready metadata rows red. */ 466 private class TableRenderer 467 extends DefaultTableCellRenderer { 468 /** Retrieve the component used to rubberstamp the table based on the given parameters. 469 * @param table The <strong>JTable</strong> to rendered. 470 * @param value The <strong>Object</strong> whose representation will be shown in the table row. 471 * @param isSelected <i>true</i> iff the column/row is selected. 472 * @param hasFocus <i>true</i> iff the column/row is in focus. 473 * @param row An <i>int</i> specifying the target row. 474 * @param column An <i>int</i> specifying the target column. 475 * @see org.greenstone.gatherer.cdm.Language 476 */ 477 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 478 Component component = null; 479 479 // Create the component. 480 481 482 483 484 485 486 487 488 489 490 480 if(value instanceof String || value instanceof Language) { 481 JLabel label = new JLabel(value.toString()); 482 label.setOpaque(true); 483 component = label; 484 } 485 else { 486 JCheckBox check = new JCheckBox("", ((Boolean)value).booleanValue()); 487 JPanel pane = new JPanel(new BorderLayout()); 488 pane.add(check, BorderLayout.CENTER); 489 component = pane; 490 } 491 491 // Check for default property 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 492 Language language = (Language)languages_model.getValueAt(row, 1); 493 if(language.isDefault()) { 494 if(isSelected) { 495 component.setBackground(Gatherer.config.getColor("coloring.collection_selection_background", false)); 496 } 497 else { 498 component.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false)); 499 } 500 } 501 else { 502 if(isSelected) { 503 component.setBackground(table.getSelectionBackground()); 504 } 505 else { 506 component.setForeground(Color.white); 507 } 508 } 509 509 // Check for readiness 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 510 Boolean ready = (Boolean)languages_model.getValueAt(row, 0); 511 if(!ready.booleanValue()) { 512 component.setForeground(Color.red); 513 } 514 else { 515 component.setForeground(Color.black); 516 } 517 return component; 518 } 519 } 520 /** Listens for actions within the translation text field and immediately updates the collection metadata as necessary. */ 521 private class TranslationListener 522 extends KeyAdapter { 523 /** This method is called when a key has been released, and is perfect for us to synchronize the contents of the translation field with the collection metadata associated with the selected feature and language. 524 * @param event A <strong>KeyEvent</strong> containing more detail about the key released. 525 * @see org.greenstone.gatherer.cdm.CollectionMeta 526 * @see org.greenstone.gatherer.cdm.CollectionMetaManager 527 * @see org.greenstone.gatherer.cdm.Index 528 */ 529 public void keyReleased(KeyEvent event) { 530 if(current == null) { 531 String name = (String)features_list.getSelectedValue(); 532 Index index = manager.indexes.getIndex(name); 533 if(index == null) { 534 current = new CollectionMeta(manager, name, current_language, translation.getText()); 535 } 536 else { 537 current = new CollectionMeta(manager, index, current_language, translation.getText()); 538 } 539 manager.collectionmetadatum.addMetadata(current); 540 } 541 else { 542 current.update(current.getName(), current.getLanguage(), translation.getText()); 543 } 544 languages_model.cellChanged(); 545 } 546 } 547 547 }
Note:
See TracChangeset
for help on using the changeset viewer.