1 /* 2 ***************************************************************************** 3 * Copyright (C) 2000-2007, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ***************************************************************************** 6 */ 7 package com.ibm.rbm; 8 9 import java.io.*; 10 import javax.swing.*; 11 12 import com.ibm.rbm.gui.RBManagerGUI; 13 14 import java.util.*; 15 import java.awt.*; 16 import java.awt.event.*; 17 18 /** 19 * <P>This is the super class for all importer plug-in classes.</P> 20 * <P> 21 * In terms of general functionality of this class or its children classes, the following steps should happen in order: 22 * <OL> 23 * <LI>A Dialog is shown from which the user may select options about the import, including the file from which to import.</LI> 24 * <LI>The 'Import' button is pressed, closing the options dialog and opening a progress bar dialog box.</LI> 25 * <LI>The class should resolve all conflicts with locale encodings existing in the import files, but not in the active resource bundle.</LI> 26 * <LI>The class should parse resources one at a time and use the importResource() method to insert them into the resource bundle.</LI> 27 * <LI>The class should report when all resources have been read and the import is complete.</LI> 28 * </OL> 29 * </P> 30 * 31 * @author Jared Jackson 32 * @see com.ibm.rbm.RBManager 33 */ 34 public class RBImporter extends JDialog { 35 private final static int FILE_OPTION_POPULATE = 0; // Create a new locale file populated from base file 36 private final static int FILE_OPTION_EMPTY = 1; // Create a new empty locale file 37 private final static int FILE_OPTION_IGNORE = 2; // Ignore all resources from this encoding 38 private final static int FILE_OPTION_PROMPT = 3; // Prompt for each conflict 39 private final static int RESOURCE_OPTION_OVERWRITE = 0; // Use the value from the source import file 40 private final static int RESOURCE_OPTION_IGNORE = 1; // Ignore the import and use existing value 41 private final static int RESOURCE_OPTION_PROMPT = 2; // Propmpt for each conflict 42 43 protected static JFileChooser chooser; 44 protected int num_conflicts; 45 protected int num_extra_files; 46 protected String title; 47 protected RBManager rbm; 48 protected RBManagerGUI gui; 49 protected boolean pathSet = false; 50 51 // Visual Components 52 JRadioButton resourceOverwriteRadio = new JRadioButton(Resources.getTranslation("import_resource_conflict_overwrite"), false); 53 JRadioButton resourceIgnoreRadio = new JRadioButton(Resources.getTranslation("import_resource_conflict_ignore"), false); 54 JRadioButton resourcePromptRadio = new JRadioButton(Resources.getTranslation("import_conflict_prompt"), true); 55 JRadioButton fileGeneratePopulateRadio = new JRadioButton(Resources.getTranslation("import_file_conflict_generate_populate"), false); 56 JRadioButton fileGenerateEmptyRadio = new JRadioButton(Resources.getTranslation("import_file_conflict_generate_empty"), false); 57 JRadioButton fileIgnoreRadio = new JRadioButton(Resources.getTranslation("import_file_conflict_ignore"), false); 58 JRadioButton filePromptRadio = new JRadioButton(Resources.getTranslation("import_conflict_prompt"), true); 59 60 JCheckBox markTranslatedCheck = new JCheckBox(Resources.getTranslation("import_default_translated"), true); 61 JCheckBox createGroupsCheck = new JCheckBox(Resources.getTranslation("import_default_group_creation"), true); 62 JComboBox groupComboBox = new JComboBox(); 63 64 JLabel sourceLabel; 65 66 JDialog progressBarDialog; 67 JProgressBar progressBar; 68 69 /** 70 * Constructor 71 * @param title The title that appears in the Dialog box 72 * @param rbm An RBManager instance 73 * @param gui The RBManager GUI instance associated with the RBManager instance 74 */ 75 RBImporter(String title, RBManager rbm, RBManagerGUI gui)76 public RBImporter(String title, RBManager rbm, RBManagerGUI gui) { 77 super(new Frame(), title, true); 78 this.title = title; 79 this.rbm = rbm; 80 this.gui = gui; 81 init(); 82 } 83 init()84 protected void init() { 85 chooser = new JFileChooser(); 86 setupFileChooser(); 87 num_conflicts = 0; 88 num_extra_files = 0; 89 initComponents(); 90 setVisible(true); 91 } 92 setupFileChooser()93 protected void setupFileChooser() { 94 // To be overwritten 95 } 96 beginImport()97 protected void beginImport() throws IOException { 98 // To be overwritten 99 if (!pathSet) 100 throw new IOException("Path not set yet"); 101 } 102 chooseFile()103 protected void chooseFile() { 104 int result = chooser.showOpenDialog(this); 105 if (result == JFileChooser.APPROVE_OPTION) { 106 File f = chooser.getSelectedFile(); 107 sourceLabel.setText(Resources.getTranslation("import_source_file",f.getAbsolutePath())); 108 pathSet = true; 109 } 110 } 111 getChosenFile()112 protected File getChosenFile() { 113 return chooser.getSelectedFile(); 114 } 115 116 /** 117 * A super class method intended for use of nearly all subclass importers, once a resource 118 * is found by those subclasses. This method is called in order to create the new resource 119 * and handle the various conflict errors that may result as a part of that import. 120 */ 121 importResource(BundleItem item, String encoding, String group_name)122 protected void importResource(BundleItem item, String encoding, String group_name) { 123 Bundle bundle = null; 124 BundleGroup group = null; 125 BundleGroup backup_group = null; 126 127 if (group_name == null) 128 group_name = getDefaultGroup(); 129 if (encoding == null) 130 return; 131 // Get the bundle to which we will be adding this resource 132 bundle = rbm.getBundle(encoding); 133 // Skip this import if the bundle is non-existent (Should have been resolved if wanted) 134 if (bundle == null) 135 return; 136 // Find the group in the bundle, Ungrouped if non-existent 137 Vector gv = bundle.getGroupsAsVector(); 138 for (int i=0; i < gv.size(); i++) { 139 BundleGroup tempg = (BundleGroup)gv.elementAt(i); 140 if (i==0) backup_group = tempg; 141 if (tempg.getName().equals("Ungrouped Items")) backup_group = tempg; 142 else if (tempg.getName().equals(group_name)) { 143 group = tempg; 144 break; 145 } 146 } 147 if (group == null) { 148 if (getDefaultGroupCreation()) { 149 // Create a new group by this name 150 bundle.addBundleGroup(group_name, ""); 151 gv = bundle.getGroupsAsVector(); 152 for (int i=0; i < gv.size(); i++) { 153 BundleGroup tempg = (BundleGroup)gv.elementAt(i); 154 if (tempg.getName().equals(group_name)) { 155 group = tempg; 156 break; 157 } 158 } 159 } else { 160 // Use the backup_group 161 group = backup_group; 162 } 163 } 164 // If all group identification efforts fail, we fail 165 if (group == null) 166 return; 167 item.setParentGroup(group); 168 // Check for and resolve conflicts 169 if (bundle.allItems.containsKey(item.getKey())) { 170 resolveResource(bundle,item); 171 RBManagerGUI.debugMsg("Resolve conflict"); 172 } else { 173 // Insert the resource 174 bundle.addBundleItem(item); 175 } 176 } 177 178 /** 179 * This method should be called when trying to import and item whose key all ready exists within the bundle. 180 */ 181 resolveResource(Bundle bundle, BundleItem item)182 protected void resolveResource(Bundle bundle, BundleItem item) { 183 if (this.getResourceConflictOption() == RESOURCE_OPTION_IGNORE) 184 return; 185 else if (this.getResourceConflictOption() == RESOURCE_OPTION_OVERWRITE) { 186 bundle.removeItem(item.getKey()); 187 bundle.addBundleItem(item); 188 } else if (this.getResourceConflictOption() == RESOURCE_OPTION_PROMPT) { 189 BundleItem original = (BundleItem)bundle.allItems.get(item.getKey()); 190 if (original == null) 191 return; 192 String trans = original.getTranslation(); 193 String options[] = { Resources.getTranslation("import_resource_conflict_overwrite"), 194 Resources.getTranslation("import_resource_conflict_ignore")}; 195 String insert[] = {item.getKey(), (bundle.encoding.equals("") ? "(Base Class)" : bundle.encoding)}; 196 String result = (String)JOptionPane.showInputDialog(this, Resources.getTranslation("import_resource_conflict_choose", insert) + 197 "\n" + Resources.getTranslation("import_resource_conflict_choose_source", item.getTranslation()) + 198 "\n" + Resources.getTranslation("import_resource_conflict_choose_target", trans), 199 Resources.getTranslation("import_file_conflicts"), JOptionPane.QUESTION_MESSAGE, 200 null, options, options[0]); 201 if (result == null) 202 return; 203 if (result.equals(Resources.getTranslation("import_resource_conflict_overwrite"))) { 204 bundle.removeItem(item.getKey()); 205 bundle.addBundleItem(item); 206 } else if (result.equals(Resources.getTranslation("import_resource_conflict_ignore"))) 207 return; 208 } 209 } 210 211 /** 212 * Given a vector of strings containing locale encodings (e.g. {"en", "en_us", "de"}), attempts 213 * to resolve those conflicts according to the preferences selected by the user. 214 */ 215 resolveEncodings(Vector v)216 protected void resolveEncodings(Vector v) { 217 for (int i=0; i < v.size(); i++) { 218 String encoding = (String)v.elementAt(i); 219 if (encoding == null || encoding.equals("") || rbm.hasResource(encoding)) { 220 continue; 221 } 222 223 // We need to resolve this conflict 224 if (this.getFileConflictOption() == FILE_OPTION_IGNORE) continue; 225 else if (this.getFileConflictOption() == FILE_OPTION_POPULATE) { 226 rbm.createResource(null, null, null, encoding, null, null, null, true); 227 } else if (this.getFileConflictOption() == FILE_OPTION_EMPTY) { 228 rbm.createResource(null, null, null, encoding, null, null, null, true); 229 } else if (this.getFileConflictOption() == FILE_OPTION_PROMPT) { 230 String options[] = { Resources.getTranslation("import_file_conflict_generate_populate"), 231 Resources.getTranslation("import_file_conflict_generate_empty"), 232 Resources.getTranslation("import_file_conflict_ignore")}; 233 234 String result = (String)JOptionPane.showInputDialog(this, Resources.getTranslation("import_file_conflict_choose", encoding), 235 Resources.getTranslation("import_file_conflicts"), JOptionPane.QUESTION_MESSAGE, 236 null, options, options[0]); 237 if (result == null) continue; 238 if (result.equals(Resources.getTranslation("import_file_conflict_ignore"))) continue; 239 else if (result.equals(Resources.getTranslation("import_file_conflict_generate_populate"))) { 240 rbm.createResource(null, null, null, encoding, null, null, null, true); 241 } else if (result.equals(Resources.getTranslation("import_file_conflict_generate_empty"))) { 242 rbm.createResource(null, null, null, encoding, null, null, null, false); 243 } 244 } 245 } 246 gui.updateDisplayTree(); 247 } 248 249 // Returns an integer mask describing the user's selection for file resolving missing file locale conflicts 250 getFileConflictOption()251 private int getFileConflictOption() { 252 if (fileGeneratePopulateRadio.isSelected()) return FILE_OPTION_POPULATE; 253 if (fileGenerateEmptyRadio.isSelected()) return FILE_OPTION_EMPTY; 254 if (fileIgnoreRadio.isSelected()) return FILE_OPTION_IGNORE; 255 if (filePromptRadio.isSelected()) return FILE_OPTION_PROMPT; 256 return FILE_OPTION_PROMPT; 257 } 258 259 // Returns an integer mask describing the user's selection for duplicate resource key conflicts 260 getResourceConflictOption()261 private int getResourceConflictOption() { 262 if (resourceOverwriteRadio.isSelected()) return RESOURCE_OPTION_OVERWRITE; 263 if (resourceIgnoreRadio.isSelected()) return RESOURCE_OPTION_IGNORE; 264 if (resourcePromptRadio.isSelected()) return RESOURCE_OPTION_PROMPT; 265 return RESOURCE_OPTION_PROMPT; 266 } 267 268 // Returns the group name for use when no group name is specified 269 getDefaultGroup()270 protected String getDefaultGroup() { 271 return groupComboBox.getSelectedItem().toString(); 272 } 273 274 // Returns the default translation value 275 getDefaultTranslated()276 protected boolean getDefaultTranslated() { 277 return markTranslatedCheck.isSelected(); 278 } 279 280 // Returns whether or not a group of name non-existant in the active bundle is created 281 getDefaultGroupCreation()282 protected boolean getDefaultGroupCreation() { 283 return createGroupsCheck.isSelected(); 284 } 285 showProgressBar(int steps)286 protected void showProgressBar(int steps) { 287 thisWindowClosing(); 288 JDialog progressBarDialog = new JDialog(this, Resources.getTranslation("dialog_title_import_progress"), false); 289 JProgressBar progressBar = new JProgressBar(0, steps); 290 progressBar.setValue(0); 291 progressBarDialog.getContentPane().add(progressBar); 292 progressBarDialog.pack(); 293 progressBarDialog.setVisible(true); 294 } 295 incrementProgressBar()296 protected void incrementProgressBar() { 297 if (progressBar == null) return; 298 progressBar.setValue(progressBar.getValue()+1); 299 if (progressBar.getValue() == progressBar.getMaximum()) hideProgressBar(); 300 } 301 hideProgressBar()302 protected void hideProgressBar() { 303 if (progressBarDialog != null) progressBarDialog.setVisible(false); 304 } 305 306 /** 307 * Initialize the visual components for selecting an import file and setting the appropriate 308 * options 309 */ 310 initComponents()311 protected void initComponents() { 312 // Create Components 313 JLabel titleLabel = new JLabel(title); 314 sourceLabel = new JLabel(Resources.getTranslation("import_source_file","--")); 315 JLabel insertGroupLabel = new JLabel(Resources.getTranslation("import_insert_group")); 316 317 JButton fileChooseButton = new JButton(Resources.getTranslation("button_choose")); 318 JButton cancelButton = new JButton(Resources.getTranslation("button_cancel")); 319 JButton importButton = new JButton(Resources.getTranslation("button_import")); 320 321 ButtonGroup resourceGroup = new ButtonGroup(); 322 ButtonGroup fileGroup = new ButtonGroup(); 323 324 JPanel topPanel = new JPanel(new BorderLayout()); 325 JPanel midPanel = new JPanel(new BorderLayout()); 326 JPanel botPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); 327 328 JPanel topInnerPanel = new JPanel(new BorderLayout()); 329 330 Box midBox = new Box(BoxLayout.Y_AXIS); 331 332 JPanel resourcePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 333 JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 334 JPanel defaultPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); 335 JPanel defaultPanel2 = new JPanel(new BorderLayout()); 336 337 Box resourceBox = new Box(BoxLayout.Y_AXIS); 338 Box fileBox = new Box(BoxLayout.Y_AXIS); 339 Box groupBox = new Box(BoxLayout.X_AXIS); 340 341 // Setup title 342 titleLabel.setFont(new Font("Serif",Font.BOLD,16)); 343 344 // Setup panels 345 midPanel.setBorder(BorderFactory.createTitledBorder(Resources.getTranslation("import_options"))); 346 resourcePanel.setBorder(BorderFactory.createTitledBorder(Resources.getTranslation("import_resource_conflicts"))); 347 filePanel.setBorder(BorderFactory.createTitledBorder(Resources.getTranslation("import_file_conflicts"))); 348 defaultPanel.setBorder(BorderFactory.createTitledBorder(Resources.getTranslation("import_default_values"))); 349 350 // Arrange button groups 351 fileGroup.add(fileGeneratePopulateRadio); 352 fileGroup.add(fileGenerateEmptyRadio); 353 fileGroup.add(fileIgnoreRadio); 354 fileGroup.add(filePromptRadio); 355 resourceGroup.add(resourceOverwriteRadio); 356 resourceGroup.add(resourceIgnoreRadio); 357 resourceGroup.add(resourcePromptRadio); 358 359 // Add action listeners 360 cancelButton.addActionListener(new ActionListener(){ 361 public void actionPerformed(ActionEvent ev) { 362 thisWindowClosing(); 363 } 364 }); 365 366 importButton.addActionListener(new ActionListener(){ 367 public void actionPerformed(ActionEvent ev) { 368 try { 369 beginImport(); 370 gui.updateProjectTree(); 371 gui.updateDisplayTree(); 372 thisWindowClosing(); 373 } catch (IOException ioe) { 374 ioe.printStackTrace(System.err); 375 JOptionPane.showMessageDialog(null, 376 Resources.getTranslation("error") + "\n" + ioe.getLocalizedMessage(), 377 Resources.getTranslation("error"), JOptionPane.ERROR_MESSAGE); 378 } 379 } 380 }); 381 382 fileChooseButton.addActionListener(new ActionListener(){ 383 public void actionPerformed(ActionEvent ev) { 384 chooseFile(); 385 } 386 }); 387 388 // Setup combo box 389 Bundle baseBundle = ((Bundle)rbm.getBundles().elementAt(0)); 390 BundleGroup ungroupedGroup = baseBundle.getUngroupedGroup(); 391 groupComboBox = new JComboBox(baseBundle.getGroupsAsVector()); 392 int groupComboBoxCount = groupComboBox.getItemCount(); 393 for (int selectedIndex = 0; selectedIndex < groupComboBoxCount; selectedIndex++) { 394 BundleGroup bundGroup = ((BundleGroup)groupComboBox.getItemAt(selectedIndex)); 395 if (bundGroup.getName().equals(ungroupedGroup.getName())) { 396 // By default, use the ungrouped group. Probably named 'Ungrouped Items'. 397 groupComboBox.setSelectedIndex(selectedIndex); 398 break; 399 } 400 } 401 402 // Arange components 403 groupBox.add(Box.createHorizontalGlue()); 404 groupBox.add(insertGroupLabel); 405 groupBox.add(Box.createHorizontalStrut(5)); 406 groupBox.add(groupComboBox); 407 408 defaultPanel2.add(groupBox, BorderLayout.NORTH); 409 defaultPanel2.add(markTranslatedCheck, BorderLayout.CENTER); 410 defaultPanel2.add(createGroupsCheck, BorderLayout.SOUTH); 411 412 fileBox.add(fileGeneratePopulateRadio); 413 fileBox.add(fileGenerateEmptyRadio); 414 fileBox.add(fileIgnoreRadio); 415 fileBox.add(filePromptRadio); 416 417 resourceBox.add(resourceOverwriteRadio); 418 resourceBox.add(resourceIgnoreRadio); 419 resourceBox.add(resourcePromptRadio); 420 421 defaultPanel.add(defaultPanel2); 422 filePanel.add(fileBox); 423 resourcePanel.add(resourceBox); 424 425 midBox.add(resourcePanel); 426 midBox.add(filePanel); 427 midBox.add(defaultPanel); 428 429 midPanel.add(midBox, BorderLayout.CENTER); 430 431 topInnerPanel.add(sourceLabel, BorderLayout.CENTER); 432 topInnerPanel.add(fileChooseButton, BorderLayout.EAST); 433 434 topPanel.add(titleLabel, BorderLayout.NORTH); 435 topPanel.add(topInnerPanel, BorderLayout.CENTER); 436 437 botPanel.add(cancelButton); 438 botPanel.add(importButton); 439 440 getContentPane().setLayout(new BorderLayout()); 441 getContentPane().add(topPanel, BorderLayout.NORTH); 442 getContentPane().add(midPanel, BorderLayout.CENTER); 443 getContentPane().add(botPanel, BorderLayout.SOUTH); 444 445 pack(); 446 } 447 thisWindowClosing()448 protected void thisWindowClosing() { 449 setVisible(false); 450 dispose(); 451 } 452 }