private boolean expandMetaChoice(
      Writer output,
      DbObject object,
      MetaChoice choice,
      boolean state[],
      MetaClass childrenMetaClass,
      RuleOptions options)
      throws DbException, IOException, RuleException {

    boolean expanded = false;
    Object child = object.get(choice);

    if (child instanceof DbObject) {
      DbObject dbChild = (DbObject) child;
      MetaClass metaClass = dbChild.getMetaClass();
      String className = metaClass.getGUIName();
      boolean excluded = false;

      // check if child's class is excluded
      if (options != null) {
        excluded = options.isExcluded(className);

        // if not, check if parent's connection is excluded
        if (!excluded) {
          MetaClass metaClass2 = object.getMetaClass();
          String parentClassName = metaClass2.getGUIName();
          String connectionName = parentClassName + "." + choice.getGUIName();
          excluded = options.isExcluded(connectionName);
        } // end if
      } // end if

      if (!excluded) {
        if (childrenMetaClass.isAssignableFrom(metaClass)) {
          expanded |= expandChild(output, object, dbChild, 1, state, options);
        } // end if
      } // end if
    } // end if

    if ((!expanded) && (nullModifier != null)) {
      expanded |= nullModifier.expand(output, object, options);
    } // end if

    return expanded;
  } // end expandMetaChoice
  // if propertyName is in excludeList, or if className is in excludeList
  // className : like 'Table', 'Column', 'Class', ..
  // propertyName : like 'Table.Name', 'Column.Alias', ..
  protected boolean verifyExclusion(String className, String propertyName, RuleOptions options) {
    boolean excluded = false;

    if (options == null) {
      return false;
    }

    ArrayList excludeList = options.getExcludeList();

    if (excludeList != null) {
      if (excludeList.contains(className)) {
        excluded = true;
      } else if (excludeList.contains(propertyName)) {
        excluded = true;
      }
    } // end if

    return excluded;
  }
  protected boolean verifyExclusion(Serializable obj, RuleOptions options) {
    boolean excluded = false;

    if (options == null) {
      return false;
    }

    ArrayList excludeList = options.getExcludeList();

    if (obj != null) {
      if (obj instanceof DbObject) {
        DbObject dbObj = (DbObject) obj;
        MetaClass metaClass = dbObj.getMetaClass();
        String className = metaClass.getGUIName();
        if (excludeList != null) {
          if (excludeList.contains(className)) {
            excluded = true;
          }
        }
      }
    } // end if

    return excluded;
  }
  // add childrenMetaClass to filter only children of that class
  // if null, scan each child
  protected boolean expandMetaRelationN(
      Writer output,
      DbObject object,
      MetaRelationship metaRelation,
      boolean state[],
      MetaClass childrenMetaClass,
      RuleOptions options)
      throws DbException, IOException, RuleException {

    boolean expanded = false;
    DbEnumeration dbEnumChildren = null;
    DbRelationN relationN = (DbRelationN) object.get(metaRelation);
    if (childrenMetaClass == null) {
      dbEnumChildren = relationN.elements();
    } else {
      dbEnumChildren = relationN.elements(childrenMetaClass);
    }

    // a first pass to find out the number of children
    int nbChildren = 0;
    try {
      while (dbEnumChildren.hasMoreElements()) {
        dbEnumChildren.nextElement();
        nbChildren++;

        // Cancel everything if the user has decided to stop the
        // operation
        if (options != null) {
          Controller controller = options.m_controller;
          if (controller != null) {
            boolean can_continue = controller.checkPoint();
            if (!can_continue) {
              throw new RuleException(controller.getAbortedString());
            }
          }
        } // end if
      } // end while
    } finally {
      dbEnumChildren.close();
    }

    // cannot rollback to the first element, so recreate the enumeration
    if (childrenMetaClass == null) {
      dbEnumChildren = relationN.elements();
    } else {
      dbEnumChildren = relationN.elements(childrenMetaClass);
    }

    try {
      while (dbEnumChildren.hasMoreElements()) {
        DbObject child = (DbObject) dbEnumChildren.nextElement();
        MetaClass metaClass = child.getMetaClass();
        String className = metaClass.getGUIName();
        boolean excluded = false;

        // check if child's class is excluded
        if (options != null) {
          excluded = options.isExcluded(className);

          // if not, check if parent's connection is excluded
          if (!excluded) {
            metaClass = object.getMetaClass();
            String parentClassName = metaClass.getGUIName();
            String connectionName = parentClassName + "." + metaRelation.getGUIName();
            excluded = options.isExcluded(connectionName);
          } // end if
        } // end if

        if (!excluded) {
          expanded |= expandChild(output, object, child, nbChildren, state, options);
        } // end if
      } // end while
    } finally {
      dbEnumChildren.close();
    }

    boolean atLeastOneChildPrinted = state[1];

    if ((atLeastOneChildPrinted) && (suffixModifier != null)) {
      expanded |= suffixModifier.expand(output, object, options);
    } else if ((!atLeastOneChildPrinted) && (nullModifier != null)) {
      expanded |= nullModifier.expand(output, object, options);
    }

    return expanded;
  } // end expandMetaRelationN
  private boolean expandMetaRelation1(
      Writer output,
      DbObject object,
      MetaRelation1 metaRelation1,
      boolean state[],
      MetaClass childrenMetaClass,
      RuleOptions options)
      throws DbException, IOException, RuleException {

    boolean expanded = false;
    Object child;
    if (childrenMetaClass != null) {
      if (metaRelation1 == DbObject.fComposite) {
        child = object.getCompositeOfType(childrenMetaClass);
      } else {
        child = object.get(metaRelation1);
        if (child instanceof DbObject) {
          DbObject dbChild = (DbObject) child;
          MetaClass mc = dbChild.getMetaClass();
          if (mc != childrenMetaClass) {
            child = null;
          }
        }
      }
    } else {
      child = object.get(metaRelation1);
    } // end if

    if (child != null) {
      if (child instanceof DbObject) {
        DbObject dbChild = (DbObject) child;
        MetaClass metaClass = dbChild.getMetaClass();
        String className = metaClass.getGUIName();
        boolean excluded = false;

        // check if child's class is excluded
        if (options != null) {
          excluded = options.isExcluded(className);

          // if not, check if parent's connection is excluded
          if (!excluded) {
            metaClass = object.getMetaClass();
            String parentClassName = metaClass.getGUIName();
            String connectionName = parentClassName + "." + metaRelation1.getGUIName();
            excluded = options.isExcluded(connectionName);
          } // end if
        } // end if

        if (!excluded) {
          expanded |= expandChild(output, object, dbChild, 1, state, options);
        } // end if
      } // end if
    } // end if

    // if a SUF modifier has to be expanded
    if ((expanded) && (suffixModifier != null)) {
      suffixModifier.expand(output, object, options);
    }

    // if a NULL modifier has to be expanded
    if ((!expanded) && (nullModifier != null)) {
      expanded |= nullModifier.expand(output, object, options);
    }

    return expanded;
  } // end expandMetaRelation1