001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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    
032    import java.util.HashMap;
033    import java.util.Iterator;
034    import java.util.LinkedHashMap;
035    import java.util.List;
036    import java.util.Locale;
037    import java.util.Map;
038    import java.util.Set;
039    
040    /**
041     * @author Brian Wing Shun Chan
042     */
043    public class DDMStructureImpl extends DDMStructureBaseImpl {
044    
045            public DDMStructureImpl() {
046            }
047    
048            public List<String> getAvailableLocales() {
049                    Document document = getDocument();
050    
051                    Element rootElement = document.getRootElement();
052    
053                    String availableLocales = rootElement.attributeValue(
054                            "available-locales");
055    
056                    return ListUtil.fromArray(StringUtil.split(availableLocales));
057            }
058    
059            public String getDefaultLocale() {
060                    Document document = getDocument();
061    
062                    if (document == null) {
063                            Locale locale = LocaleUtil.getDefault();
064    
065                            return locale.toString();
066                    }
067    
068                    Element rootElement = document.getRootElement();
069    
070                    return rootElement.attributeValue("default-locale");
071            }
072    
073            @Override
074            public Document getDocument() {
075                    if (_document == null) {
076                            try {
077                                    _document = SAXReaderUtil.read(getXsd());
078                            }
079                            catch (Exception e) {
080                                     StackTraceElement[] stackTraceElements = e.getStackTrace();
081    
082                                     for (StackTraceElement stackTraceElement :
083                                                    stackTraceElements) {
084    
085                                             String className = stackTraceElement.getClassName();
086    
087                                             if (className.endsWith("DDMStructurePersistenceTest")) {
088                                                     return null;
089                                             }
090                                     }
091    
092                                    _log.error(e, e);
093                            }
094                    }
095    
096                    return _document;
097            }
098    
099            public String getFieldDataType(String fieldName) {
100                    return getFieldProperty(fieldName, "dataType");
101            }
102    
103            public boolean getFieldDisplayChildLabelAsValue(String fieldName) {
104                    return GetterUtil.getBoolean(
105                            getFieldProperty(fieldName, "displayChildLabelAsValue"));
106            }
107    
108            public String getFieldLabel(String fieldName, Locale locale) {
109                    return getFieldLabel(fieldName, locale.getLanguage());
110            }
111    
112            public String getFieldLabel(String fieldName, String locale) {
113                    return GetterUtil.getString(
114                            getFieldProperty(fieldName, "label", locale), fieldName);
115            }
116    
117            public Set<String> getFieldNames() {
118                    Map<String, Map<String, String>> fieldsMap = getFieldsMap();
119    
120                    return fieldsMap.keySet();
121            }
122    
123            public String getFieldProperty(String fieldName, String property) {
124                    return getFieldProperty(fieldName, property, getDefaultLocale());
125            }
126    
127            public String getFieldProperty(
128                    String fieldName, String property, String locale) {
129    
130                    Map<String, Map<String, String>> fieldsMap = _getFieldsMap(locale);
131    
132                    Map<String, String> field = fieldsMap.get(fieldName);
133    
134                    return field.get(property);
135            }
136    
137            public boolean getFieldRequired(String fieldName) {
138                    return GetterUtil.getBoolean(getFieldProperty(fieldName, "required"));
139            }
140    
141            public Map<String, String> getFields(
142                    String fieldName, String attributeName, String attributeValue) {
143    
144                    return getFields(
145                            fieldName, attributeName, attributeValue, getDefaultLocale());
146            }
147    
148            public Map<String, String> getFields(
149                    String fieldName, String attributeName, String attributeValue,
150                    String locale) {
151    
152                    try {
153                            StringBundler sb = new StringBundler(7);
154    
155                            sb.append("//dynamic-element[@name=\"");
156                            sb.append(fieldName);
157                            sb.append("\"] //dynamic-element[@");
158                            sb.append(attributeName);
159                            sb.append("=\"");
160                            sb.append(attributeValue);
161                            sb.append("\"]");
162    
163                            XPath xPathSelector = SAXReaderUtil.createXPath(sb.toString());
164    
165                            Node node = xPathSelector.selectSingleNode(getDocument());
166    
167                            if (node != null) {
168                                    return _getField(
169                                            (Element)node.asXPathResult(node.getParent()), locale);
170                            }
171                    }
172                    catch (Exception e) {
173                            _log.error(e, e);
174                    }
175    
176                    return null;
177            }
178    
179            @Override
180            public Map<String, Map<String, String>> getFieldsMap() {
181                    return _getFieldsMap(getDefaultLocale());
182            }
183    
184            public Map<String, Map<String, String>> getFieldsMap(String locale) {
185                    return _getFieldsMap(locale);
186            }
187    
188            public String getFieldType(String fieldName) {
189                    return getFieldProperty(fieldName, "type");
190            }
191    
192            public boolean hasField(String fieldName) {
193                    Map<String, Map<String, String>> fieldsMap = getFieldsMap();
194    
195                    return fieldsMap.containsKey(fieldName);
196            }
197    
198            @Override
199            public void setDocument(Document document) {
200                    _document = document;
201            }
202    
203            @Override
204            public void setFieldsMap(Map<String, Map<String, String>> fieldsMap) {
205                    _fieldsMap = fieldsMap;
206            }
207    
208            @Override
209            public void setXsd(String xsd) {
210                    super.setXsd(xsd);
211    
212                    _document = null;
213                    _fieldsMap = null;
214            }
215    
216            private Map<String, String> _getField(Element element, String locale) {
217                    Map<String, String> field = new HashMap<String, String>();
218    
219                    List<String> availableLocales = getAvailableLocales();
220    
221                    if ((locale != null) && !(availableLocales.contains(locale))) {
222                            locale = getDefaultLocale();
223                    }
224    
225                    String xPathExpression =
226                            "meta-data[@locale=\"".concat(locale).concat("\"]");
227    
228                    XPath xPathSelector = SAXReaderUtil.createXPath(xPathExpression);
229    
230                    Node node = xPathSelector.selectSingleNode(element);
231    
232                    Element metaDataElement = (Element)node.asXPathResult(node.getParent());
233    
234                    if (metaDataElement != null) {
235                            List<Element> childMetaDataElements = metaDataElement.elements();
236    
237                            for (Element childMetaDataElement : childMetaDataElements) {
238                                    String name = childMetaDataElement.attributeValue("name");
239                                    String value = childMetaDataElement.getText();
240    
241                                    field.put(name, value);
242                            }
243                    }
244    
245                    for (Attribute attribute : element.attributes()) {
246                            field.put(attribute.getName(), attribute.getValue());
247                    }
248    
249                    return field;
250            }
251    
252            private Map<String, Map<String, String>> _getFieldsMap(String locale) {
253                    if (_fieldsMap == null) {
254                            synchronized (this) {
255                                    if (_fieldsMap == null) {
256                                            _fieldsMap =
257                                                    new LinkedHashMap<String, Map<String, String>>();
258    
259                                            XPath xPathSelector = SAXReaderUtil.createXPath(
260                                                    "//dynamic-element[@dataType]");
261    
262                                            List<Node> nodes = xPathSelector.selectNodes(
263                                                    getDocument());
264    
265                                            Iterator<Node> itr = nodes.iterator();
266    
267                                            while (itr.hasNext()) {
268                                                    Element element = (Element)itr.next();
269    
270                                                    String name = element.attributeValue("name");
271    
272                                                    _fieldsMap.put(name, _getField(element, locale));
273                                            }
274                                    }
275                            }
276                    }
277    
278                    return _fieldsMap;
279            }
280    
281            private static Log _log = LogFactoryUtil.getLog(DDMStructureImpl.class);
282    
283            @CacheField
284            private Document _document;
285    
286            @CacheField
287            private Map<String, Map<String, String>> _fieldsMap;
288    
289    }