package cmu.conditional;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import de.fosd.typechef.featureexpr.FeatureExpr;
import gov.nasa.jpf.vm.MJIEnv;
/**
* Non conditional value.
*
* @author Jens Meinicke
*
* @param <T>
*/
public class One<T> extends Conditional<T> implements Cloneable {
public static final One<?> NULL = new One<>(null);
public static final One<Boolean> FALSE = new One<>(Boolean.FALSE);
public static final One<Boolean> TRUE = new One<>(Boolean.TRUE);
public static final One<Integer> MJIEnvNULL = new One<>(MJIEnv.NULL);
private T value;
public One(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public T getValue(final boolean ignore) {
return getValue();
}
@Override
public <U> Conditional<U> mapfr(FeatureExpr inFeature, BiFunction<FeatureExpr, T, Conditional<U>> f) {
return f.apply(inFeature, value);
}
@Override
public void mapfr(FeatureExpr inFeature, BiConsumer<FeatureExpr, T> f) {
f.accept(inFeature, value);
}
@Override
public String toString() {
String s = "One(";
if (value instanceof int[]) {
s += Arrays.toString((int[]) value);
} else if (value instanceof long[]) {
s += Arrays.toString((long[]) value);
} else if (value instanceof double[]) {
s += Arrays.toString((double[]) value);
} else if (value instanceof float[]) {
s += Arrays.toString((float[]) value);
} else if (value instanceof char[]) {
s += Arrays.toString((char[]) value);
} else {
s += value;
}
return s + ')';
}
@Override
public Conditional<T> simplify(FeatureExpr ctx) {
if (ctx == null) {
throw new RuntimeException("ctx == null");
}
return this;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof One) {
if (value == ((One<?>) obj).value) {
return true;
}
if (value instanceof char[]) {
Arrays.equals((char[]) value, (char[]) ((One<?>) obj).value);
}
if (((One<?>) obj).value != null && value != null && ((One<?>) obj).value.equals(value))
return true;
}
return false;
}
public int hashCode() {
return value.hashCode();
}
@Override
public List<T> toList() {
List<T> list = new LinkedList<>();
list.add(value);
return list;
}
@Override
protected void toMap(FeatureExpr f, Map<T, FeatureExpr> map) {
FeatureExpr ctx = map.get(value);
if (ctx == null) {
map.put(value, f);
} else {
map.put(value, f.or(ctx));
}
}
@Override
public Conditional<T> clone() {
return new One<>(value);
}
@Override
public Conditional<T> simplifyValues() {
return this;
}
@Override
public int size() {
return 1;
}
/*################################################
* cache methods for int, byte, char
*/
public static One<Boolean> valueOf(boolean value) {
return value ? TRUE : FALSE;
}
/**
* Only use this for values: -128 <= x <= 128
* @return Returns a cached One<Integer>
*/
public static One<Integer> valueOf(int value) {
if (-128 <= value && value <= 128) {
return IntegerCache.cache[value + 128];
}
return new One<>(value);
}
@SuppressWarnings("unchecked")
private static class IntegerCache {
static final One<Integer>[] cache = new One[128- (-128) + 1];
static {
int j = -128;
for (int k = 0; k < cache.length; ++k) {
cache[k] = new One<>(Integer.valueOf(j++));
}
}
}
public static One<Byte> valueOf(byte value) {
return ByteCache.cache[value - Byte.MIN_VALUE];
}
@SuppressWarnings("unchecked")
private static class ByteCache {
static final One<Byte>[] cache = new One[-Byte.MIN_VALUE + Byte.MAX_VALUE + 1];
static {
byte j = Byte.MIN_VALUE;
for (int k = 0; k < cache.length; ++k) {
cache[k] = new One<>(Byte.valueOf(j++));
}
}
}
public static One<Character> valueOf(char c) {
if (c <= 127) {
return CharacterCache.cache[(int)c];
}
return new One<>(c);
}
@SuppressWarnings("unchecked")
private static class CharacterCache {
static final One<Character>[] cache = new One[127 + 1];
static {
for (int k = 0; k < cache.length; k++) {
cache[k] = new One<>(Character.valueOf((char)k));
}
}
}
@Override
public boolean isOne() {
return true;
}
}