/**
   * Loop over a signer tag looking for seinfo, package and cert tags. A {@link Policy} instance
   * will be created and returned in the process. During the pass all other tag elements will be
   * skipped.
   *
   * @param parser an XmlPullParser object representing a signer element.
   * @return the constructed {@link Policy} instance
   * @throws IOException
   * @throws XmlPullParserException
   * @throws IllegalArgumentException if any of the validation checks fail while parsing tag values.
   * @throws IllegalStateException if any of the invariants fail when constructing the {@link
   *     Policy} instance.
   */
  private static Policy readSignerOrThrow(XmlPullParser parser)
      throws IOException, XmlPullParserException {

    parser.require(XmlPullParser.START_TAG, null, "signer");
    Policy.PolicyBuilder pb = new Policy.PolicyBuilder();

    // Check for a cert attached to the signer tag. We allow a signature
    // to appear as an attribute as well as those attached to cert tags.
    String cert = parser.getAttributeValue(null, "signature");
    if (cert != null) {
      pb.addSignature(cert);
    }

    while (parser.next() != XmlPullParser.END_TAG) {
      if (parser.getEventType() != XmlPullParser.START_TAG) {
        continue;
      }

      String tagName = parser.getName();
      if ("seinfo".equals(tagName)) {
        String seinfo = parser.getAttributeValue(null, "value");
        pb.setGlobalSeinfoOrThrow(seinfo);
        readSeinfo(parser);
      } else if ("package".equals(tagName)) {
        readPackageOrThrow(parser, pb);
      } else if ("cert".equals(tagName)) {
        String sig = parser.getAttributeValue(null, "signature");
        pb.addSignature(sig);
        readCert(parser);
      } else {
        skip(parser);
      }
    }

    return pb.build();
  }
  /**
   * Loop over a package element looking for seinfo child tags. If found return the value attribute
   * of the seinfo tag, otherwise return null. All other tags encountered will be skipped.
   *
   * @param parser an XmlPullParser object representing a package element.
   * @param pb a Policy.PolicyBuilder instance to build
   * @throws IOException
   * @throws XmlPullParserException
   * @throws IllegalArgumentException if any of the validation checks fail while parsing tag values.
   * @throws IllegalStateException if there is a duplicate seinfo tag for the current package tag.
   */
  private static void readPackageOrThrow(XmlPullParser parser, Policy.PolicyBuilder pb)
      throws IOException, XmlPullParserException {
    parser.require(XmlPullParser.START_TAG, null, "package");
    String pkgName = parser.getAttributeValue(null, "name");

    while (parser.next() != XmlPullParser.END_TAG) {
      if (parser.getEventType() != XmlPullParser.START_TAG) {
        continue;
      }

      String tagName = parser.getName();
      if ("seinfo".equals(tagName)) {
        String seinfo = parser.getAttributeValue(null, "value");
        pb.addInnerPackageMapOrThrow(pkgName, seinfo);
        readSeinfo(parser);
      } else {
        skip(parser);
      }
    }
  }