// Path: src/main/java/com/timgroup/stanislavski/magic/matchers/MagicJavaBeanMatcher.java
// public final class MagicJavaBeanMatcher<T, I> implements Predicate<MethodCall>, FinalCallHandler<Object> {
//     private final Class<T> targetClass;
// 
//     public static class MagicJavaBeanMatcherBuilder<T> {
//         private Class<T> targetClass;
//         private MagicJavaBeanMatcherBuilder(Class<T> targetClass) {
//             this.targetClass = targetClass;
//         }
//         public <I> I using(Class<I> interfaceClass) {
//             MagicJavaBeanMatcher<T, I> matcher = new MagicJavaBeanMatcher<T, I>(targetClass);
//             return InterceptingMethodCallRecorder.proxying(interfaceClass, matcher, matcher);
//         }
//     }
//     
//     public static <T> MagicJavaBeanMatcher.MagicJavaBeanMatcherBuilder<T> matching(Class<T> targetClass) {
//         return new MagicJavaBeanMatcher.MagicJavaBeanMatcherBuilder<T>(targetClass);
//     }
//     
//     private MagicJavaBeanMatcher(Class<T> targetClass) {
//         this.targetClass = targetClass;
//     }
// 
//     @Override
//     public Object handle(MethodCall closingCall,
//                           Iterable<MethodCall> callHistory) {
//         try {
//             return closingCall.applyTo(makeMatcherFrom(callHistory));
//         } catch (RuntimeException e) {
//             throw e;
//         } catch (Throwable e) {
//             throw new RuntimeException(e);
//         }
//     }
// 
//     @Override
//     public boolean apply(MethodCall methodCall) {
//         return methodCall.targetClass().equals(Matcher.class) || methodCall.targetClass().equals(SelfDescribing.class);
//     }
//     
//     private Matcher<T> makeMatcherFrom(Iterable<MethodCall> callHistory) {
//         return new InstanceWithPropertiesMatcher<T>(targetClass, JavaBeanPropertyMatcherMaker.interpret(targetClass, callHistory));
//     }
// }


import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.Test;
import com.google.common.base.Supplier;
import com.timgroup.stanislavski.interpreters.AddressesProperty;
import com.timgroup.stanislavski.magic.matchers.MagicJavaBeanMatcher;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
            @AddressesProperty("quest")
            Builder havingTheNobleQuest(Supplier<Quest> quest);
        }

        public static Builder builder() {
            return MagicRecordBuilder.building(ImmutableRecord.class).using(ImmutableRecord.Builder.class);
        }
    }

    public static interface QuestMatcher extends Matcher<Quest> {
        @AddressesProperty("object") QuestMatcher for_the(String object);
        @AddressesProperty("declaration") QuestMatcher declaring(String declaration); 
    }
    
    public QuestMatcher the_quest() {
        return MagicJavaBeanMatcher.matching(Quest.class).using(QuestMatcher.class);
    }
    
    public static interface RecordMatcher extends Matcher<ImmutableRecord> {
        RecordMatcher with_name(String name);
        RecordMatcher with_name(Matcher<? super String> name);
        RecordMatcher with_age(Integer age);
        RecordMatcher with_favourite_colour(String favouriteColour);
        @AddressesProperty("quest")
        RecordMatcher having_the_noble_quest(Quest quest);
        @AddressesProperty("quest")
        RecordMatcher having_the_noble_quest(Matcher<? super Quest> quest);
    }

    private RecordMatcher a_record() {
// Path: src/main/java/com/timgroup/stanislavski/magic/matchers/MagicJavaBeanMatcher.java
// public final class MagicJavaBeanMatcher<T, I> implements Predicate<MethodCall>, FinalCallHandler<Object> {
//     private final Class<T> targetClass;
// 
//     public static class MagicJavaBeanMatcherBuilder<T> {
//         private Class<T> targetClass;
//         private MagicJavaBeanMatcherBuilder(Class<T> targetClass) {
//             this.targetClass = targetClass;
//         }
//         public <I> I using(Class<I> interfaceClass) {
//             MagicJavaBeanMatcher<T, I> matcher = new MagicJavaBeanMatcher<T, I>(targetClass);
//             return InterceptingMethodCallRecorder.proxying(interfaceClass, matcher, matcher);
//         }
//     }
//     
//     public static <T> MagicJavaBeanMatcher.MagicJavaBeanMatcherBuilder<T> matching(Class<T> targetClass) {
//         return new MagicJavaBeanMatcher.MagicJavaBeanMatcherBuilder<T>(targetClass);
//     }
//     
//     private MagicJavaBeanMatcher(Class<T> targetClass) {
//         this.targetClass = targetClass;
//     }
// 
//     @Override
//     public Object handle(MethodCall closingCall,
//                           Iterable<MethodCall> callHistory) {
//         try {
//             return closingCall.applyTo(makeMatcherFrom(callHistory));
//         } catch (RuntimeException e) {
//             throw e;
//         } catch (Throwable e) {
//             throw new RuntimeException(e);
//         }
//     }
// 
//     @Override
//     public boolean apply(MethodCall methodCall) {
//         return methodCall.targetClass().equals(Matcher.class) || methodCall.targetClass().equals(SelfDescribing.class);
//     }
//     
//     private Matcher<T> makeMatcherFrom(Iterable<MethodCall> callHistory) {
//         return new InstanceWithPropertiesMatcher<T>(targetClass, JavaBeanPropertyMatcherMaker.interpret(targetClass, callHistory));
//     }
// }


// Path: src/test/java/com/timgroup/stanislavski/magic/builders/MagicImmutableRecordBuilderTest.java
import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.Test;
import com.google.common.base.Supplier;
import com.timgroup.stanislavski.interpreters.AddressesProperty;
import com.timgroup.stanislavski.magic.matchers.MagicJavaBeanMatcher;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

            @AddressesProperty("quest")
            Builder havingTheNobleQuest(Supplier<Quest> quest);
        }

        public static Builder builder() {
            return MagicRecordBuilder.building(ImmutableRecord.class).using(ImmutableRecord.Builder.class);
        }
    }

    public static interface QuestMatcher extends Matcher<Quest> {
        @AddressesProperty("object") QuestMatcher for_the(String object);
        @AddressesProperty("declaration") QuestMatcher declaring(String declaration); 
    }
    
    public QuestMatcher the_quest() {
        return MagicJavaBeanMatcher.matching(Quest.class).using(QuestMatcher.class);
    }
    
    public static interface RecordMatcher extends Matcher<ImmutableRecord> {
        RecordMatcher with_name(String name);
        RecordMatcher with_name(Matcher<? super String> name);
        RecordMatcher with_age(Integer age);
        RecordMatcher with_favourite_colour(String favouriteColour);
        @AddressesProperty("quest")
        RecordMatcher having_the_noble_quest(Quest quest);
        @AddressesProperty("quest")
        RecordMatcher having_the_noble_quest(Matcher<? super Quest> quest);
    }

    private RecordMatcher a_record() {
        return MagicJavaBeanMatcher.matching(ImmutableRecord.class).using(RecordMatcher.class);