001/* 002 * (C) Copyright 2006-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 * Nuxeo - Thierry Delprat <tdelprat@nuxeo.com> - Mock implementation 018 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 019 */ 020 021package org.nuxeo.ecm.core.schema.types.constraints; 022 023import java.io.Serializable; 024import java.util.ArrayList; 025import java.util.Collections; 026import java.util.HashMap; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Locale; 030import java.util.Map; 031import java.util.Set; 032 033import org.apache.commons.lang3.StringUtils; 034 035/** 036 * <p> 037 * This constraint ensures some object's String representation is in an enumeration. 038 * </p> 039 * 040 * @since 7.1 041 */ 042public class EnumConstraint extends AbstractConstraint { 043 044 private static final long serialVersionUID = 1L; 045 046 private static final String NAME = "EnumConstraint"; 047 048 private static final String PNAME_VALUES = "Values"; 049 050 protected final Set<String> possibleValues; 051 052 /** 053 * Supports any objects, use their String representation. 054 */ 055 public EnumConstraint(List<?> possibleValues) { 056 this.possibleValues = new HashSet<>(); 057 for (Object possibleValue : possibleValues) { 058 this.possibleValues.add(possibleValue.toString()); 059 } 060 } 061 062 public EnumConstraint(Object... possibleValues) { 063 this.possibleValues = new HashSet<>(); 064 for (Object possibleValue : possibleValues) { 065 this.possibleValues.add(possibleValue.toString()); 066 } 067 } 068 069 @Override 070 public boolean validate(Object object) { 071 if (object == null) { 072 return true; 073 } 074 return possibleValues.contains(object.toString()); 075 } 076 077 /** 078 * Here, value is : <br> 079 * name = {@value #NAME} <br> 080 * parameter = 081 * <ul> 082 * <li>{@value #PNAME_VALUES} : List[value1, value2, value3]</li> 083 * </ul> 084 */ 085 @Override 086 public Description getDescription() { 087 Map<String, Serializable> params = new HashMap<>(); 088 params.put(EnumConstraint.PNAME_VALUES, new ArrayList<>(possibleValues)); 089 return new Description(EnumConstraint.NAME, params); 090 } 091 092 public Set<String> getPossibleValues() { 093 return Collections.unmodifiableSet(possibleValues); 094 } 095 096 @Override 097 public String getErrorMessage(Object invalidValue, Locale locale) { 098 // test whether there's a custom translation for this field constraint specific translation 099 // the expected key is label.schema.constraint.violation.[ConstraintName] 100 // follow the AbstractConstraint behavior otherwise 101 List<String> pathTokens = new ArrayList<>(); 102 pathTokens.add(MESSAGES_KEY); 103 pathTokens.add(EnumConstraint.NAME); 104 String key = StringUtils.join(pathTokens, '.'); 105 Object[] params = new Object[] { StringUtils.join(getPossibleValues(), ", ") }; 106 Locale computedLocale = locale != null ? locale : Constraint.MESSAGES_DEFAULT_LANG; 107 String message = getMessageString(MESSAGES_BUNDLE, key, params, computedLocale); 108 if (message != null && !message.trim().isEmpty() && !key.equals(message)) { 109 // use a custom constraint message if there's one 110 return message; 111 } else { 112 // follow AbstractConstraint behavior otherwise 113 return super.getErrorMessage(invalidValue, computedLocale); 114 } 115 } 116 117 @Override 118 public int hashCode() { 119 final int prime = 31; 120 int result = 1; 121 result = prime * result + ((possibleValues == null) ? 0 : possibleValues.hashCode()); 122 return result; 123 } 124 125 @Override 126 public boolean equals(Object obj) { 127 if (this == obj) { 128 return true; 129 } 130 if (obj == null) { 131 return false; 132 } 133 if (getClass() != obj.getClass()) { 134 return false; 135 } 136 EnumConstraint other = (EnumConstraint) obj; 137 if (possibleValues == null) { 138 if (other.possibleValues != null) { 139 return false; 140 } 141 } else if (!possibleValues.equals(other.possibleValues)) { 142 return false; 143 } 144 return true; 145 } 146 147}