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