1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.datamodel.language;
20
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.Locale;
24 import java.util.Map;
25
26 import org.apache.logging.log4j.LogManager;
27 import org.apache.logging.log4j.Logger;
28 import org.mycore.backend.jpa.MCREntityManagerProvider;
29 import org.mycore.common.MCRConstants;
30 import org.mycore.common.MCRSession;
31 import org.mycore.common.MCRSessionMgr;
32 import org.mycore.common.MCRTransactionHelper;
33 import org.mycore.common.config.MCRConfiguration2;
34 import org.mycore.datamodel.classifications2.MCRCategory;
35 import org.mycore.datamodel.classifications2.MCRCategoryDAO;
36 import org.mycore.datamodel.classifications2.MCRCategoryDAOFactory;
37 import org.mycore.datamodel.classifications2.MCRCategoryID;
38 import org.mycore.datamodel.classifications2.MCRLabel;
39
40
41
42
43
44
45
46
47
48
49 public class MCRLanguageFactory {
50 private static final Logger LOGGER = LogManager.getLogger();
51
52 private static final MCRLanguageFactory SINGLETON = new MCRLanguageFactory();
53
54 public static final MCRLanguage GERMAN = MCRLanguageFactory.instance().getLanguage("de");
55
56 public static final MCRLanguage ENGLISH = MCRLanguageFactory.instance().getLanguage("en");
57
58
59
60
61 private Map<String, MCRLanguage> languageByCode = new HashMap<>();
62
63
64
65
66 private MCRCategoryID classification;
67
68 private MCRCategoryDAO categoryDAO = MCRCategoryDAOFactory.getInstance();
69
70
71
72
73 private long classificationLastRead = Long.MIN_VALUE;
74
75
76
77
78 private String codeOfDefaultLanguage;
79
80 private MCRLanguageFactory() {
81 codeOfDefaultLanguage = MCRConfiguration2.getString("MCR.Metadata.DefaultLang")
82 .orElse(MCRConstants.DEFAULT_LANG);
83 initDefaultLanguages();
84
85 classification = MCRConfiguration2.getString("MCR.LanguageClassification")
86 .map(MCRCategoryID::rootID)
87 .orElse(null);
88 }
89
90
91
92
93 public static MCRLanguageFactory instance() {
94 return SINGLETON;
95 }
96
97
98
99
100 public MCRLanguage getDefaultLanguage() {
101 return getLanguage(codeOfDefaultLanguage);
102 }
103
104
105
106
107
108
109
110 public MCRLanguage getLanguage(String code) {
111 if (classificationHasChanged()) {
112 initLanguages();
113 }
114
115 return lookupLanguage(code);
116 }
117
118 private MCRLanguage lookupLanguage(String code) {
119 if ((!languageByCode.containsKey(code)) && code.contains("-") && !code.startsWith("x-")) {
120 code = code.split("-")[0];
121 }
122
123 if (!languageByCode.containsKey(code)) {
124 LOGGER.warn("Unknown language: {}", code);
125 buildLanguage(code, code.length() > 2 ? code : null, null);
126 }
127
128 return languageByCode.get(code);
129 }
130
131
132
133
134
135
136
137
138
139
140
141 public final boolean isSupportedLanguage(String code) {
142 if (code == null) {
143 return false;
144 }
145 code = code.trim();
146 if (code.length() == 0) {
147 return false;
148 }
149 if (code.startsWith("x-") || code.startsWith("i-")) {
150 return true;
151 }
152 return languageByCode.containsKey(code);
153 }
154
155
156
157
158
159 private boolean classificationHasChanged() {
160
161 return MCRConfiguration2.getBoolean("MCR.Persistence.Database.Enable").orElse(true)
162 && MCREntityManagerProvider.getEntityManagerFactory() != null && (classification != null)
163 && (categoryDAO.getLastModified() > classificationLastRead);
164 }
165
166
167
168
169 private void initLanguages() {
170 languageByCode.clear();
171 initDefaultLanguages();
172 readLanguageClassification();
173 }
174
175
176
177
178 private void initDefaultLanguages() {
179 MCRLanguage de = buildLanguage("de", "deu", "ger");
180 MCRLanguage en = buildLanguage("en", "eng", null);
181 de.setLabel(de, "Deutsch");
182 de.setLabel(en, "German");
183 en.setLabel(de, "Englisch");
184 en.setLabel(en, "English");
185 }
186
187
188
189
190
191
192
193
194 private MCRLanguage buildLanguage(String xmlCode, String termCode, String biblCode) {
195 MCRLanguage language = new MCRLanguage();
196 addCode(language, MCRLanguageCodeType.xmlCode, xmlCode);
197 if (termCode != null) {
198 addCode(language, MCRLanguageCodeType.termCode, termCode);
199 addCode(language, MCRLanguageCodeType.biblCode, biblCode == null ? termCode : biblCode);
200 }
201 Locale locale = Arrays.stream(Locale.getAvailableLocales())
202 .filter(l -> l.toString().equals(xmlCode))
203 .findFirst()
204 .orElseGet(() -> {
205 String[] codeParts = xmlCode.split("_");
206 switch (codeParts.length) {
207 case 1:
208 return new Locale(codeParts[0]);
209 case 2:
210 return new Locale(codeParts[0], codeParts[1]);
211 default:
212 return new Locale(codeParts[0], codeParts[1], codeParts[2]);
213 }
214
215 });
216 language.setLocale(locale);
217 return language;
218 }
219
220
221
222
223 private void addCode(MCRLanguage language, MCRLanguageCodeType type, String code) {
224 language.setCode(type, code);
225 languageByCode.put(code, language);
226 }
227
228
229
230
231 private void readLanguageClassification() {
232 MCRSession session = MCRSessionMgr.getCurrentSession();
233 if (!MCRTransactionHelper.isTransactionActive()) {
234 MCRTransactionHelper.beginTransaction();
235 buildLanguagesFromClassification();
236 MCRTransactionHelper.commitTransaction();
237 } else {
238 buildLanguagesFromClassification();
239 }
240 }
241
242
243
244
245 private void buildLanguagesFromClassification() {
246 this.classificationLastRead = categoryDAO.getLastModified();
247
248 MCRCategory root = categoryDAO.getCategory(classification, -1);
249 if (root == null) {
250 LOGGER.warn("Language classification {} not found", classification.getRootID());
251 return;
252 }
253
254 for (MCRCategory category : root.getChildren()) {
255 buildLanguage(category);
256 }
257 }
258
259
260
261
262 private void buildLanguage(MCRCategory category) {
263 String xmlCode = category.getId().getID();
264 String termCode = category.getLabel("x-term").map(MCRLabel::getText).orElse(null);
265 String biblCode = category.getLabel("x-bibl").map(MCRLabel::getText).orElse(termCode);
266
267 MCRLanguage language = buildLanguage(xmlCode, termCode, biblCode);
268
269 category
270 .getLabels()
271 .stream()
272 .filter(l -> !l.getLang().startsWith("x-"))
273 .sequential()
274 .forEach(l -> {
275 MCRLanguage languageOfLabel = lookupLanguage(l.getLang());
276 language.setLabel(languageOfLabel, l.getText());
277 });
278 }
279 }