/* * Copyright 2012 Vincent Lhote * * This library 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.1 of the License, or (at your option) any later version. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package plugin.overland.util; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import org.jdom2.Element; /** * Localized String. This class is used when there is language dependent * information in XML. It stores an element and eventually all of its * translations. If PCGen UI language can only be changed after a restart, the * other language information is not stored to reduce memory usage. * * @author Vincent Lhote * */ // TODO move to pcgen.?.util or gmgen.?.util public class Localized { /** Indicates if the PCGen need to be restarted to change the locale. In that case, no storing of other locale */ private static final boolean NEED_RESTART = true; // ### XML element/attribute ### private static final String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$ private static final String ELEMENT_LOC = "loc"; //$NON-NLS-1$ private static final String ATTRIBUTE_LANGUAGE = "language"; //$NON-NLS-1$ /** used to produce names based on element name when the {@value #ATTRIBUTE_DEFAULTNAME} is missing */ private static Map<String, Integer> unnamedCount = new HashMap<>(); /** This is the default string of the node */ private String defaultName; /** This is a map of the different strings by languages. Not used if {@link #NEED_RESTART} is {@code true}. */ private Map<String, String> languageNames; /** Contains the string for the current locale. Only used if {@link #NEED_RESTART} is {@code true}. */ private String defaultLocaleName; /** * If no attribute is defined, the default name is empty. * @param element * @param attribute if {@code null}, uses the trimmed text of the node. */ public Localized(Element element, String attribute) { if (attribute == null) defaultName = element.getTextTrim(); else defaultName = element.getAttributeValue(attribute); update(element, attribute); } /** * Use a name based on the element name if no {@linkplain #defaultName} is defined. * @param element */ public Localized(Element element) { this(element, ATTRIBUTE_NAME); // use the element name if no default name, and a unique number if (defaultName == null) { String name = element.getName(); Integer i = unnamedCount.get(name); synchronized (unnamedCount) { if (i == null) { i = 1; } else { i += 1; } unnamedCount.put(name, i); } defaultName = element.getName() + i; } } private void addName(String lang, String name) { if (NEED_RESTART && Locale.getDefault().getLanguage().equals(lang)) { defaultLocaleName = name; } else { if (languageNames == null) { languageNames = new HashMap<>(); } languageNames.put(lang, name); } } private String toString(Locale l) { if (languageNames != null) { String lang = l.getLanguage(); if (languageNames.containsKey(lang)) { return languageNames.get(lang); } } return defaultName; } @Override public String toString() { if (NEED_RESTART) { if (defaultLocaleName != null) return defaultLocaleName; else return defaultName; } return toString(Locale.getDefault()); } /** * * @param e * @param attribute if {@code null}, use the trimmed text. */ private void update(Element e, String attribute) { List<?> children = e.getChildren(ELEMENT_LOC); for (Object object : children) { if (object instanceof Element) { Element child = (Element) object; String lang = child.getAttributeValue(ATTRIBUTE_LANGUAGE); String name; if (attribute == null) name = child.getTextTrim(); else name = child.getAttributeValue(attribute); if (lang != null && !lang.isEmpty()) addName(lang, name); } } } }