/** Parse the given string, return resulting data if appropriate. */
  ParseResult internalParse(
      String s, Map<String, Integer> targetUnionDecisions, boolean mustConsumeStr) {
    //
    // If there's no target decision, then go ahead and try all branches.
    //
    if (targetUnionDecisions == null || targetUnionDecisions.get(name) == null) {
      for (InferredType subelt : unionTypes) {
        ParseResult pr = subelt.internalParse(s, targetUnionDecisions, false);
        if (pr != null
            && (!mustConsumeStr
                || (mustConsumeStr && pr.getRemainingString().trim().length() == 0))) {
          return new ParseResult(pr.getData(), pr.hasData(), pr.getRemainingString());
        }
      }
      return null;
    }

    //
    // If there is a target decision, then carry it out.
    //
    InferredType subelt = unionTypes.get(targetUnionDecisions.get(name));
    ParseResult pr = subelt.internalParse(s, targetUnionDecisions, false);
    if (pr != null
        && (!mustConsumeStr || (mustConsumeStr && pr.getRemainingString().trim().length() == 0))) {
      return new ParseResult(pr.getData(), pr.hasData(), pr.getRemainingString());
    }
    return null;
  }
  /** Parse the given string, return resulting data if appropriate. */
  ParseResult internalParse(
      String s, Map<String, Integer> targetUnionDecisions, boolean mustConsumeStr) {
    boolean hasData = false;
    GenericData.Record gdr = new GenericData.Record(getAvroSchema());
    String currentStr = s;

    for (InferredType subelt : structTypes) {
      if (currentStr.length() == 0) {
        return null;
      }
      ParseResult pr = subelt.internalParse(currentStr, targetUnionDecisions, false);
      if (pr == null) {
        return null;
      }
      if (pr.hasData()) {
        hasData = true;
        gdr.put(subelt.getName(), pr.getData());
      }
      currentStr = pr.getRemainingString();
    }
    if (mustConsumeStr && currentStr.trim().length() != 0) {
      return null;
    }
    return new ParseResult(gdr, hasData, currentStr);
  }
  /** Parse the given string, return resulting data if appropriate. */
  ParseResult internalParse(
      String s, Map<String, Integer> targetUnionDecisions, boolean mustConsumeStr) {
    boolean hasData = false;
    Schema localSchema = getAvroSchema();
    GenericData.Array gda = new GenericData.Array(5, localSchema);
    Map<String, Integer> curUnionDecisions = new HashMap<String, Integer>();
    String currentStr = s;

    while (true) {
      ParseResult pr = bodyType.internalParse(currentStr, targetUnionDecisions, false);
      if (pr == null) {
        break;
      }
      assert (pr.hasData());

      gda.add(pr.getData());
      currentStr = pr.getRemainingString();
    }
    if (mustConsumeStr && currentStr.trim().length() != 0) {
      return null;
    }
    return new ParseResult(gda, true, currentStr);
  }