001
014
015 package com.liferay.portlet.dynamicdatamapping.model.impl;
016
017 import com.liferay.portal.LocaleException;
018 import com.liferay.portal.kernel.exception.SystemException;
019 import com.liferay.portal.kernel.log.Log;
020 import com.liferay.portal.kernel.log.LogFactoryUtil;
021 import com.liferay.portal.kernel.util.GetterUtil;
022 import com.liferay.portal.kernel.util.HtmlUtil;
023 import com.liferay.portal.kernel.util.ListUtil;
024 import com.liferay.portal.kernel.util.LocaleUtil;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.kernel.util.StringUtil;
027 import com.liferay.portal.kernel.util.Validator;
028 import com.liferay.portal.kernel.xml.Attribute;
029 import com.liferay.portal.kernel.xml.Document;
030 import com.liferay.portal.kernel.xml.Element;
031 import com.liferay.portal.kernel.xml.Node;
032 import com.liferay.portal.kernel.xml.SAXReaderUtil;
033 import com.liferay.portal.kernel.xml.XPath;
034 import com.liferay.portal.model.CacheField;
035 import com.liferay.portlet.dynamicdatamapping.StructureFieldException;
036 import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
037 import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
038 import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
039
040 import java.util.HashMap;
041 import java.util.Iterator;
042 import java.util.LinkedHashMap;
043 import java.util.List;
044 import java.util.Locale;
045 import java.util.Map;
046 import java.util.Set;
047 import java.util.concurrent.ConcurrentHashMap;
048
049
052 public class DDMStructureImpl extends DDMStructureBaseImpl {
053
054 public DDMStructureImpl() {
055 }
056
057 @Override
058 public List<String> getAvailableLocales() {
059 Document document = getDocument();
060
061 Element rootElement = document.getRootElement();
062
063 String availableLocales = rootElement.attributeValue(
064 "available-locales");
065
066 return ListUtil.fromArray(StringUtil.split(availableLocales));
067 }
068
069 @Override
070 public String getDefaultLocale() {
071 Document document = getDocument();
072
073 if (document == null) {
074 Locale locale = LocaleUtil.getDefault();
075
076 return locale.toString();
077 }
078
079 Element rootElement = document.getRootElement();
080
081 return rootElement.attributeValue("default-locale");
082 }
083
084 @Override
085 public Document getDocument() {
086 if (_document == null) {
087 try {
088 _document = SAXReaderUtil.read(getXsd());
089 }
090 catch (Exception e) {
091 StackTraceElement[] stackTraceElements = e.getStackTrace();
092
093 for (StackTraceElement stackTraceElement : stackTraceElements) {
094 String className = stackTraceElement.getClassName();
095
096 if (className.endsWith("DDMStructurePersistenceTest")) {
097 return null;
098 }
099 }
100
101 _log.error(e, e);
102 }
103 }
104
105 return _document;
106 }
107
108 @Override
109 public String getFieldDataType(String fieldName)
110 throws StructureFieldException {
111
112 return getFieldProperty(fieldName, "dataType");
113 }
114
115 @Override
116 public String getFieldLabel(String fieldName, Locale locale)
117 throws StructureFieldException {
118
119 return getFieldLabel(fieldName, LocaleUtil.toLanguageId(locale));
120 }
121
122 @Override
123 public String getFieldLabel(String fieldName, String locale)
124 throws StructureFieldException {
125
126 return GetterUtil.getString(
127 getFieldProperty(fieldName, "label", locale), fieldName);
128 }
129
130 @Override
131 public Set<String> getFieldNames() {
132 Map<String, Map<String, String>> fieldsMap = getFieldsMap();
133
134 return fieldsMap.keySet();
135 }
136
137 @Override
138 public String getFieldProperty(String fieldName, String property)
139 throws StructureFieldException {
140
141 return getFieldProperty(fieldName, property, getDefaultLocale());
142 }
143
144 @Override
145 public String getFieldProperty(
146 String fieldName, String property, String locale)
147 throws StructureFieldException {
148
149 if (!hasField(fieldName)) {
150 throw new StructureFieldException();
151 }
152
153 Map<String, Map<String, String>> fieldsMap = getFieldsMap(locale);
154
155 Map<String, String> field = fieldsMap.get(fieldName);
156
157 return field.get(property);
158 }
159
160 @Override
161 public boolean getFieldRequired(String fieldName)
162 throws StructureFieldException {
163
164 return GetterUtil.getBoolean(getFieldProperty(fieldName, "required"));
165 }
166
167 @Override
168 public Map<String, String> getFields(
169 String fieldName, String attributeName, String attributeValue) {
170
171 return getFields(
172 fieldName, attributeName, attributeValue, getDefaultLocale());
173 }
174
175 @Override
176 public Map<String, String> getFields(
177 String fieldName, String attributeName, String attributeValue,
178 String locale) {
179
180 try {
181 if ((attributeName == null) || (attributeValue == null)) {
182 return null;
183 }
184
185 Map<String, Map<String, String>> fieldsMap = getTransientFieldsMap(
186 locale);
187
188 for (Map<String, String> fields : fieldsMap.values()) {
189 String parentName = fields.get(
190 _getPrivateAttributeKey("parentName"));
191
192 if (!fieldName.equals(parentName)) {
193 continue;
194 }
195
196 if (attributeValue.equals(fields.get(attributeName))) {
197 return fields;
198 }
199 }
200 }
201 catch (Exception e) {
202 _log.error(e, e);
203 }
204
205 return null;
206 }
207
208 @Override
209 public Map<String, Map<String, String>> getFieldsMap() {
210 return getFieldsMap(getDefaultLocale());
211 }
212
213 @Override
214 public Map<String, Map<String, String>> getFieldsMap(String locale) {
215
216 _indexFieldsMap(locale);
217
218 Map<String, Map<String, String>> fieldsMap = _localizedFieldsMap.get(
219 locale);
220
221 return fieldsMap;
222 }
223
224 @Override
225 public String getFieldType(String fieldName)
226 throws StructureFieldException {
227
228 return getFieldProperty(fieldName, "type");
229 }
230
231 @Override
232 public Map<String, Map<String, Map<String, String>>>
233 getLocalizedFieldsMap() {
234
235 return _localizedFieldsMap;
236 }
237
238 @Override
239 public Map<String, Map<String, Map<String, String>>>
240 getLocalizedTransientFieldsMap() {
241
242 return _localizedTransientFieldsMap;
243 }
244
245 @Override
246 public List<DDMTemplate> getTemplates() throws SystemException {
247 return DDMTemplateLocalServiceUtil.getTemplates(getStructureId());
248 }
249
250 @Override
251 public Map<String, Map<String, String>> getTransientFieldsMap(
252 String locale) {
253
254 _indexFieldsMap(locale);
255
256 Map<String, Map<String, String>> fieldsMap =
257 _localizedTransientFieldsMap.get(locale);
258
259 return fieldsMap;
260 }
261
262 @Override
263 public boolean hasField(String fieldName) {
264 Map<String, Map<String, String>> fieldsMap = getFieldsMap();
265
266 return fieldsMap.containsKey(fieldName);
267 }
268
269 @Override
270 public void prepareLocalizedFieldsForImport(Locale defaultImportLocale)
271 throws LocaleException {
272
273 super.prepareLocalizedFieldsForImport(defaultImportLocale);
274
275 Locale ddmStructureDefaultLocale = LocaleUtil.fromLanguageId(
276 getDefaultLocale());
277
278 try {
279 setXsd(
280 DDMXMLUtil.updateXMLDefaultLocale(
281 getXsd(), ddmStructureDefaultLocale, defaultImportLocale));
282 }
283 catch (Exception e) {
284 throw new LocaleException(e);
285 }
286 }
287
288 @Override
289 public void setDocument(Document document) {
290 _document = document;
291 }
292
293 @Override
294 public void setLocalizedFieldsMap(
295 Map<String, Map<String, Map<String, String>>> localizedFieldsMap) {
296
297 _localizedFieldsMap = localizedFieldsMap;
298 }
299
300 @Override
301 public void setLocalizedTransientFieldsMap(
302 Map<String, Map<String, Map<String, String>>>
303 localizedTransientFieldsMap) {
304
305 _localizedTransientFieldsMap = localizedTransientFieldsMap;
306 }
307
308 @Override
309 public void setXsd(String xsd) {
310 super.setXsd(xsd);
311
312 _document = null;
313 _localizedFieldsMap.clear();
314 _localizedTransientFieldsMap.clear();
315 }
316
317 private Map<String, String> _getField(Element element, String locale) {
318 Map<String, String> field = new HashMap<String, String>();
319
320 List<String> availableLocales = getAvailableLocales();
321
322 if ((locale != null) && !availableLocales.contains(locale)) {
323 locale = getDefaultLocale();
324 }
325
326 locale = HtmlUtil.escapeXPathAttribute(locale);
327
328 String xPathExpression =
329 "meta-data[@locale=".concat(locale).concat("]");
330
331 XPath xPathSelector = SAXReaderUtil.createXPath(xPathExpression);
332
333 Node node = xPathSelector.selectSingleNode(element);
334
335 Element metaDataElement = (Element)node.asXPathResult(node.getParent());
336
337 if (metaDataElement != null) {
338 List<Element> childMetaDataElements = metaDataElement.elements();
339
340 for (Element childMetaDataElement : childMetaDataElements) {
341 String name = childMetaDataElement.attributeValue("name");
342 String value = childMetaDataElement.getText();
343
344 field.put(name, value);
345 }
346 }
347
348 for (Attribute attribute : element.attributes()) {
349 field.put(attribute.getName(), attribute.getValue());
350 }
351
352 Element parentElement = element.getParent();
353
354 if (parentElement != null) {
355 String parentName = parentElement.attributeValue("name");
356
357 if (Validator.isNotNull(parentName)) {
358 field.put(_getPrivateAttributeKey("parentName"), parentName);
359 }
360 }
361
362 return field;
363 }
364
365 private String _getPrivateAttributeKey(String attributeName) {
366 return StringPool.UNDERLINE.concat(attributeName).concat(
367 StringPool.UNDERLINE);
368 }
369
370 private void _indexFieldsMap(String locale) {
371 Map<String, Map<String, String>> fieldsMap = _localizedFieldsMap.get(
372 locale);
373 Map<String, Map<String, String>> transientFieldsMap =
374 _localizedTransientFieldsMap.get(locale);
375
376 if (fieldsMap != null) {
377 return;
378 }
379
380 fieldsMap = new LinkedHashMap<String, Map<String, String>>();
381 transientFieldsMap = new LinkedHashMap<String, Map<String, String>>();
382
383 XPath xPathSelector = SAXReaderUtil.createXPath("
384
385 List<Node> nodes = xPathSelector.selectNodes(getDocument());
386
387 Iterator<Node> itr = nodes.iterator();
388
389 while (itr.hasNext()) {
390 Element element = (Element)itr.next();
391
392 String name = element.attributeValue("name");
393
394 if (Validator.isNotNull(element.attributeValue("dataType"))) {
395 fieldsMap.put(name, _getField(element, locale));
396 }
397 else {
398 transientFieldsMap.put(name, _getField(element, locale));
399 }
400 }
401
402 _localizedFieldsMap.put(locale, fieldsMap);
403 _localizedTransientFieldsMap.put(locale, transientFieldsMap);
404 }
405
406 private static Log _log = LogFactoryUtil.getLog(DDMStructureImpl.class);
407
408 @CacheField
409 private Document _document;
410
411 @CacheField
412 private Map<String, Map<String, Map<String, String>>> _localizedFieldsMap =
413 new ConcurrentHashMap<String, Map<String, Map<String, String>>>();
414
415 @CacheField
416 private Map<String, Map<String, Map<String, String>>>
417 _localizedTransientFieldsMap =
418 new ConcurrentHashMap<String, Map<String, Map<String, String>>>();
419
420 }