Package ch.entwine.weblounge.common.impl.site

Source Code of ch.entwine.weblounge.common.impl.site.I18nDictionaryImpl

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.common.impl.site;

import ch.entwine.weblounge.common.impl.language.LanguageUtils;
import ch.entwine.weblounge.common.impl.util.xml.XMLUtils;
import ch.entwine.weblounge.common.impl.util.xml.XPathHelper;
import ch.entwine.weblounge.common.language.Language;
import ch.entwine.weblounge.common.site.I18nDictionary;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;

/**
* Default implementation of the site specific <code>i18n</code> dictionary.
*/
public class I18nDictionaryImpl implements I18nDictionary {

  /** Logging facility */
  private static final Logger logger = LoggerFactory.getLogger(I18nDictionaryImpl.class);

  /** The i18n directories */
  protected Map<Language, Properties> i18n = new HashMap<Language, Properties>();

  /** The defaults (language neutral) */
  private final Properties defaults = new Properties();

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#add(java.lang.String,
   *      java.lang.String)
   */
  public void add(String key, String value) {
    add(key, value, null);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#add(java.lang.String,
   *      java.lang.String, ch.entwine.weblounge.common.language.Language)
   */
  public void add(String key, String value, Language language) {
    if (key == null)
      throw new IllegalArgumentException("I18n key cannot be null");
    if (value == null)
      throw new IllegalArgumentException("I18n value cannot be null");
    Properties p = null;
    if (language != null) {
      p = i18n.get(language);
      if (p == null) {
        p = new Properties();
        i18n.put(language, p);
      }
    } else {
      p = defaults;
    }
    if (p.get(key) == null) {
      p.put(key, value);
    } else {
      logger.warn("I18n key '{}' already defined", key);
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#get(java.lang.String)
   */
  public String get(String key) {
    return get(key, null);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#get(java.lang.String,
   *      ch.entwine.weblounge.common.language.Language)
   */
  public String get(String key, Language language) {
    Properties p = null;
    if (language != null)
      p = i18n.get(language);

    if (p == null)
      p = defaults;

    String dictEntry = null;
    if (p != null)
      dictEntry = p.getProperty(key);

    // Either return the entry or try the default language fallback
    if (dictEntry != null)
      return dictEntry;
    else {
      dictEntry = defaults.getProperty(key);
      if (dictEntry != null)
        return dictEntry;
    }

    // Last resort: return the key itself
    return key;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#getAsHTML(java.lang.String)
   */
  public String getAsHTML(String key) {
    String value = get(key);
    return value != null ? StringEscapeUtils.escapeHtml(value) : null;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#getAsHTML(java.lang.String,
   *      ch.entwine.weblounge.common.language.Language)
   */
  public String getAsHTML(String key, Language language) {
    String value = get(key, language);
    return value != null ? StringEscapeUtils.escapeHtml(value) : null;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#remove(java.lang.String)
   */
  public void remove(String key) {
    defaults.remove(key);
    for (Properties p : i18n.values()) {
      p.remove(key);
    }
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.site.I18nDictionary#remove(java.lang.String,
   *      ch.entwine.weblounge.common.language.Language)
   */
  public void remove(String key, Language language) {
    Properties p = null;
    if (language != null)
      p = i18n.get(language);
    else
      p = defaults;
    if (p != null)
      p.remove(key);
  }

  /**
   * Adds the the dictionary found in <code>file</code> to the current i18n
   * definitions. The implementation tries to derive the language from the
   * filename, which is expected to be of the form
   * <code>&lt;name&gt;_&lt;language&gt;.xml</code>, where &lt;language&gt; is
   * the ISO language identifier.
   *
   * @param url
   *          the i18n dictionary
   */
  public void addDictionary(URL url) {
    String name = FilenameUtils.getBaseName(url.getFile());
    Language language = null;
    String languageId = null;
    int lidstart = name.indexOf('_') + 1;
    if (lidstart > 0 && lidstart < name.length()) {
      languageId = name.substring(lidstart);
      language = LanguageUtils.getLanguage(languageId);
    }
    addDictionary(url, language);
  }

  /**
   * Adds the the dictionary found in <code>file</code> to the current i18n
   * definitions.
   *
   * @param url
   *          the i18n dictionary
   * @param language
   *          the dictionary language
   */
  public void addDictionary(URL url, Language language) {
    DocumentBuilder docBuilder;
    try {
      docBuilder = XMLUtils.getDocumentBuilder();
      Document doc = docBuilder.parse(url.openStream());

      if (language != null)
        logger.debug("Reading i18n dictionary {} ({})", url.getFile(), language);
      else
        logger.debug("Reading default i18n dictionary {}", url.getFile());

      // Get the target properties

      Properties p = null;
      if (language != null) {
        p = i18n.get(language);
        if (p == null) {
          p = new Properties();
          i18n.put(language, p);
        }
      } else {
        p = defaults;
      }

      int invalidKeys = 0;
      int invalidValues = 0;

      // Read and store the messages

      XPath path = XMLUtils.getXPath();
      NodeList nodes = XPathHelper.selectList(doc, "/resources/string", path);
      for (int j = 0; j < nodes.getLength(); j++) {
        Node messageNode = nodes.item(j);
        String key = XPathHelper.valueOf(messageNode, "@name", path);
        String value = XPathHelper.valueOf(messageNode, "text()", path);
        if (key == null) {
          invalidKeys++;
          continue;
        }
        if (value == null) {
          logger.debug("I18n dictionary {} lacks a value for key '{}'", url, key);
          invalidValues++;
          continue;
        }
        if (p.containsKey(key)) {
          logger.warn("I18n key '{}' redefined in {}", key, url);
        }
        p.put(key, value);
      }

      if (invalidKeys > 0)
        logger.warn("I18n dictionary {} contains {} entries withou a key", url, invalidKeys);
      if (invalidValues > 0)
        logger.warn("I18n dictionary {} contains {} keys without values", url, invalidValues);

    } catch (ParserConfigurationException e) {
      logger.warn("Parser configuration error when reading i18n dictionary {}: {}", url, e.getMessage());
    } catch (SAXException e) {
      logger.warn("SAX exception while parsing i18n dictionary {}: {}", url, e.getMessage());
    } catch (IOException e) {
      logger.warn("IO exception while parsing i18n dictionary {}: {}", url, e.getMessage());
    }
  }

}
TOP

Related Classes of ch.entwine.weblounge.common.impl.site.I18nDictionaryImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.