/**
   * Parse recovery tag
   *
   * @param reader reader
   * @return the parsed recovery object
   * @throws XMLStreamException in case of error
   * @throws ParserException in case of error
   * @throws ValidateException in case of error
   */
  protected Recovery parseRecovery(XMLStreamReader reader)
      throws XMLStreamException, ParserException, ValidateException {

    Boolean noRecovery = null;
    Credential security = null;
    Extension plugin = null;

    for (Recovery.Attribute attribute : Recovery.Attribute.values()) {
      switch (attribute) {
        case NO_RECOVERY:
          {
            noRecovery = attributeAsBoolean(reader, attribute.getLocalName(), Boolean.FALSE);
            break;
          }
        default:
          break;
      }
    }

    while (reader.hasNext()) {
      switch (reader.nextTag()) {
        case END_ELEMENT:
          {
            if (XaDataSource.Tag.forName(reader.getLocalName()) == XaDataSource.Tag.RECOVERY) {
              return new Recovery(security, plugin, noRecovery);
            } else {
              if (Recovery.Tag.forName(reader.getLocalName()) == Recovery.Tag.UNKNOWN) {
                throw new ParserException(bundle.unexpectedEndTag(reader.getLocalName()));
              }
            }
            break;
          }
        case START_ELEMENT:
          {
            Recovery.Tag tag = Recovery.Tag.forName(reader.getLocalName());
            switch (tag) {
              case RECOVER_CREDENTIAL:
                {
                  security = parseCredential(reader);
                  break;
                }
              case RECOVER_PLUGIN:
                {
                  plugin = parseExtension(reader, tag.getLocalName());
                  break;
                }
              default:
                throw new ParserException(bundle.unexpectedElement(reader.getLocalName()));
            }
            break;
          }
      }
    }
    throw new ParserException(bundle.unexpectedEndOfDocument());
  }
  /**
   * parse a {@link CommonXaPool} object
   *
   * @param reader reader
   * @return the parsed {@link CommonXaPool} object
   * @throws XMLStreamException XMLStreamException
   * @throws ParserException ParserException
   * @throws ValidateException ValidateException
   */
  protected CommonXaPool parseXaPool(XMLStreamReader reader)
      throws XMLStreamException, ParserException, ValidateException {
    Integer minPoolSize = null;
    Integer maxPoolSize = null;
    Boolean prefill = Boolean.FALSE;
    FlushStrategy flushStrategy = FlushStrategy.FAILING_CONNECTION_ONLY;
    Boolean interleaving = Boolean.FALSE;
    Boolean isSameRmOverride = Boolean.FALSE;
    Boolean padXid = Boolean.FALSE;
    Boolean noTxSeparatePool = Boolean.FALSE;
    Boolean wrapXaDataSource = Boolean.TRUE;
    Boolean useStrictMin = Boolean.FALSE;

    while (reader.hasNext()) {
      switch (reader.nextTag()) {
        case END_ELEMENT:
          {
            if (XaDataSource.Tag.forName(reader.getLocalName()) == XaDataSource.Tag.XA_POOL) {

              return new CommonXaPoolImpl(
                  minPoolSize,
                  maxPoolSize,
                  prefill,
                  useStrictMin,
                  flushStrategy,
                  isSameRmOverride,
                  interleaving,
                  padXid,
                  wrapXaDataSource,
                  noTxSeparatePool);

            } else {
              if (CommonXaPool.Tag.forName(reader.getLocalName()) == CommonXaPool.Tag.UNKNOWN) {
                throw new ParserException(bundle.unexpectedEndTag(reader.getLocalName()));
              }
            }
            break;
          }
        case START_ELEMENT:
          {
            switch (CommonXaPool.Tag.forName(reader.getLocalName())) {
              case MAX_POOL_SIZE:
                {
                  maxPoolSize = elementAsInteger(reader);
                  break;
                }
              case MIN_POOL_SIZE:
                {
                  minPoolSize = elementAsInteger(reader);
                  break;
                }
              case INTERLEAVING:
                {
                  interleaving = elementAsBoolean(reader);
                  break;
                }
              case IS_SAME_RM_OVERRIDE:
                {
                  isSameRmOverride = elementAsBoolean(reader);
                  break;
                }
              case NO_TX_SEPARATE_POOLS:
                {
                  noTxSeparatePool = elementAsBoolean(reader);
                  break;
                }
              case PAD_XID:
                {
                  padXid = elementAsBoolean(reader);
                  break;
                }
              case WRAP_XA_RESOURCE:
                {
                  wrapXaDataSource = elementAsBoolean(reader);
                  break;
                }
              case PREFILL:
                {
                  prefill = elementAsBoolean(reader);
                  break;
                }
              case USE_STRICT_MIN:
                {
                  useStrictMin = elementAsBoolean(reader);
                  break;
                }
              case FLUSH_STRATEGY:
                {
                  flushStrategy = elementAsFlushStrategy(reader);
                  break;
                }
              default:
                throw new ParserException(bundle.unexpectedElement(reader.getLocalName()));
            }
            break;
          }
      }
    }
    throw new ParserException(bundle.unexpectedEndOfDocument());
  }