void updateGenericsFor(Class<?> type) {
   setClass0(type);
   try {
     setPropertyType(findPropertyType(this.readMethodRef.get(), this.writeMethodRef.get()));
   } catch (IntrospectionException exception) {
     setPropertyType(null);
   }
 }
 /**
  * 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);
  }
  /**
   * Sets the method that should be used to write the property value.
   *
   * @param writeMethod The new write method.
   * @throws IntrospectionException if the write method is invalid
   */
  public synchronized void setWriteMethod(@Nullable Method writeMethod)
      throws IntrospectionException {
    this.writeMethodRef.set(writeMethod);
    if (writeMethod == null) {
      writeMethodName = null;
      return;
    }
    // Set the property type - which validates the method
    setPropertyType(findPropertyType(getReadMethod(), writeMethod));
    setClass0(writeMethod.getDeclaringClass());

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

    readMethodName = readMethod.getName();
    setTransient(readMethod.getAnnotation(Transient.class));
  }
  /**
   * 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.
   */
  @Pure
  public synchronized @Nullable Method getWriteMethod() {
    Method writeMethod = this.writeMethodRef.get();
    if (writeMethod == null) {
      Class<?> cls = getClass0();
      if (cls == null || (writeMethodName == null && !this.writeMethodRef.isSet())) {
        // 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 = Introspector.SET_PREFIX + getBaseName();
      }

      Class<?>[] args = (type == null) ? null : new Class<?>[] {type};
      writeMethod = Introspector.findMethod(cls, writeMethodName, 1, args);
      if (writeMethod != null) {
        if (!writeMethod.getReturnType().equals(void.class)) {
          writeMethod = null;
        }
      }
      try {
        setWriteMethod(writeMethod);
      } catch (IntrospectionException ex) {
        // fall through
      }
    }
    return writeMethod;
  }
  /**
   * 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 =
          Introspector.findMethod(
              cls, writeMethodName, 1, (type == null) ? null : new Class[] {type});
      try {
        setWriteMethod(writeMethod);
      } catch (IntrospectionException ex) {
        // fall through
      }
    }
    return writeMethod;
  }
  /**
   * Creates {@code PropertyDescriptor} from the specified property info.
   *
   * @param entry the pair of values, where the {@code key} is the base name of the property (the
   *     rest of the method name) and the {@code value} is the automatically generated property info
   * @param bound the flag indicating whether it is possible to treat this property as a bound
   *     property
   * @since 9
   */
  PropertyDescriptor(Entry<String, PropertyInfo> entry, boolean bound) {
    String base = entry.getKey();
    PropertyInfo info = entry.getValue();
    setName(Introspector.decapitalize(base));
    setReadMethod0(info.getReadMethod());
    setWriteMethod0(info.getWriteMethod());
    setPropertyType(info.getPropertyType());
    setConstrained(info.isConstrained());
    setBound(bound && info.is(PropertyInfo.Name.bound));

    boolean isExpert = info.is(PropertyInfo.Name.expert);
    setValue(PropertyInfo.Name.expert.name(), isExpert); // compatibility
    setExpert(isExpert);

    boolean isHidden = info.is(PropertyInfo.Name.hidden);
    setValue(PropertyInfo.Name.hidden.name(), isHidden); // compatibility
    setHidden(isHidden);

    setPreferred(info.is(PropertyInfo.Name.preferred));

    boolean isRequired = info.is(PropertyInfo.Name.required);
    setValue(PropertyInfo.Name.required.name(), isRequired);

    boolean visual = info.is(PropertyInfo.Name.visualUpdate);
    setValue(PropertyInfo.Name.visualUpdate.name(), visual);

    Object description = info.get(PropertyInfo.Name.description);
    if (description != null) {
      setShortDescription(description.toString());
    }
    Object values = info.get(PropertyInfo.Name.enumerationValues);
    if (values != null) {
      setValue(PropertyInfo.Name.enumerationValues.name(), values);
    }
    this.baseName = base;
  }
 /**
  * Sets the method that should be used to write the property value.
  *
  * @param writeMethod The new write method.
  * @throws IntrospectionException if the write method is invalid
  * @since 1.2
  */
 public synchronized void setWriteMethod(Method writeMethod) throws IntrospectionException {
   // Set the property type - which validates the method
   setPropertyType(findPropertyType(getReadMethod(), writeMethod));
   setWriteMethod0(writeMethod);
 }
 /**
  * Sets the method that should be used to read the property value.
  *
  * @param readMethod The new read method.
  * @throws IntrospectionException if the read method is invalid
  * @since 1.2
  */
 public synchronized void setReadMethod(Method readMethod) throws IntrospectionException {
   // The property type is determined by the read method.
   setPropertyType(findPropertyType(readMethod, this.writeMethodRef.get()));
   setReadMethod0(readMethod);
 }