1   /**
2    * Copyright (c) 2000-2009 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   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portal.model;
21  
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.util.GetterUtil;
25  import com.liferay.portal.kernel.util.ListUtil;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.kernel.xml.Document;
28  import com.liferay.portal.kernel.xml.Element;
29  import com.liferay.portal.kernel.xml.SAXReader;
30  import com.liferay.portal.service.ClassNameLocalServiceUtil;
31  import com.liferay.portal.util.PropsKeys;
32  import com.liferay.portal.util.PropsUtil;
33  
34  import java.util.HashMap;
35  import java.util.Iterator;
36  import java.util.List;
37  import java.util.Map;
38  import java.util.Set;
39  import java.util.TreeSet;
40  
41  /**
42   * <a href="ModelHintsImpl.java.html"><b><i>View Source</i></b></a>
43   *
44   * @author Brian Wing Shun Chan
45   *
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 =
78              (Map<String, Object>)_modelFields.get(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 List<String> getModels() {
96          return ListUtil.fromCollection(_models);
97      }
98  
99      public String getType(String model, String field) {
100         Map<String, Object> fields =
101             (Map<String, Object>)_modelFields.get(model);
102 
103         if (fields == null) {
104             return null;
105         }
106         else {
107             return (String)fields.get(field + _TYPE_SUFFIX);
108         }
109     }
110 
111     public Map<String, String> getHints(String model, String field) {
112         Map<String, Object> fields =
113             (Map<String, Object>)_modelFields.get(model);
114 
115         if (fields == null) {
116             return null;
117         }
118         else {
119             return (Map<String, String>)fields.get(field + _HINTS_SUFFIX);
120         }
121     }
122 
123     public void read(ClassLoader classLoader, String source) throws Exception {
124         String xml = null;
125 
126         try {
127             xml = StringUtil.read(classLoader, source);
128         }
129         catch (Exception e) {
130             if (_log.isWarnEnabled()) {
131                 _log.warn("Cannot load " + source);
132             }
133         }
134 
135         if (xml == null) {
136             return;
137         }
138 
139         if (_log.isDebugEnabled()) {
140             _log.debug("Loading " + source);
141         }
142 
143         Document doc = _saxReader.read(xml);
144 
145         Element root = doc.getRootElement();
146 
147         Iterator<Element> itr1 = root.elements("hint-collection").iterator();
148 
149         while (itr1.hasNext()) {
150             Element hintCollection = itr1.next();
151 
152             String name = hintCollection.attributeValue("name");
153 
154             Map<String, String> hints = _hintCollections.get(name);
155 
156             if (hints == null) {
157                 hints = new HashMap<String, String>();
158 
159                 _hintCollections.put(name, hints);
160             }
161 
162             Iterator<Element> itr2 = hintCollection.elements("hint").iterator();
163 
164             while (itr2.hasNext()) {
165                 Element hint = itr2.next();
166 
167                 String hintName = hint.attributeValue("name");
168                 String hintValue = hint.getText();
169 
170                 hints.put(hintName, hintValue);
171             }
172         }
173 
174         itr1 = root.elements("model").iterator();
175 
176         while (itr1.hasNext()) {
177             Element model = itr1.next();
178 
179             String name = model.attributeValue("name");
180 
181             if (classLoader != ModelHintsImpl.class.getClassLoader()) {
182                 ClassNameLocalServiceUtil.getClassName(name);
183             }
184 
185             Map<String, String> defaultHints = new HashMap<String, String>();
186 
187             _defaultHints.put(name, defaultHints);
188 
189             Element defaultHintsEl = model.element("default-hints");
190 
191             if (defaultHintsEl != null) {
192                 Iterator<Element> itr2 = defaultHintsEl.elements(
193                     "hint").iterator();
194 
195                 while (itr2.hasNext()) {
196                     Element hint = itr2.next();
197 
198                     String hintName = hint.attributeValue("name");
199                     String hintValue = hint.getText();
200 
201                     defaultHints.put(hintName, hintValue);
202                 }
203             }
204 
205             Map<String, Object> fields =
206                 (Map<String, Object>)_modelFields.get(name);
207 
208             if (fields == null) {
209                 fields = new HashMap<String, Object>();
210 
211                 _modelFields.put(name, fields);
212             }
213 
214             _models.add(name);
215 
216             Iterator<Element> itr2 = model.elements("field").iterator();
217 
218             while (itr2.hasNext()) {
219                 Element field = itr2.next();
220 
221                 String fieldName = field.attributeValue("name");
222                 String fieldType = field.attributeValue("type");
223 
224                 Map<String, String> fieldHints = new HashMap<String, String>();
225 
226                 fieldHints.putAll(defaultHints);
227 
228                 Iterator<Element> itr3 = field.elements(
229                     "hint-collection").iterator();
230 
231                 while (itr3.hasNext()) {
232                     Element hintCollection = itr3.next();
233 
234                     Map<String, String> hints = _hintCollections.get(
235                         hintCollection.attributeValue("name"));
236 
237                     fieldHints.putAll(hints);
238                 }
239 
240                 itr3 = field.elements("hint").iterator();
241 
242                 while (itr3.hasNext()) {
243                     Element hint = itr3.next();
244 
245                     String hintName = hint.attributeValue("name");
246                     String hintValue = hint.getText();
247 
248                     fieldHints.put(hintName, hintValue);
249                 }
250 
251                 fields.put(fieldName + _ELEMENTS_SUFFIX, field);
252                 fields.put(fieldName + _TYPE_SUFFIX, fieldType);
253                 fields.put(fieldName + _HINTS_SUFFIX, fieldHints);
254             }
255         }
256     }
257 
258     public void setSAXReader(SAXReader saxReader) {
259         _saxReader = saxReader;
260     }
261 
262     public String trimString(String model, String field, String value) {
263         if (value == null) {
264             return value;
265         }
266 
267         Map<String, String> hints = getHints(model, field);
268 
269         if (hints == null) {
270             return value;
271         }
272 
273         int maxLength = GetterUtil.getInteger(
274             ModelHintsConstants.TEXT_MAX_LENGTH);
275 
276         maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
277 
278         if (value.length() > maxLength) {
279             return value.substring(0, maxLength);
280         }
281         else {
282             return value;
283         }
284     }
285 
286     private static final String _ELEMENTS_SUFFIX = "_ELEMENTS";
287 
288     private static final String _TYPE_SUFFIX = "_TYPE";
289 
290     private static final String _HINTS_SUFFIX = "_HINTS";
291 
292     private static Log _log = LogFactoryUtil.getLog(ModelHintsImpl.class);
293 
294     private Map<String, Map<String, String>> _hintCollections;
295     private Map<String, Map<String, String>> _defaultHints;
296     private Map<String, Object> _modelFields;
297     private Set<String> _models;
298     private SAXReader _saxReader;
299 
300 }