package inhibeans.demo;

import inhibeans.binding.BooleanBinding;

import java.util.function.Predicate;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableBooleanValue;

public class AndGateDemo {

    interface AndGate {
        void setInputs(boolean a, boolean b);
        ObservableBooleanValue a();
        ObservableBooleanValue b();
        ObservableBooleanValue output();
    }

    static void test(AndGate gate) {
        class Counter {
            int count = 0;
            public void inc() { count += 1; }
            public int get() { return count; }
        }

        Predicate<AndGate> consistent = g ->
            g.output().get() == (g.a().get() && g.b().get());

        gate.setInputs(false, false);
        assert gate.output().get() == false;

        Counter na = new Counter();
        Counter nb = new Counter();
        Counter no = new Counter();

        gate.a().addListener(observable -> {
            assert consistent.test(gate);
            na.inc();
        });
        gate.b().addListener(observable -> {
            assert consistent.test(gate);
            nb.inc();
        });
        gate.output().addListener(observable -> {
            assert consistent.test(gate);
            no.inc();
        });

        gate.setInputs(true, true);
        assert gate.output().get() == true;

        assert na.get() == 1;
        assert nb.get() == 1;
        assert no.get() == 1;
    }

    public static void main(String[] args) {
        AndGate gate = new AndGate() {
            private final BooleanProperty a = new SimpleBooleanProperty();
            private final BooleanProperty b = new SimpleBooleanProperty();
            private final BooleanBinding output = new BooleanBinding() {
                { bind(a, b); }
                @Override
                protected boolean computeValue() {
                    return a.get() && b.get();
                }
            };

            @Override
            public void setInputs(boolean a, boolean b) {
                output.block();
                this.a.set(a);
                this.b.set(b);
                output.release();
            }

            @Override public ObservableBooleanValue a() { return a; }
            @Override public ObservableBooleanValue b() { return b; }
            @Override public ObservableBooleanValue output() { return output; }
        };

        test(gate);
        System.out.println("AndGate implementation passed the test.");
    }
}

@@ -1513,83 +1513,51 @@
     
-public static void main(String%5B%5D args) %7B%0A        AndGate gate = new
+static class AndGateImpl implements
  AndGate
 () %7B
@@ -1552,18 +1552,16 @@
  AndGate
-()
  %7B%0A     
@@ -1555,36 +1555,32 @@
 dGate %7B%0A        
-    
 private final Bo
@@ -1626,36 +1626,32 @@
 erty();%0A        
-  
-  
 private final Bo
@@ -1693,28 +1693,24 @@
 Property();%0A
-    
         priv
@@ -1778,20 +1778,16 @@
         
-    
 %7B bind(a
@@ -1798,36 +1798,32 @@
 ; %7D%0A            
-   
- 
 @Override%0A      
@@ -1808,36 +1808,32 @@
       @Override%0A
-    
             prot
@@ -1879,20 +1879,16 @@
         
- 
-   
 return a
@@ -1922,18 +1922,10 @@
     
-    %7D%0A    
+%7D%0A
     
@@ -1932,36 +1932,32 @@
     %7D;%0A%0A        
- 
-   
 @Override%0A      
@@ -1942,36 +1942,32 @@
       @Override%0A
-    
         public v
@@ -2012,28 +2012,24 @@
             
-    
 output.block
@@ -2040,28 +2040,24 @@
             
-  
-  
 this.a.set(a
@@ -2059,20 +2059,16 @@
 set(a);%0A
-    
         
@@ -2094,28 +2094,24 @@
             
-    
 output.relea
@@ -2120,35 +2120,27 @@
 ();%0A        
-  
-  
 %7D%0A%0A
-    
         @Ove
@@ -2193,36 +2193,32 @@
 rn a; %7D%0A        
-    
 @Override public
@@ -2259,36 +2259,32 @@
 rn b; %7D%0A        
-   
- 
 @Override public
@@ -2343,33 +2343,86 @@
     
+%7D%0A%0A
     
-%7D;%0A%0A        test(gate
+public static void main(String%5B%5D args) %7B%0A        test(new AndGateImpl()
 );%0A 

Reorganize AndGateDemo.