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

knowledgepixels / nanodash / 20268103742

16 Dec 2025 12:35PM UTC coverage: 15.441% (+0.08%) from 15.358%
20268103742

Pull #330

github

web-flow
Merge c35eff5f3 into c20c94c1b
Pull Request #330: Add plain paragraph view

601 of 4986 branches covered (12.05%)

Branch coverage included in aggregate %.

1583 of 9158 relevant lines covered (17.29%)

2.25 hits per line

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

0.0
src/main/java/com/knowledgepixels/nanodash/ResourceView.java
1
package com.knowledgepixels.nanodash;
2

3
import com.knowledgepixels.nanodash.template.Template;
4
import com.knowledgepixels.nanodash.template.TemplateData;
5
import com.knowledgepixels.nanodash.vocabulary.KPXL_TERMS;
6
import org.eclipse.rdf4j.model.IRI;
7
import org.eclipse.rdf4j.model.Literal;
8
import org.eclipse.rdf4j.model.Statement;
9
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
10
import org.eclipse.rdf4j.model.vocabulary.RDF;
11
import org.eclipse.rdf4j.model.vocabulary.RDFS;
12
import org.nanopub.Nanopub;
13
import org.slf4j.Logger;
14
import org.slf4j.LoggerFactory;
15

16
import java.io.Serializable;
17
import java.util.*;
18

19
/**
20
 * A class representing a Resource View.
21
 */
22
public class ResourceView implements Serializable {
23

24
    private static final Logger logger = LoggerFactory.getLogger(ResourceView.class);
×
25

26
    static Map<IRI, Integer> columnWidths = new HashMap<>();
×
27

28
    static {
29
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_1_OF_12, 1);
×
30
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_2_OF_12, 2);
×
31
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_3_OF_12, 3);
×
32
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_4_OF_12, 4);
×
33
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_5_OF_12, 5);
×
34
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_6_OF_12, 6);
×
35
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_7_OF_12, 7);
×
36
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_8_OF_12, 8);
×
37
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_9_OF_12, 9);
×
38
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_10_OF_12, 10);
×
39
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_11_OF_12, 11);
×
40
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_12_OF_12, 12);
×
41
    }
42

43
    private static Map<String, ResourceView> resourceViews = new HashMap<>();
×
44

45
    /**
46
     * Get a ResourceView by its ID.
47
     *
48
     * @param id the ID of the ResourceView
49
     * @return the ResourceView object
50
     */
51
    public static ResourceView get(String id) {
52
        String npId = id.replaceFirst("^(.*[^A-Za-z0-9-_]RA[A-Za-z0-9-_]{43})[^A-Za-z0-9-_].*$", "$1");
×
53
        // Automatically selecting latest version of view definition:
54
        // TODO This should be made configurable at some point, so one can make it a fixed version.
55
        String latestNpId = QueryApiAccess.getLatestVersionId(npId);
×
56
        String latestId = id;
×
57
        Nanopub np = Utils.getAsNanopub(latestNpId);
×
58
        if (!latestNpId.equals(npId)) {
×
59
            Set<String> embeddedIris = Utils.getEmbeddedIriIds(np);
×
60
            if (embeddedIris.size() == 1) {
×
61
                latestId = embeddedIris.iterator().next();
×
62
            } else {
63
                latestNpId = npId;
×
64
                np = Utils.getAsNanopub(npId);
×
65
            }
66
        }
67
        if (!resourceViews.containsKey(latestId)) {
×
68
            try {
69
                resourceViews.put(latestId, new ResourceView(latestId, np));
×
70
            } catch (Exception ex) {
×
71
                logger.error("Couldn't load nanopub for resource: " + id, ex);
×
72
            }
×
73
        }
74
        return resourceViews.get(latestId);
×
75
    }
76

77
    private String id;
78
    private Nanopub nanopub;
79
    private IRI viewKind;
80
    private String label;
81
    private String title = "View";
×
82
    private GrlcQuery query;
83
    private String queryField = "resource";
×
84
    private Integer pageSize;
85
    private Integer displayWidth;
86
    private String structuralPosition;
87
    private List<IRI> viewResultActionList = new ArrayList<>();
×
88
    private List<IRI> viewEntryActionList = new ArrayList<>();
×
89
    private Set<IRI> appliesToClasses = new HashSet<>();
×
90
    private Set<IRI> appliesToNamespaces = new HashSet<>();
×
91
    private Map<IRI, Template> actionTemplateMap = new HashMap<>();
×
92
    private Map<IRI, String> actionTemplateTargetFieldMap = new HashMap<>();
×
93
    private Map<IRI, IRI> actionTemplateTypeMap = new HashMap<>();
×
94
    private Map<IRI, String> actionTemplatePartFieldMap = new HashMap<>();
×
95
    private Map<IRI, String> actionTemplateQueryMappingMap = new HashMap<>();
×
96
    private Map<IRI, String> labelMap = new HashMap<>();
×
97
    private IRI viewType;
98

