// *****************************************************************************
 public static AttrIntro findOrCreateAttrInfo(
     Hashtable attrs,
     String attrName,
     String methodName,
     Class supposedTypeClass,
     String whereType,
     int methodType) {
   AttrIntro ai = (AttrIntro) attrs.get(attrName);
   if (ai == null) {
     ai = new AttrIntro();
     ai.name = attrName;
     ai.type = supposedTypeClass.getName();
     if ((methodType & GETTER_METHODTYPE) != 0) ai.getName = methodName;
     if ((methodType & SETTER_METHODTYPE) != 0) ai.setName = methodName;
     ai.getName = methodName;
     ai.whereType = whereType;
     attrs.put(ai.name, ai);
   } else if (ai.type == null || ai.type.equals(supposedTypeClass.getName())) {
     if ((methodType & GETTER_METHODTYPE) != 0) ai.getName = methodName;
     if ((methodType & SETTER_METHODTYPE) != 0) ai.setName = methodName;
   } else {
     return null;
   }
   return ai;
 }
  // *****************************************************************************
  public static void mergeWithRuntimeModelBean(ManagedBean managedBean, Class objectClass) {

    if (objectClass == null) return;
    Hashtable attrs = new Hashtable();

    // Introspect and get all the methods
    Method[] methods = objectClass.getMethods();
    for (int j = 0; j < methods.length; ++j) {
      if (Modifier.isStatic(methods[j].getModifiers())) continue;
      if (!Modifier.isPublic(methods[j].getModifiers())) continue;
      if (methods[j].getDeclaringClass() == Object.class) continue;

      String methodName = methods[j].getName();
      Class params[] = methods[j].getParameterTypes();
      Class ret = methods[j].getReturnType();

      // ----------GETTER----------------
      if ((methodName.startsWith("get") || methodName.startsWith("is"))
          &&
          //                !methodName.startsWith( "getDefault" ) &&
          params.length == 0
          && supportedType(ret)) {
        findOrCreateAttrInfo(
            attrs,
            getAttrNameFromMethodName(methodName, false),
            methodName,
            ret,
            LOCATED_IN_RUNTIMEBEAN,
            GETTER_METHODTYPE);
      }
      // ----------SETTER----------------
      else if (methodName.startsWith("set") && params.length == 1 && supportedType(params[0])) {
        findOrCreateAttrInfo(
            attrs,
            getAttrNameFromMethodName(methodName, false),
            methodName,
            params[0],
            LOCATED_IN_RUNTIMEBEAN,
            SETTER_METHODTYPE);

      }
      // ----------OPERATIONS----------------
      else {
        OperationInfo operationInfo = getOperationInfo(methods[j], LOCATED_IN_RUNTIMEBEAN);
        mergeWithOperationInfo(managedBean, operationInfo);
      }
    }

    // **** A T T R I B U T E S ******
    if (attrs.size() > 0) {
      AttributeInfo[] infos = managedBean.getAttributes();
      Hashtable infosTable = new Hashtable();
      for (int i = 0; i < infos.length; i++) {
        infosTable.put(infos[i].getName(), infos[i]);
      }

      String key;
      Enumeration keys = attrs.keys();
      while (keys.hasMoreElements()) {
        key = (String) keys.nextElement();
        AttrIntro ai = (AttrIntro) attrs.get(key);
        AttributeInfo info = (AttributeInfo) infosTable.get(key);
        if (info == null) {
          ai.whereType = LOCATED_IN_RUNTIMEBEAN;
          info = ai.createAttributeInfo();
          managedBean.addAttribute(info);
          infosTable.put(key, info);
        } else {
          ai.mergeWithAttributeInfo(info);
        }
      }
    }
  }
  // *****************************************************************************
  public static void mergeWithConfigBean(ManagedBean managedBean, Class objectClass, int mode) {

    if (objectClass == null) return;
    Hashtable attrs = new Hashtable();
    Hashtable children = new Hashtable();
    int shift = 0;

    // Introspect and get all the methods
    Method[] methods = objectClass.getMethods();
    for (int j = 0; j < methods.length; ++j) {
      String methodName = methods[j].getName();

      // ----------GETTER----------------
      if (methodName.startsWith("get") || methodName.startsWith("is")) {
        shift = methodName.startsWith("is") ? 2 : 3;
        if (Modifier.isStatic(methods[j].getModifiers())
            || !Modifier.isPublic(methods[j].getModifiers())) {
          continue;
        }
        Class params[] = methods[j].getParameterTypes();
        if (params.length != 0) {
          continue;
        }
        if (methods[j].getDeclaringClass() != objectClass) continue;

        Class ret = methods[j].getReturnType();
        if (!supportedType(ret)) {
          // maybe this is child
          String childClassName = ret.getName();
          if (childClassName.endsWith("." + methodName.substring(shift))
              || childClassName.endsWith("." + methodName.substring(shift) + ";")) {
            children.put(methodName.substring(shift), childClassName);
          }
          continue;
        }
        if ((mode & EXPOSE_GETTERS) == 0) continue;
        //                if(methodName.startsWith( "getDefault" ))
        //                    continue;

        AttrIntro ai = (AttrIntro) attrs.get(getAttrNameFromMethodName(methodName, true));
        if (ai == null) {
          ai = new AttrIntro();
          ai.name = getAttrNameFromMethodName(methodName, true);
          attrs.put(ai.name, ai);
        }
        if (ai.type != null) {
          if (!ai.type.equals(ret.getName())) continue;
        } else {
          ai.type = ret.getName();
        }
        ai.getName = methodName;
        // ----------SETTER----------------
      } else if (methodName.startsWith("set")) {
        if ((mode & EXPOSE_SETTERS) == 0) continue;

        Class params[] = methods[j].getParameterTypes();
        if (params.length != 1) {
          continue;
        }
        if (!supportedType(params[0])) {
          continue;
        }
        if (!Modifier.isPublic(methods[j].getModifiers())) {
          continue;
        }
        if (methods[j].getDeclaringClass() != objectClass) continue;

        AttrIntro ai = (AttrIntro) attrs.get(getAttrNameFromMethodName(methodName, true));
        if (ai == null) {
          ai = new AttrIntro();
          ai.name = getAttrNameFromMethodName(methodName, true);
          attrs.put(ai.name, ai);
        }
        if (ai.type != null) {
          if (!ai.type.equals(params[0].getName())) continue;
        } else {
          ai.type = params[0].getName();
        }
        ai.setName = methodName;
        if (methodName.startsWith("setDefault")) // ???
        {
          ai.setName = "set" + methodName.substring(3);
        }

      } else {
        continue;
      }
    }

    OperationInfo operationInfo;

    // **** A T T R I B U T E S ******
    //        attrs.remove("x_path");
    //        attrs.remove("attribute_names");
    //        attrs.remove("monitoring_enabled");

    if (attrs.size() > 0) {
      AttributeInfo[] infos = managedBean.getAttributes();
      Hashtable infosTable = new Hashtable();
      for (int i = 0; i < infos.length; i++) {
        infosTable.put(infos[i].getName(), infos[i]);
      }

      String key;
      Enumeration keys = attrs.keys();
      while (keys.hasMoreElements()) {
        key = (String) keys.nextElement();
        AttrIntro ai = (AttrIntro) attrs.get(key);
        AttributeInfo info = (AttributeInfo) infosTable.get(key);
        if (info == null) {
          ai.whereType = LOCATED_IN_CONFIGBEAN;
          info = ai.createAttributeInfo();
          managedBean.addAttribute(info);
          infosTable.put(key, info);
        } else {
          ai.mergeWithAttributeInfo(info);
        }
      }

      // getDefaultAttributeValue
      operationInfo =
          createOperationInfo(
              "getDefaultAttributeValue",
              "INFO",
              "java.lang.String",
              new ParameterInfo("attributeName", "java.lang.String", null),
              LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);
    }

    // classnames values for method's types
    String nameClass = "javax.management.ObjectName";
    String attrClass = "javax.management.Attribute";
    String namesClass = (new ObjectName[0]).getClass().getName();
    String attrListClass = (new AttributeList()).getClass().getName();
    String stringsClass = (new String[0]).getClass().getName();

    FieldInfo field;
    ParameterInfo param;

    // **** P R O P E R T I E S  ******
    if (children.get("ElementProperty") != null) {
      children.remove("ElementProperty");

      // getProperties
      operationInfo =
          createOperationInfo("getProperties", "INFO", attrListClass, null, LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);

      // getDefaulCustomProperties
      //            operationInfo = createOperationInfo("getDefaultCustomProperties", "INFO",
      //                   attrListClass, null, null);
      //            mergeWithOperationInfo(managedBean, operationInfo);

      // getProperty
      operationInfo =
          createOperationInfo(
              "getPropertyValue",
              "INFO",
              "java.lang.Object",
              new ParameterInfo("propertyName", "java.lang.String", null),
              LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);

      // setProperty
      operationInfo =
          createOperationInfo(
              "setProperty",
              "ACTION",
              "void",
              new ParameterInfo("nameAndValue", attrClass, null),
              LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);
    }

    // **** S Y S T E M       P R O P E R T I E S  ******
    if (children.get("SystemProperty") != null) {
      children.remove("SystemProperty");

      // getSystemProperties
      operationInfo =
          createOperationInfo(
              "getSystemProperties", "INFO", attrListClass, null, LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);

      // getSystemProperty
      operationInfo =
          createOperationInfo(
              "getSystemPropertyValue",
              "INFO",
              "java.lang.Object",
              new ParameterInfo("propertyName", "java.lang.String", null),
              LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);

      // setSystemProperty
      operationInfo =
          createOperationInfo(
              "setSystemProperty",
              "ACTION",
              "void",
              new ParameterInfo("nameAndValue", attrClass, null),
              LOCATED_IN_CONFIGBEAN);
      mergeWithOperationInfo(managedBean, operationInfo);
    }

    // **** C H I L D R E N  ******

    // children.remove("ElementProperty");

    if (children.size() > 0) {
      String key;
      Enumeration keys = children.keys();
      while (keys.hasMoreElements()) {
        key = (String) keys.nextElement();
        String clazz = (String) children.get(key);
        boolean bMulti = clazz.charAt(0) == '[' ? true : false;
        String childName = getAttrNameFromMethodName(key, true, '-');
        // getter
        if ((mode & EXPOSE_GETCHILD) != 0) {
          // get child (ObjectName)
          operationInfo =
              createOperationInfo(
                  "get" + key,
                  "INFO",
                  bMulti ? namesClass : nameClass,
                  null,
                  LOCATED_IN_CONFIGBEAN);
          addDataToChildOperInfo(childName, bMulti, operationInfo);
          mergeWithOperationInfo(managedBean, operationInfo);
          if (bMulti) {
            // get child NamesList(ObjectName)
            operationInfo =
                createOperationInfo(
                    "get" + key + GET_LISTNAMES_OP_SUFFIX, "INFO", stringsClass, null, null);
            addDataToChildOperInfo(childName, bMulti, operationInfo);
            mergeWithOperationInfo(managedBean, operationInfo);
          }

          // getChildByKey
          if (bMulti) {
            String prefix = "get" + key + "By";
            for (int j = 0; j < methods.length; ++j) {
              String methodName = methods[j].getName();
              if (methodName.startsWith(prefix)) {
                operationInfo =
                    createOperationInfo(
                        methodName,
                        "INFO",
                        nameClass,
                        new ParameterInfo("key", "java.lang.String", null),
                        LOCATED_IN_CONFIGBEAN);
                addDataToChildOperInfo(childName, bMulti, operationInfo);
                mergeWithOperationInfo(managedBean, operationInfo);
                break;
              }
            }
          }
        }
        if ((mode & EXPOSE_CREATECHILD) != 0) {
          // CreateChild
          String prefix = bMulti ? "add" + key : "set" + key;
          for (int j = 0; j < methods.length; ++j) {
            String methodName = methods[j].getName();
            if (methodName.startsWith(prefix)) {
              operationInfo =
                  createOperationInfo(
                      "create" + key,
                      "ACTION_INFO",
                      nameClass,
                      new ParameterInfo("attribute_list", attrListClass, null),
                      LOCATED_IN_CONFIGBEAN);
              addDataToChildOperInfo(childName, bMulti, operationInfo);
              mergeWithOperationInfo(managedBean, operationInfo);
              break;
            }
          }
        }
        if ((mode & EXPOSE_DESTROYCHILD) != 0) {
          if (!bMulti) {
            operationInfo =
                createOperationInfo("remove" + key, "ACTION", "void", null, LOCATED_IN_CONFIGBEAN);
            addDataToChildOperInfo(childName, bMulti, operationInfo);
            mergeWithOperationInfo(managedBean, operationInfo);
          } else {
            String prefix = "get" + key + "By";
            for (int j = 0; j < methods.length; ++j) {
              String methodName = methods[j].getName();
              if (methodName.startsWith(prefix)) {
                operationInfo =
                    createOperationInfo(
                        "remove" + methodName.substring(3),
                        "ACTION",
                        "void",
                        new ParameterInfo("key", "java.lang.String", null),
                        LOCATED_IN_CONFIGBEAN);
                addDataToChildOperInfo(childName, bMulti, operationInfo);
                mergeWithOperationInfo(managedBean, operationInfo);
                break;
              }
            }
          }
        }
      }
    }
  }