/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.reflection.impl.bean;

import net.ranides.assira.generic.Wrapper;
import net.ranides.assira.reflection.BeanProperty;
import net.ranides.assira.reflection.IClass;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public abstract class ABeanProperty implements BeanProperty {
    
    private final IClass<?> type;
    private final String name;

    public ABeanProperty(IClass<?> type, String name) {
        this.type = type;
        this.name = name;
    }

    @Override
    public String name() {
        return name;
    }

    @Override
    public IClass<?> type() {
        return type;
    }

    @Override
    public Wrapper<Object> bind(Object that) {
        return new RWrapper(that);
    }
    
    @Override
    public <T> Wrapper<T> $bind(Object that) {
        return (Wrapper)new RWrapper(that);
    }

    @Override
    public <T> T $get(Object that) {
        return (T)get(that);
    }
    @Override
    public Object replace(Object that, Object value) {
        Object prv = isReadable() ? get(that) : null;
        set(that, value);
        return prv;
    }

    private class RWrapper implements Wrapper<Object> {
        
        private final Object that;

        public RWrapper(Object that) {
            this.that = that;
        }

        @Override
        public Object get() {
            return ABeanProperty.this.get(that);
        }

        @Override
        public void set(Object value) {
            ABeanProperty.this.set(that, value);
        }

        @Override
        public Object replace(Object value) {
            return ABeanProperty.this.replace(that, value);
        }

        @Override
        public IClass<?> type() {
            return ABeanProperty.this.type();
        }
        
    }

}
