package io.ebeaninternal.server.type;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.text.TextException;

import javax.persistence.EnumType;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.util.EnumSet;
import java.util.LinkedHashSet;
import java.util.Set;

JPA standard based Enum scalar type.

Converts between bean Enum types to database string or integer columns.

The limitation of this class is that it converts the Enum to either the ordinal or string value of the Enum. If you wish to convert the Enum to some other value then you should look at the Ebean specific @EnumMapping.

/** * JPA standard based Enum scalar type. * <p> * Converts between bean Enum types to database string or integer columns. * </p> * <p> * The limitation of this class is that it converts the Enum to either the ordinal or string value * of the Enum. If you wish to convert the Enum to some other value then you should look at the * Ebean specific @EnumMapping. * </p> */
public class ScalarTypeEnumStandard { @SuppressWarnings({"rawtypes", "unchecked"}) public static class StringEnum extends EnumBase implements ScalarTypeEnum { private final int length;
Create a ScalarTypeEnum.
/** * Create a ScalarTypeEnum. */
public StringEnum(Class enumType) { super(enumType, false, Types.VARCHAR); this.length = maxValueLength(enumType); } @Override public boolean isCompatible(EnumType enumType) { return EnumType.STRING == enumType; }
Return the IN values for DB constraint construction.
/** * Return the IN values for DB constraint construction. */
@Override public Set<String> getDbCheckConstraintValues() { LinkedHashSet<String> values = new LinkedHashSet<>(); Object[] ea = enumType.getEnumConstants(); for (Object anEa : ea) { Enum<?> e = (Enum<?>) anEa; values.add("'" + e.name() + "'"); } return values; } private int maxValueLength(Class<?> enumType) { int maxLen = 0; Object[] ea = enumType.getEnumConstants(); for (Object anEa : ea) { Enum<?> e = (Enum<?>) anEa; maxLen = Math.max(maxLen, e.name().length()); } return maxLen; } @Override public int getLength() { return length; } @Override public void bind(DataBinder binder, Object value) throws SQLException { if (value == null) { binder.setNull(Types.VARCHAR); } else { binder.setString(format(value)); } } @Override public Object read(DataReader reader) throws SQLException { String string = reader.getString(); if (string == null) { return null; } else { return parse(string); } }
Convert the Boolean value to the db value.
/** * Convert the Boolean value to the db value. */
@Override public Object toJdbcType(Object beanValue) { if (beanValue == null) { return null; } return format(beanValue); } @Override public Object toBeanType(Object dbValue) { if (dbValue == null || dbValue instanceof Enum<?>) { return dbValue; } return Enum.valueOf(enumType, (String) dbValue); } } @SuppressWarnings({"rawtypes", "unchecked"}) public static class OrdinalEnum extends EnumBase implements ScalarTypeEnum { private final Object[] enumArray;
Create a ScalarTypeEnum.
/** * Create a ScalarTypeEnum. */
public OrdinalEnum(Class enumType) { super(enumType, false, Types.INTEGER); this.enumArray = EnumSet.allOf(enumType).toArray(); } @Override public boolean isCompatible(EnumType enumType) { return EnumType.ORDINAL == enumType; }
Return the IN values for DB constraint construction.
/** * Return the IN values for DB constraint construction. */
@Override public Set<String> getDbCheckConstraintValues() { LinkedHashSet<String> values = new LinkedHashSet<>(); for (Object anEnumArray : enumArray) { Enum<?> e = (Enum<?>) anEnumArray; values.add(Integer.toString(e.ordinal())); } return values; } @Override public void bind(DataBinder binder, Object value) throws SQLException { if (value == null) { binder.setNull(Types.INTEGER); } else { binder.setInt(((Enum<?>) value).ordinal()); } } @Override public Object read(DataReader reader) throws SQLException { Integer ordinal = reader.getInt(); if (ordinal == null) { return null; } else { if (ordinal < 0 || ordinal >= enumArray.length) { String m = "Unexpected ordinal [" + ordinal + "] out of range [" + enumArray.length + "]"; throw new IllegalStateException(m); } return enumArray[ordinal]; } }
Convert the Enum value to the db value.
/** * Convert the Enum value to the db value. */
@Override public Object toJdbcType(Object beanValue) { if (beanValue == null) { return null; } return ((Enum<?>) beanValue).ordinal(); }
Convert the db value to the Enum value.
/** * Convert the db value to the Enum value. */
@Override public Object toBeanType(Object dbValue) { if (dbValue == null || dbValue instanceof Enum<?>) { return dbValue; } int ordinal = (Integer) dbValue; if (ordinal < 0 || ordinal >= enumArray.length) { String m = "Unexpected ordinal [" + ordinal + "] out of range [" + enumArray.length + "]"; throw new IllegalStateException(m); } return enumArray[ordinal]; } } @SuppressWarnings({"rawtypes", "unchecked"}) public abstract static class EnumBase extends ScalarTypeBase { protected final Class enumType; public EnumBase(Class<?> type, boolean jdbcNative, int jdbcType) { super(type, jdbcNative, jdbcType); this.enumType = type; } @Override public String format(Object value) { return ((Enum<?>) value).name(); } @Override public String formatValue(Object value) { return ((Enum<?>) value).name(); } @Override public Object parse(String value) { return Enum.valueOf(enumType, value); } @Override public Object convertFromMillis(long systemTimeMillis) { throw new TextException("Not Supported"); } @Override public boolean isDateTimeCapable() { return false; } @Override public Object jsonRead(JsonParser parser) throws IOException { if (parser.getCodec() != null) { return parser.readValueAs(enumType); } else { return parse(parser.getValueAsString()); } } @Override public void jsonWrite(JsonGenerator writer, Object value) throws IOException { if (writer.getCodec() != null) { writer.writeObject(value); } else { writer.writeString(formatValue(value)); } } @Override public DocPropertyType getDocType() { return DocPropertyType.ENUM; } @Override public Object readData(DataInput dataInput) throws IOException { if (!dataInput.readBoolean()) { return null; } else { return parse(dataInput.readUTF()); } } @Override public void writeData(DataOutput dataOutput, Object value) throws IOException { if (value == null) { dataOutput.writeBoolean(false); } else { ScalarHelp.writeUTF(dataOutput, format(value)); } } } }