/*
   * see java.beans.FeatureDescriptor#FeatureDescriptor(FeatureDescriptor)
   */
  public static void copyNonMethodProperties(PropertyDescriptor source, PropertyDescriptor target)
      throws IntrospectionException {

    target.setExpert(source.isExpert());
    target.setHidden(source.isHidden());
    target.setPreferred(source.isPreferred());
    target.setName(source.getName());
    target.setShortDescription(source.getShortDescription());
    target.setDisplayName(source.getDisplayName());

    // copy all attributes (emulating behavior of private FeatureDescriptor#addTable)
    Enumeration<String> keys = source.attributeNames();
    while (keys.hasMoreElements()) {
      String key = keys.nextElement();
      target.setValue(key, source.getValue(key));
    }

    // see java.beans.PropertyDescriptor#PropertyDescriptor(PropertyDescriptor)
    target.setPropertyEditorClass(source.getPropertyEditorClass());
    target.setBound(source.isBound());
    target.setConstrained(source.isConstrained());
  }
  public static void main(String[] args) throws Exception {

    BeanInfo i = Introspector.getBeanInfo(C.class, Object.class);
    Checker.checkEq("description", i.getBeanDescriptor().getShortDescription(), "CHILD");

    PropertyDescriptor[] pds = i.getPropertyDescriptors();
    Checker.checkEq("number of properties", pds.length, 1);
    PropertyDescriptor p = pds[0];

    Checker.checkEq("property description", p.getShortDescription(), "CHILDPROPERTY");
    Checker.checkEq("isBound", p.isBound(), childFlag);
    Checker.checkEq("isExpert", p.isExpert(), childFlag);
    Checker.checkEq("isHidden", p.isHidden(), childFlag);
    Checker.checkEq("isPreferred", p.isPreferred(), childFlag);
    Checker.checkEq("required", p.getValue("required"), childFlag);
    Checker.checkEq("visualUpdate", p.getValue("visualUpdate"), childFlag);

    Checker.checkEnumEq(
        "enumerationValues",
        p.getValue("enumerationValues"),
        new Object[] {"BOTTOM", 3, "javax.swing.SwingConstants.BOTTOM"});
  }