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 getMessageKey() { 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 return StringUtils.join(pathTokens, '.'); 069 } 070 071 @Override 072 public String getErrorMessage(Object invalidValue, Locale locale) { 073 String keyConstraint = getMessageKey(); 074 String computedInvalidValue = "null"; 075 if (invalidValue != null) { 076 String invalidValueString = invalidValue.toString(); 077 if (invalidValueString.length() > 20) { 078 computedInvalidValue = invalidValueString.substring(0, 15) + "..."; 079 } else { 080 computedInvalidValue = invalidValueString; 081 } 082 } 083 Object[] params = new Object[] { computedInvalidValue }; 084 Locale computedLocale = locale != null ? locale : Constraint.MESSAGES_DEFAULT_LANG; 085 String message = getMessageString(MESSAGES_BUNDLE, keyConstraint, params, computedLocale); 086 087 if (message != null && !message.trim().isEmpty() && !keyConstraint.equals(message)) { 088 // use a constraint specific message if there's one 089 return message; 090 } else { 091 params = new Object[] { computedInvalidValue, toString() }; 092 message = getMessageString(MESSAGES_BUNDLE, MESSAGES_KEY, params, computedLocale); 093 if (message != null && !message.trim().isEmpty() && !keyConstraint.equals(message)) { 094 // use a generic message if there's one 095 return message; 096 } else { 097 // use a hard coded message 098 return String.format(HARD_CODED_CONTRAINT_ERROR_MESSAGE, toString(), computedInvalidValue); 099 } 100 } 101 } 102 103 /** 104 * Try to get the message from the given message bundle. If the bundle is not found or the key is not found, return 105 * null. 106 * 107 * @since 7.2 108 */ 109 public static String getMessageString(String bundleName, String key, Object[] params, Locale locale) { 110 try { 111 return I18NUtils.getMessageString(MESSAGES_BUNDLE, key, params, locale); 112 } catch (MissingResourceException e) { 113 log.trace("No bundle found", e); 114 return null; 115 } 116 } 117 118}