1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portal.model;
16  
17  import com.liferay.portal.kernel.log.Log;
18  import com.liferay.portal.kernel.log.LogFactoryUtil;
19  import com.liferay.portal.kernel.util.GetterUtil;
20  import com.liferay.portal.kernel.util.ListUtil;
21  import com.liferay.portal.kernel.util.PropsKeys;
22  import com.liferay.portal.kernel.util.StringUtil;
23  import com.liferay.portal.kernel.util.Tuple;
24  import com.liferay.portal.kernel.xml.Document;
25  import com.liferay.portal.kernel.xml.Element;
26  import com.liferay.portal.kernel.xml.SAXReader;
27  import com.liferay.portal.service.ClassNameLocalServiceUtil;
28  import com.liferay.portal.util.PropsUtil;
29  
30  import java.io.InputStream;
31  
32  import java.util.ArrayList;
33  import java.util.Collections;
34  import java.util.HashMap;
35  import java.util.Iterator;
36  import java.util.LinkedHashMap;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.Set;
40  import java.util.TreeSet;
41  
42  /**
43   * <a href="ModelHintsImpl.java.html"><b><i>View Source</i></b></a>
44   *
45   * @author Brian Wing Shun Chan
46   */
47  public class ModelHintsImpl implements ModelHints {
48  
49      public void afterPropertiesSet() {
50          _hintCollections = new HashMap<String, Map<String, String>>();
51          _defaultHints = new HashMap<String, Map<String, String>>();
52          _modelFields = new HashMap<String, Object>();
53          _models = new TreeSet<String>();
54  
55          try {
56              ClassLoader classLoader = getClass().getClassLoader();
57  
58              String[] configs = StringUtil.split(
59                  PropsUtil.get(PropsKeys.MODEL_HINTS_CONFIGS));
60  
61              for (int i = 0; i < configs.length; i++) {
62                  read(classLoader, configs[i]);
63              }
64          }
65          catch (Exception e) {
66              _log.error(e, e);
67          }
68      }
69  
70      public Map<String, String> getDefaultHints(String model) {
71          return _defaultHints.get(model);
72      }
73  
74      public com.liferay.portal.kernel.xml.Element getFieldsEl(
75          String model, String field) {
76  
77          Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
78              model);
79  
80          if (fields == null) {
81              return null;
82          }
83          else {
84              Element fieldsEl = (Element)fields.get(field + _ELEMENTS_SUFFIX);
85  
86              if (fieldsEl == null) {
87                  return null;
88              }
89              else {
90                  return fieldsEl;
91              }
92          }
93      }
94  
95      public Map<String, String> getHints(String model, String field) {
96          Map<String, Object> fields =
97              (Map<String, Object>)_modelFields.get(model);
98  
99          if (fields == null) {
100             return null;
101         }
102         else {
103             return (Map<String, String>)fields.get(field + _HINTS_SUFFIX);
104         }
105     }
106 
107     public List<String> getModels() {
108         return ListUtil.fromCollection(_models);
109     }
110 
111     public Tuple getSanitizeTuple(String model, String field) {
112         Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
113             model);
114 
115         if (fields == null) {
116             return null;
117         }
118         else {
119             return (Tuple)fields.get(field + _SANITIZE_SUFFIX);
120         }
121     }
122 
123     public List<Tuple> getSanitizeTuples(String model) {
124         Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
125             model);
126 
127         if (fields == null) {
128             return Collections.EMPTY_LIST;
129         }
130         else {
131             List<Tuple> sanitizeTuples = new ArrayList<Tuple>();
132 
133             for (String key : fields.keySet()) {
134                 if (key.endsWith(_SANITIZE_SUFFIX)) {
135                     Tuple sanitizeTuple = (Tuple)fields.get(key);
136 
137                     sanitizeTuples.add(sanitizeTuple);
138                 }
139             }
140 
141             return sanitizeTuples;
142         }
143     }
144 
145     public String getType(String model, String field) {
146         Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
147             model);
148 
149         if (fields == null) {
150             return null;
151         }
152         else {
153             return (String)fields.get(field + _TYPE_SUFFIX);
154         }
155     }
156 
157     public boolean isLocalized(String model, String field) {
158         Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
159             model);
160 
161         if (fields == null) {
162             return false;
163         }
164         else {
165             Boolean localized = (Boolean)fields.get(
166                 field + _LOCALIZATION_SUFFIX);
167 
168             if (localized != null) {
169                 return localized;
170             }
171             else {
172                 return false;
173             }
174         }
175     }
176 
177     public void read(ClassLoader classLoader, String source) throws Exception {
178         InputStream is = classLoader.getResourceAsStream(source);
179 
180         if (is == null) {
181             if (_log.isWarnEnabled()) {
182                 _log.warn("Cannot load " + source);
183             }
184             return;
185         }
186         else {
187             if (_log.isDebugEnabled()) {
188                 _log.debug("Loading " + source);
189             }
190         }
191 
192         Document doc = _saxReader.read(is);
193 
194         Element root = doc.getRootElement();
195 
196         Iterator<Element> itr1 = root.elements("hint-collection").iterator();
197 
198         while (itr1.hasNext()) {
199             Element hintCollection = itr1.next();
200 
201             String name = hintCollection.attributeValue("name");
202 
203             Map<String, String> hints = _hintCollections.get(name);
204 
205             if (hints == null) {
206                 hints = new HashMap<String, String>();
207 
208                 _hintCollections.put(name, hints);
209             }
210 
211             Iterator<Element> itr2 = hintCollection.elements("hint").iterator();
212 
213             while (itr2.hasNext()) {
214                 Element hint = itr2.next();
215 
216                 String hintName = hint.attributeValue("name");
217                 String hintValue = hint.getText();
218 
219                 hints.put(hintName, hintValue);
220             }
221         }
222 
223         itr1 = root.elements("model").iterator();
224 
225         while (itr1.hasNext()) {
226             Element model = itr1.next();
227 
228             String name = model.attributeValue("name");
229 
230             if (classLoader != ModelHintsImpl.class.getClassLoader()) {
231                 ClassNameLocalServiceUtil.getClassName(name);
232             }
233 
234             Map<String, String> defaultHints = new HashMap<String, String>();
235 
236             _defaultHints.put(name, defaultHints);
237 
238             Element defaultHintsEl = model.element("default-hints");
239 
240             if (defaultHintsEl != null) {
241                 Iterator<Element> itr2 = defaultHintsEl.elements(
242                     "hint").iterator();
243 
244                 while (itr2.hasNext()) {
245                     Element hint = itr2.next();
246 
247                     String hintName = hint.attributeValue("name");
248                     String hintValue = hint.getText();
249 
250                     defaultHints.put(hintName, hintValue);
251                 }
252             }
253 
254             Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
255                 name);
256 
257             if (fields == null) {
258                 fields = new LinkedHashMap<String, Object>();
259 
260                 _modelFields.put(name, fields);
261             }
262 
263             _models.add(name);
264 
265             Iterator<Element> itr2 = model.elements("field").iterator();
266 
267             while (itr2.hasNext()) {
268                 Element field = itr2.next();
269 
270                 String fieldName = field.attributeValue("name");
271                 String fieldType = field.attributeValue("type");
272                 boolean fieldLocalized = GetterUtil.getBoolean(
273                     field.attributeValue("localized"));
274 
275                 Map<String, String> fieldHints = new HashMap<String, String>();
276 
277                 fieldHints.putAll(defaultHints);
278 
279                 Iterator<Element> itr3 = field.elements(
280                     "hint-collection").iterator();
281 
282                 while (itr3.hasNext()) {
283                     Element hintCollection = itr3.next();
284 
285                     Map<String, String> hints = _hintCollections.get(
286                         hintCollection.attributeValue("name"));
287 
288                     fieldHints.putAll(hints);
289                 }
290 
291                 itr3 = field.elements("hint").iterator();
292 
293                 while (itr3.hasNext()) {
294                     Element hint = itr3.next();
295 
296                     String hintName = hint.attributeValue("name");
297                     String hintValue = hint.getText();
298 
299                     fieldHints.put(hintName, hintValue);
300                 }
301 
302                 Tuple fieldSanitize = null;
303 
304                 Element sanitize = field.element("sanitize");
305 
306                 if (sanitize != null) {
307                     String contentType = sanitize.attributeValue(
308                         "content-type");
309                     String modes = sanitize.attributeValue("modes");
310 
311                     fieldSanitize = new Tuple(fieldName, contentType, modes);
312                 }
313 
314                 fields.put(fieldName + _ELEMENTS_SUFFIX, field);
315                 fields.put(fieldName + _TYPE_SUFFIX, fieldType);
316                 fields.put(fieldName + _LOCALIZATION_SUFFIX, fieldLocalized);
317                 fields.put(fieldName + _HINTS_SUFFIX, fieldHints);
318 
319                 if (fieldSanitize != null) {
320                     fields.put(fieldName + _SANITIZE_SUFFIX, fieldSanitize);
321                 }
322             }
323         }
324     }
325 
326     public void setSAXReader(SAXReader saxReader) {
327         _saxReader = saxReader;
328     }
329 
330     public String trimString(String model, String field, String value) {
331         if (value == null) {
332             return value;
333         }
334 
335         Map<String, String> hints = getHints(model, field);
336 
337         if (hints == null) {
338             return value;
339         }
340 
341         int maxLength = GetterUtil.getInteger(
342             ModelHintsConstants.TEXT_MAX_LENGTH);
343 
344         maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
345 
346         if (value.length() > maxLength) {
347             return value.substring(0, maxLength);
348         }
349         else {
350             return value;
351         }
352     }
353 
354     private static final String _ELEMENTS_SUFFIX = "_ELEMENTS";
355 
356     private static final String _HINTS_SUFFIX = "_HINTS";
357 
358     private static final String _LOCALIZATION_SUFFIX = "_LOCALIZATION";
359 
360     private static final String _SANITIZE_SUFFIX = "_SANITIZE_SUFFIX";
361 
362     private static final String _TYPE_SUFFIX = "_TYPE";
363 
364     private static Log _log = LogFactoryUtil.getLog(ModelHintsImpl.class);
365 
366     private Map<String, Map<String, String>> _defaultHints;
367     private Map<String, Map<String, String>> _hintCollections;
368     private Map<String, Object> _modelFields;
369     private Set<String> _models;
370     private SAXReader _saxReader;
371 
372 }