// Path: src/main/java/com/timgroup/karg/reference/Setter.java
// public interface Setter<O, T> {
//     T set(O object, T newValue);
// }


import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.timgroup.karg.reference.Setter;
    
    public static <C, V> PropertyAccessor<C, V> forProperty(String propertyName,
                                                            GetterMethod<C, V> getter,
                                                            SetterMethod<C, V> setter) {
        return new PropertyAccessor<C, V>(propertyName, getter, setter);
    }
    
    private final String propertyName;
    private final GetterMethod<C, V> getter;
    private final Optional<SetterMethod<C, V>> setter;
    
    private PropertyAccessor(String propertyName, GetterMethod<C, V> getter) {
        this.propertyName = propertyName;
        this.getter = getter;
        this.setter = Optional.absent();
    }
    
    private PropertyAccessor(String propertyName, GetterMethod<C, V> getter, SetterMethod<C, V> setter) {
        this.propertyName = propertyName;
        this.getter = getter;
        this.setter = Optional.of(setter);
    }
    
    @Override
    public V get(C object) {
        return getter.get(object);
    }

    @Override
    public V set(C object, V newValue) {
// Path: src/main/java/com/timgroup/karg/reference/Setter.java
// public interface Setter<O, T> {
//     T set(O object, T newValue);
// }


// Path: src/main/java/com/timgroup/karg/reflection/PropertyAccessor.java
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.timgroup.karg.reference.Setter;

    
    public static <C, V> PropertyAccessor<C, V> forProperty(String propertyName,
                                                            GetterMethod<C, V> getter,
                                                            SetterMethod<C, V> setter) {
        return new PropertyAccessor<C, V>(propertyName, getter, setter);
    }
    
    private final String propertyName;
    private final GetterMethod<C, V> getter;
    private final Optional<SetterMethod<C, V>> setter;
    
    private PropertyAccessor(String propertyName, GetterMethod<C, V> getter) {
        this.propertyName = propertyName;
        this.getter = getter;
        this.setter = Optional.absent();
    }
    
    private PropertyAccessor(String propertyName, GetterMethod<C, V> getter, SetterMethod<C, V> setter) {
        this.propertyName = propertyName;
        this.getter = getter;
        this.setter = Optional.of(setter);
    }
    
    @Override
    public V get(C object) {
        return getter.get(object);
    }

    @Override
    public V set(C object, V newValue) {
        Setter<C, V> notNullSetter = setter.get();