blob: 847dd81cc2a0c165a0181dea5952ed3dccdb183d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.openjpa.persistence;
import java.util.Arrays;
/**
* Converts a given user-specified value to a target type consumable by the kernel.
* Used by hint processing.
*
* @author Pinaki Poddar
* @since 2.0.0
* @unpublished
*/
public interface HintValueConverter {
/**
* Convert the user-specified value to a kernel consumable value.
*
* @param original the user-specified value
* @return an equivalent value consumable by a kernel construct.
*
* @exception IllegalArgumentException if the given value can not be converted.
*/
Object convert(Object original);
/**
* Affirm if this receiver can convert the value of the given type.
*/
boolean canConvert(Class<?> type);
/**
* Convert the enum value to an enumerated set of constants.
*
* @author Pinaki Poddar
*
*/
static class EnumToInteger implements HintValueConverter {
private Class<? extends Enum<?>> _type;
private Integer[] map;
public EnumToInteger(Class<? extends Enum<?>> enumType, int[] numbers) {
try {
_type = enumType;
Enum<?>[] values = (Enum<?>[])enumType.getMethod("values", null).invoke(null, (Class<?>[])null);
map = new Integer[values.length];
int i = 0;
for (Enum<?> v : values) {
map[v.ordinal()] = numbers[i++];
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public Object convert(Object e) {
if (e.getClass() == _type)
return map[((Enum<?>)e).ordinal()];
return e;
}
public boolean canConvert(Class<?> type) {
return Enum.class.isAssignableFrom(type);
}
}
/**
* Converts an OpenJPA specific enum to an equivalent kernel constant.
*
* @author Pinaki Poddar
*
*/
public static class OpenJPAEnumToInteger implements HintValueConverter {
private OpenJPAEnum<?> _prototype;
public OpenJPAEnumToInteger(OpenJPAEnum<?> prototype) {
_prototype = prototype;
}
public Object convert(Object e) {
if (e.getClass() == _prototype.getClass())
return ((OpenJPAEnum<Enum<?>>)e).toKernelConstant();
if (e instanceof String) {
return _prototype.convertToKernelConstant(e.toString());
}
if (e instanceof Integer) {
return _prototype.convertToKernelConstant((Integer)e);
}
return e;
}
public boolean canConvert(Class<?> type) {
return OpenJPAEnum.class.isAssignableFrom(type)
|| type == String.class
|| type == Integer.class
|| type == int.class;
}
}
/**
* Converts a String to an integer.
*
* @author Pinaki Poddar
*
*/
public static class StringToInteger implements HintValueConverter {
private String[] strings;
private Integer[] numbers;
/**
* Construct a converter that will simply translate a numeric string to a integer.
*/
public StringToInteger() {
}
/**
* Construct a converter that will translate any of the given strings to corresponding integer.
* Both arrays must not be null, must not contain null elements and must have the same dimension.
*
* @param strings
* @param numbers
*/
public StringToInteger(String[] strings, int[] numbers) {
if (strings == null || numbers == null || strings.length != numbers.length)
throw new IllegalArgumentException();
this.strings = new String[strings.length];
this.numbers = new Integer[numbers.length];
for (int i = 0; i < strings.length; i++) {
this.strings[i] = strings[i];
this.numbers[i] = numbers[i];
}
}
public Object convert(Object s) {
if (s instanceof String == false)
return s;
String str = s.toString();
if (strings == null) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Can not convert " + str + " . Expected a numeric string");
}
}
for (int i = 0; i < strings.length; i++) {
if (strings[i].equalsIgnoreCase(str))
return numbers[i];
}
throw new IllegalArgumentException("Can not convert " + str + " . Valid input is " +
Arrays.toString(strings));
}
public boolean canConvert(Class<?> cls) {
return String.class == cls;
}
}
public static class StringToBoolean implements HintValueConverter {
public Object convert(Object v) {
if (v instanceof String)
return Boolean.valueOf(v.toString());
if (v instanceof Boolean)
return v;
return v;
}
public boolean canConvert(Class<?> cls) {
return String.class == cls || Boolean.class == cls || boolean.class == cls;
}
}
}