@Test
 public void testParseForPrimitive() throws Exception {
   // the 'numChildren' property has type Long.TYPE and *not* Long.class
   final AhcPropertyAccessor accessor =
       new AhcMapperExpressionParser(AhcMapperLogger.DEBUG_STDOUT)
           .parse(ClassB.class, "numChildren", Long.class, null, true);
   assertTrue(accessor.isReadable());
   assertTrue(accessor.isWritable());
 }
  @Test
  public void testParseSingleWriteOnly() throws Exception {
    final AhcPropertyAccessor accessor =
        new AhcMapperExpressionParser(AhcMapperLogger.DEBUG_STDOUT)
            .parse(ClassCyclicChild.class, "writeOnly", String.class, null, true);

    assertEquals(MethodBasedPropertyAccessor.class, accessor.getClass());
    assertEquals(true, accessor.isPrimary());
    assertEquals(false, accessor.isReadable());
    assertEquals(true, accessor.isWritable());
    assertEquals("writeOnly", accessor.getName());

    final ClassCyclicChild o = new ClassCyclicChild();
    accessor.setValue(o, "abc");
    assertEquals("abc", o.getReadOnly());
  }
  @Test
  public void testParseSingle() throws Exception {
    final AhcPropertyAccessor accessor =
        new AhcMapperExpressionParser(AhcMapperLogger.DEBUG_STDOUT)
            .parse(ClassA.class, "firstName", String.class, null, true);

    assertEquals(MethodBasedPropertyAccessor.class, accessor.getClass());
    assertEquals(true, accessor.isPrimary());
    assertEquals(true, accessor.isReadable());
    assertEquals(true, accessor.isWritable());
    assertEquals("firstName", accessor.getName());

    final ClassA a = new ClassA();
    accessor.setValue(a, "first");
    assertEquals("first", a.getFirstName());
    assertEquals("first", accessor.getValue(a));
  }
  @Test
  public void testParseCascadeWriteOnly() throws Exception {
    final AhcPropertyAccessor accessor =
        new AhcMapperExpressionParser(AhcMapperLogger.DEBUG_STDOUT)
            .parse(ClassCyclicParent.class, "child.writeOnly", String.class, null, true);

    assertEquals(MethodPathBasedPropertyAccessor.class, accessor.getClass());
    assertEquals(true, accessor.isPrimary());
    assertEquals(false, accessor.isReadable());
    assertEquals(true, accessor.isWritable());
    assertEquals("child.writeOnly", accessor.getName());

    final ClassCyclicParent o = new ClassCyclicParent();
    o.setChild(new ClassCyclicChild());
    accessor.setValue(o, "12345");
    assertEquals("12345", o.getChild().getReadOnly());
  }
  @Test
  public void testParseOgnl() throws Exception {
    final AhcPropertyAccessor accessor =
        new AhcMapperExpressionParser(AhcMapperLogger.DEBUG_STDOUT)
            .parse(ClassA.class, "phone[0].phone", String.class, null, true);

    assertEquals(OgnlPropertyAccessor.class, accessor.getClass());
    assertEquals(true, accessor.isPrimary());
    assertEquals(true, accessor.isReadable());
    assertEquals(true, accessor.isWritable());
    assertEquals("phone[0].phone", accessor.getName());

    final ClassA a = new ClassA();
    a.getPhone().add(new InnerClassA());
    accessor.setValue(a, "xyz");
    assertEquals("xyz", a.getPhone().get(0).getPhone());
    assertEquals("xyz", accessor.getValue(a));
  }
  @Test
  public void testParseSimpleCascade() throws Exception {
    final AhcPropertyAccessor accessor =
        new AhcMapperExpressionParser(AhcMapperLogger.DEBUG_STDOUT)
            .parse(ClassCyclicParent.class, "child.name", String.class, null, true);

    assertEquals(MethodPathBasedPropertyAccessor.class, accessor.getClass());
    assertEquals(true, accessor.isPrimary());
    assertEquals(true, accessor.isReadable());
    assertEquals(true, accessor.isWritable());
    assertEquals("child.name", accessor.getName());

    final ClassCyclicParent o = new ClassCyclicParent();
    o.setChild(new ClassCyclicChild());
    accessor.setValue(o, "abc");
    assertEquals("abc", o.getChild().getName());
    assertEquals("abc", accessor.getValue(o));

    try {
      accessor.getValue(new ClassCyclicParent());
      fail("exception expected");
    } catch (NullPointerException exc) {
    }
  }