/** Create the appropriate properties for a bean. */
  public void createProperties(DeployBeanDescriptor<?> desc) {

    createProperties(desc, desc.getBeanType(), 0);
    desc.sortProperties();

    // check the transient properties...
    Iterator<DeployBeanProperty> it = desc.propertiesAll();

    while (it.hasNext()) {
      DeployBeanProperty prop = it.next();
      if (prop.isTransient()) {
        if (prop.getWriteMethod() == null || prop.getReadMethod() == null) {
          // Typically a helper method ... this is expected
          logger.finest("... transient: " + prop.getFullBeanName());
        } else {
          // dubious, possible error...
          String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
          logger.warning(msg);
        }
      }
    }
  }
 public void process(DeployBeanDescriptor<?> desc) {
   InheritInfo inheritInfo = finalMap.get(desc.getBeanType());
   desc.setInheritInfo(inheritInfo);
 }
  /**
   * reflect the bean properties from Class. Some of these properties may not map to database
   * columns.
   */
  private void createProperties(DeployBeanDescriptor<?> desc, Class<?> beanType, int level) {

    boolean scalaObject = desc.isScalaObject();

    try {
      Method[] declaredMethods = beanType.getDeclaredMethods();
      Field[] fields = beanType.getDeclaredFields();

      for (int i = 0; i < fields.length; i++) {

        Field field = fields[i];
        if (Modifier.isStatic(field.getModifiers())) {
          // not interested in static fields

        } else if (Modifier.isTransient(field.getModifiers())) {
          // not interested in transient fields
          logger.finer("Skipping transient field " + field.getName() + " in " + beanType.getName());

        } else if (ignoreFieldByName(field.getName())) {
          // not interested this field (ebean or aspectJ field)

        } else {

          String fieldName = getFieldName(field, beanType);
          String initFieldName = initCap(fieldName);

          Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
          Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);

          DeployBeanProperty prop = createProp(level, desc, field, beanType, getter, setter);
          if (prop == null) {
            // transient annotation on unsupported type

          } else {
            // set a order that gives priority to inherited properties
            // push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
            int sortOverride = prop.getSortOverride();
            prop.setSortOrder((level * 10000 + 100 - i + sortOverride));

            DeployBeanProperty replaced = desc.addBeanProperty(prop);
            if (replaced != null) {
              if (replaced.isTransient()) {
                // expected for inheritance...
              } else {
                String msg = "Huh??? property " + prop.getFullBeanName() + " being defined twice";
                msg += " but replaced property was not transient? This is not expected?";
                logger.warning(msg);
              }
            }
          }
        }
      }

      Class<?> superClass = beanType.getSuperclass();

      if (!superClass.equals(Object.class)) {
        // recursively add any properties in the inheritance heirarchy
        // up to the Object.class level...
        createProperties(desc, superClass, level + 1);
      }

    } catch (PersistenceException ex) {
      throw ex;

    } catch (Exception ex) {
      throw new PersistenceException(ex);
    }
  }
  @SuppressWarnings({"unchecked", "rawtypes"})
  private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {

    Class<?> propertyType = field.getType();
    Class<?> innerType = propertyType;

    // check for Collection type (list, set or map)
    ManyType manyType = determineManyType.getManyType(propertyType);

    if (manyType != null) {
      // List, Set or Map based object
      Class<?> targetType = determineTargetType(field);
      if (targetType == null) {
        Transient transAnnotation = field.getAnnotation(Transient.class);
        if (transAnnotation != null) {
          // not supporting this field (generic type used)
          return null;
        }
        logger.warning(
            "Could not find parameter type (via reflection) on "
                + desc.getFullName()
                + " "
                + field.getName());
      }
      return createManyType(desc, targetType, manyType);
    }

    if (innerType.isEnum() || innerType.isPrimitive()) {
      return new DeployBeanProperty(desc, propertyType, null, null);
    }

    ScalarType<?> scalarType = typeManager.getScalarType(innerType);
    if (scalarType != null) {
      return new DeployBeanProperty(desc, propertyType, scalarType, null);
    }

    CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
    if (compoundType != null) {
      return new DeployBeanPropertyCompound(desc, propertyType, compoundType, null);
    }

    if (!isTransientField(field)) {
      try {
        CheckImmutableResponse checkImmutable = typeManager.checkImmutable(innerType);
        if (checkImmutable.isImmutable()) {
          if (checkImmutable.isCompoundType()) {
            // use reflection to support compound immutable value objects
            typeManager.recursiveCreateScalarDataReader(innerType);
            compoundType = typeManager.getCompoundType(innerType);
            if (compoundType != null) {
              return new DeployBeanPropertyCompound(desc, propertyType, compoundType, null);
            }

          } else {
            // use reflection to support simple immutable value objects
            scalarType = typeManager.recursiveCreateScalarTypes(innerType);
            return new DeployBeanProperty(desc, propertyType, scalarType, null);
          }
        }
      } catch (Exception e) {
        logger.log(Level.SEVERE, "Error with " + desc + " field:" + field.getName(), e);
      }
    }

    return new DeployBeanPropertyAssocOne(desc, propertyType);
  }