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 return;
216 }
217 else {
218 if (_log.isDebugEnabled()) {
219 _log.debug("Loading " + source);
220 }
221 }
222
223 Document doc = _saxReader.read(is);
224
225 Element root = doc.getRootElement();
226
227 Iterator<Element> itr1 = root.elements("hint-collection").iterator();
228
229 while (itr1.hasNext()) {
230 Element hintCollection = itr1.next();
231
232 String name = hintCollection.attributeValue("name");
233
234 Map<String, String> hints = _hintCollections.get(name);
235
236 if (hints == null) {
237 hints = new HashMap<String, String>();
238
239 _hintCollections.put(name, hints);
240 }
241
242 Iterator<Element> itr2 = hintCollection.elements("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 hints.put(hintName, hintValue);
251 }
252 }
253
254 itr1 = root.elements("model").iterator();
255
256 while (itr1.hasNext()) {
257 Element model = itr1.next();
258
259 String name = model.attributeValue("name");
260
261 if (classLoader != ModelHintsImpl.class.getClassLoader()) {
262 ClassNameLocalServiceUtil.getClassName(name);
263 }
264
265 Map<String, String> defaultHints = new HashMap<String, String>();
266
267 _defaultHints.put(name, defaultHints);
268
269 Element defaultHintsEl = model.element("default-hints");
270
271 if (defaultHintsEl != null) {
272 Iterator<Element> itr2 = defaultHintsEl.elements(
273 "hint").iterator();
274
275 while (itr2.hasNext()) {
276 Element hint = itr2.next();
277
278 String hintName = hint.attributeValue("name");
279 String hintValue = hint.getText();
280
281 defaultHints.put(hintName, hintValue);
282 }
283 }
284
285 Map<String, Object> fields = (Map<String, Object>)_modelFields.get(
286 name);
287
288 if (fields == null) {
289 fields = new LinkedHashMap<String, Object>();
290
291 _modelFields.put(name, fields);
292 }
293
294 _models.add(name);
295
296 Iterator<Element> itr2 = model.elements("field").iterator();
297
298 while (itr2.hasNext()) {
299 Element field = itr2.next();
300
301 String fieldName = field.attributeValue("name");
302 String fieldType = field.attributeValue("type");
303 boolean fieldLocalized = GetterUtil.getBoolean(
304 field.attributeValue("localized"));
305
306 Map<String, String> fieldHints = new HashMap<String, String>();
307
308 fieldHints.putAll(defaultHints);
309
310 Iterator<Element> itr3 = field.elements(
311 "hint-collection").iterator();
312
313 while (itr3.hasNext()) {
314 Element hintCollection = itr3.next();
315
316 Map<String, String> hints = _hintCollections.get(
317 hintCollection.attributeValue("name"));
318
319 fieldHints.putAll(hints);
320 }
321
322 itr3 = field.elements("hint").iterator();
323
324 while (itr3.hasNext()) {
325 Element hint = itr3.next();
326
327 String hintName = hint.attributeValue("name");
328 String hintValue = hint.getText();
329
330 fieldHints.put(hintName, hintValue);
331 }
332
333 Tuple fieldSanitize = null;
334
335 Element sanitize = field.element("sanitize");
336
337 if (sanitize != null) {
338 String contentType = sanitize.attributeValue(
339 "content-type");
340 String modes = sanitize.attributeValue("modes");
341
342 fieldSanitize = new Tuple(fieldName, contentType, modes);
343 }
344
345 Map<String, Tuple> fieldValidators =
346 new TreeMap<String, Tuple>();
347
348 itr3 = field.elements("validator").iterator();
349
350 while (itr3.hasNext()) {
351 Element validator = itr3.next();
352
353 String validatorName = validator.attributeValue("name");
354
355 if (Validator.isNull(validatorName)) {
356 continue;
357 }
358
359 String validatorErrorMessage = GetterUtil.getString(
360 validator.attributeValue("error-message"));
361 String validatorValue = GetterUtil.getString(
362 validator.getText());
363 boolean customValidator = isCustomValidator(validatorName);
364
365 if (customValidator) {
366 validatorName = buildCustomValidatorName(validatorName);
367 }
368
369 Tuple fieldValidator = new Tuple(
370 fieldName, validatorName, validatorErrorMessage,
371 validatorValue, customValidator);
372
373 fieldValidators.put(validatorName, fieldValidator);
374 }
375
376 fields.put(fieldName + _ELEMENTS_SUFFIX, field);
377 fields.put(fieldName + _TYPE_SUFFIX, fieldType);
378 fields.put(fieldName + _LOCALIZATION_SUFFIX, fieldLocalized);
379 fields.put(fieldName + _HINTS_SUFFIX, fieldHints);
380
381 if (fieldSanitize != null) {
382 fields.put(fieldName + _SANITIZE_SUFFIX, fieldSanitize);
383 }
384
385 if (!fieldValidators.isEmpty()) {
386 fields.put(
387 fieldName + _VALIDATORS_SUFFIX,
388 ListUtil.fromMapValues(fieldValidators));
389 }
390 }
391 }
392 }
393
394 public void setSAXReader(SAXReader saxReader) {
395 _saxReader = saxReader;
396 }
397
398 public String trimString(String model, String field, String value) {
399 if (value == null) {
400 return value;
401 }
402
403 Map<String, String> hints = getHints(model, field);
404
405 if (hints == null) {
406 return value;
407 }
408
409 int maxLength = GetterUtil.getInteger(
410 ModelHintsConstants.TEXT_MAX_LENGTH);
411
412 maxLength = GetterUtil.getInteger(hints.get("max-length"), maxLength);
413
414 if (value.length() > maxLength) {
415 return value.substring(0, maxLength);
416 }
417 else {
418 return value;
419 }
420 }
421
422 private static final String _ELEMENTS_SUFFIX = "_ELEMENTS";
423
424 private static final String _HINTS_SUFFIX = "_HINTS";
425
426 private static final String _LOCALIZATION_SUFFIX = "_LOCALIZATION";
427
428 private static final String _SANITIZE_SUFFIX = "_SANITIZE_SUFFIX";
429
430 private static final String _TYPE_SUFFIX = "_TYPE";
431
432 private static final String _VALIDATORS_SUFFIX = "_VALIDATORS";
433
434 private static Log _log = LogFactoryUtil.getLog(ModelHintsImpl.class);
435
436 private Map<String, Map<String, String>> _defaultHints;
437 private Map<String, Map<String, String>> _hintCollections;
438 private Map<String, Object> _modelFields;
439 private Set<String> _models;
440 private SAXReader _saxReader;
441
442 }