• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kit-data-manager / ro-crate-java / #357

16 Apr 2025 04:19PM UTC coverage: 86.147%. First build
#357

Pull #233

github

Pfeil
fix: replace get() with path() for safer JSON node access in CustomPreview
Pull Request #233: Version 2.1.0

532 of 690 new or added lines in 19 files covered. (77.1%)

1878 of 2180 relevant lines covered (86.15%)

0.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/main/java/edu/kit/datamanager/ro_crate/util/JsonLdExpander.java
1
package edu.kit.datamanager.ro_crate.util;
2

3
import com.fasterxml.jackson.databind.*;
4
import com.fasterxml.jackson.databind.node.*;
5

6
import java.util.*;
7

8
import java.io.File;
9

10
/**
11
 * Utility class for expanding and pruning JSON-LD documents.
12
 *
13
 * This class provides functionality to resolve references in JSON-LD based on "@id" values,
14
 * expanding the data structure by replacing references with their full content.
15
 * It also handles circular references to prevent infinite recursion.
16
 *
17
 * @author jejkal
18
 */
NEW
19
public class JsonLdExpander {
×
20

21
    public static JsonNode expandAndPrune(File jsonLdFile) throws Exception {
NEW
22
        ObjectMapper mapper = new ObjectMapper();
×
NEW
23
        JsonNode root = mapper.readTree(jsonLdFile);
×
NEW
24
        return expandAndPrune(root);
×
25
    }
26

27
    public static JsonNode expandAndPrune(JsonNode root) throws IllegalArgumentException {
NEW
28
        if (root == null) {
×
NEW
29
            throw new IllegalArgumentException("Root node must not be null.");
×
30
        }
NEW
31
        JsonNode graph = root.path("@graph");
×
NEW
32
        ObjectMapper mapper = new ObjectMapper();
×
33
        // Index all items by @id
NEW
34
        Map<String, JsonNode> idMap = new HashMap<>();
×
NEW
35
        for (JsonNode node : graph) {
×
NEW
36
            if (node.has("@id")) {
×
NEW
37
                idMap.put(node.path("@id").asText(), node);
×
38
            }
NEW
39
        }
×
40

41
        // Track which ids were directly referenced and expanded
NEW
42
        Set<String> expandedIds = new HashSet<>();
×
43

NEW
44
        ArrayNode expandedGraph = mapper.createArrayNode();
×
NEW
45
        for (JsonNode node : graph) {
×
46
            // Include only if it's NOT a referenced/expanded object
NEW
47
            if (node.has("@id") && expandedIds.contains(node.path("@id").asText())) {
×
NEW
48
                continue; // skip referenced/expanded nodes
×
49
            }
50

NEW
51
            JsonNode expandedNode = expandNode(node, idMap, expandedIds, mapper, new HashSet<>());
×
NEW
52
            expandedGraph.add(expandedNode);
×
NEW
53
        }
×
54

55
        // Rebuild root
NEW
56
        ObjectNode newRoot = mapper.createObjectNode();
×
NEW
57
        newRoot.set("@context", root.path("@context"));
×
NEW
58
        newRoot.set("@graph", expandedGraph);
×
NEW
59
        return newRoot;
×
60
    }
61

62
    private static JsonNode expandNode(JsonNode node, Map<String, JsonNode> idMap, Set<String> expandedIds, ObjectMapper mapper, Set<String> visited) {
NEW
63
        if (!node.isObject()) {
×
NEW
64
            return node;
×
65
        }
66

NEW
67
        ObjectNode result = mapper.createObjectNode();
×
NEW
68
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
×
69

NEW
70
        while (fields.hasNext()) {
×
NEW
71
            Map.Entry<String, JsonNode> entry = fields.next();
×
NEW
72
            String key = entry.getKey();
×
NEW
73
            JsonNode value = entry.getValue();
×
74

NEW
75
            if (value.isObject() && value.has("@id")) {
×
NEW
76
                String refId = value.path("@id").asText();
×
NEW
77
                if (!visited.contains(refId) && idMap.containsKey(refId)) {
×
NEW
78
                    visited.add(refId);
×
NEW
79
                    expandedIds.add(refId);
×
NEW
80
                    result.set(key, expandNode(idMap.getOrDefault(refId, NullNode.getInstance()), idMap, expandedIds, mapper, new HashSet<>(visited)));
×
81
                } else {
NEW
82
                    result.set(key, value);
×
83
                }
NEW
84
            } else if (value.isArray()) {
×
NEW
85
                ArrayNode newArray = mapper.createArrayNode();
×
NEW
86
                for (JsonNode element : value) {
×
NEW
87
                    if (element.isObject() && element.has("@id")) {
×
NEW
88
                        String refId = element.path("@id").asText();
×
NEW
89
                        if (!visited.contains(refId) && idMap.containsKey(refId)) {
×
NEW
90
                            visited.add(refId);
×
NEW
91
                            expandedIds.add(refId);
×
NEW
92
                            newArray.add(expandNode(idMap.getOrDefault(refId, NullNode.getInstance()), idMap, expandedIds, mapper, new HashSet<>(visited)));
×
93
                        } else {
NEW
94
                            newArray.add(element);
×
95
                        }
NEW
96
                    } else {
×
NEW
97
                        newArray.add(expandNode(element, idMap, expandedIds, mapper, visited));
×
98
                    }
NEW
99
                }
×
NEW
100
                result.set(key, newArray);
×
NEW
101
            } else if (value.isObject()) {
×
NEW
102
                result.set(key, expandNode(value, idMap, expandedIds, mapper, visited));
×
103
            } else {
NEW
104
                result.set(key, value);
×
105
            }
NEW
106
        }
×
107

NEW
108
        return result;
×
109
    }
110
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc