001/* 002 * (C) Copyright 2014 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 016 */ 017 018package org.nuxeo.ecm.core.schema.types.constraints; 019 020import java.util.ArrayList; 021import java.util.Calendar; 022import java.util.Date; 023import java.util.List; 024import java.util.Locale; 025import java.util.MissingResourceException; 026 027import org.apache.commons.lang.StringUtils; 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030import org.nuxeo.common.utils.i18n.I18NUtils; 031 032/** 033 * <p> 034 * This constraint ensures some date representation is in an enumeration. 035 * </p> 036 * <p> 037 * This constraint can validate any {@link Date} or {@link Calendar}. This constraint also support {@link Number} types 038 * whose long value is recognised as number of milliseconds since January 1, 1970, 00:00:00 GMT. 039 * </p> 040 * 041 * @since 7.1 042 */ 043public abstract class AbstractConstraint implements Constraint { 044 045 private static final long serialVersionUID = 1L; 046 047 private static final Log log = LogFactory.getLog(AbstractConstraint.class); 048 049 private static final String HARD_CODED_CONTRAINT_ERROR_MESSAGE = "The constraint '%s' failed for value %s"; 050 051 @Override 052 public final String toString() { 053 return getDescription().toString(); 054 } 055 056 @Override 057 public String getErrorMessage(Object invalidValue, Locale locale) { 058 // test whether there's a constraint specific translation 059 // the expected key is label.schema.constraint.violation.[TheConstraintName] 060 // if there's none, replies to a generic message 061 // the expected key is label.schema.constraint.violation 062 // if there's none, replies to a hard coded message 063 List<String> pathTokens = new ArrayList<String>(); 064 pathTokens.add(MESSAGES_KEY); 065 pathTokens.add(getDescription().getName()); 066 String keyConstraint = StringUtils.join(pathTokens, '.'); 067 String computedInvalidValue = "null"; 068 if (invalidValue != null) { 069 String invalidValueString = invalidValue.toString(); 070 if (invalidValueString.length() > 20) { 071 computedInvalidValue = invalidValueString.substring(0, 15) + "..."; 072 } else { 073 computedInvalidValue = invalidValueString; 074 } 075 } 076 Object[] params = new Object[] { computedInvalidValue }; 077 Locale computedLocale = locale != null ? locale : Constraint.MESSAGES_DEFAULT_LANG; 078 String message = getMessageString(MESSAGES_BUNDLE, keyConstraint, params, computedLocale); 079 080 if (message != null && !message.trim().isEmpty() && !keyConstraint.equals(message)) { 081 // use a constraint specific message if there's one 082 return message; 083 } else { 084 params = new Object[] { computedInvalidValue, toString() }; 085 message = getMessageString(MESSAGES_BUNDLE, MESSAGES_KEY, params, computedLocale); 086 if (message != null && !message.trim().isEmpty() && !keyConstraint.equals(message)) { 087 // use a generic message if there's one 088 return message; 089 } else { 090 // use a hard coded message 091 return String.format(HARD_CODED_CONTRAINT_ERROR_MESSAGE, toString(), computedInvalidValue); 092 } 093 } 094 } 095 096 /** 097 * Try to get the message from the given message bundle. If the bundle is not found or the key is not found, return 098 * null. 099 * 100 * @since 7.2 101 */ 102 public static String getMessageString(String bundleName, String key, Object[] params, Locale locale) { 103 try { 104 return I18NUtils.getMessageString(MESSAGES_BUNDLE, key, params, locale); 105 } catch (MissingResourceException e) { 106 log.trace("No bundle found", e); 107 return null; 108 } 109 } 110 111}