001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.dynamicdatamapping.model.impl;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.ListUtil;
021    import com.liferay.portal.kernel.util.LocaleUtil;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.xml.Attribute;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.Element;
027    import com.liferay.portal.kernel.xml.Node;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portal.kernel.xml.XPath;
030    import com.liferay.portal.model.CacheField;
031    import com.liferay.portlet.dynamicdatamapping.StructureFieldException;
032    
033    import java.util.HashMap;
034    import java.util.Iterator;
035    import java.util.LinkedHashMap;
036    import java.util.List;
037    import java.util.Locale;
038    import java.util.Map;
039    import java.util.Set;
040    
041    /**
042     * @author Brian Wing Shun Chan
043     */
044    public class DDMStructureImpl extends DDMStructureBaseImpl {
045    
046            public DDMStructureImpl() {
047            }
048    
049            public List<String> getAvailableLocales() {
050                    Document document = getDocument();
051    
052                    Element rootElement = document.getRootElement();
053    
054                    String availableLocales = rootElement.attributeValue(
055                            "available-locales");
056    
057                    return ListUtil.fromArray(StringUtil.split(availableLocales));
058            }
059    
060            public String getDefaultLocale() {
061                    Document document = getDocument();
062    
063                    if (document == null) {
064                            Locale locale = LocaleUtil.getDefault();
065    
066                            return locale.toString();
067                    }
068    
069                    Element rootElement = document.getRootElement();
070    
071                    return rootElement.attributeValue("default-locale");
072            }
073    
074            @Override
075            public Document getDocument() {
076                    if (_document == null) {
077                            try {
078                                    _document = SAXReaderUtil.read(getXsd());
079                            }
080                            catch (Exception e) {
081                                     StackTraceElement[] stackTraceElements = e.getStackTrace();
082    
083                                     for (StackTraceElement stackTraceElement :
084                                                    stackTraceElements) {
085    
086                                             String className = stackTraceElement.getClassName();
087    
088                                             if (className.endsWith("DDMStructurePersistenceTest")) {
089                                                     return null;
090                                             }
091                                     }
092    
093                                    _log.error(e, e);
094                            }
095                    }
096    
097                    return _document;
098            }
099    
100            public String getFieldDataType(String fieldName)
101                    throws StructureFieldException {
102    
103                    return getFieldProperty(fieldName, "dataType");
104            }
105    
106            public String getFieldLabel(String fieldName, Locale locale)
107                    throws StructureFieldException {
108    
109                    return getFieldLabel(fieldName, locale.getLanguage());
110            }
111    
112            public String getFieldLabel(String fieldName, String locale)
113                    throws StructureFieldException {
114    
115                    return GetterUtil.getString(
116                            getFieldProperty(fieldName, "label", locale), fieldName);
117            }
118    
119            public Set<String> getFieldNames() {
120                    Map<String, Map<String, String>> fieldsMap = getFieldsMap();
121    
122                    return fieldsMap.keySet();
123            }
124    
125            public String getFieldProperty(String fieldName, String property)
126                    throws StructureFieldException {
127    
128                    return getFieldProperty(fieldName, property, getDefaultLocale());
129            }
130    
131            public String getFieldProperty(
132                            String fieldName, String property, String locale)
133                    throws StructureFieldException {
134    
135                    if (!hasField(fieldName)) {
136                            throw new StructureFieldException();
137                    }
138    
139                    Map<String, Map<String, String>> fieldsMap = _getFieldsMap(locale);
140    
141                    Map<String, String> field = fieldsMap.get(fieldName);
142    
143                    return field.get(property);
144            }
145    
146            public boolean getFieldRequired(String fieldName)
147                    throws StructureFieldException {
148    
149                    return GetterUtil.getBoolean(getFieldProperty(fieldName, "required"));
150            }
151    
152            public Map<String, String> getFields(
153                    String fieldName, String attributeName, String attributeValue) {
154    
155                    return getFields(
156                            fieldName, attributeName, attributeValue, getDefaultLocale());
157            }
158    
159            public Map<String, String> getFields(
160                    String fieldName, String attributeName, String attributeValue,
161                    String locale) {
162    
163                    try {
164                            StringBundler sb = new StringBundler(7);
165    
166                            sb.append("//dynamic-element[@name=\"");
167                            sb.append(fieldName);
168                            sb.append("\"] //dynamic-element[@");
169                            sb.append(attributeName);
170                            sb.append("=\"");
171                            sb.append(attributeValue);
172                            sb.append("\"]");
173    
174                            XPath xPathSelector = SAXReaderUtil.createXPath(sb.toString());
175    
176                            Node node = xPathSelector.selectSingleNode(getDocument());
177    
178                            if (node != null) {
179                                    return _getField(
180                                            (Element)node.asXPathResult(node.getParent()), locale);
181                            }
182                    }
183                    catch (Exception e) {
184                            _log.error(e, e);
185                    }
186    
187                    return null;
188            }
189    
190            @Override
191            public Map<String, Map<String, String>> getFieldsMap() {
192                    return _getFieldsMap(getDefaultLocale());
193            }
194    
195            public Map<String, Map<String, String>> getFieldsMap(String locale) {
196                    return _getFieldsMap(locale);
197            }
198    
199            public String getFieldType(String fieldName)
200                    throws StructureFieldException {
201    
202                    return getFieldProperty(fieldName, "type");
203            }
204    
205            public boolean hasField(String fieldName) {
206                    Map<String, Map<String, String>> fieldsMap = getFieldsMap();
207    
208                    return fieldsMap.containsKey(fieldName);
209            }
210    
211            @Override
212            public void setDocument(Document document) {
213                    _document = document;
214            }
215    
216            @Override
217            public void setFieldsMap(Map<String, Map<String, String>> fieldsMap) {
218                    _fieldsMap = fieldsMap;
219            }
220    
221            @Override
222            public void setXsd(String xsd) {
223                    super.setXsd(xsd);
224    
225                    _document = null;
226                    _fieldsMap = null;
227            }
228    
229            private Map<String, String> _getField(Element element, String locale) {
230                    Map<String, String> field = new HashMap<String, String>();
231    
232                    List<String> availableLocales = getAvailableLocales();
233    
234                    if ((locale != null) && !(availableLocales.contains(locale))) {
235                            locale = getDefaultLocale();
236                    }
237    
238                    String xPathExpression =
239                            "meta-data[@locale=\"".concat(locale).concat("\"]");
240    
241                    XPath xPathSelector = SAXReaderUtil.createXPath(xPathExpression);
242    
243                    Node node = xPathSelector.selectSingleNode(element);
244    
245                    Element metaDataElement = (Element)node.asXPathResult(node.getParent());
246    
247                    if (metaDataElement != null) {
248                            List<Element> childMetaDataElements = metaDataElement.elements();
249    
250                            for (Element childMetaDataElement : childMetaDataElements) {
251                                    String name = childMetaDataElement.attributeValue("name");
252                                    String value = childMetaDataElement.getText();
253    
254                                    field.put(name, value);
255                            }
256                    }
257    
258                    for (Attribute attribute : element.attributes()) {
259                            field.put(attribute.getName(), attribute.getValue());
260                    }
261    
262                    return field;
263            }
264    
265            private Map<String, Map<String, String>> _getFieldsMap(String locale) {
266                    if (_fieldsMap == null) {
267                            synchronized (this) {
268                                    if (_fieldsMap == null) {
269                                            _fieldsMap =
270                                                    new LinkedHashMap<String, Map<String, String>>();
271    
272                                            XPath xPathSelector = SAXReaderUtil.createXPath(
273                                                    "//dynamic-element[@dataType]");
274    
275                                            List<Node> nodes = xPathSelector.selectNodes(getDocument());
276    
277                                            Iterator<Node> itr = nodes.iterator();
278    
279                                            while (itr.hasNext()) {
280                                                    Element element = (Element)itr.next();
281    
282                                                    String name = element.attributeValue("name");
283    
284                                                    _fieldsMap.put(name, _getField(element, locale));
285                                            }
286                                    }
287                            }
288                    }
289    
290                    return _fieldsMap;
291            }
292    
293            private static Log _log = LogFactoryUtil.getLog(DDMStructureImpl.class);
294    
295            @CacheField
296            private Document _document;
297    
298            @CacheField
299            private Map<String, Map<String, String>> _fieldsMap;
300    
301    }