001
014
015 package com.liferay.portal.model;
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.PropsKeys;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Tuple;
025 import com.liferay.portal.kernel.util.Validator;
026 import com.liferay.portal.kernel.xml.Document;
027 import com.liferay.portal.kernel.xml.Element;
028 import com.liferay.portal.kernel.xml.SAXReader;
029 import com.liferay.portal.service.ClassNameLocalServiceUtil;
030 import com.liferay.portal.util.PropsUtil;
031 import com.liferay.util.PwdGenerator;
032
033 import java.io.InputStream;
034
035 import java.util.ArrayList;
036 import java.util.Collections;
037 import java.util.HashMap;
038 import java.util.Iterator;
039 import java.util.LinkedHashMap;
040 import java.util.List;
041 import java.util.Map;
042 import java.util.Set;
043 import java.util.TreeMap;
044 import java.util.TreeSet;
045
046
049 public class ModelHintsImpl implements ModelHints {
050
051 public void afterPropertiesSet() {
052 _hintCollections = new HashMap<String, Map<String, String>>();
053 _defaultHints = new HashMap<String, Map<String, String>>();
054 _modelFields = new HashMap<String, Object>();
055 _models = new TreeSet<String>();
056
057 try {
058 ClassLoader classLoader = getClass().getClassLoader();
059
060 String[] configs = StringUtil.split(
061 PropsUtil.get(PropsKeys.MODEL_HINTS_CONFIGS));
062
063 for (int i = 0; i < configs.length; i++) {
064 read(classLoader, configs[i]);
065 }
066 }
067 catch (Exception e) {
068 _log.error(e, e);
069 }
070 }
071
072 public String buildCustomValidatorName(String validatorName) {
073 return validatorName.concat(StringPool.UNDERLINE).concat(
074 PwdGenerator.getPassword(PwdGenerator.KEY3, 4));
075 }
076
077 public Map<String, String> getDefaultHints(String model) {
078 return _defaultHints.get(model);
079 }
080
081 public com.liferay.portal.kernel.xml.Element getFieldsEl(
082 String model, String field) {
083
084 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
085 model);
086
087 if (fields == null) {
088 return null;
089 }
090 else {
091 Element fieldsEl = (Element)fields.get(field + _ELEMENTS_SUFFIX);
092
093 if (fieldsEl == null) {
094 return null;
095 }
096 else {
097 return fieldsEl;
098 }
099 }
100 }
101
102 public Map<String, String> getHints(String model, String field) {
103 Map<String, Object> fields =
104 (Map<String, Object>)_modelFields.get(model);
105
106 if (fields == null) {
107 return null;
108 }
109 else {
110 return (Map<String, String>)fields.get(field + _HINTS_SUFFIX);
111 }
112 }
113
114 public List<String> getModels() {
115 return ListUtil.fromCollection(_models);
116 }
117
118 public Tuple getSanitizeTuple(String model, String field) {
119 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
120 model);
121
122 if (fields == null) {
123 return null;
124 }
125 else {
126 return (Tuple)fields.get(field + _SANITIZE_SUFFIX);
127 }
128 }
129
130 public List<Tuple> getSanitizeTuples(String model) {
131 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
132 model);
133
134 if (fields == null) {
135 return Collections.emptyList();
136 }
137 else {
138 List<Tuple> sanitizeTuples = new ArrayList<Tuple>();
139
140 for (Map.Entry<String, Object> entry : fields.entrySet()) {
141 String key = entry.getKey();
142
143 if (key.endsWith(_SANITIZE_SUFFIX)) {
144 Tuple sanitizeTuple = (Tuple)entry.getValue();
145
146 sanitizeTuples.add(sanitizeTuple);
147 }
148 }
149
150 return sanitizeTuples;
151 }
152 }
153
154 public String getType(String model, String field) {
155 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
156 model);
157
158 if (fields == null) {
159 return null;
160 }
161 else {
162 return (String)fields.get(field + _TYPE_SUFFIX);
163 }
164 }
165
166 public List<Tuple> getValidators(String model, String field) {
167 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
168 model);
169
170 if ((fields == null) ||
171 (fields.get(field + _VALIDATORS_SUFFIX) == null)) {
172
173 return null;
174 }
175 else {
176 return (List<Tuple>)fields.get(field + _VALIDATORS_SUFFIX);
177 }
178 }
179
180 public boolean isCustomValidator(String validatorName) {
181 if (validatorName.equals("custom")) {
182 return true;
183 }
184
185 return false;
186 }
187
188 public boolean isLocalized(String model, String field) {
189 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
190 model);
191
192 if (fields == null) {
193 return false;
194 }
195 else {
196 Boolean localized = (Boolean)fields.get(
197 field + _LOCALIZATION_SUFFIX);
198
199 if (localized != null) {
200 return localized;
201 }
202 else {
203 return false;
204 }
205 }
206 }
207
208 public void read(ClassLoader classLoader, String source) throws Exception {
209 InputStream is = classLoader.getResourceAsStream(source);
210
211 if (is == null) {
212 if (_log.isWarnEnabled()) {
213 _log.warn("Cannot load " + source);
214 }
215
216 return;
217 }
218 else {
219 if (_log.isDebugEnabled()) {
220 _log.debug("Loading " + source);
221 }
222 }
223
224 Document doc = _saxReader.read(is);
225
226 Element root = doc.getRootElement();
227
228 Iterator<Element> itr1 = root.elements("hint-collection").iterator();
229
230 while (itr1.hasNext()) {
231 Element hintCollection = itr1.next();
232
233 String name = hintCollection.attributeValue("name");
234
235 Map<String, String> hints = _hintCollections.get(name);
236
237 if (hints == null) {
238 hints = new HashMap<String, String>();
239
240 _hintCollections.put(name, hints);
241 }
242
243 Iterator<Element> itr2 = hintCollection.elements("hint").iterator();
244
245 while (itr2.hasNext()) {
246 Element hint = itr2.next();
247
248 String hintName = hint.attributeValue("name");
249 String hintValue = hint.getText();
250
251 hints.put(hintName, hintValue);
252 }
253 }
254
255 itr1 = root.elements("model").iterator();
256
257 while (itr1.hasNext()) {
258 Element model = itr1.next();
259
260 String name = model.attributeValue("name");
261
262 if (classLoader != ModelHintsImpl.class.getClassLoader()) {
263 ClassNameLocalServiceUtil.getClassName(name);
264 }
265
266 Map<String, String> defaultHints = new HashMap<String, String>();
267
268 _defaultHints.put(name, defaultHints);
269
270 Element defaultHintsEl = model.element("default-hints");
271
272 if (defaultHintsEl != null) {
273 Iterator<Element> itr2 = defaultHintsEl.elements(
274 "hint").iterator();
275
276 while (itr2.hasNext()) {
277 Element hint = itr2.next();
278
279 String hintName = hint.attributeValue("name");
280 String hintValue = hint.getText();
281
282 defaultHints.put(hintName, hintValue);
283 }
284 }
285
286 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
287 name);
288
289 if (fields == null) {
290 fields = new LinkedHashMap<String, Object>();
291
292 _modelFields.put(name, fields);
293 }
294
295 _models.add(name);
296
297 Iterator<Element> itr2 = model.elements("field").iterator();
298
299 while (itr2.hasNext()) {
300 Element field = itr2.next();
301
302 String fieldName = field.attributeValue("name");
303 String fieldType = field.attributeValue("type");
304 boolean fieldLocalized = GetterUtil.getBoolean(
305 field.attributeValue("localized"));
306
307 Map<String, String> fieldHints = new HashMap<String, String>();
308
309 fieldHints.putAll(defaultHints);
310
311 Iterator<Element> itr3 = field.elements(
312 "hint-collection").iterator();
313
314 while (itr3.hasNext()) {
315 Element hintCollection = itr3.next();
316
317 Map<String, String> hints = _hintCollections.get(
318 hintCollection.attributeValue("name"));
319
320 fieldHints.putAll(hints);
321 }
322
323 itr3 = field.elements("hint").iterator();
324
325 while (itr3.hasNext()) {
326 Element hint = itr3.next();
327
328 String hintName = hint.attributeValue("name");
329 String hintValue = hint.getText();
330
331 fieldHints.put(hintName, hintValue);
332 }
333
334 Tuple fieldSanitize = null;
335
336 Element sanitize = field.element("sanitize");
337
338 if (sanitize != null) {
339 String contentType = sanitize.attributeValue(
340 "content-type");
341 String modes = sanitize.attributeValue("modes");
342
343 fieldSanitize = new Tuple(fieldName, contentType, modes);
344 }
345
346 Map<String, Tuple> fieldValidators =
347 new TreeMap<String, Tuple>();
348
349 itr3 = field.elements("validator").iterator();
350
351 while (itr3.hasNext()) {
352 Element validator = itr3.next();
353
354 String validatorName = validator.attributeValue("name");
355
356 if (Validator.isNull(validatorName)) {
357 continue;
358 }
359
360 String validatorErrorMessage = GetterUtil.getString(
361 validator.attributeValue("error-message"));
362 String validatorValue = GetterUtil.getString(
363 validator.getText());
364 boolean customValidator = isCustomValidator(validatorName);
365
366 if (customValidator) {
367 validatorName = buildCustomValidatorName(validatorName);
368 }
369
370 Tuple fieldValidator = new Tuple(
371 fieldName, validatorName, validatorErrorMessage,
372 validatorValue, customValidator);
373
374 fieldValidators.put(validatorName, fieldValidator);
375 }
376
377 fields.put(fieldName + _ELEMENTS_SUFFIX, field);
378 fields.put(fieldName + _TYPE_SUFFIX, fieldType);
379 fields.put(fieldName + _LOCALIZATION_SUFFIX, fieldLocalized);
380 fields.put(fieldName + _HINTS_SUFFIX, fieldHints);
381
382 if (fieldSanitize != null) {
383 fields.put(fieldName + _SANITIZE_SUFFIX, fieldSanitize);
384 }
385
386 if (!fieldValidators.isEmpty()) {
387 fields.put(
388 fieldName + _VALIDATORS_SUFFIX,
389 ListUtil.fromMapValues(fieldValidators));
390 }
391 }
392 }
393 }
394
395 public void setSAXReader(SAXReader saxReader) {
396 _saxReader = saxReader;
397 }
398
399 public String trimString(String model, String field, String value) {
400 if (value == null) {
401 return value;
402 }
403
404 Map<String, String> hints = getHints(model, field);
405
406 if (hints == null) {
407 return value;
408 }
409
410 int maxLength = GetterUtil.getInteger(
411 ModelHintsConstants.TEXT_MAX_LENGTH);
412
413 maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
414
415 if (value.length() > maxLength) {
416 return value.substring(0, maxLength);
417 }
418 else {
419 return value;
420 }
421 }
422
423 private static final String _ELEMENTS_SUFFIX = "_ELEMENTS";
424
425 private static final String _HINTS_SUFFIX = "_HINTS";
426
427 private static final String _LOCALIZATION_SUFFIX = "_LOCALIZATION";
428
429 private static final String _SANITIZE_SUFFIX = "_SANITIZE_SUFFIX";
430
431 private static final String _TYPE_SUFFIX = "_TYPE";
432
433 private static final String _VALIDATORS_SUFFIX = "_VALIDATORS";
434
435 private static Log _log = LogFactoryUtil.getLog(ModelHintsImpl.class);
436
437 private Map<String, Map<String, String>> _defaultHints;
438 private Map<String, Map<String, String>> _hintCollections;
439 private Map<String, Object> _modelFields;
440 private Set<String> _models;
441 private SAXReader _saxReader;
442
443 }