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