/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.viewpoint;
import java.text.Collator;
import java.util.Collections;
import java.util.Comparator;
import java.util.Hashtable;
import java.util.Vector;
import java.util.logging.Logger;
import org.openflexo.antar.binding.BindingModel;
import org.openflexo.foundation.viewpoint.ViewPoint.ViewPointBuilder;
import org.openflexo.foundation.viewpoint.inspector.InspectorEntry;
import org.openflexo.localization.FlexoLocalization;
import org.openflexo.localization.Language;
import org.openflexo.localization.LocalizedDelegate;
public class LocalizedDictionary extends ViewPointObject implements LocalizedDelegate {
private static final Logger logger = Logger.getLogger(LocalizedDictionary.class.getPackage().getName());
private ViewPoint _calc;
private Vector<LocalizedEntry> _entries;
private final Hashtable<Language, Hashtable<String, String>> _values;
private Vector<DynamicEntry> dynamicEntries = null;
public LocalizedDictionary(ViewPointBuilder builder) {
super(builder);
_entries = new Vector<LocalizedEntry>();
_values = new Hashtable<Language, Hashtable<String, String>>();
if (builder != null) {
_calc = builder.getViewPoint();
}
}
@Override
public ViewPoint getViewPoint() {
return _calc;
}
public void setCalc(ViewPoint calc) {
_calc = calc;
}
public Vector<LocalizedEntry> getEntries() {
return _entries;
}
public void setEntries(Vector<LocalizedEntry> someEntries) {
_entries = someEntries;
}
public void addToEntries(LocalizedEntry entry) {
entry.setLocalizedDictionary(this);
_entries.add(entry);
logger.fine("Add entry key:" + entry.getKey() + " lang=" + entry.getLanguage() + " value:" + entry.getValue());
Language lang = Language.retrieveLanguage(entry.getLanguage());
if (lang == null) {
logger.warning("Undefined language: " + entry.getLanguage());
return;
}
getDictForLang(lang).put(entry.getKey(), entry.getValue());
}
public void removeFromEntries(LocalizedEntry entry) {
entry.setLocalizedDictionary(null);
_entries.remove(entry);
}
private LocalizedEntry getEntry(Language language, String key) {
for (LocalizedEntry entry : getEntries()) {
if (Language.retrieveLanguage(entry.getLanguage()) == language && key.equals(entry.getKey())) {
return entry;
}
}
return null;
}
private Hashtable<String, String> getDictForLang(Language lang) {
Hashtable<String, String> dict = _values.get(lang);
if (dict == null) {
dict = new Hashtable<String, String>();
_values.put(lang, dict);
}
return dict;
}
@Override
public String getInspectorName() {
// TODO Auto-generated method stub
return null;
}
/*public String getDefaultValue(String key, Language language) {
// logger.info("Searched default value for key "+key+" return "+FlexoLocalization.localizedForKey(key));
if (getParent() != null) {
return FlexoLocalization.localizedForKeyAndLanguage(getParent(), key, language);
}
return key;
}*/
@Override
public String getLocalizedForKeyAndLanguage(String key, Language language) {
// if (isSearchingNewEntries) logger.info("-------> called localizedForKeyAndLanguage() key="+key+" lang="+language);
return getDictForLang(language).get(key);
/*String returned = getDictForLang(language).get(key);
if (returned == null) {
String defaultValue = getDefaultValue(key, language);
if (handleNewEntry(key, language)) {
if (!key.equals(defaultValue)) {
addToEntries(new LocalizedEntry(this, key, language.getName(), defaultValue));
logger.fine("Calc LocalizedDictionary: store value " + defaultValue + " for key " + key + " for language " + language);
} else {
getDictForLang(language).put(key, defaultValue);
logger.fine("Calc LocalizedDictionary: undefined value for key " + key + " for language " + language);
}
// dynamicEntries = null;
}
return defaultValue;
}
return returned;*/
}
public void setLocalizedForKeyAndLanguage(String key, String value, Language language) {
getDictForLang(language).put(key, value);
LocalizedEntry entry = getEntry(language, key);
if (entry == null) {
addToEntries(new LocalizedEntry(this, key, language.getName(), value));
} else {
entry.setValue(value);
}
}
private boolean handleNewEntry = false;
@Override
public boolean handleNewEntry(String key, Language language) {
return handleNewEntry;
}
public class DynamicEntry {
private String key;
public DynamicEntry(String aKey) {
key = aKey;
}
public String getKey() {
return key;
}
public void setKey(String aNewKey) {
String oldKey = key;
for (Language l : Language.availableValues()) {
String oldValue = _values.get(l).get(oldKey);
_values.get(l).remove(oldKey);
if (oldValue != null) {
_values.get(l).put(aNewKey, oldValue);
}
LocalizedEntry e = getEntry(l, oldKey);
if (e != null) {
e.setKey(aNewKey);
}
}
key = aNewKey;
}
public String getEnglish() {
return getLocalizedForKeyAndLanguage(key, Language.ENGLISH);
}
public void setEnglish(String value) {
setLocalizedForKeyAndLanguage(key, value, Language.ENGLISH);
}
public String getFrench() {
return getLocalizedForKeyAndLanguage(key, Language.FRENCH);
}
public void setFrench(String value) {
setLocalizedForKeyAndLanguage(key, value, Language.FRENCH);
}
public String getDutch() {
return getLocalizedForKeyAndLanguage(key, Language.DUTCH);
}
public void setDutch(String value) {
setLocalizedForKeyAndLanguage(key, value, Language.DUTCH);
}
@Override
public String toString() {
return "(key=" + key + "{en=" + getEnglish() + ";fr=" + getFrench() + ";du=" + getDutch() + "})";
}
}
// This method is really not efficient, but only called in the context of locales editor
// This issue is not really severe.
private Vector<String> buildAllKeys() {
Vector<String> returned = new Vector<String>();
for (Language l : _values.keySet()) {
for (String key : _values.get(l).keySet()) {
if (!returned.contains(key)) {
returned.add(key);
}
}
}
return returned;
}
// This method is really not efficient, but only called in the context of locales editor
// Impact of this issue is not really severe.
public Vector<DynamicEntry> getDynamicEntries() {
if (dynamicEntries == null) {
dynamicEntries = new Vector<DynamicEntry>();
for (String key : buildAllKeys()) {
dynamicEntries.add(new DynamicEntry(key));
}
Collections.sort(dynamicEntries, new Comparator<DynamicEntry>() {
@Override
public int compare(DynamicEntry o1, DynamicEntry o2) {
return Collator.getInstance().compare(o1.key, o2.key);
}
});
}
return dynamicEntries;
}
private DynamicEntry getDynamicEntry(String key) {
if (key == null) {
return null;
}
for (DynamicEntry entry : getDynamicEntries()) {
if (key.equals(entry.key)) {
return entry;
}
}
return null;
}
public void refresh() {
logger.fine("Refresh called on FIBLocalizedDictionary " + Integer.toHexString(hashCode()));
dynamicEntries = null;
setChanged();
notifyObservers();
}
public DynamicEntry addEntry() {
String newKey = "key";
Vector<String> allKeys = buildAllKeys();
boolean keyAlreadyExists = allKeys.contains(newKey);
int index = 1;
while (keyAlreadyExists) {
newKey = "key" + index;
keyAlreadyExists = allKeys.contains(newKey);
index++;
}
addToEntries(new LocalizedEntry(this, newKey, FlexoLocalization.getCurrentLanguage().getName(), newKey));
refresh();
return getDynamicEntry(newKey);
}
public void deleteEntry(DynamicEntry entry) {
for (Language l : Language.availableValues()) {
_values.get(l).remove(entry.getKey());
LocalizedEntry e = getEntry(l, entry.getKey());
if (e != null) {
_entries.remove(e);
}
}
refresh();
}
public void searchNewEntries() {
logger.info("Search new entries");
for (EditionPattern ep : getViewPoint().getEditionPatterns()) {
checkAndRegisterLocalized(ep.getName());
for (EditionScheme es : ep.getEditionSchemes()) {
checkAndRegisterLocalized(es.getLabel());
checkAndRegisterLocalized(es.getDescription());
for (EditionSchemeParameter p : es.getParameters()) {
checkAndRegisterLocalized(p.getLabel());
}
for (InspectorEntry entry : ep.getInspector().getEntries()) {
checkAndRegisterLocalized(entry.getLabel());
}
}
}
dynamicEntries = null;
getViewPoint().setChanged();
getViewPoint().notifyObservers();
}
private void checkAndRegisterLocalized(String key) {
handleNewEntry = true;
FlexoLocalization.localizedForKey(this, key);
// getLocalizedForKeyAndLanguage(key, FlexoLocalization.getCurrentLanguage());
handleNewEntry = false;
}
@Override
public BindingModel getBindingModel() {
return getViewPoint().getBindingModel();
}
@Override
public boolean registerNewEntry(String key, Language language, String value) {
System.out.println("Register entry key=" + key + " lang=" + language + " value=" + value);
setLocalizedForKeyAndLanguage(key, value, language);
return true;
}
@Override
public LocalizedDelegate getParent() {
return FlexoLocalization.getMainLocalizer();
}
@Override
public String getLanguageRepresentation() {
return "<not_implemented:" + getFullyQualifiedName() + ">";
}
}