/*
 * Copyright 2000-2009 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;

/**
 * @author max
 */
public class Conditions {
  private Conditions() {}

  public static <T> Condition<T> alwaysTrue() {
    return (Condition<T>)TRUE;
  }
  public static <T> Condition<T> alwaysFalse() {
    return (Condition<T>)FALSE;
  }

  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);
  }

  private static class Not<T> implements Condition<T> {
    private final Condition<T> myCondition;

    public Not(Condition<T> condition) {
      myCondition = condition;
    }

    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;
    }

    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;
    }

    public boolean value(final T object) {
      return t1.value(object) || t2.value(object);
    }
  }

  public static Condition<Object> TRUE = new Condition<Object>() {
    public boolean value(final Object object) {
      return true;
    }
  };
  public static Condition<Object> FALSE = new Condition<Object>() {
    public boolean value(final Object object) {
      return false;
    }
  };
}

@@ -631,16 +631,89 @@
 .util;%0A%0A
+import com.intellij.reference.SoftReference;%0A%0Aimport java.util.HashMap;%0A%0A
 /**%0A * @
@@ -1243,24 +1243,121 @@
 c1, c2);%0A  %7D
+%0A  public static %3CT%3E Condition%3CT%3E cached(Condition%3CT%3E c) %7B%0A    return new SoftRefCache%3CT%3E(c);%0A  %7D
 %0A%0A  private 
@@ -2582,15 +2582,792 @@
 ;%0A    %7D%0A
-
   %7D;
+%0A%0A  private static class SoftRefCache%3CT%3E implements Condition%3CT%3E %7B%0A    private final HashMap%3CInteger, Pair%3CSoftReference%3CT%3E, Boolean%3E%3E myCache = new HashMap%3CInteger, Pair%3CSoftReference%3CT%3E, Boolean%3E%3E();%0A    private final Condition%3CT%3E myCondition;%0A%0A    public SoftRefCache(Condition%3CT%3E condition) %7B%0A      myCondition = condition;%0A    %7D%0A%0A    @Override%0A    public final boolean value(T object) %7B%0A      final int key = object.hashCode();%0A      final Pair%3CSoftReference%3CT%3E, Boolean%3E entry = myCache.get(key);%0A      if (entry == null %7C%7C entry.first.get() != object) %7B%0A        boolean value = myCondition.value(object);%0A        myCache.put(key, Pair.create(new SoftReference%3CT%3E(object), value));%0A        return value;%0A      %7D%0A      else %7B%0A        return entry.second;%0A      %7D%0A    %7D%0A  %7D
 %0A%7D%0A

refactor JS class chooser dialog filters