001/* 002 * (C) Copyright 2014-2018 Nuxeo (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 018 */ 019 020package org.nuxeo.ecm.core.schema.types.constraints; 021 022import java.util.ArrayList; 023import java.util.Calendar; 024import java.util.Date; 025import java.util.List; 026import java.util.Locale; 027import java.util.MissingResourceException; 028 029import org.apache.commons.lang3.StringUtils; 030import org.apache.commons.logging.Log; 031import org.apache.commons.logging.LogFactory; 032import org.nuxeo.common.utils.i18n.I18NUtils; 033 034/** 035 * <p> 036 * This constraint ensures some date representation is in an enumeration. 037 * </p> 038 * <p> 039 * This constraint can validate any {@link Date} or {@link Calendar}. This constraint also support {@link Number} types 040 * whose long value is recognised as number of milliseconds since January 1, 1970, 00:00:00 GMT. 041 * </p> 042 * 043 * @since 7.1 044 */ 045public abstract class AbstractConstraint implements Constraint { 046 047 private static final long serialVersionUID = 1L; 048 049 private static final Log log = LogFactory.getLog(AbstractConstraint.class); 050 051 private static final String HARD_CODED_CONTRAINT_ERROR_MESSAGE = "The constraint '%s' failed for value %s"; 052 053 @Override 054 public final String toString() { 055 return getDescription().toString(); 056 } 057 058 @Override 059 public String getErrorMessage(Object invalidValue, Locale locale) { 060 // test whether there's a constraint specific translation 061 // the expected key is label.schema.constraint.violation.[TheConstraintName] 062 // if there's none, replies to a generic message 063 // the expected key is label.schema.constraint.violation 064 // if there's none, replies to a hard coded message 065 List<String> pathTokens = new ArrayList<>(); 066 pathTokens.add(MESSAGES_KEY); 067 pathTokens.add(getDescription().getName()); 068 String keyConstraint = StringUtils.join(pathTokens, '.'); 069 String computedInvalidValue = "null"; 070 if (invalidValue != null) { 071 String invalidValueString = invalidValue.toString(); 072 if (invalidValueString.length() > 20) { 073 computedInvalidValue = invalidValueString.substring(0, 15) + "..."; 074 } else { 075 computedInvalidValue = invalidValueString; 076 } 077 } 078 Object[] params = new Object[] { computedInvalidValue }; 079 Locale computedLocale = locale != null ? locale : Constraint.MESSAGES_DEFAULT_LANG; 080 String message = getMessageString(MESSAGES_BUNDLE, keyConstraint, params, computedLocale); 081 082 if (message != null && !message.trim().isEmpty() && !keyConstraint.equals(message)) { 083 // use a constraint specific message if there's one 084 return message; 085 } else { 086 params = new Object[] { computedInvalidValue, toString() }; 087 message = getMessageString(MESSAGES_BUNDLE, MESSAGES_KEY, params, computedLocale); 088 if (message != null && !message.trim().isEmpty() && !keyConstraint.equals(message)) { 089 // use a generic message if there's one 090 return message; 091 } else { 092 // use a hard coded message 093 return String.format(HARD_CODED_CONTRAINT_ERROR_MESSAGE, toString(), computedInvalidValue); 094 } 095 } 096 } 097 098 /** 099 * Try to get the message from the given message bundle. If the bundle is not found or the key is not found, return 100 * null. 101 * 102 * @since 7.2 103 */ 104 public static String getMessageString(String bundleName, String key, Object[] params, Locale locale) { 105 try { 106 return I18NUtils.getMessageString(MESSAGES_BUNDLE, key, params, locale); 107 } catch (MissingResourceException e) { 108 log.trace("No bundle found", e); 109 return null; 110 } 111 } 112 113}