001: /*
002: *****************************************************************************
003: * Copyright (C) 2000-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *****************************************************************************
006: */
007: package com.ibm.rbm;
008:
009: import java.io.*;
010: import javax.swing.*;
011:
012: import com.ibm.rbm.gui.RBManagerGUI;
013:
014: import java.util.*;
015: import java.awt.*;
016: import java.awt.event.*;
017:
018: /**
019: * <P>This is the super class for all importer plug-in classes.</P>
020: * <P>
021: * In terms of general functionality of this class or its children classes, the following steps should happen in order:
022: * <OL>
023: * <LI>A Dialog is shown from which the user may select options about the import, including the file from which to import.</LI>
024: * <LI>The 'Import' button is pressed, closing the options dialog and opening a progress bar dialog box.</LI>
025: * <LI>The class should resolve all conflicts with locale encodings existing in the import files, but not in the active resource bundle.</LI>
026: * <LI>The class should parse resources one at a time and use the importResource() method to insert them into the resource bundle.</LI>
027: * <LI>The class should report when all resources have been read and the import is complete.</LI>
028: * </OL>
029: * </P>
030: *
031: * @author Jared Jackson
032: * @see com.ibm.rbm.RBManager
033: */
034: public class RBImporter extends JDialog {
035: private final static int FILE_OPTION_POPULATE = 0; // Create a new locale file populated from base file
036: private final static int FILE_OPTION_EMPTY = 1; // Create a new empty locale file
037: private final static int FILE_OPTION_IGNORE = 2; // Ignore all resources from this encoding
038: private final static int FILE_OPTION_PROMPT = 3; // Prompt for each conflict
039: private final static int RESOURCE_OPTION_OVERWRITE = 0; // Use the value from the source import file
040: private final static int RESOURCE_OPTION_IGNORE = 1; // Ignore the import and use existing value
041: private final static int RESOURCE_OPTION_PROMPT = 2; // Propmpt for each conflict
042:
043: protected static JFileChooser chooser;
044: protected int num_conflicts;
045: protected int num_extra_files;
046: protected String title;
047: protected RBManager rbm;
048: protected RBManagerGUI gui;
049: protected boolean pathSet = false;
050:
051: // Visual Components
052: JRadioButton resourceOverwriteRadio = new JRadioButton(Resources
053: .getTranslation("import_resource_conflict_overwrite"),
054: false);
055: JRadioButton resourceIgnoreRadio = new JRadioButton(Resources
056: .getTranslation("import_resource_conflict_ignore"), false);
057: JRadioButton resourcePromptRadio = new JRadioButton(Resources
058: .getTranslation("import_conflict_prompt"), true);
059: JRadioButton fileGeneratePopulateRadio = new JRadioButton(Resources
060: .getTranslation("import_file_conflict_generate_populate"),
061: false);
062: JRadioButton fileGenerateEmptyRadio = new JRadioButton(Resources
063: .getTranslation("import_file_conflict_generate_empty"),
064: false);
065: JRadioButton fileIgnoreRadio = new JRadioButton(Resources
066: .getTranslation("import_file_conflict_ignore"), false);
067: JRadioButton filePromptRadio = new JRadioButton(Resources
068: .getTranslation("import_conflict_prompt"), true);
069:
070: JCheckBox markTranslatedCheck = new JCheckBox(Resources
071: .getTranslation("import_default_translated"), true);
072: JCheckBox createGroupsCheck = new JCheckBox(Resources
073: .getTranslation("import_default_group_creation"), true);
074: JComboBox groupComboBox = new JComboBox();
075:
076: JLabel sourceLabel;
077:
078: JDialog progressBarDialog;
079: JProgressBar progressBar;
080:
081: /**
082: * Constructor
083: * @param title The title that appears in the Dialog box
084: * @param rbm An RBManager instance
085: * @param gui The RBManager GUI instance associated with the RBManager instance
086: */
087:
088: public RBImporter(String title, RBManager rbm, RBManagerGUI gui) {
089: super (new Frame(), title, true);
090: this .title = title;
091: this .rbm = rbm;
092: this .gui = gui;
093: init();
094: }
095:
096: protected void init() {
097: chooser = new JFileChooser();
098: setupFileChooser();
099: num_conflicts = 0;
100: num_extra_files = 0;
101: initComponents();
102: setVisible(true);
103: }
104:
105: protected void setupFileChooser() {
106: // To be overwritten
107: }
108:
109: protected void beginImport() throws IOException {
110: // To be overwritten
111: if (!pathSet)
112: throw new IOException("Path not set yet");
113: }
114:
115: protected void chooseFile() {
116: int result = chooser.showOpenDialog(this );
117: if (result == JFileChooser.APPROVE_OPTION) {
118: File f = chooser.getSelectedFile();
119: sourceLabel.setText(Resources.getTranslation(
120: "import_source_file", f.getAbsolutePath()));
121: pathSet = true;
122: }
123: }
124:
125: protected File getChosenFile() {
126: return chooser.getSelectedFile();
127: }
128:
129: /**
130: * A super class method intended for use of nearly all subclass importers, once a resource
131: * is found by those subclasses. This method is called in order to create the new resource
132: * and handle the various conflict errors that may result as a part of that import.
133: */
134:
135: protected void importResource(BundleItem item, String encoding,
136: String group_name) {
137: Bundle bundle = null;
138: BundleGroup group = null;
139: BundleGroup backup_group = null;
140:
141: if (group_name == null)
142: group_name = getDefaultGroup();
143: if (encoding == null)
144: return;
145: // Get the bundle to which we will be adding this resource
146: bundle = rbm.getBundle(encoding);
147: // Skip this import if the bundle is non-existent (Should have been resolved if wanted)
148: if (bundle == null)
149: return;
150: // Find the group in the bundle, Ungrouped if non-existent
151: Vector gv = bundle.getGroupsAsVector();
152: for (int i = 0; i < gv.size(); i++) {
153: BundleGroup tempg = (BundleGroup) gv.elementAt(i);
154: if (i == 0)
155: backup_group = tempg;
156: if (tempg.getName().equals("Ungrouped Items"))
157: backup_group = tempg;
158: else if (tempg.getName().equals(group_name)) {
159: group = tempg;
160: break;
161: }
162: }
163: if (group == null) {
164: if (getDefaultGroupCreation()) {
165: // Create a new group by this name
166: bundle.addBundleGroup(group_name, "");
167: gv = bundle.getGroupsAsVector();
168: for (int i = 0; i < gv.size(); i++) {
169: BundleGroup tempg = (BundleGroup) gv.elementAt(i);
170: if (tempg.getName().equals(group_name)) {
171: group = tempg;
172: break;
173: }
174: }
175: } else {
176: // Use the backup_group
177: group = backup_group;
178: }
179: }
180: // If all group identification efforts fail, we fail
181: if (group == null)
182: return;
183: item.setParentGroup(group);
184: // Check for and resolve conflicts
185: if (bundle.allItems.containsKey(item.getKey())) {
186: resolveResource(bundle, item);
187: RBManagerGUI.debugMsg("Resolve conflict");
188: } else {
189: // Insert the resource
190: bundle.addBundleItem(item);
191: }
192: }
193:
194: /**
195: * This method should be called when trying to import and item whose key all ready exists within the bundle.
196: */
197:
198: protected void resolveResource(Bundle bundle, BundleItem item) {
199: if (this .getResourceConflictOption() == RESOURCE_OPTION_IGNORE)
200: return;
201: else if (this .getResourceConflictOption() == RESOURCE_OPTION_OVERWRITE) {
202: bundle.removeItem(item.getKey());
203: bundle.addBundleItem(item);
204: } else if (this .getResourceConflictOption() == RESOURCE_OPTION_PROMPT) {
205: BundleItem original = (BundleItem) bundle.allItems.get(item
206: .getKey());
207: if (original == null)
208: return;
209: String trans = original.getTranslation();
210: String options[] = {
211: Resources
212: .getTranslation("import_resource_conflict_overwrite"),
213: Resources
214: .getTranslation("import_resource_conflict_ignore") };
215: String insert[] = {
216: item.getKey(),
217: (bundle.encoding.equals("") ? "(Base Class)"
218: : bundle.encoding) };
219: String result = (String) JOptionPane
220: .showInputDialog(
221: this ,
222: Resources.getTranslation(
223: "import_resource_conflict_choose",
224: insert)
225: + "\n"
226: + Resources
227: .getTranslation(
228: "import_resource_conflict_choose_source",
229: item
230: .getTranslation())
231: + "\n"
232: + Resources
233: .getTranslation(
234: "import_resource_conflict_choose_target",
235: trans),
236: Resources
237: .getTranslation("import_file_conflicts"),
238: JOptionPane.QUESTION_MESSAGE, null,
239: options, options[0]);
240: if (result == null)
241: return;
242: if (result
243: .equals(Resources
244: .getTranslation("import_resource_conflict_overwrite"))) {
245: bundle.removeItem(item.getKey());
246: bundle.addBundleItem(item);
247: } else if (result.equals(Resources
248: .getTranslation("import_resource_conflict_ignore")))
249: return;
250: }
251: }
252:
253: /**
254: * Given a vector of strings containing locale encodings (e.g. {"en", "en_us", "de"}), attempts
255: * to resolve those conflicts according to the preferences selected by the user.
256: */
257:
258: protected void resolveEncodings(Vector v) {
259: for (int i = 0; i < v.size(); i++) {
260: String encoding = (String) v.elementAt(i);
261: if (encoding == null || encoding.equals("")
262: || rbm.hasResource(encoding)) {
263: continue;
264: }
265:
266: // We need to resolve this conflict
267: if (this .getFileConflictOption() == FILE_OPTION_IGNORE)
268: continue;
269: else if (this .getFileConflictOption() == FILE_OPTION_POPULATE) {
270: rbm.createResource(null, null, null, encoding, null,
271: null, null, true);
272: } else if (this .getFileConflictOption() == FILE_OPTION_EMPTY) {
273: rbm.createResource(null, null, null, encoding, null,
274: null, null, true);
275: } else if (this .getFileConflictOption() == FILE_OPTION_PROMPT) {
276: String options[] = {
277: Resources
278: .getTranslation("import_file_conflict_generate_populate"),
279: Resources
280: .getTranslation("import_file_conflict_generate_empty"),
281: Resources
282: .getTranslation("import_file_conflict_ignore") };
283:
284: String result = (String) JOptionPane
285: .showInputDialog(
286: this ,
287: Resources.getTranslation(
288: "import_file_conflict_choose",
289: encoding),
290: Resources
291: .getTranslation("import_file_conflicts"),
292: JOptionPane.QUESTION_MESSAGE, null,
293: options, options[0]);
294: if (result == null)
295: continue;
296: if (result.equals(Resources
297: .getTranslation("import_file_conflict_ignore")))
298: continue;
299: else if (result
300: .equals(Resources
301: .getTranslation("import_file_conflict_generate_populate"))) {
302: rbm.createResource(null, null, null, encoding,
303: null, null, null, true);
304: } else if (result
305: .equals(Resources
306: .getTranslation("import_file_conflict_generate_empty"))) {
307: rbm.createResource(null, null, null, encoding,
308: null, null, null, false);
309: }
310: }
311: }
312: gui.updateDisplayTree();
313: }
314:
315: // Returns an integer mask describing the user's selection for file resolving missing file locale conflicts
316:
317: private int getFileConflictOption() {
318: if (fileGeneratePopulateRadio.isSelected())
319: return FILE_OPTION_POPULATE;
320: if (fileGenerateEmptyRadio.isSelected())
321: return FILE_OPTION_EMPTY;
322: if (fileIgnoreRadio.isSelected())
323: return FILE_OPTION_IGNORE;
324: if (filePromptRadio.isSelected())
325: return FILE_OPTION_PROMPT;
326: return FILE_OPTION_PROMPT;
327: }
328:
329: // Returns an integer mask describing the user's selection for duplicate resource key conflicts
330:
331: private int getResourceConflictOption() {
332: if (resourceOverwriteRadio.isSelected())
333: return RESOURCE_OPTION_OVERWRITE;
334: if (resourceIgnoreRadio.isSelected())
335: return RESOURCE_OPTION_IGNORE;
336: if (resourcePromptRadio.isSelected())
337: return RESOURCE_OPTION_PROMPT;
338: return RESOURCE_OPTION_PROMPT;
339: }
340:
341: // Returns the group name for use when no group name is specified
342:
343: protected String getDefaultGroup() {
344: return groupComboBox.getSelectedItem().toString();
345: }
346:
347: // Returns the default translation value
348:
349: protected boolean getDefaultTranslated() {
350: return markTranslatedCheck.isSelected();
351: }
352:
353: // Returns whether or not a group of name non-existant in the active bundle is created
354:
355: protected boolean getDefaultGroupCreation() {
356: return createGroupsCheck.isSelected();
357: }
358:
359: protected void showProgressBar(int steps) {
360: this WindowClosing();
361: JDialog progressBarDialog = new JDialog(this , Resources
362: .getTranslation("dialog_title_import_progress"), false);
363: JProgressBar progressBar = new JProgressBar(0, steps);
364: progressBar.setValue(0);
365: progressBarDialog.getContentPane().add(progressBar);
366: progressBarDialog.pack();
367: progressBarDialog.show();
368: }
369:
370: protected void incrementProgressBar() {
371: if (progressBar == null)
372: return;
373: progressBar.setValue(progressBar.getValue() + 1);
374: if (progressBar.getValue() == progressBar.getMaximum())
375: hideProgressBar();
376: }
377:
378: protected void hideProgressBar() {
379: if (progressBarDialog != null)
380: progressBarDialog.setVisible(false);
381: }
382:
383: /**
384: * Initialize the visual components for selecting an import file and setting the appropriate
385: * options
386: */
387:
388: protected void initComponents() {
389: // Create Components
390: JLabel titleLabel = new JLabel(title);
391: sourceLabel = new JLabel(Resources.getTranslation(
392: "import_source_file", "--"));
393: JLabel insertGroupLabel = new JLabel(Resources
394: .getTranslation("import_insert_group"));
395:
396: JButton fileChooseButton = new JButton(Resources
397: .getTranslation("button_choose"));
398: JButton cancelButton = new JButton(Resources
399: .getTranslation("button_cancel"));
400: JButton importButton = new JButton(Resources
401: .getTranslation("button_import"));
402:
403: ButtonGroup resourceGroup = new ButtonGroup();
404: ButtonGroup fileGroup = new ButtonGroup();
405:
406: JPanel topPanel = new JPanel(new BorderLayout());
407: JPanel midPanel = new JPanel(new BorderLayout());
408: JPanel botPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
409:
410: JPanel topInnerPanel = new JPanel(new BorderLayout());
411:
412: Box midBox = new Box(BoxLayout.Y_AXIS);
413:
414: JPanel resourcePanel = new JPanel(new FlowLayout(
415: FlowLayout.LEFT));
416: JPanel filePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
417: JPanel defaultPanel = new JPanel(
418: new FlowLayout(FlowLayout.LEFT));
419: JPanel defaultPanel2 = new JPanel(new BorderLayout());
420:
421: Box resourceBox = new Box(BoxLayout.Y_AXIS);
422: Box fileBox = new Box(BoxLayout.Y_AXIS);
423: Box groupBox = new Box(BoxLayout.X_AXIS);
424:
425: // Setup title
426: titleLabel.setFont(new Font("Serif", Font.BOLD, 16));
427:
428: // Setup panels
429: midPanel.setBorder(BorderFactory.createTitledBorder(Resources
430: .getTranslation("import_options")));
431: resourcePanel.setBorder(BorderFactory
432: .createTitledBorder(Resources
433: .getTranslation("import_resource_conflicts")));
434: filePanel.setBorder(BorderFactory.createTitledBorder(Resources
435: .getTranslation("import_file_conflicts")));
436: defaultPanel.setBorder(BorderFactory
437: .createTitledBorder(Resources
438: .getTranslation("import_default_values")));
439:
440: // Arrange button groups
441: fileGroup.add(fileGeneratePopulateRadio);
442: fileGroup.add(fileGenerateEmptyRadio);
443: fileGroup.add(fileIgnoreRadio);
444: fileGroup.add(filePromptRadio);
445: resourceGroup.add(resourceOverwriteRadio);
446: resourceGroup.add(resourceIgnoreRadio);
447: resourceGroup.add(resourcePromptRadio);
448:
449: // Add action listeners
450: cancelButton.addActionListener(new ActionListener() {
451: public void actionPerformed(ActionEvent ev) {
452: this WindowClosing();
453: }
454: });
455:
456: importButton.addActionListener(new ActionListener() {
457: public void actionPerformed(ActionEvent ev) {
458: try {
459: beginImport();
460: gui.updateProjectTree();
461: gui.updateDisplayTree();
462: this WindowClosing();
463: } catch (IOException ioe) {
464: ioe.printStackTrace(System.err);
465: JOptionPane.showMessageDialog(null, Resources
466: .getTranslation("error")
467: + "\n" + ioe.getLocalizedMessage(),
468: Resources.getTranslation("error"),
469: JOptionPane.ERROR_MESSAGE);
470: }
471: }
472: });
473:
474: fileChooseButton.addActionListener(new ActionListener() {
475: public void actionPerformed(ActionEvent ev) {
476: chooseFile();
477: }
478: });
479:
480: // Setup combo box
481: Bundle baseBundle = ((Bundle) rbm.getBundles().elementAt(0));
482: BundleGroup ungroupedGroup = baseBundle.getUngroupedGroup();
483: groupComboBox = new JComboBox(baseBundle.getGroupsAsVector());
484: int groupComboBoxCount = groupComboBox.getItemCount();
485: for (int selectedIndex = 0; selectedIndex < groupComboBoxCount; selectedIndex++) {
486: BundleGroup bundGroup = ((BundleGroup) groupComboBox
487: .getItemAt(selectedIndex));
488: if (bundGroup.getName().equals(ungroupedGroup.getName())) {
489: // By default, use the ungrouped group. Probably named 'Ungrouped Items'.
490: groupComboBox.setSelectedIndex(selectedIndex);
491: break;
492: }
493: }
494:
495: // Arange components
496: groupBox.add(Box.createHorizontalGlue());
497: groupBox.add(insertGroupLabel);
498: groupBox.add(Box.createHorizontalStrut(5));
499: groupBox.add(groupComboBox);
500:
501: defaultPanel2.add(groupBox, BorderLayout.NORTH);
502: defaultPanel2.add(markTranslatedCheck, BorderLayout.CENTER);
503: defaultPanel2.add(createGroupsCheck, BorderLayout.SOUTH);
504:
505: fileBox.add(fileGeneratePopulateRadio);
506: fileBox.add(fileGenerateEmptyRadio);
507: fileBox.add(fileIgnoreRadio);
508: fileBox.add(filePromptRadio);
509:
510: resourceBox.add(resourceOverwriteRadio);
511: resourceBox.add(resourceIgnoreRadio);
512: resourceBox.add(resourcePromptRadio);
513:
514: defaultPanel.add(defaultPanel2);
515: filePanel.add(fileBox);
516: resourcePanel.add(resourceBox);
517:
518: midBox.add(resourcePanel);
519: midBox.add(filePanel);
520: midBox.add(defaultPanel);
521:
522: midPanel.add(midBox, BorderLayout.CENTER);
523:
524: topInnerPanel.add(sourceLabel, BorderLayout.CENTER);
525: topInnerPanel.add(fileChooseButton, BorderLayout.EAST);
526:
527: topPanel.add(titleLabel, BorderLayout.NORTH);
528: topPanel.add(topInnerPanel, BorderLayout.CENTER);
529:
530: botPanel.add(cancelButton);
531: botPanel.add(importButton);
532:
533: getContentPane().setLayout(new BorderLayout());
534: getContentPane().add(topPanel, BorderLayout.NORTH);
535: getContentPane().add(midPanel, BorderLayout.CENTER);
536: getContentPane().add(botPanel, BorderLayout.SOUTH);
537:
538: pack();
539: }
540:
541: protected void this WindowClosing() {
542: setVisible(false);
543: dispose();
544: }
545: }
|