protected SolrInputDocument readDoc()

in solr/core/src/java/org/apache/solr/handler/loader/XMLLoader.java [323:479]


  protected SolrInputDocument readDoc(XMLStreamReader parser, boolean forgiveNameAttr)
      throws XMLStreamException {
    SolrInputDocument doc = new SolrInputDocument();

    String attrName;
    String attrVal;
    for (int i = 0; i < parser.getAttributeCount(); i++) {
      attrName = parser.getAttributeLocalName(i);
      if ("boost".equals(attrName)) {
        String message =
            "Ignoring document boost: "
                + parser.getAttributeValue(i)
                + " as index-time boosts are not supported anymore";
        if (WARNED_ABOUT_INDEX_TIME_BOOSTS.compareAndSet(false, true)) {
          log.warn(message);
        } else {
          log.debug(message);
        }
      } else {
        if (!(NAME.equals(attrName) && forgiveNameAttr)) {
          log.warn("XML element <doc> has invalid XML attr: {}", attrName);
        }
      }
    }

    StringBuilder text = new StringBuilder();
    String currentFieldName = null;
    boolean isNull = false;
    boolean isLabeledChildDoc = false;
    String update = null;
    Collection<SolrInputDocument> subDocs = null;
    Map<String, Map<String, Object>> updateMap = null;
    boolean complete = false;
    while (!complete) {
      int event = parser.next();
      switch (event) {
          // Add everything to the text
        case XMLStreamConstants.SPACE:
        case XMLStreamConstants.CDATA:
        case XMLStreamConstants.CHARACTERS:
          text.append(parser.getText());
          break;

        case XMLStreamConstants.END_ELEMENT:
          if ("doc".equals(parser.getLocalName())) {
            if (subDocs != null && !subDocs.isEmpty()) {
              doc.addChildDocuments(subDocs);
              subDocs = null;
            }
            complete = true;
            break;
          } else if ("field".equals(parser.getLocalName())) {
            // should I warn in some text has been found too
            Object v = isNull ? null : text.toString();
            if (update != null) {
              if (updateMap == null) updateMap = new HashMap<>();
              Map<String, Object> extendedValues =
                  updateMap.computeIfAbsent(currentFieldName, k -> CollectionUtil.newHashMap(1));
              Object val = extendedValues.get(update);
              if (val == null) {
                extendedValues.put(update, v);
              } else {
                // multiple val are present
                if (val instanceof List) {
                  @SuppressWarnings("unchecked")
                  List<Object> list = (List<Object>) val;
                  list.add(v);
                } else {
                  List<Object> values = new ArrayList<>();
                  values.add(val);
                  values.add(v);
                  extendedValues.put(update, values);
                }
              }
              break;
            }
            if (!isLabeledChildDoc) {
              // only add data if this is not a childDoc, since it was added already
              doc.addField(currentFieldName, v);
            } else {
              // reset so next field is not treated as child doc
              isLabeledChildDoc = false;
            }
            // field is over
            currentFieldName = null;
          }
          break;

        case XMLStreamConstants.START_ELEMENT:
          text.setLength(0);
          String localName = parser.getLocalName();
          if ("doc".equals(localName)) {
            if (currentFieldName != null) { // enclosed in <field>
              // flag to prevent spaces after doc from being added
              isLabeledChildDoc = true;
              SolrInputDocument child = readDoc(parser);
              if (doc.containsKey(currentFieldName)) {
                doc.getField(currentFieldName).addValue(child);
              } else {
                final List<Object> list = new ArrayList<>(List.of(child));
                doc.addField(currentFieldName, list);
              }
            } else {
              final String subdocName = parser.getAttributeValue(null, NAME);
              if (subdocName != null) { // <doc name=""> enclosed in <doc>
                doc.addField(subdocName, readDoc(parser, true));
              } else { // unnamed <doc> enclosed in <doc>
                if (subDocs == null) {
                  subDocs = new ArrayList<>();
                }
                subDocs.add(readDoc(parser));
              }
            }
          } else {
            if (!"field".equals(localName)) {
              String msg = "XML element <doc> has invalid XML child element: " + localName;
              log.warn(msg);
              throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, msg);
            }
            update = null;
            isNull = false;
            for (int i = 0; i < parser.getAttributeCount(); i++) {
              attrName = parser.getAttributeLocalName(i);
              attrVal = parser.getAttributeValue(i);
              if (NAME.equals(attrName)) {
                currentFieldName = attrVal;
              } else if ("boost".equals(attrName)) {
                String message =
                    "Ignoring field boost: "
                        + attrVal
                        + " as index-time boosts are not supported anymore";
                if (WARNED_ABOUT_INDEX_TIME_BOOSTS.compareAndSet(false, true)) {
                  log.warn(message);
                } else {
                  log.debug(message);
                }
              } else if ("null".equals(attrName)) {
                isNull = StrUtils.parseBoolean(attrVal);
              } else if ("update".equals(attrName)) {
                update = attrVal;
              } else {
                log.warn("XML element <field> has invalid XML attr: {}", attrName);
              }
            }
          }
          break;
      }
    }

    if (updateMap != null) {
      for (Map.Entry<String, Map<String, Object>> entry : updateMap.entrySet()) {
        doc.addField(entry.getKey(), entry.getValue());
      }
    }

    return doc;
  }