001/* 002 * Copyright 2002-2014 the original author or authors. 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 * https://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 017package org.springframework.beans.propertyeditors; 018 019import java.beans.PropertyEditorSupport; 020 021import org.springframework.util.StringUtils; 022 023/** 024 * Editor for a {@link Character}, to populate a property 025 * of type {@code Character} or {@code char} from a String value. 026 * 027 * <p>Note that the JDK does not contain a default 028 * {@link java.beans.PropertyEditor property editor} for {@code char}! 029 * {@link org.springframework.beans.BeanWrapperImpl} will register this 030 * editor by default. 031 * 032 * <p>Also supports conversion from a Unicode character sequence; e.g. 033 * {@code u0041} ('A'). 034 * 035 * @author Juergen Hoeller 036 * @author Rob Harrop 037 * @author Rick Evans 038 * @since 1.2 039 * @see Character 040 * @see org.springframework.beans.BeanWrapperImpl 041 */ 042public class CharacterEditor extends PropertyEditorSupport { 043 044 /** 045 * The prefix that identifies a string as being a Unicode character sequence. 046 */ 047 private static final String UNICODE_PREFIX = "\\u"; 048 049 /** 050 * The length of a Unicode character sequence. 051 */ 052 private static final int UNICODE_LENGTH = 6; 053 054 055 private final boolean allowEmpty; 056 057 058 /** 059 * Create a new CharacterEditor instance. 060 * <p>The "allowEmpty" parameter controls whether an empty String is to be 061 * allowed in parsing, i.e. be interpreted as the {@code null} value when 062 * {@link #setAsText(String) text is being converted}. If {@code false}, 063 * an {@link IllegalArgumentException} will be thrown at that time. 064 * @param allowEmpty if empty strings are to be allowed 065 */ 066 public CharacterEditor(boolean allowEmpty) { 067 this.allowEmpty = allowEmpty; 068 } 069 070 071 @Override 072 public void setAsText(String text) throws IllegalArgumentException { 073 if (this.allowEmpty && !StringUtils.hasLength(text)) { 074 // Treat empty String as null value. 075 setValue(null); 076 } 077 else if (text == null) { 078 throw new IllegalArgumentException("null String cannot be converted to char type"); 079 } 080 else if (isUnicodeCharacterSequence(text)) { 081 setAsUnicode(text); 082 } 083 else if (text.length() == 1) { 084 setValue(Character.valueOf(text.charAt(0))); 085 } 086 else { 087 throw new IllegalArgumentException("String [" + text + "] with length " + 088 text.length() + " cannot be converted to char type: neither Unicode nor single character"); 089 } 090 } 091 092 @Override 093 public String getAsText() { 094 Object value = getValue(); 095 return (value != null ? value.toString() : ""); 096 } 097 098 099 private boolean isUnicodeCharacterSequence(String sequence) { 100 return (sequence.startsWith(UNICODE_PREFIX) && sequence.length() == UNICODE_LENGTH); 101 } 102 103 private void setAsUnicode(String text) { 104 int code = Integer.parseInt(text.substring(UNICODE_PREFIX.length()), 16); 105 setValue(Character.valueOf((char) code)); 106 } 107 108}