/**
  * Gets the Class object for the property.
  *
  * @return The Java type info for the property. Note that the "Class" object may describe a
  *     built-in Java type such as "int". The result may be "null" if this is an indexed property
  *     that does not support non-indexed access.
  *     <p>This is the type that will be returned by the ReadMethod.
  */
 public synchronized Class<?> getPropertyType() {
   Class type = getPropertyType0();
   if (type == null) {
     try {
       type = findPropertyType(getReadMethod(), getWriteMethod());
       setPropertyType(type);
     } catch (IntrospectionException ex) {
       // Fall
     }
   }
   return type;
 }
  /**
   * Sets the method that should be used to write the property value.
   *
   * @param writeMethod The new write method.
   */
  public synchronized void setWriteMethod(Method writeMethod) throws IntrospectionException {
    if (writeMethod == null) {
      writeMethodName = null;
      writeMethodRef = null;
      return;
    }
    // Set the property type - which validates the method
    setPropertyType(findPropertyType(getReadMethod(), writeMethod));
    setClass0(writeMethod.getDeclaringClass());

    writeMethodName = writeMethod.getName();
    writeMethodRef = createReference(writeMethod, true);
  }
  /**
   * Sets the method that should be used to read the property value.
   *
   * @param readMethod The new read method.
   */
  public synchronized void setReadMethod(Method readMethod) throws IntrospectionException {
    if (readMethod == null) {
      readMethodName = null;
      readMethodRef = null;
      return;
    }
    // The property type is determined by the read method.
    setPropertyType(findPropertyType(readMethod, getWriteMethod0()));
    setClass0(readMethod.getDeclaringClass());

    readMethodName = readMethod.getName();
    readMethodRef = createReference(readMethod, true);
  }
  /**
   * Gets the method that should be used to write the property value.
   *
   * @return The method that should be used to write the property value. May return null if the
   *     property can't be written.
   */
  public synchronized Method getWriteMethod() {
    Method writeMethod = getWriteMethod0();
    if (writeMethod == null) {
      Class cls = getClass0();
      if (cls == null || (writeMethodName == null && writeMethodRef == null)) {
        // The write method was explicitly set to null.
        return null;
      }

      // We need the type to fetch the correct method.
      Class type = getPropertyType0();
      if (type == null) {
        try {
          // Can't use getPropertyType since it will lead to recursive
          // loop.
          type = findPropertyType(getReadMethod(), null);
          setPropertyType(type);
        } catch (IntrospectionException ex) {
          // Without the correct property type we can't be guaranteed
          // to find the correct method.
          return null;
        }
      }

      if (writeMethodName == null) {
        writeMethodName = "set" + getBaseName();
      }

      writeMethod =
          MethodUtils.findAccessibleMethodIncludeInterfaces(
              cls, writeMethodName, 1, (type == null) ? null : new Class[] {type});
      try {
        setWriteMethod(writeMethod);
      } catch (IntrospectionException ex) {
        // fall through
      }
    }
    return writeMethod;
  }