You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by vg...@apache.org on 2003/11/27 04:41:10 UTC

cvs commit: cocoon-2.2/src/java/org/apache/cocoon/transformation I18nTransformer.java

vgritsenko    2003/11/26 19:41:10

  Modified:    src/java/org/apache/cocoon/transformation
                        I18nTransformer.java
  Log:
  Remove deprecated configuration syntax. Code cleanup.
  
  Revision  Changes    Path
  1.15      +210 -306  cocoon-2.2/src/java/org/apache/cocoon/transformation/I18nTransformer.java
  
  Index: I18nTransformer.java
  ===================================================================
  RCS file: /home/cvs/cocoon-2.2/src/java/org/apache/cocoon/transformation/I18nTransformer.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- I18nTransformer.java	22 Oct 2003 18:07:15 -0000	1.14
  +++ I18nTransformer.java	27 Nov 2003 03:41:10 -0000	1.15
  @@ -90,6 +90,7 @@
    * {@link org.apache.cocoon.acting.LocaleAction#getLocaleAttribute(Map, String) } for details.
    * It then attempts to find a <strong>message catalogue</strong> that satisifies
    * the particular locale, and use it for for text replacement within i18n markup.
  + * 
    * <p>Catalogues are maintained in separate files, with a naming convention
    * similar to that of ResourceBundle (See java.util.ResourceBundle).
    * ie.
  @@ -174,10 +175,11 @@
    *  <li><strong>cache-at-startup</strong>: flag whether to cache
    *      messages at startup (false by default).
    * </ul>
  - * <p>Note: before using multiple catalogues was supported, the catalogue name
  - * and location was specified using elements named <code>catalogue-name</code> and
  - * <code>catalogue-location</code>. This syntax is still supported, but can't be used
  - * concurrently with the new syntax.
  + * 
  + * <p><strong>NOTE:</strong> before using multiple catalogues was supported,
  + * the catalogue name and location was specified using elements named
  + * <code>catalogue-name</code> and <code>catalogue-location</code>. This syntax is
  + * <strong>NOT</strong> supported anymore.
    *
    * <p>To use the transformer in a pipeline, simply specify it in a particular
    * transform. eg:
  @@ -253,7 +255,7 @@
               "http://apache.org/cocoon/i18n/2.0";
   
       /**
  -     * Did we already encountered a old namespace ? This is static to ensure that
  +     * Did we already encountered an old namespace? This is static to ensure that
        * the associated message will be logged only once.
        */
       private static boolean deprecationFound = false;
  @@ -703,12 +705,6 @@
        */
       public static final String I18N_FRACTION_DIGITS_ATTRIBUTE = "fraction-digits";
   
  -    // NOP Validity object: i18n transformer is cached forever
  -    // FIXME (KP): Cache validity should be generated by
  -    // Bundle implementations.
  -    private static final SourceValidity I18N_NOP_VALIDITY =
  -            new org.apache.excalibur.source.impl.validity.NOPValidity();
  -
       // States of the transformer
       private static final int STATE_OUTSIDE                       = 0;
       private static final int STATE_INSIDE_TEXT                   = 10;
  @@ -722,6 +718,7 @@
       private static final int STATE_INSIDE_TIME                   = 62;
       private static final int STATE_INSIDE_NUMBER                 = 63;
   
  +
       // All date-time related parameter types and element names
       private static final Set dateTypes;
   
  @@ -733,14 +730,14 @@
   
       static {
           // initialize date types set
  -        HashSet set = new HashSet();
  +        HashSet set = new HashSet(5);
           set.add(I18N_DATE_ELEMENT);
           set.add(I18N_TIME_ELEMENT);
           set.add(I18N_DATE_TIME_ELEMENT);
           dateTypes = Collections.unmodifiableSet(set);
   
           // initialize number types set
  -        set = new HashSet();
  +        set = new HashSet(9);
           set.add(I18N_NUMBER_ELEMENT);
           set.add(I18N_PERCENT_ELEMENT);
           set.add(I18N_CURRENCY_ELEMENT);
  @@ -750,7 +747,7 @@
           numberTypes = Collections.unmodifiableSet(set);
   
           // Initialize date patterns map
  -        Map map = new HashMap();
  +        Map map = new HashMap(7);
           map.put("SHORT", new Integer(DateFormat.SHORT));
           map.put("MEDIUM", new Integer(DateFormat.MEDIUM));
           map.put("LONG", new Integer(DateFormat.LONG));
  @@ -758,6 +755,7 @@
           datePatterns = Collections.unmodifiableMap(map);
       }
   
  +
       // Component manager for this component
       protected ServiceManager manager;
   
  @@ -834,12 +832,6 @@
       // i18n configuration variables
       //
   
  -    // Catalogue name value
  -    private String catalogueName;
  -
  -    // Catalogue location value
  -    private String catalogueLocation;
  -
       // id of the default catalogue
       private String defaultCatalogueId;
   
  @@ -855,6 +847,7 @@
       // Helper variable used to hold the old untranslated value
       private String globalUntranslated;
   
  +
       /**
        * Returns the current locale setting of this transformer instance.
        * @return current Locale object
  @@ -868,7 +861,22 @@
        * Generates unique key for the current locale.
        */
       public java.io.Serializable getKey() {
  -        return catalogueLocation + '/' + catalogueName + '?' + this.locale;
  +        // TODO: Key should be composed out of used catalogues locations, and locale.
  +        //       Right now it is hardcoded only to default catalogue location.
  +        CatalogueInfo catalogueInfo = (CatalogueInfo)catalogues.get(defaultCatalogueId);
  +        StringBuffer key = new StringBuffer();
  +        if (catalogueInfo != null) {
  +            key.append(catalogueInfo.resolvedLocation);
  +        }
  +        key.append("?");
  +        if (locale != null) {
  +            key.append(locale.getLanguage());
  +            key.append("_");
  +            key.append(locale.getCountry());
  +            key.append("_");
  +            key.append(locale.getVariant());
  +        }
  +        return key.toString();
       }
   
       /**
  @@ -877,21 +885,22 @@
        * if this instance is not cacheable.
        */
       public SourceValidity getValidity() {
  -        return I18N_NOP_VALIDITY;
  +        // FIXME (KP): Cache validity should be generated by
  +        // Bundle implementations.
  +        return org.apache.excalibur.source.impl.validity.NOPValidity.SHARED_INSTANCE;
       }
   
       /**
        * Implementation of composable interface.
        * Looksup the Bundle Factory to be used.
        */
  -    public void service(ServiceManager manager) {
  +    public void service(ServiceManager manager) throws ServiceException {
           this.manager = manager;
           try {
               this.factory = (BundleFactory)manager.lookup(BundleFactory.ROLE);
  -
  -            debug("BundleFactory is obtained");
  -        } catch (ServiceException ce) {
  -            this.getLogger().error("BundleFactory is not loaded", ce);
  +        } catch (ServiceException e) {
  +            getLogger().debug("Failed to load BundleFactory", e);
  +            throw e;
           }
       }
   
  @@ -900,71 +909,44 @@
        * Configure this transformer.
        */
       public void configure(Configuration conf) throws ConfigurationException {
  -        if (factory == null) {
  -            throw new ConfigurationException("BundleFactory component is not found.");
  -        }
           // read in the config options from the transformer definition
  -
  -        // there are two possible configuration methods:
  -        //  (1) the one dating from before multiple catalogues were supported:
  -        //      in this case the elements catalogue-name and catalogue-location specify
  -        //      the catalogue to be used
  -        //  (2) the new one supporting mulitple catalogues
  -
  -        // obtain the base name of the message catalogue
  -        Configuration child = conf.getChild(I18N_CATALOGUE_NAME);
  -        catalogueName = child.getValue(null);
  -
  -        // obtain the directory location of message catalogues
  -        child = conf.getChild(I18N_CATALOGUE_LOCATION);
  -        catalogueLocation = child.getValue(null);
  -
           Configuration cataloguesConf = conf.getChild("catalogues", false);
   
  -        if ((catalogueName != null || catalogueLocation != null) && cataloguesConf != null) {
  -            // if old and new style configuration are used at the same time...
  -            throw new ConfigurationException("I18nTransformer: old and new configuration style are used at the same time. Use either the 'catalogue-name' and 'catalogue-location' elements or use the 'catalogues' element, but don't use both at the same time.");
  -        } else if (catalogueName != null || catalogueLocation != null) {
  -            if (!(catalogueName != null && catalogueLocation != null))
  -                throw new ConfigurationException("I18nTransformer: catalogue-name and catalogue-location must both be specified");
  -            if (getLogger().isDebugEnabled())
  -                getLogger().debug("using old-style configuration: name = " + catalogueName
  -                        + ", location = " + catalogueLocation);
  -        } else if (cataloguesConf == null) {
  -            // if both old and new style configuration are missing ...
  -            throw new ConfigurationException("Missing configuration for the I18nTransformer: a 'catalogues' element specifying the catalogues is required.");
  -        } else {
  -            // new configuration style
  -            Configuration[] catalogueConfs = cataloguesConf.getChildren("catalogue");
  -            for (int i = 0; i < catalogueConfs.length; i++) {
  -                String id = catalogueConfs[i].getAttribute("id");
  -                String name = catalogueConfs[i].getAttribute("name");
  -                String location = catalogueConfs[i].getAttribute("location");
  -                CatalogueInfo newCatalogueInfo;
  -                try {
  -                    newCatalogueInfo = new CatalogueInfo(name, location);
  -                } catch (PatternException e) {
  -                    throw new ConfigurationException("I18nTransformer: error in name or location attribute on catalogue element with id " + id, e);
  -                }
  -                catalogues.put(id, newCatalogueInfo);
  -            }
  +        // new configuration style
  +        Configuration[] catalogueConfs = cataloguesConf.getChildren("catalogue");
  +        for (int i = 0; i < catalogueConfs.length; i++) {
  +            String id = catalogueConfs[i].getAttribute("id");
  +            String name = catalogueConfs[i].getAttribute("name");
  +            String location = catalogueConfs[i].getAttribute("location");
  +            CatalogueInfo newCatalogueInfo;
  +            try {
  +                newCatalogueInfo = new CatalogueInfo(name, location);
  +            } catch (PatternException e) {
  +                throw new ConfigurationException("I18nTransformer: error in name or location " +
  +                                                 "attribute on catalogue element with id " + id, e);
  +            }
  +            catalogues.put(id, newCatalogueInfo);
  +        }
   
  -            defaultCatalogueId = cataloguesConf.getAttribute("default");
  -            if (!catalogues.containsKey(defaultCatalogueId))
  -                throw new ConfigurationException("I18nTransformer: default catalogue id '" + defaultCatalogueId + "' denotes a nonexisting catalogue");
  +        this.defaultCatalogueId = cataloguesConf.getAttribute("default");
  +        if (!catalogues.containsKey(this.defaultCatalogueId)) {
  +            throw new ConfigurationException("I18nTransformer: default catalogue id '" +
  +                                             this.defaultCatalogueId + "' denotes a nonexisting catalogue");
           }
   
           // obtain default text to use for untranslated messages
  -        child = conf.getChild(I18N_UNTRANSLATED);
  -        untranslated = child.getValue(null);
  -        debug("Default untranslated text is '" + untranslated + "'");
  +        untranslated = conf.getChild(I18N_UNTRANSLATED).getValue(null);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("Default untranslated text is '" + untranslated + "'");
  +        }
   
           // obtain config option, whether to cache messages at startup time
  -        child = conf.getChild(I18N_CACHE_STARTUP);
  -        cacheAtStartup = child.getValueAsBoolean(false);
  -        debug((cacheAtStartup ? "will" : "won't") +
  +        cacheAtStartup = conf.getChild(I18N_CACHE_STARTUP).getValueAsBoolean(false);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug((cacheAtStartup ? "will" : "won't") +
                 " cache messages during startup, by default"
  -        );
  +            );
  +        }
       }
   
       /**
  @@ -972,25 +954,18 @@
        */
       public void setup(SourceResolver resolver, Map objectModel, String source,
                         Parameters parameters)
  -            throws ProcessingException, SAXException, IOException {
  +    throws ProcessingException, SAXException, IOException {
   
           this.sourceResolver = resolver;
           this.objectModel = objectModel;
   
           try {
               // check parameters to see if anything has been locally overloaded
  -            String localCatLocation = null;
  -            String localCatName = null;
               String localUntranslated = null;
               String lc = null;
               String localDefaultCatalogueId = null;
   
               if (parameters != null) {
  -                // localCatLocation and localCatName are to support old-style configuration
  -                localCatLocation =
  -                        parameters.getParameter(I18N_CATALOGUE_LOCATION, null);
  -                localCatName =
  -                        parameters.getParameter(I18N_CATALOGUE_NAME, null);
                   localUntranslated =
                           parameters.getParameter(I18N_UNTRANSLATED, null);
                   lc = parameters.getParameter(I18N_LOCALE, null);
  @@ -1011,8 +986,9 @@
   
               // Get current locale
               Locale locale = I18nUtils.parseLocale(lc);
  -            if (getLogger().isDebugEnabled())
  -                debug("using locale " + locale.toString());
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("Using locale " + locale.toString());
  +            }
   
               // Initialize instance state variables
               this.locale             = locale;
  @@ -1033,99 +1009,39 @@
   
               // give the defaultCatalogue variable its value -- first look if it's locally overridden
               // and otherwise use the component-wide defaults.
  -            if (localCatLocation != null || localCatName != null) {
  -                // first local old configuration style
  -                localCatName = localCatName != null ? localCatName : catalogueName;
  -                localCatLocation = localCatLocation != null ? localCatLocation : catalogueLocation;
  -                if (localCatName == null || localCatLocation == null)
  -                    throw new ProcessingException("I18nTransformer: incorrect usage: either catalogue-name or catalogue-location are not specified.");
  -                defaultCatalogue = getCatalogue(localCatName, localCatLocation);
  -            } else if ((localDefaultCatalogueId != null || localCatLocation != null) && localCatName != null) {
  -                // throw error if old and new configuration style are used at the same time
  -                throw new ProcessingException("I18nTransformer: either specify 'catalogue-name' and 'catalogue-location' or specify 'default-catalogue-id', but don't mix the two configuration styles.");
  -            } else if (localDefaultCatalogueId != null) {
  +            if (localDefaultCatalogueId != null) {
                   // then if new local configuration style
                   CatalogueInfo catalogueInfo = (CatalogueInfo)catalogues.get(localDefaultCatalogueId);
  -                if (catalogueInfo == null)
  -                    throw new ProcessingException("I18nTransformer: '" + localDefaultCatalogueId + "' is not an existing catalogue id.");
  +                if (catalogueInfo == null) {
  +                    throw new ProcessingException("I18nTransformer: '" +
  +                                                  localDefaultCatalogueId +
  +                                                  "' is not an existing catalogue id.");
  +                }
                   defaultCatalogue = catalogueInfo.getCatalogue();
  -            } else if (catalogueName != null && catalogueLocation != null) {
  -                // then global old configuration style
  -                defaultCatalogue = getCatalogue(catalogueName, catalogueLocation);
               } else {
  -                // then global new configuration style
                   defaultCatalogue = ((CatalogueInfo)catalogues.get(defaultCatalogueId)).getCatalogue();
               }
  -            if (getLogger().isDebugEnabled())
  -                getLogger().debug("using default catalogue " + defaultCatalogue);
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("Using default catalogue " + defaultCatalogue);
  +            }
   
               // Create and initialize a formatter
               this.formatter = new MessageFormat("");
               this.formatter.setLocale(locale);
  -
           } catch (Exception e) {
  -            debug("exception generated, leaving unconfigured");
  +            getLogger().debug("exception generated, leaving unconfigured");
               throw new ProcessingException(e.getMessage(), e);
           }
       }
   
  -    private Bundle getCatalogue(String name, String location) throws Exception
  -    {
  -        synchronized (factory) {
  -            configureFactory(location);
  -            return (Bundle)factory.select(name, locale);
  -        }
  -    }
  -
  -    /**
  -     * Internal setup of XML resource factory.
  -     *
  -     * REVISIT (MC): when we can get the resolver anywhere, we can pass the
  -     * configuration object directly to XMLResourceBundle.
  -     */
  -    protected void configureFactory(String location) throws Exception {
  -        // configure the factory to log correctly and cache catalogues
  -        DefaultConfiguration configuration =
  -                new DefaultConfiguration("name", "location");
  -        DefaultConfiguration cacheConf =
  -                new DefaultConfiguration(
  -                        BundleFactory.ConfigurationKeys.CACHE_AT_STARTUP,
  -                        "location"
  -                );
  -        cacheConf.setValue(new Boolean(cacheAtStartup).toString());
  -        configuration.addChild(cacheConf);
  -
  -        // set the root location for message catalogues
  -        DefaultConfiguration dirConf =
  -                new DefaultConfiguration(
  -                        BundleFactory.ConfigurationKeys.ROOT_DIRECTORY,
  -                        "location"
  -                );
  -
  -        debug("catalog location:" + location);
  -        Source source = null;
  -        try {
  -            source = sourceResolver.resolveURI(location);
  -            String systemId = source.getURI();
  -            debug("catalog directory:" + systemId);
  -            dirConf.setValue(systemId);
  -            configuration.addChild(dirConf);
  -        } finally {
  -            if (source != null)
  -                sourceResolver.release(source);
  -        }
  -
  -        // Pass created configuration object to the factory
  -        ((Configurable)factory).configure(configuration);
  -        debug("factory configured");
  -    }
   
       //
       // Standard SAX event handlers
       //
   
       public void startElement(String uri, String name, String raw,
  -                             Attributes attr) throws SAXException {
  +                             Attributes attr)
  +    throws SAXException {
   
           // Handle previously buffered characters
           if (current_state != STATE_OUTSIDE && strBuffer != null) {
  @@ -1134,21 +1050,27 @@
           }
   
           // Process start element event
  -        if (I18N_OLD_NAMESPACE_URI.equals(uri)) {
  +        if (I18N_NAMESPACE_URI.equals(uri)) {
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("Starting i18n element: " + name);
  +            }
  +            startI18NElement(name, attr);
  +
  +        } else if (I18N_OLD_NAMESPACE_URI.equals(uri)) {
               if (!deprecationFound) {
                   deprecationFound = true;
  -                this.getLogger().warn("The namespace '"
  -                                      + I18N_OLD_NAMESPACE_URI
  -                                      + "' for i18n is not supported any more, use: '"
  -                                      + I18N_NAMESPACE_URI + "'");
  +                getLogger().warn("The namespace '" +
  +                                 I18N_OLD_NAMESPACE_URI +
  +                                 "' for i18n is deprecated, use: '" +
  +                                 I18N_NAMESPACE_URI + "'");
  +            }
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("Starting deprecated i18n element: " + name);
               }
  -            debug("Starting deprecated i18n element: " + name);
               startI18NElement(name, attr);
   
  -        } else if (I18N_NAMESPACE_URI.equals(uri)) {
  -            debug("Starting i18n element: " + name);
  -            startI18NElement(name, attr);
  -        } else { // We have a non i18n element event
  +        } else {
  +            // We have a non i18n element event
               if (current_state == STATE_OUTSIDE) {
                   super.startElement(uri, name, raw,
                                      translateAttributes(name, attr));
  @@ -1215,7 +1137,9 @@
       private void startI18NElement(String name, Attributes attr)
               throws SAXException {
   
  -        debug("Start i18n element: " + name);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("Start i18n element: " + name);
  +        } 
   
           if (I18N_TEXT_ELEMENT.equals(name)) {
               if (current_state != STATE_OUTSIDE
  @@ -1247,15 +1171,14 @@
                   // Try the namespaced attribute
                   currentCatalogueId = attr.getValue(I18N_NAMESPACE_URI, I18N_CATALOGUE_ATTRIBUTE);
               }
  -            if (prev_state != STATE_INSIDE_PARAM)
  +            if (prev_state != STATE_INSIDE_PARAM) {
                   tr_text_recorder = null;
  +            }
   
               if (current_key != null) {
                   tr_text_recorder = getMirrorRecorder(current_key, null);
  -                //debug("Got translation: " + tr_text_recorder);
               }
   
  -
           } else if (I18N_TRANSLATE_ELEMENT.equals(name)) {
               if (current_state != STATE_OUTSIDE) {
                   throw new SAXException(
  @@ -1332,7 +1255,9 @@
   
                   // Perform soft locale matching
                   if (this.locale.toString().startsWith(locale)) {
  -                    debug("Locale matching: " + locale);
  +                    if (getLogger().isDebugEnabled()) {
  +                        getLogger().debug("Locale matching: " + locale);
  +                    }
                       translate_copy = true;
                   }
               }
  @@ -1349,9 +1274,10 @@
                   );
               }
   
  -            debug("Matching any locale");
  -            if (!translate_end)
  +            getLogger().debug("Matching any locale");
  +            if (!translate_end) {
                   translate_copy = true;
  +            }
   
               prev_state = current_state;
               current_state = STATE_INSIDE_OTHERWISE;
  @@ -1461,7 +1387,9 @@
       }
   
       private void endI18NElement(String name) throws SAXException {
  -        debug("End i18n element: " + name);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("End i18n element: " + name);
  +        }
           switch (current_state) {
               case STATE_INSIDE_TEXT:
                   endTextElement();
  @@ -1497,7 +1425,7 @@
       }
   
       private void i18nCharacters(String textValue)
  -            throws SAXException {
  +    throws SAXException {
   
           if (textValue == null) {
               return;
  @@ -1507,7 +1435,9 @@
           if (textValue.length() == 0)
               return;
   
  -        debug( "i18n message text = '" + textValue + "'" );
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug( "i18n message text = '" + textValue + "'" );
  +        }
   
           switch (current_state) {
               case STATE_INSIDE_TEXT:
  @@ -1532,7 +1462,7 @@
   
               case STATE_INSIDE_CHOOSE:
                   // No characters allowed. Send an exception ?
  -                debug("No characters allowed inside <i18n:choose> tags");
  +                getLogger().debug("No characters allowed inside <i18n:choose> tags");
                   break;
   
               case STATE_INSIDE_DATE:
  @@ -1557,15 +1487,15 @@
       // Translate all attributes that are listed in i18n:attr attribute
       private Attributes translateAttributes(String name, Attributes attr) {
   
  -        if(attr == null)
  +        if (attr == null) {
               return attr;
  +        }
   
           AttributesImpl temp_attr = new AttributesImpl(attr);
   
           // Translate all attributes from i18n:attr="name1 name2 ..."
           // using their values as keys
           int i18n_attr_index = temp_attr.getIndex(I18N_NAMESPACE_URI,I18N_ATTR_ATTRIBUTE);
  -
           if (i18n_attr_index == -1) {
               // Try the old namespace
               i18n_attr_index = temp_attr.getIndex(I18N_OLD_NAMESPACE_URI,I18N_ATTR_ATTRIBUTE);
  @@ -1588,8 +1518,7 @@
                       // the colon denotes a catalogue id
                       int colonPos = text2translate.indexOf(":");
                       String catalogueId = null;
  -                    if (colonPos != -1)
  -                    {
  +                    if (colonPos != -1) {
                           catalogueId = text2translate.substring(0, colonPos);
                           text2translate = text2translate.substring(colonPos + 1, text2translate.length());
                       }
  @@ -1629,8 +1558,9 @@
                           tr_text_recorder = getMirrorRecorder(text_recorder.text(), text_recorder);
                       } else {
                           // We have the key, but couldn't find a transltation
  -                        if (getLogger().isDebugEnabled())
  -                            debug("translation not found for key " + current_key);
  +                        if (getLogger().isDebugEnabled()) {
  +                            getLogger().debug("translation not found for key " + current_key);
  +                        }
                           // use the untranslated-text only when the content of the i18n:text
                           // element was empty
                           if (text_recorder.empty() && untranslatedRecorder != null) {
  @@ -1684,30 +1614,39 @@
           if (paramType != null) {
               // We have a typed parameter
   
  -            debug("Param type: " + paramType);
  -            if (formattingParams.get(I18N_VALUE_ATTRIBUTE) == null &&
  -                    param_value != null) {
  -
  -                debug("Put param value: " + param_value);
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("Param type: " + paramType);
  +            }
  +            if (formattingParams.get(I18N_VALUE_ATTRIBUTE) == null && param_value != null) {
  +                if (getLogger().isDebugEnabled()) {
  +                    getLogger().debug("Put param value: " + param_value);
  +                }
                   formattingParams.put(I18N_VALUE_ATTRIBUTE, param_value);
               }
   
               // Check if we have a date or a number parameter
               if (dateTypes.contains(paramType)) {
  -                debug("Formatting date_time param: " + formattingParams);
  +                if (getLogger().isDebugEnabled()) {
  +                    getLogger().debug("Formatting date_time param: " + formattingParams);
  +                }
                   param_value = formatDate_Time(formattingParams);
               } else if (numberTypes.contains(paramType)) {
  -                debug("Formatting number param: " + formattingParams);
  +                if (getLogger().isDebugEnabled()) {
  +                    getLogger().debug("Formatting number param: " + formattingParams);
  +                }
                   param_value = formatNumber(formattingParams);
               }
  -            debug("Added substitution param: " + param_value);
  +            if (getLogger().isDebugEnabled()) {
  +                getLogger().debug("Added substitution param: " + param_value);
  +            }
           }
   
           param_value = null;
           current_state = STATE_INSIDE_TRANSLATE;
   
  -        if(param_recorder == null)
  +        if(param_recorder == null) {
               return;
  +        }
   
           indexedParams.put(param_name, param_recorder.clone());
       }
  @@ -1715,8 +1654,8 @@
       private void endTranslateElement() throws SAXException {
           if (tr_text_recorder != null) {
               if (getLogger().isDebugEnabled()) {
  -                debug("End of translate with params");
  -                debug("Fragment for substitution : " + tr_text_recorder.text());
  +                getLogger().debug("End of translate with params");
  +                getLogger().debug("Fragment for substitution : " + tr_text_recorder.text());
               }
               tr_text_recorder.send(super.contentHandler, indexedParams);
               tr_text_recorder = null;
  @@ -1875,8 +1814,10 @@
           }
   
           // we have all necessary data here: do formatting.
  -        debug("### Formatting date: " + dateValue + " with localized pattern "
  -              + to_fmt.toLocalizedPattern() + " for locale: " + locale);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("### Formatting date: " + dateValue + " with localized pattern " +
  +                              to_fmt.toLocalizedPattern() + " for locale: " + locale);
  +        }
           return to_fmt.format(dateValue);
       }
   
  @@ -1915,15 +1856,15 @@
           // type
           String type = (String)params.get(I18N_TYPE_ATTRIBUTE);
   
  -         // fraction-digits
  -         int fractionDigits = -1;
  -         try {
  -             String fd = (String)params.get(I18N_FRACTION_DIGITS_ATTRIBUTE);
  -             if (fd != null)
  -                 fractionDigits = Integer.parseInt(fd);
  -         } catch (NumberFormatException nfe) {
  -             getLogger().warn("Error in number format with fraction-digits", nfe);
  -         }
  +        // fraction-digits
  +        int fractionDigits = -1;
  +        try {
  +            String fd = (String)params.get(I18N_FRACTION_DIGITS_ATTRIBUTE);
  +            if (fd != null)
  +                fractionDigits = Integer.parseInt(fd);
  +        } catch (NumberFormatException nfe) {
  +            getLogger().warn("Error in number format with fraction-digits", nfe);
  +        }
   
           // parsed number
           Number numberValue = null;
  @@ -1963,7 +1904,6 @@
               to_fmt.setMaximumFractionDigits(309);
               for (int i = value.length() - 1;
                    i >= 0 && value.charAt(i) != dec; i--, decAt++) {
  -
               }
   
               if (decAt < value.length())to_fmt.setMinimumFractionDigits(decAt);
  @@ -2047,49 +1987,70 @@
           // we have all necessary data here: do formatting.
           String result = to_fmt.format(numberValue);
           if (appendDec) result = result + dec;
  -        debug("i18n:number result: " + result);
  +        if (getLogger().isDebugEnabled()) {
  +            getLogger().debug("i18n:number result: " + result);
  +        }
           return result;
       }
   
       //-- Dictionary handling routins
   
       /**
  -     * Helper method to retrieve a message from the dictionary.
  -     * mattam: now only used for i:attr.
  -     * A default value is returned if message is not found
  +     * Helper method to retrieve a message Node from the dictionary.
  +     * A default value is returned if message is not found.
        *
        * @param catalogueId if not null, this catalogue will be used instead of the default one.
        */
  -    private String getString(String key, String catalogueId, String defaultValue) {
  +    private Node getNode(String catalogueId, String key) {
           try {
               Bundle catalogue = defaultCatalogue;
               if (catalogueId != null) {
                   CatalogueInfo catalogueInfo = (CatalogueInfo)catalogues.get(catalogueId);
                   if (catalogueInfo == null) {
  -                    if (getLogger().isDebugEnabled())
  -                        debug("Catalogue not found: " + catalogueId + ", could not translate key " + key);
  -                    return defaultValue;
  +                    if (getLogger().isDebugEnabled()) {
  +                        getLogger().debug("Catalogue not found: " + catalogueId +
  +                                          ", could not translate key " + key);
  +                    }
  +                    return null;
                   }
                   try {
                       catalogue = catalogueInfo.getCatalogue();
                   } catch (Exception e) {
  -                    getLogger().error("Error getting catalogue " + catalogueInfo.getName() + " from location " + catalogueInfo.getLocation() + " for locale " + locale + ", will not translate key " + key);
  -                    return defaultValue;
  +                    getLogger().error("Error getting catalogue " + catalogueInfo.getName() +
  +                                      " from location " + catalogueInfo.getLocation() +
  +                                      " for locale " + locale +
  +                                      ", will not translate key " + key);
  +                    return null;
                   }
               }
  -            Node res = (Node)catalogue.getObject(
  -                    I18N_CATALOGUE_PREFIX + "[@key='" + key + "']");
  -
  -            String value = getTextValue(res);
  -            return value != null ? value : defaultValue;
  +            return (Node)catalogue.getObject(I18N_CATALOGUE_PREFIX +
  +                                             "[@key='" + key + "']");
           } catch (MissingResourceException e)  {
  +            getLogger().debug("Untranslated key: '" + key + "'");
  +            return null;
  +        }
  +    }
  +
  +    /**
  +     * Helper method to retrieve a message from the dictionary.
  +     * mattam: now only used for i:attr.
  +     * A default value is returned if message is not found
  +     *
  +     * @param catalogueId if not null, this catalogue will be used instead of the default one.
  +     */
  +    private String getString(String key, String catalogueId, String defaultValue) {
  +        final Node res = getNode(catalogueId, key);
  +        if (res == null) {
               return defaultValue;
           }
  +        return getTextValue(res);
       }
   
       // Helper method to get the text value of the node.
       private static String getTextValue(Node node) {
  -        if (node == null) return null;
  +        if (node == null) {
  +            return null;
  +        } 
   
           NodeList list = node.getChildNodes();
           int listsize = list.getLength();
  @@ -2108,49 +2069,24 @@
           return itemValue.toString();
       }
   
  -    // Helper method to retrieve a message from the dictionary.
  -    // A default value is returned if message is not found
  +    /**
  +     * Helper method to retrieve a message from the dictionary.
  +     * A default value is returned if message is not found.
  +     */ 
       private MirrorRecorder getMirrorRecorder(String key, MirrorRecorder defaultValue) {
  -        try {
  -            Bundle catalogue = defaultCatalogue;
  -            if (currentCatalogueId != null) {
  -                CatalogueInfo catalogueInfo = (CatalogueInfo)catalogues.get(currentCatalogueId);
  -                if (catalogueInfo == null) {
  -                    if (getLogger().isDebugEnabled())
  -                        debug("Catalogue not found: " + currentCatalogueId + ", could not translate key " + key);
  -                    return defaultValue;
  -                }
  -                try {
  -                    catalogue = catalogueInfo.getCatalogue();
  -                } catch (Exception e) {
  -                    getLogger().error("Error getting catalogue " + catalogueInfo.getName() + " from location " + catalogueInfo.getLocation() + " for locale " + locale + ", will not translate key " + key);
  -                    return defaultValue;
  -                }
  -            }
  -            MirrorRecorder value = new MirrorRecorder (
  -                    (Node)catalogue.getObject(
  -                            I18N_CATALOGUE_PREFIX + "[@key='" + key + "']"));
  -
  -            if (value == null)
  -                return defaultValue;
  -
  -            return value;
  -
  -        } catch (MissingResourceException e) {
  -            debug("Untranslated key: '" + key + "'");
  +        Node value = getNode(currentCatalogueId, key);
  +        if (value == null) {
               return defaultValue;
           }
  -    }
   
  -    // Helper method to debug messages
  -    private void debug(String msg) {
  -        getLogger().debug("I18nTransformer: " + msg);
  +        return new MirrorRecorder(value);
       }
   
       public void reset() {
           // restore untranslated-text if necessary
  -        if (globalUntranslated != null)
  +        if (globalUntranslated != null) {
               untranslated = globalUntranslated;
  +        }
           untranslatedRecorder = null;
   
           // clean up default catalogue
  @@ -2159,8 +2095,7 @@
   
           // clean up the other catalogues
           Iterator catalogueIt = catalogues.values().iterator();
  -        while (catalogueIt.hasNext())
  -        {
  +        while (catalogueIt.hasNext()) {
               CatalogueInfo catalogueInfo = (CatalogueInfo)catalogueIt.next();
               catalogueInfo.releaseCatalog();
           }
  @@ -2203,61 +2138,30 @@
               return resolvedLocation;
           }
   
  -        private void resolve() throws PatternException {
  -            if (resolvedLocation == null)
  +        private void resolve() throws Exception {
  +            if (resolvedLocation == null) {
                   resolvedLocation = location.resolve(null, objectModel);
  -            if (resolvedName == null)
  +            }
  +            if (resolvedName == null) {
                   resolvedName = name.resolve(null, objectModel);
  +            }
           }
   
           public Bundle getCatalogue() throws Exception {
               if (catalogue == null) {
                   resolve();
  -                synchronized(factory) {
  -                    configureFactory(resolvedLocation);
  -                    catalogue = (Bundle)factory.select(resolvedName, locale);
  -                }
  +                catalogue = (Bundle) factory.select(resolvedLocation, resolvedName, locale);
               }
               return catalogue;
           }
   
           public void releaseCatalog() {
  -            // would it be necessary to first configure the factory here?
  -            if (catalogue != null)
  +            if (catalogue != null) {
                   factory.release(catalogue);
  +            }
               catalogue = null;
               resolvedName = null;
               resolvedLocation = null;
           }
       }
  -
  -/*
  -    static public void main(String[] args) {
  -        Locale locale = null;
  -        Locale[] locales = Locale.getAvailableLocales();
  -
  -        for (int i = 0; i < locales.length; i++) {
  -            locale = locales[i];n
  -            SimpleDateFormat fmt =
  -                    (SimpleDateFormat)DateFormat.getDateTimeInstance(
  -                            DateFormat.DEFAULT,
  -                            DateFormat.DEFAULT,
  -                            locale
  -                    );
  -
  -            String localized = fmt.format(new Date());
  -            NumberFormat n_fmt = NumberFormat.getCurrencyInstance(locale);
  -            String money = n_fmt.format(1210.5);
  -
  -            System.out.println(
  -                    "Locale ["
  -                    + locale.getLanguage() + ", "
  -                    + locale.getCountry() + ", "
  -                    + locale.getVariant() + "] : "
  -                    + locale.getDisplayName()
  -                    + " \t Date: " + localized
  -                    + " \t Money: " + money);
  -        }
  -    }
  -*/
   }