/** Loads the load groups of cmp fields from the xml element */
  private void loadLoadGroupsXml(Element element) throws DeploymentException {

    Element loadGroupsElement = MetaData.getOptionalChild(element, "load-groups");
    if (loadGroupsElement == null) {
      // no info, default work already done in constructor
      return;
    }

    // only allowed for cmp 2.x
    if (isCMP1x) {
      throw new DeploymentException("load-groups are only allowed " + "for CMP 2.x");
    }

    // load each group
    Iterator groups = MetaData.getChildrenByTagName(loadGroupsElement, "load-group");
    while (groups.hasNext()) {
      Element groupElement = (Element) groups.next();

      // get the load-group-name
      String loadGroupName = MetaData.getUniqueChildContent(groupElement, "load-group-name");
      if (loadGroups.containsKey(loadGroupName)) {
        throw new DeploymentException(
            "Load group already defined: " + " load-group-name=" + loadGroupName);
      }
      if (loadGroupName.equals("*")) {
        throw new DeploymentException(
            "The * load group is automatically " + "defined and can't be overriden");
      }
      ArrayList group = new ArrayList();

      // add each field
      Iterator fields = MetaData.getChildrenByTagName(groupElement, "field-name");
      while (fields.hasNext()) {
        String fieldName = MetaData.getElementContent((Element) fields.next());

        // check if the field is a cmp field that it is not a pk memeber
        JDBCCMPFieldMetaData field = getCMPFieldByName(fieldName);
        if (field != null && field.isPrimaryKeyMember()) {
          throw new DeploymentException(
              "Primary key fields can not be"
                  + " a member of a load group: "
                  + " load-group-name="
                  + loadGroupName
                  + " field-name="
                  + fieldName);
        }

        group.add(fieldName);
      }

      loadGroups.put(loadGroupName, Collections.unmodifiableList(group));
    }
  }
  /**
   * Constructs jdbc entity meta data defined in the jdbcApplication and with the data from the
   * entity meta data which is loaded from the ejb-jar.xml file.
   *
   * @param jdbcApplication the application in which this entity is defined
   * @param entity the entity meta data for this entity that is loaded from the ejb-jar.xml file
   * @throws DeploymentException if an problem occures while loading the classes or if data in the
   *     ejb-jar.xml is inconsistent with data from jbosscmp-jdbc.xml file
   */
  public JDBCEntityMetaData(JDBCApplicationMetaData jdbcApplication, EntityMetaData entity)
      throws DeploymentException {
    this.jdbcApplication = jdbcApplication;
    entityName = entity.getEjbName();
    listCacheMax = 1000;
    fetchSize = 0;

    try {
      entityClass = getClassLoader().loadClass(entity.getEjbClass());
    } catch (ClassNotFoundException e) {
      throw new DeploymentException("entity class not found for ejb-name: " + entityName, e);
    }

    try {
      primaryKeyClass = getClassLoader().loadClass(entity.getPrimaryKeyClass());
    } catch (ClassNotFoundException e) {
      throw new DeploymentException(
          "could not load primary key class: " + entity.getPrimaryKeyClass());
    }

    isCMP1x = entity.isCMP1x();
    if (isCMP1x) {
      abstractSchemaName =
          (entity.getAbstractSchemaName() == null ? entityName : entity.getAbstractSchemaName());
    } else {
      abstractSchemaName = entity.getAbstractSchemaName();
    }

    primaryKeyFieldName = entity.getPrimKeyField();

    String home = entity.getHome();
    if (home != null) {
      try {
        homeClass = getClassLoader().loadClass(home);
      } catch (ClassNotFoundException e) {
        throw new DeploymentException("home class not found: " + home);
      }
      try {
        remoteClass = getClassLoader().loadClass(entity.getRemote());
      } catch (ClassNotFoundException e) {
        throw new DeploymentException("remote class not found: " + entity.getRemote());
      }
    } else {
      homeClass = null;
      remoteClass = null;
    }

    String localHome = entity.getLocalHome();
    if (localHome != null) {
      try {
        localHomeClass = getClassLoader().loadClass(localHome);
      } catch (ClassNotFoundException e) {
        throw new DeploymentException("local home class not found: " + localHome);
      }
      try {
        localClass = getClassLoader().loadClass(entity.getLocal());
      } catch (ClassNotFoundException e) {
        throw new DeploymentException("local class not found: " + entity.getLocal());
      }
    } else {
      // we must have a home or local home
      if (home == null) {
        throw new DeploymentException(
            "Entity must have atleast a home " + "or local home: " + entityName);
      }

      localHomeClass = null;
      localClass = null;
    }

    // we replace the . by _ because some dbs die on it...
    // the table name may be overridden in importXml(jbosscmp-jdbc.xml)
    tableName = entityName.replace('.', '_');

    // Warn: readTimeOut should be setup before cmp fields are created
    // otherwise readTimeOut in cmp fields will be set to 0 by default
    dataSourceName = null;
    datasourceMappingName = null;
    datasourceMapping = null;
    createTable = false;
    removeTable = false;
    alterTable = false;
    rowLocking = false;
    primaryKeyConstraint = false;
    readOnly = false;
    readTimeOut = -1;
    tablePostCreateCmd = null;
    qlCompiler = null;
    throwRuntimeExceptions = false;

    // build the metadata for the cmp fields now in case there is
    // no jbosscmp-jdbc.xml
    List nonPkFieldNames = new ArrayList();
    for (Iterator i = entity.getCMPFields(); i.hasNext(); ) {
      String cmpFieldName = (String) i.next();
      JDBCCMPFieldMetaData cmpField = new JDBCCMPFieldMetaData(this, cmpFieldName);
      cmpFields.add(cmpField);
      cmpFieldsByName.put(cmpFieldName, cmpField);
      if (!cmpField.isPrimaryKeyMember()) {
        nonPkFieldNames.add(cmpFieldName);
      }
    }

    // AL: add unknown primary key if primaryKeyClass is Object
    // AL: this is set up only in this constructor
    // AL: because, AFAIK, others are called with default value
    // AL: produced by this one
    if (primaryKeyClass == java.lang.Object.class) {
      JDBCCMPFieldMetaData upkField = new JDBCCMPFieldMetaData(this);
      cmpFields.add(upkField);
      cmpFieldsByName.put(upkField.getFieldName(), upkField);
    }

    // set eager load fields to all group.
    eagerLoadGroup = "*";

    // Create no lazy load groups. By default every thing is eager loaded.
    // build the metadata for the queries now in case there is no
    // jbosscmp-jdbc.xml
    queryFactory = new JDBCQueryMetaDataFactory(this);

    for (Iterator queriesIterator = entity.getQueries(); queriesIterator.hasNext(); ) {
      QueryMetaData queryData = (QueryMetaData) queriesIterator.next();
      Map newQueries = queryFactory.createJDBCQueryMetaData(queryData);
      // overrides defaults added above
      queries.putAll(newQueries);
    }

    // Create no relationship roles for this entity, will be added
    // by the relation meta data

    readAhead = JDBCReadAheadMetaData.DEFAULT;
    cleanReadAheadOnLoad = false;
    entityCommand = null;
    optimisticLocking = null;
    audit = null;
  }