[Schmitzm-commits] r907 - in trunk/src/schmitzm: lang swing swing/resource/locales

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Thu Jun 10 22:15:32 CEST 2010


Author: mojays
Date: 2010-06-10 22:15:31 +0200 (Thu, 10 Jun 2010)
New Revision: 907

Modified:
   trunk/src/schmitzm/lang/ResourceProvider.java
   trunk/src/schmitzm/swing/ResourceProviderManagerFrame.java
   trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle.properties
   trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle_de.properties
Log:
Update functionality in ResourceProvider and ResourceProviderManagerFrame

Modified: trunk/src/schmitzm/lang/ResourceProvider.java
===================================================================
--- trunk/src/schmitzm/lang/ResourceProvider.java	2010-06-10 11:12:57 UTC (rev 906)
+++ trunk/src/schmitzm/lang/ResourceProvider.java	2010-06-10 20:15:31 UTC (rev 907)
@@ -29,16 +29,27 @@
  ******************************************************************************/
 package schmitzm.lang;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
 import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.text.DateFormat;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.MissingResourceException;
+import java.util.Properties;
+import java.util.PropertyResourceBundle;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.SortedSet;
@@ -46,6 +57,8 @@
 
 import org.apache.log4j.Logger;
 
+import schmitzm.io.FileInputStream;
+import schmitzm.io.IOUtil;
 import schmitzm.jfree.JFreeChartUtil;
 
 /**
@@ -163,23 +176,20 @@
      * @param missingResourceString
      *            Alternativ-String der - wenn fehlende Ressourcen ignoriert
      *            werden - von {@link #getString(String)} zurueckgegeben wird
+     * @param register
+     *            Flag, ob das neue Bundle registriert werden soll (nur fuer interne
+     *            Zwecke verfuegbar!)            
      */
     protected ResourceProvider(String defaultResourceBundle, Locale rootLocale,
-            boolean ignoreMissingResource, String missingResourceString) {
+            boolean ignoreMissingResource, String missingResourceString, boolean register) {
         this.defaultResourceBundle = defaultResourceBundle;
         this.rootLocale = rootLocale;
         this.resourceBundle = null;
         this.ignoreMissingResource = ignoreMissingResource;
         this.missingResourceString = missingResourceString;
         // Registrieren des neuen ResourceProvider
-        RESOURCE_PROVIDER.put(defaultResourceBundle, this);
-        // Wenn Auto-Reset aktiviert, automatisch das Alternativ-Bundle
-        // setzen, mit dem Original-Bundle als Prefix
-        if ( autoReset )
-          resetResourceBundle(autoResetBundle, getDefaultBundleSimpleName());
-        
-        // Registrieren des neuen ResourceProvider als sortierbare Liste
-        RESOURCE_PROVIDER_SORTABLE.add(this);
+        if( register )
+          registerResourceProvider(this);
     }
 
     /**
@@ -202,7 +212,7 @@
       // only create a new provider if none is yet created for
       // the bundle name
       if ( provider == null ) {
-        provider = new ResourceProvider(defaultResourceBundle,rootLocale,ignoreMissingResource,missingResourceString);
+        provider = new ResourceProvider(defaultResourceBundle,rootLocale,ignoreMissingResource,missingResourceString,true);
       }
       return provider;
     }
@@ -762,7 +772,8 @@
 	 *            wenn {@code true}, wird eine bestehende Datei erweitert,
 	 *            andernfalls ueberschrieben
 	 * @param rootPath
-	 *            
+	 *            Pfad unterhalb dem das Bundle-Package angelegt wird (wenn {@code null}
+	 *            wird der Pfad aus dem System-Classpath ermittelt)
 	 */
 	public static void createPropertyFile(ResourceProvider provider, Locale l,
 			boolean append, File rootPath) throws URISyntaxException, FileNotFoundException, MalformedURLException {
@@ -793,7 +804,7 @@
 		// Keys mit Dummy-Werten in Datei schreiben
 		for (String key : provider.getKeys()) {
 			
-			// Some spacial characters have to be escaped, e.g. Newline \n
+			// Some special characters have to be escaped, e.g. Newline \n
 			String originalString = provider.getString(key);
 			originalString = originalString.replaceAll("\\n", "\\\\n");
 			
@@ -806,14 +817,145 @@
 		out.close();
 	}
 
-	/**
+    /**
+     * Erzeugt eine Property-Datei ({@code .properties}) fuer ein Resource
+     * Bundle. In dieser sind <b>NUR diejenigen</b> Keys des Bundles enthalten,
+     * welche in der angegebenen {@link Locale} derzeit nicht explizit hinterlegt
+     * sind.
+     * 
+     * @param provider
+     *            Resource-Provider fuer welches auf fehlende Definitionen
+     *            geprueft wird
+     * @param l
+     *            Sprache, die geprueft wird
+     * @param append
+     *            wenn {@code true}, wird eine bestehende Datei erweitert,
+     *            andernfalls ueberschrieben
+     * @param rootPath
+     *            Pfad unterhalb dem das Bundle-Package angelegt wird
+     *            
+     * @exception IllegalArgumentException wenn {@code append = FALSE} und
+     *            {@code rootPath = NULL}, da dann die bestehende Bundle-Datei
+     *            ueberschrieben wuerde
+     */
+    public static boolean updatePropertyFile(ResourceProvider provider, Locale l,
+            boolean append, File rootPath) throws URISyntaxException, FileNotFoundException, MalformedURLException, IOException {
+      if ( !append && rootPath == null )
+        throw new IllegalArgumentException("NULL-rootPath only allowed on append mode. Otherwise the existing bundle file would be overwritten!");
+
+      File existingBundleFile = getPropertyFile(provider, l, null);
+      File newBundleFile = getPropertyFile(provider, l, rootPath);
+      // create package subdirectories if necessary
+      if ( newBundleFile.getParentFile() != null )
+        newBundleFile.getParentFile().mkdirs(); 
+      // Neuen ResourceProvider nur fuer die angegebene Locale erstellen,
+      // um Fallback zu vermeiden
+      ResourceProvider inBundle = new ResourceProvider(
+          provider.getDefaultBundleName()+"_"+l.toString(),
+          l,
+          false,
+          "???",
+          false
+      );
+      if ( !provider.getDefaultBundleName().equals( provider.getBundleName() ) )
+        inBundle.resetResourceBundle(provider.getBundleName()+"_"+l.toString(), provider.getKeyPrefix());
+
+      // Updates zunaechst in Buffer schreiben, da (bei append = TRUE)
+      // die Ausgabe-Datei u.U. identisch mit der Eingabe-Datei!
+      StringBuffer pipedOut = new StringBuffer();
+
+      // Update-Header erstellen
+      if (!newBundleFile.exists() || newBundleFile.length() == 0) {
+        pipedOut.append("# ----------------------------------------------------------------------------------").append("\n");
+        pipedOut.append("#  LANGUAGE: " + l.toString() + " = " + l.getDisplayLanguage()).append("\n");
+        pipedOut.append("# ----------------------------------------------------------------------------------").append("\n");
+      }
+      pipedOut.append("# Original bundle: " + provider.getDefaultBundleName()).append("\n");
+      pipedOut.append("# UPDATE ["+DateFormat.getInstance().format(new Date())+"]").append("\n");
+
+      // etwaiges Key-Prefix ermitteln
+      String prefix = provider.getKeyPrefix();
+      if (prefix == null)
+        prefix = "";
+      if (!prefix.equals(""))
+        prefix += ".";
+
+      // Pruefen, welche Keys des Providers in der Property-Datei
+      // der angegebenen Locale fehlen. Diese mit Dummy-Wert in die
+      // Update-Datei schreiben.
+      boolean updates = false;
+      for (String key : provider.getKeys()) {
+        try {
+          if (inBundle != null)
+            inBundle.getObject(key);
+        } catch (MissingResourceException err) {
+          // Ressource fehlt --> in Update aufnehmen
+          // Dummy-Wert fuer Key erzeugen (und spezielle Zeichen escapen)
+          String originalString = provider.getString(key);
+          originalString = originalString.replaceAll("\\n", "\\\\n");
+          pipedOut.append(prefix + key + "=?" + l.toString() + "? " + originalString).append("\n");
+          updates = true;
+        }
+        
+      }   
+      pipedOut.append("# ----------------------------------------------------------------------------------").append("\n");
+      
+      // Gepufferte Updates in Bundle-Datei schreiben 
+      if ( updates ) {
+        // Ausgabe-Datei oeffnen
+        PrintWriter      outWriter = new PrintWriter(new FileOutputStream(newBundleFile,append));
+        // Gepufferte Updates als Eingabe-Stream oeffnen
+        BufferedReader   newProp   = new BufferedReader(new StringReader(pipedOut.toString())); 
+        // Alle Zeilen in Ausgabe-Datei uebertragen
+        String           propLine  = null;
+        while( (propLine = newProp.readLine()) != null )
+          outWriter.println(propLine);
+        // Ausgabe-Stream schliessen
+        outWriter.flush();
+        outWriter.close();
+        // Eingabe-Stream schliessen
+        newProp.close();
+      }
+      return updates;
+    }
+
+    /**
 	 * Liefert alle instanziierten {@link ResourceProvider}.
 	 */
 	public static SortableVector<ResourceProvider> getRegisteredResourceProvider() {
-	  return RESOURCE_PROVIDER_SORTABLE;
+	  return new SortableVector<ResourceProvider>(RESOURCE_PROVIDER_SORTABLE);
 	}
 	
 	/**
+	 * Registriert einen {@link ResourceProvider} in der Liste der
+	 * instanziierten {@link ResourceProvider}. Wird automatisch im Konstruktor
+	 * gemacht, deshalb ist diese Methode {@code private}!
+	 * @param rp ein {@link ResourceProvider}
+	 */
+	private static void registerResourceProvider(ResourceProvider rp) {
+      // Registrieren des neuen ResourceProvider
+      RESOURCE_PROVIDER.put(rp.getDefaultBundleName(), rp);
+      // Wenn Auto-Reset aktiviert, automatisch das Alternativ-Bundle
+      // setzen, mit dem Original-Bundle als Prefix
+      if ( autoReset )
+        rp.resetResourceBundle(autoResetBundle, rp.getDefaultBundleSimpleName());
+      
+      // Registrieren des neuen ResourceProvider als sortierbare Liste
+      RESOURCE_PROVIDER_SORTABLE.add(rp);	  
+	}
+	
+	/**
+	 * Entfernt einen {@link ResourceProvider} aus der Liste der registrierten
+	 * {@link ResourceProvider}.
+	 */
+	public static void unregisterResourceProvider(ResourceProvider rp) {
+	  if ( rp == null )
+	    return;
+	  RESOURCE_PROVIDER.remove(rp.getDefaultBundleName());
+	  RESOURCE_PROVIDER_SORTABLE.remove(rp);
+	}
+	
+	/**
 	 * (De)Aktiviert, dass jeder instanziiere {@link ResourceProvider} automatisch
 	 * auf ein alternatives Bundle resettet wird (mittels {@link ResourceProvider#resetResourceBundle(String, String)}).
      * Als Prefix wird jeweils der Name des Original-Bundles verwendet. 
@@ -829,6 +971,6 @@
 	  if ( backdated )
 	    for (ResourceProvider rp : RESOURCE_PROVIDER_SORTABLE)
 	      rp.resetResourceBundle(bundle, rp.getDefaultBundleSimpleName() );
-	}
-	
+  }
+
 }

Modified: trunk/src/schmitzm/swing/ResourceProviderManagerFrame.java
===================================================================
--- trunk/src/schmitzm/swing/ResourceProviderManagerFrame.java	2010-06-10 11:12:57 UTC (rev 906)
+++ trunk/src/schmitzm/swing/ResourceProviderManagerFrame.java	2010-06-10 20:15:31 UTC (rev 907)
@@ -33,15 +33,19 @@
 import java.awt.AWTEvent;
 import java.awt.BorderLayout;
 import java.awt.Component;
+import java.awt.Cursor;
 import java.awt.FlowLayout;
+import java.awt.Graphics;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.WindowEvent;
 import java.io.File;
+import java.lang.reflect.InvocationTargetException;
 import java.util.Locale;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.Vector;
 
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
@@ -50,8 +54,11 @@
 import javax.swing.JOptionPane;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.SwingWorker;
 import javax.swing.table.AbstractTableModel;
 
+import schmitzm.io.IOUtil;
 import schmitzm.lang.LocaleComparator;
 import schmitzm.lang.ResourceProvider;
 import schmitzm.swing.event.InputOptionAdapter;
@@ -67,6 +74,7 @@
   private JLabel    infoText         = null; // use JLabel to interpret HTML
   private JButton   cancelButton     = null;
   private JButton   newLangButton    = null;
+  private JButton   updateLangButton = null;
   private JButton   openFolderButton = null;
   private JTable    bundleTable      = null;
   private JPanel    controlPanel     = null;
@@ -123,7 +131,7 @@
   private void initGUI(String infoMess) throws Exception  {
     //imageLabel.setIcon(new ImageIcon(XuluMainFrame_Infodialog.class.getResource("[Ihre Grafik]")));
     this.setTitle(getResource("Title"));
-    this.setSize(500,400);
+    this.setSize(650,400);
     this.getContentPane().setLayout(new BorderLayout());
     
     if (infoMess != null) {
@@ -142,6 +150,8 @@
     cancelButton.addActionListener(this);
     newLangButton = new JButton(getResource("NewLang"));
     newLangButton.addActionListener(this);
+    updateLangButton = new JButton(getResource("UpdateLang"));
+    updateLangButton.addActionListener(this);
     openFolderButton = new JButton(SwingUtil.R("OpenFolder"));
     openFolderButton.addActionListener(this);
 
@@ -149,6 +159,7 @@
     controlPanel.setLayout( new FlowLayout(FlowLayout.CENTER) );
     controlPanel.add( cancelButton );
     controlPanel.add( newLangButton );
+    controlPanel.add( updateLangButton );
     controlPanel.add( openFolderButton );
 
     if ( infoText != null )
@@ -187,27 +198,45 @@
     TreeSet<Locale> sortedLocales = new TreeSet<Locale>(new LocaleComparator(true));
     for (Locale l : Locale.getAvailableLocales())
       sortedLocales.add(l);
+  
+    InputOption[] dialogOption = prepareLanguageDialog(sortedLocales, true);
+    newLangDialog_LangDesc = (SelectionInputOption) dialogOption[0];
+    newLangDialog_LangCode = (ManualInputOption) dialogOption[1];
+  }
 
+  /**
+   * Prepares the input options for a dialog to choose a language. The dialog
+   * itself must be created by {@link MultipleOptionPane}.
+   * @param locales   the available locales in the input options 
+   * @param inclOther flag whether the option "Other language" is available
+   * @return
+   */
+  private InputOption[] prepareLanguageDialog(Set<Locale> locales, boolean inclOther) {
     // insert descriptions and language codes to arrays
-    String[] avLocaleDesc = new String[sortedLocales.size()+1];
-    String[] avLocaleCode = new String[sortedLocales.size()+1];
+    int      avLocaleSize = locales.size();
+    if ( inclOther )
+      avLocaleSize++;
+    String[] avLocaleDesc = new String[avLocaleSize];
+    String[] avLocaleCode = new String[avLocaleSize];
     int i = 0;
-    for (Locale l : sortedLocales) {
+    for (Locale l : locales) {
       avLocaleDesc[i] = l.getDisplayName();
       avLocaleCode[i] = l.toString();
       i++;
     }
     // additional option "other language"
-    avLocaleDesc[i] = getResource("OtherLang");
-    avLocaleCode[i] = "";
-
+    if ( inclOther ) {
+      avLocaleDesc[i] = getResource("OtherLang");
+      avLocaleCode[i] = "";
+    }
+    
     // create input option for the language code
-    newLangDialog_LangCode = new ManualInputOption.Text(
+    final ManualInputOption langCode = new ManualInputOption.Text(
       getResource("LanguageCode"),
       true
     );
     // create input option for predefined languages
-    newLangDialog_LangDesc = new SelectionInputOption.Combo(
+    final SelectionInputOption langDesc = new SelectionInputOption.Combo(
       getResource("Language"),
       true,
       avLocaleCode,
@@ -216,14 +245,25 @@
     );
     // if the language selection changes, also the language code should
     // change
-    newLangDialog_LangDesc.addInputOptionListener(new InputOptionAdapter() {
+    langDesc.addInputOptionListener(new InputOptionAdapter() {
       public void optionChanged(InputOption option, Object oldValue, Object newValue) {
-        newLangDialog_LangCode.setValue(newValue);
-        newLangDialog_LangCode.transferFocus();
-        newLangDialog_LangCode.setEnabled( "".equals(newValue));
+        langCode.setValue(newValue);
+        langCode.transferFocus();
+        langCode.setEnabled( "".equals(newValue));
       }
     });
+    
+    // Fill return array
+    InputOption[] inputOption = new InputOption[] {
+         langDesc,
+         langCode
+    };
+    return inputOption;
+    
+
   }
+  
+  
 
   /**
    * Closes the window, if {@code e} is a <code>WindowEvent.WINDOW_CLOSING<code>-event.
@@ -258,7 +298,8 @@
     if ( input == null )
       return;
 
-    // create the property files for all bundles
+    setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR) );
+   // create the property files for all bundles
     Locale newLocale = new Locale((String)input[1]);
     try {
       // check whether the file exists for one bundle
@@ -287,6 +328,7 @@
       ResourceBundle.clearCache();
       ((AbstractTableModel)bundleTable.getModel()).fireTableDataChanged();
       // show message
+      setCursor( Cursor.getDefaultCursor() );
       JOptionPane.showMessageDialog(
                                     this,
                                     getResource("FinishMess"),
@@ -294,11 +336,59 @@
                                     JOptionPane.INFORMATION_MESSAGE
                                   );
     } catch (Exception err) {
+     setCursor( Cursor.getDefaultCursor() );
+     ExceptionDialog.show(this,err,err.getClass().getSimpleName(),null);
+    }
+  }
+
+  /**
+   * Opens the language dialog and creates the new bundles.
+   */
+  private void updateLanguage() {
+    // sort the provided languages according to their description
+    TreeSet<Locale> sortedLocales = new TreeSet<Locale>(new LocaleComparator(true));
+    for (ResourceProvider rp : ResourceProvider.getRegisteredResourceProvider())
+      for (Locale l : rp.getAvailableLocales(false))
+        sortedLocales.add(l);
+    InputOption[] dialogOption = prepareLanguageDialog(sortedLocales, false);
+    ((SelectionInputOption) dialogOption[0]).setSelectedIndex(0);
+    
+    // show the dialog
+    Object[] input = MultipleOptionPane.showMultipleInputDialog(
+        this,
+        getResource("UpdateLang"),
+        dialogOption
+    );
+    if ( input == null )
+      return;
+
+    setCursor( Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR) );
+    // create the property files for all bundles
+    Locale updateLocale = new Locale((String)input[1]);
+    try {
+      // Update files (with APPEND-function)
+      int updatedFiles = 0;
+      for ( ResourceProvider rp : new Vector<ResourceProvider>(ResourceProvider.getRegisteredResourceProvider()) )
+        if ( ResourceProvider.updatePropertyFile(rp, updateLocale, true, getRootPath()) )
+          updatedFiles++;
+
+      // Update table
+      ResourceBundle.clearCache();
+      ((AbstractTableModel)bundleTable.getModel()).fireTableDataChanged();
+      // show message
+      setCursor( Cursor.getDefaultCursor() );
+      JOptionPane.showMessageDialog(
+                                    this,
+                                    getResource("UpdateMess",updatedFiles),
+                                    SwingUtil.R("Information")+"...",
+                                    JOptionPane.INFORMATION_MESSAGE
+                                  );
+    } catch (Exception err) {
+      setCursor( Cursor.getDefaultCursor() );
       ExceptionDialog.show(this,err,err.getClass().getSimpleName(),null);
     }
   }
 
-
   /**
    * Performs the button action.
    */
@@ -307,6 +397,8 @@
       cancel();
     if (e.getSource() == newLangButton)
       createNewLanguage();
+    if (e.getSource() == updateLangButton)
+      updateLanguage();
     if (e.getSource() == openFolderButton)
       SwingUtil.openOSFolder(getRootPath());
   }

Modified: trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle.properties
===================================================================
--- trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle.properties	2010-06-10 11:12:57 UTC (rev 906)
+++ trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle.properties	2010-06-10 20:15:31 UTC (rev 907)
@@ -218,9 +218,11 @@
 ResourceProviderManagerFrame.RootLang=Root language
 ResourceProviderManagerFrame.AdditionalLang=Additional languages
 ResourceProviderManagerFrame.NewLang=Create new language files...
+ResourceProviderManagerFrame.UpdateLang=Update language files...
 ResourceProviderManagerFrame.OtherLang=<other language>
 ResourceProviderManagerFrame.Language=Language
 ResourceProviderManagerFrame.LanguageCode=Language code
 ResourceProviderManagerFrame.FinishMess=Property files successfully created...
+ResourceProviderManagerFrame.UpdateMess=${0} resource bundles updated...
 
 

Modified: trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle_de.properties
===================================================================
--- trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle_de.properties	2010-06-10 11:12:57 UTC (rev 906)
+++ trunk/src/schmitzm/swing/resource/locales/SwingResourceBundle_de.properties	2010-06-10 20:15:31 UTC (rev 907)
@@ -204,7 +204,9 @@
 ResourceProviderManagerFrame.RootLang=Standard Sprache
 ResourceProviderManagerFrame.AdditionalLang=Weitere Sprachen
 ResourceProviderManagerFrame.NewLang=Neue Sprachdateien anlegen...
+ResourceProviderManagerFrame.UpdateLang=Sprachdateien aktualisieren...
 ResourceProviderManagerFrame.OtherLang=<andere Sprache>
 ResourceProviderManagerFrame.Language=Sprache
 ResourceProviderManagerFrame.LanguageCode=Sprachcode
 ResourceProviderManagerFrame.FinishMess=Property-Dateien erfolgreich erstellt...
+ResourceProviderManagerFrame.UpdateMess=${0} Sprach-Pakete aktualisiert...



More information about the Schmitzm-commits mailing list