// Path: src/main/java/io/advantageous/reakt/impl/BreakerImpl.java
// public class BreakerImpl<T> implements Breaker<T> {
// 
//     /**
//      * hold service
//      */
//     private final T service;
// 
//     /**
//      * Hold blow circuit breaker flag.
//      */
//     private final AtomicLong errors = new AtomicLong();
//     private final int maxErrorCount;
//     private final Expected<Predicate<T>> brokenPredicate;
// 
//     public BreakerImpl() {
//         this.maxErrorCount = 0;
//         this.service = null;
//         this.brokenPredicate = Expected.empty();
//     }
// 
//     public BreakerImpl(final T value) {
//         this.maxErrorCount = 0;
//         this.service = Objects.requireNonNull(value);
//         this.brokenPredicate = Expected.empty();
//     }
// 
//     public BreakerImpl(final T value, final int maxErrorCount) {
//         this.service = Objects.requireNonNull(value);
//         this.maxErrorCount = maxErrorCount;
//         this.brokenPredicate = Expected.empty();
//     }
// 
//     public BreakerImpl(final T value, final int maxErrorCount, final Predicate<T> brokenPredicate) {
//         this.service = Objects.requireNonNull(value);
//         this.maxErrorCount = maxErrorCount;
//         this.brokenPredicate = Expected.of(brokenPredicate);
//     }
// 
// 
//     @Override
//     public boolean isOperational() {
//         return (this.service != null) &&
//                 (this.maxErrorCount == 0 || errorCount() < this.maxErrorCount) &&
//                 (this.brokenPredicate.isEmpty() || !this.brokenPredicate.get().test(service));
//     }
// 
//     @Override
//     public boolean isBroken() {
//         return !isOperational();
//     }
// 
//     @Override
//     public Breaker<T> ifOperational(final Consumer<? super T> consumer) {
//         try {
//             if (isOperational()) consumer.accept(this.service);
//             return this;
//         } catch (Exception ex) {
//             this.errors.incrementAndGet();
//             throw new IllegalStateException("Operation failed", ex);
//         }
//     }
// 
//     @Override
//     public Breaker<T> ifBroken(final Runnable runnable) {
//         if (isBroken()) runnable.run();
//         return this;
//     }
// 
// 
//     @Override
//     public Breaker<T> cleanup(final Consumer<? super T> consumer) {
//         if (this.service != null) consumer.accept(this.service);
//         return this;
//     }
// 
//     @Override
//     public long errorCount() {
//         return this.errors.get();
//     }
// }


import io.advantageous.reakt.impl.BreakerImpl;
import java.util.function.Consumer;
import java.util.function.Predicate;
/*
 *
 *  Copyright (c) 2016. Rick Hightower, Geoff Chandler
 *
 *  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 io.advantageous.reakt;




/**
 * Represents a Circuit Breaker.
 * The contained service can be broken (open circuit) or operational (closed circuit).
 * <p>
 * This represents a service which may or may not be available.
 * </p>
 * We were using Expected a lot where we really wanted something like a Breaker.
 * <p>
 * This could be extended to blow the circuit with different conditions by providing
 * your own Breaker.
 * </p>
 * <p>
 * Also we want to use interfaces for all core concepts.
 * </p>
 * In addition we wanted callback for ifBroken and ifOperational.
 * <p>
 * If a service is active and healthy, {@code isOperational()} will return {@code true}.
 * If a service is not healthy or not working, {code isBroken()} will return {@code true}.
 * </p>
 * This is heavily modeled after {@code Expected} optional.
 *
 * @author Rick Hightower
 * @author Geoff Chandler
 */
public interface Breaker<T> {
    /**
     * Common instance for {@code broken()}.
     */
    Breaker OPENED = new BreakerImpl<>();

    /**
     * Returns an open {@code Breaker} instance.  No service is present for this
     * value.
     *
     * @param <T> Type of the non-existent value
     * @return an empty {@code ExpectedImpl}
     */
    static <T> Breaker<T> broken() {
        return opened();
    }

    /**
     * Returns an open/broken {@code Breaker} instance.  No service is present for this
     * value.
     *
     * @param <T> Type of the non-existent value
     * @return an empty {@code ExpectedImpl}
     */
    static <T> Breaker<T> opened() {
        @SuppressWarnings("unchecked")
        Breaker<T> t = OPENED;
        return t;
    }