99
    private ResourceView(String id, Nanopub nanopub) {
×
100
        this.id = id;
×
101
        this.nanopub = nanopub;
×
102
        List<IRI> actionList = new ArrayList<>();
×
103
        boolean resourceViewTypeFound = false;
×
104
        for (Statement st : nanopub.getAssertion()) {
×
105
            if (st.getSubject().stringValue().equals(id)) {
×
106
                if (st.getPredicate().equals(RDF.TYPE)) {
×
107
                    if (st.getObject().equals(KPXL_TERMS.RESOURCE_VIEW)) {
×
108
                        resourceViewTypeFound = true;
×
109
                    }
110
                    if (st.getObject().equals(KPXL_TERMS.TABULAR_VIEW) || st.getObject().equals(KPXL_TERMS.LIST_VIEW) || st.getObject().equals(KPXL_TERMS.PLAIN_PARAGRAPH_VIEW)) {
×
111
                        viewType = (IRI) st.getObject();
×
112
                    }
113
                } else if (st.getPredicate().equals(DCTERMS.IS_VERSION_OF) && st.getObject() instanceof IRI objIri) {
×
114
                    viewKind = objIri;
×
115
                } else if (st.getPredicate().equals(RDFS.LABEL)) {
×
116
                    label = st.getObject().stringValue();
×
117
                } else if (st.getPredicate().equals(DCTERMS.TITLE)) {
×
118
                    title = st.getObject().stringValue();
×
119
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_VIEW_QUERY)) {
×
120
                    query = GrlcQuery.get(st.getObject().stringValue());
×
121
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_VIEW_QUERY_TARGET_FIELD)) {
×
122
                    queryField = st.getObject().stringValue();
×
123
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_VIEW_ACTION) && st.getObject() instanceof IRI objIri) {
×
124
                    actionList.add(objIri);
×
125
                } else if (st.getPredicate().equals(KPXL_TERMS.APPLIES_TO_NAMESPACE) && st.getObject() instanceof IRI objIri) {
×
126
                    appliesToNamespaces.add(objIri);
×
127
                } else if (st.getPredicate().equals(KPXL_TERMS.APPLIES_TO_INSTANCES_OF) && st.getObject() instanceof IRI objIri) {
×
128
                    appliesToClasses.add(objIri);
×
129
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_VIEW_TARGET_CLASS) && st.getObject() instanceof IRI objIri) {
×
130
                    // Deprecated
131
                    appliesToClasses.add(objIri);
×
132
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_PAGE_SIZE) && st.getObject() instanceof Literal objL) {
×
133
                    try {
134
                        pageSize = Integer.parseInt(objL.stringValue());
×
135
                    } catch (NumberFormatException ex) {
×
136
                        logger.error("Invalid page size value: " + objL.stringValue(), ex);
×
137
                    }
×
138
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_DISPLAY_WIDTH) && st.getObject() instanceof IRI objIri) {
×
139
                    displayWidth = columnWidths.get(objIri);
×
140
                } else if (st.getPredicate().equals(KPXL_TERMS.HAS_STRUCTURAL_POSITION) && st.getObject() instanceof Literal objL) {
×
141
                    structuralPosition = objL.stringValue();
×
142
                }
143
            } else if (st.getPredicate().equals(KPXL_TERMS.HAS_ACTION_TEMPLATE)) {
×
144
                Template template = TemplateData.get().getTemplate(st.getObject().stringValue());
×
145
                actionTemplateMap.put((IRI) st.getSubject(), template);
×
146
            } else if (st.getPredicate().equals(KPXL_TERMS.HAS_ACTION_TEMPLATE_TARGET_FIELD)) {
×
147
                actionTemplateTargetFieldMap.put((IRI) st.getSubject(), st.getObject().stringValue());
×
148
            } else if (st.getPredicate().equals(KPXL_TERMS.HAS_ACTION_TEMPLATE_PART_FIELD)) {
×
149
                actionTemplatePartFieldMap.put((IRI) st.getSubject(), st.getObject().stringValue());
×
150
            } else if (st.getPredicate().equals(KPXL_TERMS.HAS_ACTION_TEMPLATE_QUERY_MAPPING)) {
×
151
                actionTemplateQueryMappingMap.put((IRI) st.getSubject(), st.getObject().stringValue());
×
152
            } else if (st.getPredicate().equals(RDFS.LABEL)) {
×
153
                labelMap.put((IRI) st.getSubject(), st.getObject().stringValue());
×
154
            } else if (st.getPredicate().equals(RDF.TYPE)) {
×
155
                if (st.getObject().equals(KPXL_TERMS.VIEW_ACTION) || st.getObject().equals(KPXL_TERMS.VIEW_ENTRY_ACTION)) {
×
156
                    actionTemplateTypeMap.put((IRI) st.getSubject(), (IRI) st.getObject());
×
157
                }
158
            }
159
        }
×
160
        for (IRI actionIri : actionList) {
×
161
            if (actionTemplateTypeMap.containsKey(actionIri) && actionTemplateTypeMap.get(actionIri).equals(KPXL_TERMS.VIEW_ENTRY_ACTION)) {
×
162
                viewEntryActionList.add(actionIri);
×
163
            } else {
164
                viewResultActionList.add(actionIri);
×
165
            }
166
        }
