/*
* Copyright 2015, The Querydsl Team (http://www.querydsl.com/team)
*
* 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.querydsl.core.types;
import javax.annotation.concurrent.Immutable;
/**
* {@code ConstantImpl} is the default implementation of the {@link Constant} interface
*
* @author tiwe
* @param <T> expression type
*/
@Immutable
public final class ConstantImpl<T> extends ExpressionBase<T> implements Constant<T> {
private static final long serialVersionUID = -3898138057967814118L;
private static final int CACHE_SIZE = 256;
private static class Constants {
@SuppressWarnings({"rawtypes", "unchecked"}) //generic array creation not possible
private static final Constant<Character>[] CHARACTERS = new Constant[CACHE_SIZE];
@SuppressWarnings({"rawtypes", "unchecked"}) //generic array creation not possible
private static final Constant<Byte>[] BYTES = new Constant[CACHE_SIZE];
@SuppressWarnings({"rawtypes", "unchecked"}) //generic array creation not possible
private static final Constant<Integer>[] INTEGERS = new Constant[CACHE_SIZE];
@SuppressWarnings({"rawtypes", "unchecked"}) //generic array creation not possible
private static final Constant<Long>[] LONGS = new Constant[CACHE_SIZE];
@SuppressWarnings({"rawtypes", "unchecked"}) //generic array creation not possible
private static final Constant<Short>[] SHORTS = new Constant[CACHE_SIZE];
private static final Constant<Boolean> FALSE = new ConstantImpl<Boolean>(Boolean.FALSE);
private static final Constant<Boolean> TRUE = new ConstantImpl<Boolean>(Boolean.TRUE);
static {
for (int i = 0; i < CACHE_SIZE; i++) {
INTEGERS[i] = new ConstantImpl<Integer>(Integer.class, i);
SHORTS[i] = new ConstantImpl<Short>(Short.class, (short) i);
BYTES[i] = new ConstantImpl<Byte>(Byte.class, (byte) i);
CHARACTERS[i] = new ConstantImpl<Character>(Character.class, (char) i);
LONGS[i] = new ConstantImpl<Long>(Long.class, (long) i);
}
}
}
public static Constant<Boolean> create(boolean b) {
return b ? Constants.TRUE : Constants.FALSE;
}
public static Constant<Byte> create(byte i) {
if (i >= 0) {
return Constants.BYTES[i];
} else {
return new ConstantImpl<Byte>(Byte.class, i);
}
}
public static Constant<Character> create(char i) {
if (i < CACHE_SIZE) {
return Constants.CHARACTERS[i];
} else {
return new ConstantImpl<Character>(Character.class, i);
}
}
public static Constant<Integer> create(int i) {
if (i >= 0 && i < CACHE_SIZE) {
return Constants.INTEGERS[i];
} else {
return new ConstantImpl<Integer>(Integer.class, i);
}
}
public static Constant<Long> create(long i) {
if (i >= 0 && i < CACHE_SIZE) {
return Constants.LONGS[(int) i];
} else {
return new ConstantImpl<Long>(Long.class, i);
}
}
public static Constant<Short> create(short i) {
if (i >= 0 && i < CACHE_SIZE) {
return Constants.SHORTS[i];
} else {
return new ConstantImpl<Short>(Short.class, i);
}
}
public static <T> Constant<T> create(T obj) {
return new ConstantImpl<T>(obj);
}
public static <T> Constant<T> create(Class<T> type, T constant) {
return new ConstantImpl<T>(type, constant);
}
private final T constant;
/**
* Create a new Constant for the given object
*
* @param constant constant
*/
@SuppressWarnings("unchecked") //The class of the constant will mandate the type
private ConstantImpl(T constant) {
this((Class) constant.getClass(), constant);
}
/**
* Create a new Constant of the given type for the given object
*
* @param type type of the expression
* @param constant constant
*/
private ConstantImpl(Class<T> type, T constant) {
super(type);
this.constant = constant;
}
@Override
public <R, C> R accept(Visitor<R, C> v, C context) {
return v.visit(this, context);
}
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
} else if (o instanceof Constant<?>) {
return ((Constant<?>) o).getConstant().equals(constant);
} else {
return false;
}
}
@Override
public T getConstant() {
return constant;
}
}