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