package com.fasterxml.jackson.jr.ob.impl;

import java.io.IOException;
import java.lang.reflect.Method;

import com.fasterxml.jackson.core.io.SerializedString;
import com.fasterxml.jackson.jr.ob.JSONObjectException;

public final class BeanProperty
{
    protected final SerializedString _name;
    
    protected final Class<?> _rawType;

    /**
     * Pre-resolved type id for reading/writing values, if statically known.
     *<p>
     * Note: yes, access is without either volatile or synchronized. But it is
     * an atomic type; so in the very worst case, modification just won't
     * stick. It will never result in invalid value being accessible.
     */
    protected int _typeId;
    
    protected final Method _getMethod, _setMethod;

    public BeanProperty(String name, Class<?> rawType, int typeId,
            Method readMethod, Method writeMethod)
    {
        this(new SerializedString(name), rawType, typeId, readMethod, writeMethod);
    }

    protected BeanProperty(SerializedString name, Class<?> rawType, int typeId,
            Method getMethod, Method setMethod)
    {
        _name = name;
        _rawType = rawType;
        _getMethod = getMethod;
        _setMethod = setMethod;
        _typeId = typeId;
    }

    public void overridTypeId(int id) {
        _typeId = id;
    }

    public Class<?> getType() { return _rawType; }
    
    public int getTypeId() { return _typeId; }

    public SerializedString getName() { return _name; }
    
    public SerializedString getNameIfHasSetter() {
        return (_setMethod == null) ? null : _name;
    }
    
    public Object getValueFor(Object bean) throws IOException
    {
        try {
            return _getMethod.invoke(bean);
        } catch (Exception e) {
            throw new JSONObjectException("Failed to access property '"+_name+"' (type "
                    +_rawType.getName()+"; exception "+e.getClass().getName()+"): "
                    +e.getMessage(), e);
        }
    }

    public Object setValueFor(Object bean, Object value) throws IOException
    {
        if (_setMethod == null) {
            String cls = (_getMethod == null) ? "UNKNOWN" : _getMethod.getDeclaringClass().getName();
            throw new IllegalStateException("No setter for property '"+_name+"' (type "+cls+")");
        }
        try {
            return _setMethod.invoke(bean, value);
        } catch (Exception e) {
            Throwable t = e;
            while (t.getCause() != null) {
                t = t.getCause();
            }
            throw new JSONObjectException("Failed to set property '"+_name+"' (type "
                    +_rawType.getName()+"; exception "+e.getClass().getName()+"): "
                    +e.getMessage(), e);
        }
    }
}

@@ -1647,32 +1647,178 @@
 Exception%0A    %7B%0A
+        if (_getMethod == null) %7B%0A            throw new IllegalStateException(%22No getter for property '%22+_name+%22' (type %22+_bean()+%22)%22);%0A        %7D%0A
         try %7B%0A  
@@ -1807,32 +1807,32 @@
 %7D%0A        try %7B%0A
-
             retu
@@ -2242,110 +2242,8 @@
 ) %7B%0A
-            String cls = (_getMethod == null) ? %22UNKNOWN%22 : _getMethod.getDeclaringClass().getName();%0A
     
@@ -2330,11 +2330,15 @@
 e %22+
-cls
+_bean()
 +%22)%22
@@ -2770,32 +2770,32 @@
 tMessage(), e);%0A
-
         %7D%0A    %7D%0A
@@ -2793,11 +2793,333 @@
  %7D%0A    %7D
+%0A%0A    protected String _bean() %7B%0A        Class%3C?%3E cls;%0A        if (_getMethod != null) %7B%0A            cls = _getMethod.getDeclaringClass();%0A        %7D else if (_setMethod != null) %7B%0A            cls = _setMethod.getDeclaringClass();%0A        %7D else %7B%0A            return %22UNKNOWN%22;%0A        %7D%0A        return cls.getName();%0A    %7D
 %0A%7D%0A

Add a sanity check for existence of get method as well