in log4j-converter-config/src/main/java/org/apache/logging/converter/config/internal/v2/AbstractJacksonConfigurationMapper.java [119:176]
private ObjectNode convertToObjectNode(
ConfigurationNode configurationNode, JsonNodeFactory nodeFactory, boolean explicitTypeAttribute) {
ObjectNode objectNode = nodeFactory.objectNode();
if (explicitTypeAttribute || requiresExplicitTypeAttribute(configurationNode)) {
objectNode.set(TYPE_ATTRIBUTE, nodeFactory.textNode(configurationNode.getPluginName()));
}
configurationNode.getAttributes().forEach(objectNode::put);
// If multiple nodes have the same name, we need to use JSON arrays or explicit type attributes.
// For a given plugin type, the strategy is:
// * For the first group of nodes with the given type we use an array.
// * If there is a second group of nodes with the same plugin name, we use an explicit type attribute.
//
// This strategy does not require us to reorder the children elements, which is not a functionally neutral
// operation
// (e.g., for filters).
Iterator<? extends ConfigurationNode> childrenIterator =
configurationNode.getChildren().iterator();
Collection<String> visitedPluginNames = new HashSet<>();
Collection<ConfigurationNode> similarChildren = new ArrayList<>();
@Nullable String similarChildrenPluginName = null;
int counter = 1;
while (childrenIterator.hasNext()) {
ConfigurationNode child = childrenIterator.next();
String childPluginName = child.getPluginName();
// If the plugin name is the same, add to the current group
if (childPluginName.equals(similarChildrenPluginName)) {
similarChildren.add(child);
continue;
}
// We have a new group
if (!similarChildren.isEmpty()) {
// Flush the previous group
JsonNode childNode = convertToJsonNode(similarChildren, nodeFactory);
String childKey = childNode instanceof ObjectNode && childNode.get(TYPE_ATTRIBUTE) != null
? "id" + counter++
: similarChildrenPluginName;
objectNode.set(childKey, convertToJsonNode(similarChildren, nodeFactory));
}
if (visitedPluginNames.add(childPluginName)) {
// 1. This is the first group with the given plugin name:
similarChildrenPluginName = childPluginName;
similarChildren.clear();
similarChildren.add(child);
} else {
// 2. Use an explicit type attribute
objectNode.set("id" + counter++, convertToObjectNode(child, nodeFactory, true));
}
}
// Flush the last group
if (!similarChildren.isEmpty()) {
JsonNode childNode = convertToJsonNode(similarChildren, nodeFactory);
String childKey = childNode instanceof ObjectNode && childNode.get(TYPE_ATTRIBUTE) != null
? "id" + counter
: similarChildrenPluginName;
objectNode.set(childKey, convertToJsonNode(similarChildren, nodeFactory));
}
return objectNode;
}