    /**
     * Returns an {@code Breaker} using the specified present value, which must not be null.
     *
     * @param <T>   the class of the value
     * @param value the value to be present. Must be non-null
     * @return an {@code ExpectedImpl} with the value present
     * @throws NullPointerException if value is null
     */
    static <T> Breaker<T> operational(T value) {
// Path: src/main/java/io/advantageous/reakt/impl/BreakerImpl.java
// public class BreakerImpl<T> implements Breaker<T> {
// 
//     /**
//      * hold service
//      */
//     private final T service;
// 
//     /**
//      * Hold blow circuit breaker flag.
//      */
//     private final AtomicLong errors = new AtomicLong();
//     private final int maxErrorCount;
//     private final Expected<Predicate<T>> brokenPredicate;
// 
//     public BreakerImpl() {
//         this.maxErrorCount = 0;
//         this.service = null;
//         this.brokenPredicate = Expected.empty();
//     }
// 
//     public BreakerImpl(final T value) {
//         this.maxErrorCount = 0;
//         this.service = Objects.requireNonNull(value);
//         this.brokenPredicate = Expected.empty();
//     }
// 
//     public BreakerImpl(final T value, final int maxErrorCount) {
//         this.service = Objects.requireNonNull(value);
//         this.maxErrorCount = maxErrorCount;
//         this.brokenPredicate = Expected.empty();
//     }
// 
//     public BreakerImpl(final T value, final int maxErrorCount, final Predicate<T> brokenPredicate) {
//         this.service = Objects.requireNonNull(value);
//         this.maxErrorCount = maxErrorCount;
//         this.brokenPredicate = Expected.of(brokenPredicate);
//     }
// 
// 
//     @Override
//     public boolean isOperational() {
//         return (this.service != null) &&
//                 (this.maxErrorCount == 0 || errorCount() < this.maxErrorCount) &&
//                 (this.brokenPredicate.isEmpty() || !this.brokenPredicate.get().test(service));
//     }
// 
//     @Override
//     public boolean isBroken() {
//         return !isOperational();
//     }
// 
//     @Override
//     public Breaker<T> ifOperational(final Consumer<? super T> consumer) {
//         try {
//             if (isOperational()) consumer.accept(this.service);
//             return this;
//         } catch (Exception ex) {
//             this.errors.incrementAndGet();
//             throw new IllegalStateException("Operation failed", ex);
//         }
//     }
// 
//     @Override
//     public Breaker<T> ifBroken(final Runnable runnable) {
//         if (isBroken()) runnable.run();
//         return this;
//     }
// 
// 
//     @Override
//     public Breaker<T> cleanup(final Consumer<? super T> consumer) {
//         if (this.service != null) consumer.accept(this.service);
//         return this;
//     }
// 
//     @Override
//     public long errorCount() {
//         return this.errors.get();
//     }
// }


// Path: src/main/java/io/advantageous/reakt/Breaker.java
import io.advantageous.reakt.impl.BreakerImpl;
import java.util.function.Consumer;
import java.util.function.Predicate;

/*
 *
 *  Copyright (c) 2016. Rick Hightower, Geoff Chandler
 *
 *  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 io.advantageous.reakt;




/**
 * Represents a Circuit Breaker.
 * The contained service can be broken (open circuit) or operational (closed circuit).
 * <p>
 * This represents a service which may or may not be available.
 * </p>
 * We were using Expected a lot where we really wanted something like a Breaker.
 * <p>
 * This could be extended to blow the circuit with different conditions by providing
 * your own Breaker.
 * </p>
 * <p>
 * Also we want to use interfaces for all core concepts.
 * </p>
 * In addition we wanted callback for ifBroken and ifOperational.
 * <p>
 * If a service is active and healthy, {@code isOperational()} will return {@code true}.
 * If a service is not healthy or not working, {code isBroken()} will return {@code true}.
 * </p>
 * This is heavily modeled after {@code Expected} optional.
 *
 * @author Rick Hightower
 * @author Geoff Chandler
 */
public interface Breaker<T> {
    /**
     * Common instance for {@code broken()}.
     */
    Breaker OPENED = new BreakerImpl<>();

    /**
     * Returns an open {@code Breaker} instance.  No service is present for this
     * value.
     *
     * @param <T> Type of the non-existent value
     * @return an empty {@code ExpectedImpl}
     */
    static <T> Breaker<T> broken() {
        return opened();
    }

    /**
     * Returns an open/broken {@code Breaker} instance.  No service is present for this
     * value.
     *
     * @param <T> Type of the non-existent value
     * @return an empty {@code ExpectedImpl}
     */
    static <T> Breaker<T> opened() {
        @SuppressWarnings("unchecked")
        Breaker<T> t = OPENED;
        return t;
    }

    /**
     * Returns an {@code Breaker} using the specified present value, which must not be null.
     *
     * @param <T>   the class of the value
     * @param value the value to be present. Must be non-null
     * @return an {@code ExpectedImpl} with the value present
     * @throws NullPointerException if value is null
     */
    static <T> Breaker<T> operational(T value) {
        return new BreakerImpl<>(value);