/*
* Copyright (C) 2013-2017 NTT DATA Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.terasoluna.gfw.common.codelist.i18n;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import org.terasoluna.gfw.common.codelist.CodeList;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import com.google.common.collect.Tables;
/**
* Simple implementation of {@link I18nCodeList}<br>
* <p>
* {@link I18nCodeList} has a table of codelist.<br>
* Each row is a codelist for each language and represented as <strong>unmodifiable linked hash maps</strong>.<br>
* The key of rows is {@link Locale}.The key of columns is {@link String}(code). <br>
* There are 3 ways to express the following table.
* </p>
* <table border=1>
* <caption>code list table of week</caption>
* <tr>
* <th>row=Locale,column=code</th>
* <th>0</th>
* <th>1</th>
* <th>2</th>
* <th>3</th>
* <th>4</th>
* <th>5</th>
* <th>6</th>
* </tr>
* <tr>
* <th>en</th>
* <td>Sun.</td>
* <td>Mon.</td>
* <td>Tue.</td>
* <td>Wed.</td>
* <td>Thu.</td>
* <td>Fri.</td>
* <td>Sat.</td>
* </tr>
* <tr>
* <th>ja</th>
* <td>日</td>
* <td>月</td>
* <td>火</td>
* <td>水</td>
* <td>木</td>
* <td>金</td>
* <td>土</td>
* </tr>
* </table>
* <h3>(Way 1) set by rows</h3>
*
* <pre>
* <bean id="CL_I18N_WEEK"
* class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList">
* <property name="rows">
* <util:map>
* <entry key="en">
* <util:map>
* <entry key="0" value="Sun." />
* <entry key="1" value="Mon." />
* <entry key="2" value="Tue." />
* <entry key="3" value="Wed." />
* <entry key="4" value="Thu." />
* <entry key="5" value="Fri." />
* <entry key="6" value="Sat." />
* </util:map>
* </entry>
* <entry key="ja">
* <util:map>
* <entry key="0" value="日" />
* <entry key="1" value="月" />
* <entry key="2" value="火" />
* <entry key="3" value="水" />
* <entry key="4" value="木" />
* <entry key="5" value="金" />
* <entry key="6" value="土" />
* </util:map>
* </entry>
* </util:map>
* </property>
* </bean>
* </pre>
*
* <h3>(Way2) set by rows with codelist</h3>
*
* <pre>
* <bean id="CL_I18N_WEEK"
* class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList">
* <property name="rowsByCodeList">
* <util:map>
* <entry key="en" value-ref="CL_WEEK_EN" />
* <entry key="ja" value-ref="CL_WEEK_JA" />
* </util:map>
* </property>
* </bean>
*
* <bean id="CL_WEEK_EN" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList">
* <property name="map">
* <util:map>
* <entry key="0" value="Sun." />
* <entry key="1" value="Mon." />
* <entry key="2" value="Tue." />
* <entry key="3" value="Wed." />
* <entry key="4" value="Thu." />
* <entry key="5" value="Fri." />
* <entry key="6" value="Sat." />
* </util:map>
* </property>
* </bean>
*
* <bean id="CL_WEEK_JA" class="org.terasoluna.gfw.common.codelist.SimpleMapCodeList">
* <property name="map">
* <util:map>
* <entry key="0" value="日" />
* <entry key="1" value="月" />
* <entry key="2" value="火" />
* <entry key="3" value="水" />
* <entry key="4" value="木" />
* <entry key="5" value="金" />
* <entry key="6" value="土" />
* </util:map>
* </property>
* </bean>
* </pre>
*
* <h3>(Way3) set by columns</h3>
*
* <pre>
* <bean id="CL_I18N_WEEK"
* class="org.terasoluna.gfw.common.codelist.i18n.SimpleI18nCodeList">
* <property name="columns">
* <util:map>
* <entry key="0">
* <util:map>
* <entry key="en" value="Sun." />
* <entry key="ja" value="日" />
* </util:map>
* </entry>
* <entry key="1">
* <util:map>
* <entry key="en" value="Mon." />
* <entry key="ja" value="月" />
* </util:map>
* </entry>
* <entry key="2">
* <util:map>
* <entry key="en" value="Tue." />
* <entry key="ja" value="火" />
* </util:map>
* </entry>
* <entry key="3">
* <util:map>
* <entry key="en" value="Wed." />
* <entry key="ja" value="水" />
* </util:map>
* </entry>
* <entry key="4">
* <util:map>
* <entry key="en" value="Thu." />
* <entry key="ja" value="木" />
* </util:map>
* </entry>
* <entry key="5">
* <util:map>
* <entry key="en" value="Fri." />
* <entry key="ja" value="金" />
* </util:map>
* </entry>
* <entry key="6">
* <util:map>
* <entry key="en" value="Sat." />
* <entry key="ja" value="土" />
* </util:map>
* </entry>
* </util:map>
* </property>
* </bean>
* </pre>
*/
public class SimpleI18nCodeList extends AbstractI18nCodeList implements
InitializingBean {
/**
* Logger.
*/
private static final Logger logger = LoggerFactory
.getLogger(SimpleI18nCodeList.class);
/**
* codelist table.
*/
Table<Locale, String, String> codeListTable;
/**
* supplier to return a {@link LinkedHashMap} object.
*/
private static final Supplier<LinkedHashMap<String, String>> LINKED_HASH_MAP_SUPPLIER = new Supplier<LinkedHashMap<String, String>>() {
@Override
public LinkedHashMap<String, String> get() {
return Maps.newLinkedHashMap();
}
};
/**
* <p>
* returns row of codelist table.
* </p>
* @see org.terasoluna.gfw.common.codelist.i18n.I18nCodeList#asMap(java.util.Locale)
*/
@Override
public Map<String, String> asMap(Locale locale) {
Assert.notNull(locale, "locale is null");
return codeListTable.row(locale);
}
/**
* check whether the code list table is null.<br>
* <p>
* output warn log in case of table is null.
* </p>
*/
private void checkTable() {
if (codeListTable != null) {
logger.warn("Codelist table has already built, but re-build");
}
}
/**
* set table by rows ({@link Map}).<br>
* <p>
* The key is {@link Locale} and the value is {@link Map} which represents {@link CodeList}.<br>
* </p>
* @param rows table by rows ({@link Map}) per locale
*/
public void setRows(Map<Locale, Map<String, String>> rows) {
checkTable();
Table<Locale, String, String> table = createTable();
for (Map.Entry<Locale, Map<String, String>> e : rows.entrySet()) {
Locale locale = e.getKey();
Map<String, String> row = e.getValue();
for (Map.Entry<String, String> re : row.entrySet()) {
String value = re.getKey();
String label = re.getValue();
table.put(locale, value, label);
}
}
this.codeListTable = Tables.unmodifiableTable(table);
}
/**
* set table by rows ({@link CodeList})<br>
* <p>
* The key is {@link Locale} and the value is {@link CodeList}.<br>
* </p>
* @param rows table by rows ({@link CodeList}) per locale
*/
public void setRowsByCodeList(Map<Locale, CodeList> rows) {
checkTable();
Table<Locale, String, String> table = createTable();
for (Map.Entry<Locale, CodeList> e : rows.entrySet()) {
Locale locale = e.getKey();
Map<String, String> row = e.getValue().asMap();
for (Map.Entry<String, String> re : row.entrySet()) {
String value = re.getKey();
String label = re.getValue();
table.put(locale, value, label);
}
}
this.codeListTable = Tables.unmodifiableTable(table);
}
/**
* set table by columns ({@link Map})<br>
* <p>
* The key is {@link Locale} and value is {@link Map}. <br>
* </p>
* @param cols table by columns ({@link Map}) per locale
*/
public void setColumns(Map<String, Map<Locale, String>> cols) {
checkTable();
Table<Locale, String, String> table = createTable();
for (Map.Entry<String, Map<Locale, String>> e : cols.entrySet()) {
String value = e.getKey();
Map<Locale, String> col = e.getValue();
for (Map.Entry<Locale, String> ce : col.entrySet()) {
Locale locale = ce.getKey();
String label = ce.getValue();
table.put(locale, value, label);
}
}
this.codeListTable = Tables.unmodifiableTable(table);
}
/**
* create table which consist of {@link LinkedHashMap} factory.
* @return table
*/
private Table<Locale, String, String> createTable() {
Map<Locale, Map<String, String>> backingMap = Maps.newLinkedHashMap();
Table<Locale, String, String> table = Tables.newCustomTable(backingMap,
LINKED_HASH_MAP_SUPPLIER);
return table;
}
/**
* <p>
* check whether codeListTable is initialized.
* </p>
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
Assert.notNull(codeListTable, "codeListTable is not initialized!");
}
}