void traverse(
      Element uElem, XSElementDecl element, XSDocumentInfo schemaDoc, SchemaGrammar grammar) {

    // General Attribute Checking
    Object[] attrValues = fAttrChecker.checkAttributes(uElem, false, schemaDoc);

    // create identity constraint
    String uName = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];

    if (uName == null) {
      reportSchemaError(
          "s4s-att-must-appear",
          new Object[] {DOMUtil.getLocalName(uElem), SchemaSymbols.ATT_NAME},
          uElem);
      // return this array back to pool
      fAttrChecker.returnAttrArray(attrValues, schemaDoc);
      return;
    }

    UniqueOrKey uniqueOrKey = null;
    if (DOMUtil.getLocalName(uElem).equals(SchemaSymbols.ELT_UNIQUE)) {
      uniqueOrKey =
          new UniqueOrKey(
              schemaDoc.fTargetNamespace, uName, element.fName, IdentityConstraint.IC_UNIQUE);
    } else {
      uniqueOrKey =
          new UniqueOrKey(
              schemaDoc.fTargetNamespace, uName, element.fName, IdentityConstraint.IC_KEY);
    }
    // it's XSDElementTraverser's job to ensure that there's no
    // duplication (or if there is that restriction is involved
    // and there's identity).

    // If errors occurred in traversing the identity constraint, then don't
    // add it to the schema, to avoid errors when processing the instance.
    if (traverseIdentityConstraint(uniqueOrKey, uElem, schemaDoc, attrValues)) {
      // and stuff this in the grammar
      if (grammar.getIDConstraintDecl(uniqueOrKey.getIdentityConstraintName()) == null) {
        grammar.addIDConstraintDecl(element, uniqueOrKey);
      }

      final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
      final IdentityConstraint idc =
          grammar.getIDConstraintDecl(uniqueOrKey.getIdentityConstraintName(), loc);
      if (idc == null) {
        grammar.addIDConstraintDecl(element, uniqueOrKey, loc);
      }

      // handle duplicates
      if (fSchemaHandler.fTolerateDuplicates) {
        if (idc != null) {
          if (idc instanceof UniqueOrKey) {
            uniqueOrKey = (UniqueOrKey) uniqueOrKey;
          }
        }
        fSchemaHandler.addIDConstraintDecl(uniqueOrKey);
      }
    }

    // and fix up attributeChecker
    fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  } // traverse(Element,XSDElementDecl,XSDocumentInfo, SchemaGrammar)
  void traverse(
      Element krElem, XSElementDecl element, XSDocumentInfo schemaDoc, SchemaGrammar grammar) {

    // General Attribute Checking
    Object[] attrValues = fAttrChecker.checkAttributes(krElem, false, schemaDoc);

    // create identity constraint
    String krName = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
    if (krName == null) {
      reportSchemaError(
          "s4s-att-must-appear",
          new Object[] {SchemaSymbols.ELT_KEYREF, SchemaSymbols.ATT_NAME},
          krElem);
      // return this array back to pool
      fAttrChecker.returnAttrArray(attrValues, schemaDoc);
      return;
    }
    QName kName = (QName) attrValues[XSAttributeChecker.ATTIDX_REFER];
    if (kName == null) {
      reportSchemaError(
          "s4s-att-must-appear",
          new Object[] {SchemaSymbols.ELT_KEYREF, SchemaSymbols.ATT_REFER},
          krElem);
      // return this array back to pool
      fAttrChecker.returnAttrArray(attrValues, schemaDoc);
      return;
    }

    UniqueOrKey key = null;
    IdentityConstraint ret =
        (IdentityConstraint)
            fSchemaHandler.getGlobalDecl(
                schemaDoc, XSDHandler.IDENTITYCONSTRAINT_TYPE, kName, krElem);
    // if ret == null, we've already reported an error in getGlobalDecl
    // we report an error only when ret != null, and the return type keyref
    if (ret != null) {
      if (ret.getCategory() == IdentityConstraint.IC_KEY
          || ret.getCategory() == IdentityConstraint.IC_UNIQUE) {
        key = (UniqueOrKey) ret;
      } else {
        reportSchemaError(
            "src-resolve", new Object[] {kName.rawname, "identity constraint key/unique"}, krElem);
      }
    }

    if (key == null) {
      fAttrChecker.returnAttrArray(attrValues, schemaDoc);
      return;
    }

    KeyRef keyRef = new KeyRef(schemaDoc.fTargetNamespace, krName, element.fName, key);

    // If errors occurred in traversing the identity constraint, then don't
    // add it to the schema, to avoid errors when processing the instance.
    if (traverseIdentityConstraint(keyRef, krElem, schemaDoc, attrValues)) {
      // Schema Component Constraint: Identity-constraint Definition Properties Correct
      // 2 If the {identity-constraint category} is keyref, the cardinality of the {fields} must
      // equal that of the {fields} of the {referenced key}.
      if (key.getFieldCount() != keyRef.getFieldCount()) {
        reportSchemaError(
            "c-props-correct.2", new Object[] {krName, key.getIdentityConstraintName()}, krElem);
      } else {
        // add key reference to element decl
        // and stuff this in the grammar
        if (grammar.getIDConstraintDecl(keyRef.getIdentityConstraintName()) == null) {
          grammar.addIDConstraintDecl(element, keyRef);
        }

        // also add it to extended map
        final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
        final IdentityConstraint idc =
            grammar.getIDConstraintDecl(keyRef.getIdentityConstraintName(), loc);
        if (idc == null) {
          grammar.addIDConstraintDecl(element, keyRef, loc);
        }

        // handle duplicates
        if (fSchemaHandler.fTolerateDuplicates) {
          if (idc != null) {
            if (idc instanceof KeyRef) {
              keyRef = (KeyRef) idc;
            }
          }
          fSchemaHandler.addIDConstraintDecl(keyRef);
        }
      }
    }

    // and put back attributes
    fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  } // traverse(Element,int,XSDocumentInfo, SchemaGrammar)