blob: ef3c0d2acbf6e156b8f0b1c82def90ba5e89a02a [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.intellij.openapi.util;
import com.intellij.reference.SoftReference;
import com.intellij.util.ArrayUtilRt;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
/**
* @author max
*/
public class Conditions {
private Conditions() {}
@NotNull
public static <T> Condition<T> alwaysTrue() {
return (Condition<T>)TRUE;
}
@NotNull
public static <T> Condition<T> alwaysFalse() {
return (Condition<T>)FALSE;
}
public static <T> Condition<T> instanceOf(final Class<?> clazz) {
return new Condition<T>() {
@Override
public boolean value(T t) {
return clazz.isInstance(t);
}
};
}
public static <T> Condition<T> is(final T option) {
return new Condition<T>() {
@Override
public boolean value(T t) {
return Comparing.equal(t, option);
}
};
}
public static <T> Condition<T> oneOf(final T... options) {
return new Condition<T>() {
@Override
public boolean value(T t) {
return ArrayUtilRt.find(options, t) >= 0;
}
};
}
public static <T> Condition<T> not(Condition<T> c) {
return new Not<T>(c);
}
public static <T> Condition<T> and(Condition<T> c1, Condition<T> c2) {
return new And<T>(c1, c2);
}
public static <T> Condition<T> or(Condition<T> c1, Condition<T> c2) {
return new Or<T>(c1, c2);
}
public static <T> Condition<T> cached(Condition<T> c) {
return new SoftRefCache<T>(c);
}
private static class Not<T> implements Condition<T> {
private final Condition<T> myCondition;
public Not(Condition<T> condition) {
myCondition = condition;
}
@Override
public boolean value(T value) {
return !myCondition.value(value);
}
}
private static class And<T> implements Condition<T> {
private final Condition<T> t1;
private final Condition<T> t2;
public And(final Condition<T> t1, final Condition<T> t2) {
this.t1 = t1;
this.t2 = t2;
}
@Override
public boolean value(final T object) {
return t1.value(object) && t2.value(object);
}
}
private static class Or<T> implements Condition<T> {
private final Condition<T> t1;
private final Condition<T> t2;
public Or(final Condition<T> t1, final Condition<T> t2) {
this.t1 = t1;
this.t2 = t2;
}
@Override
public boolean value(final T object) {
return t1.value(object) || t2.value(object);
}
}
public static Condition<Object> TRUE = new Condition<Object>() {
@Override
public boolean value(final Object object) {
return true;
}
};
public static Condition<Object> FALSE = new Condition<Object>() {
@Override
public boolean value(final Object object) {
return false;
}
};
private static class SoftRefCache<T> implements Condition<T> {
private final HashMap<Integer, Pair<SoftReference<T>, Boolean>> myCache = new HashMap<Integer, Pair<SoftReference<T>, Boolean>>();
private final Condition<T> myCondition;
public SoftRefCache(Condition<T> condition) {
myCondition = condition;
}
@Override
public final boolean value(T object) {
final int key = object.hashCode();
final Pair<SoftReference<T>, Boolean> entry = myCache.get(key);
if (entry == null || entry.first.get() != object) {
boolean value = myCondition.value(object);
myCache.put(key, Pair.create(new SoftReference<T>(object), value));
return value;
}
else {
return entry.second;
}
}
}
}