/*
* Copyright 2012-2013 Eric F. Savage, code@efsavage.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ajah.spring.mvc.editor;
import java.beans.PropertyEditorSupport;
import com.ajah.util.Identifiable;
import com.ajah.util.IdentifiableEnum;
import com.ajah.util.StringUtils;
/**
* Generic class that will map an enum based on its {@link Identifiable#getId()}
* method.
*
* @author <a href="http://efsavage.com">Eric F. Savage</a>, <a
* href="mailto:code@efsavage.com">code@efsavage.com</a>.
*
* @param <E>
*/
public class IdentifiableEnumPropertyEditor<E extends IdentifiableEnum<?>> extends PropertyEditorSupport {
private final E[] values;
private final boolean matchId;
private final boolean matchEnumName;
private final boolean matchName;
private final boolean matchCode;
private final boolean caseSensitive;
/**
* Pass the result of Enum.getValues() because I can't seem to find a way to
* derive this from the type parameter.
*
* Matches on ID only, case-sensitive. See
* {@link #IdentifiableEnumPropertyEditor(IdentifiableEnum[], boolean, boolean, boolean, boolean, boolean)}
* for other options.
*
* @param values
* The values of the enum.
*/
public IdentifiableEnumPropertyEditor(final E[] values) {
this(values, true, false, false, false, true);
}
/**
* Pass the result of Enum.getValues() because I can't seem to find a way to
* derive this from the type parameter.
*
* This is the most flexible option, with all matching enabled.
*
* @param values
* The values of the enum.
* @param caseSensitive
* Should matching be case sensitive?
*/
public IdentifiableEnumPropertyEditor(final E[] values, final boolean caseSensitive) {
this(values, true, true, true, true, caseSensitive);
}
/**
* Pass the result of Enum.getValues() because I can't seem to find a way to
* derive this from the type parameter.
*
* @param values
* The values of the enum.
* @param matchId
* Match on the enum's ID?
* @param matchEnumName
* Match on the enum's name() value?
* @param matchName
* Match on the enum's getName() value?
* @param matchCode
* Match on the enum's code ID?
* @param caseSensitive
* Should matching be case sensitive?
*/
public IdentifiableEnumPropertyEditor(final E[] values, final boolean matchId, final boolean matchEnumName, final boolean matchName, final boolean matchCode, final boolean caseSensitive) {
this.values = values;
this.matchId = matchId;
this.matchEnumName = matchEnumName;
this.matchName = matchName;
this.matchCode = matchCode;
this.caseSensitive = caseSensitive;
}
/**
* Matches strings, is aware of the caseSensitive property.
*
* @param first
* The first string to match.
* @param second
* The second string to match.
* @return The results of {@link String#equals(Object)} or
* {@link String#equalsIgnoreCase(String)} as appropriate.
*/
private boolean equals(final String first, final String second) {
if (this.caseSensitive) {
return first.equals(second);
}
return first.equalsIgnoreCase(second);
}
/**
* Gets the property value as a string suitable for presentation to a human
* to edit.
*
* @return The property value as a string suitable for presentation to a
* human to edit.
* <p>
* Returns null if the value can't be expressed as a string.
* <p>
* If a non-null value is returned, then the PropertyEditor should
* be prepared to parse that string back in setAsText().
*/
@SuppressWarnings("unchecked")
@Override
public String getAsText() {
return (getValue() != null) ? ((E) getValue()).getId().toString() : null;
}
/**
* Sets the property value by parsing a given String. May raise
* java.lang.IllegalArgumentException if either the String is badly
* formatted or if this kind of property can't be expressed as text.
*
* @param text
* The string to be parsed.
*/
@Override
public void setAsText(final String text) throws java.lang.IllegalArgumentException {
if (StringUtils.isBlank(text)) {
setValue(null);
return;
}
for (final E candidate : this.values) {
if (this.matchId && equals(candidate.getId().toString(), text)) {
setValue(candidate);
return;
}
if (this.matchEnumName && equals(candidate.name(), text)) {
setValue(candidate);
return;
}
if (this.matchName && equals(candidate.getName(), text)) {
setValue(candidate);
return;
}
if (this.matchCode && equals(candidate.getCode(), text)) {
setValue(candidate);
return;
}
}
throw new java.lang.IllegalArgumentException(text);
}
}