001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.modeshape.common.function;
018
019import java.util.Objects;
020
021/**
022 * A simple predicate that takes a single argument.
023 * 
024 * @param <T> the type of input for the {@link #test(Object)} method
025 * @author Randall Hauch (rhauch@redhat.com)
026 */
027public abstract class Predicate<T> {
028
029    public abstract boolean test( T input );
030
031    /**
032     * Obtain a new predicate that performs the logical AND of this predicate and the supplied predicate.
033     * 
034     * @param other the other predicate
035     * @return the composed predicate; never null
036     */
037    public Predicate<T> and( final Predicate<T> other ) {
038        if (other == null || other == this) return this;
039        return new Predicate<T>() {
040            @Override
041            public boolean test( T input ) {
042                return Predicate.this.test(input) && other.test(input);
043            }
044        };
045    }
046
047    /**
048     * Obtain a new predicate that performs the logical OR of this predicate and the supplied predicate.
049     * 
050     * @param other the other predicate
051     * @return the composed predicate; never null
052     */
053    public Predicate<T> or( final Predicate<T> other ) {
054        if (other == null || other == this) return this;
055        return new Predicate<T>() {
056            @Override
057            public boolean test( T input ) {
058                return Predicate.this.test(input) || other.test(input);
059            }
060        };
061    }
062
063    /**
064     * Obtain a new predicate that performs the logical NOT of this predicate.
065     * 
066     * @return the composed predicate; never null
067     */
068    public Predicate<T> negate() {
069        return new Predicate<T>() {
070            @Override
071            public boolean test( T input ) {
072                return !Predicate.this.test(input);
073            }
074
075            @Override
076            public Predicate<T> negate() {
077                return Predicate.this;
078            }
079        };
080    }
081
082    /**
083     * Return a predicate that is never satisfied.
084     * 
085     * @return the predicate; never null
086     */
087    public static <T> Predicate<T> never() {
088        return new Predicate<T>() {
089            @Override
090            public boolean test( T input ) {
091                return false;
092            }
093        };
094    }
095
096    /**
097     * Return a predicate that is always satisfied.
098     * 
099     * @return the predicate; never null
100     */
101    public static <T> Predicate<T> always() {
102        return new Predicate<T>() {
103            @Override
104            public boolean test( T input ) {
105                return true;
106            }
107        };
108    }
109
110    /**
111     * Return a predicate that is equivalent to {@link Objects#equals(Object, Object)} called with the supplied object and the
112     * object passed as a parameter to the {@link #test(Object)} method.
113     * 
114     * @param obj the object to compare the test parameters
115     * @return the new predicate; never null
116     */
117    public static <T> Predicate<T> isEqual( final Object obj ) {
118        if (obj == null) {
119            return new Predicate<T>() {
120                @Override
121                public boolean test( T input ) {
122                    return input == null;
123                }
124            };
125        }
126        return new Predicate<T>() {
127            @Override
128            public boolean test( T input ) {
129                return Objects.equals(input, obj);
130            }
131        };
132    }
133}