×
167
        if (!resourceViewTypeFound) throw new IllegalArgumentException("Not a proper resource view nanopub: " + id);
×
168
        if (query == null) throw new IllegalArgumentException("Query not found: " + id);
×
169
    }
×
170

171
    /**
172
     * Gets the ID of the ResourceView.
173
     *
174
     * @return the ID of the ResourceView
175
     */
176
    public String getId() {
177
        return id;
×
178
    }
179

180
    /**
181
     * Gets the Nanopub defining this ResourceView.
182
     *
183
     * @return the Nanopub defining this ResourceView
184
     */
185
    public Nanopub getNanopub() {
186
        return nanopub;
×
187
    }
188

189
    public IRI getViewKindIri() {
190
        return viewKind;
×
191
    }
192

193
    /**
194
     * Gets the label of the ResourceView.
195
     *
196
     * @return the label of the ResourceView
197
     */
198
    public String getLabel() {
199
        return label;
×
200
    }
201

202
    /**
203
     * Gets the title of the ResourceView.
204
     *
205
     * @return the title of the ResourceView
206
     */
207
    public String getTitle() {
208
        return title;
×
209
    }
210

211
    /**
212
     * Gets the GrlcQuery associated with the ResourceView.
213
     *
214
     * @return the GrlcQuery associated with the ResourceView
215
     */
216
    public GrlcQuery getQuery() {
217
        return query;
×
218
    }
219

220
    /**
221
     * Gets the query field of the ResourceView.
222
     *
223
     * @return the query field
224
     */
225
    public String getQueryField() {
226
        return queryField;
×
227
    }
228

229
    /**
230
     * Returns the preferred page size.
231
     *
232
     * @return page size (0 = everything on first page)
233
     */
234
    public Integer getPageSize() {
235
        return pageSize;
×
236
    }
237

238
    public Integer getDisplayWidth() {
239
        return displayWidth;
×
240
    }
241

242
    public String getStructuralPosition() {
243
        return structuralPosition;
×
244
    }
245

246
    /**
247
     * Gets the list of action IRIs associated with the ResourceView.
248
     *
249
     * @return the list of action IRIs
250
     */
251
    public List<IRI> getViewResultActionList() {
252
        return viewResultActionList;
×
253
    }
254

255
    public List<IRI> getViewEntryActionList() {
256
        return viewEntryActionList;
×
257
    }
258

259
    /**
260
     * Gets the Template for a given action IRI.
261
     *
262
     * @param actionIri the action IRI
263
     * @return the Template for the action IRI
264
     */
265
    public Template getTemplateForAction(IRI actionIri) {
266
        return actionTemplateMap.get(actionIri);
×
267
    }
268

269
    /**
270
     * Gets the template field for a given action IRI.
271
     *
272
     * @param actionIri the action IRI
273
     * @return the template field for the action IRI
274
     */
275
    public String getTemplateTargetFieldForAction(IRI actionIri) {
276
        return actionTemplateTargetFieldMap.get(actionIri);
×
277
    }
278

279
    public String getTemplatePartFieldForAction(IRI actionIri) {
280
        return actionTemplatePartFieldMap.get(actionIri);
×
281
    }
282

283
    public String getTemplateQueryMapping(IRI actionIri) {
284
        return actionTemplateQueryMappingMap.get(actionIri);
×
285
    }
286

287
    /**
288
     * Gets the label for a given action IRI.
289
     *
290
     * @param actionIri the action IRI
291
     * @return the label for the action IRI
292
     */
293
    public String getLabelForAction(IRI actionIri) {
294
        return labelMap.get(actionIri);
×
295
    }
296

297
    public boolean appliesTo(String resourceId, Set<IRI> classes) {
298
        for (IRI namespace : appliesToNamespaces) {
×
299
            if (resourceId.startsWith(namespace.stringValue())) return true;
×
300
        }
×
301
        if (classes != null) {
×
302
            for (IRI c : classes) {
×
303
                if (appliesToClasses.contains(c)) return true;
×
304
            }
×
305
        }
306
        return false;
×
307
    }
308

309
    /**
310
     * Checks if the ResourceView has target classes.
311
     *
312
     * @return true if the ResourceView has target classes, false otherwise
313
     */
314
    public boolean appliesToClasses() {
315
        return !appliesToClasses.isEmpty();
×
316
    }
317

318
    /**
319
     * Checks if the ResourceView has a specific target class.
320
     *
321
     * @param targetClass the target class IRI
322
     * @return true if the ResourceView has the target class, false otherwise
323
     */
324
    public boolean appliesToClass(IRI targetClass) {
325
        return appliesToClasses.contains(targetClass);
×
326
    }
327

328
    @Override
329
    public String toString() {
330
        return id;
×
331
    }
332

333
    /**
334
     * Gets the view type of the ResourceView.
335
     *
336
     * @return the view type mode IRI
337
     */
338
    public IRI getViewType() {
339
        return viewType;
×
340
    }
341

342
}
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