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

knowledgepixels / nanodash / 19818701198

01 Dec 2025 10:02AM UTC coverage: 13.36% (-0.5%) from 13.901%
19818701198

push

github

tkuhn
feat(ResourceView): Automatically apply latest version of views

503 of 4898 branches covered (10.27%)

Branch coverage included in aggregate %.

1347 of 8949 relevant lines covered (15.05%)

0.67 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 java.io.Serializable;
4
import java.util.ArrayList;
5
import java.util.HashMap;
6
import java.util.HashSet;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.Set;
10

11
import org.eclipse.rdf4j.model.IRI;
12
import org.eclipse.rdf4j.model.Literal;
13
import org.eclipse.rdf4j.model.Statement;
14
import org.eclipse.rdf4j.model.vocabulary.DCTERMS;
15
import org.eclipse.rdf4j.model.vocabulary.RDF;
16
import org.eclipse.rdf4j.model.vocabulary.RDFS;
17
import org.nanopub.Nanopub;
18
import org.slf4j.Logger;
19
import org.slf4j.LoggerFactory;
20

21
import com.knowledgepixels.nanodash.template.Template;
22
import com.knowledgepixels.nanodash.template.TemplateData;
23
import com.knowledgepixels.nanodash.vocabulary.KPXL_TERMS;
24

25
/**
26
 * A class representing a Resource View.
27
 */
28
public class ResourceView implements Serializable {
29

30
    private static final Logger logger = LoggerFactory.getLogger(ResourceView.class);
×
31

32
    static Map<IRI, Integer> columnWidths = new HashMap<>();
×
33

34
    static {
35
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_1_OF_12, 1);
×
36
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_2_OF_12, 2);
×
37
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_3_OF_12, 3);
×
38
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_4_OF_12, 4);
×
39
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_5_OF_12, 5);
×
40
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_6_OF_12, 6);
×
41
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_7_OF_12, 7);
×
42
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_8_OF_12, 8);
×
43
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_9_OF_12, 9);
×
44
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_10_OF_12, 10);
×
45
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_11_OF_12, 11);
×
46
        columnWidths.put(KPXL_TERMS.COLUMN_WIDTH_12_OF_12, 12);
×
47
    }
48

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

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

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

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

177
    /**
178
     * Gets the ID of the ResourceView.
179
     *
180
     * @return the ID of the ResourceView
181
     */
182
    public String getId() {
183
        return id;
×
184
    }
185

186
    /**
187
     * Gets the Nanopub defining this ResourceView.
188
     *
189
     * @return the Nanopub defining this ResourceView
190
     */
191
    public Nanopub getNanopub() {
192
        return nanopub;
×
193
    }
194

195
    public IRI getViewKindIri() {
196
        return viewKind;
×
197
    }
198

199
    /**
200
     * Gets the label of the ResourceView.
201
     *
202
     * @return the label of the ResourceView
203
     */
204
    public String getLabel() {
205
        return label;
×
206
    }
207

208
    /**
209
     * Gets the title of the ResourceView.
210
     *
211
     * @return the title of the ResourceView
212
     */
213
    public String getTitle() {
214
        return title;
×
215
    }
216

217
    /**
218
     * Gets the GrlcQuery associated with the ResourceView.
219
     *
220
     * @return the GrlcQuery associated with the ResourceView
221
     */
222
    public GrlcQuery getQuery() {
223
        return query;
×
224
    }
225

226
    /**
227
     * Gets the query field of the ResourceView.
228
     *
229
     * @return the query field
230
     */
231
    public String getQueryField() {
232
        return queryField;
×
233
    }
234

235
    /**
236
     * Returns the preferred page size.
237
     *
238
     * @return page size (0 = everything on first page)
239
     */
240
    public Integer getPageSize() {
241
        return pageSize;
×
242
    }
243

244
    public Integer getDisplayWidth() {
245
        return displayWidth;
×
246
    }
247

248
    public String getStructuralPosition() {
249
        return structuralPosition;
×
250
    }
251

252
    /**
253
     * Gets the list of action IRIs associated with the ResourceView.
254
     *
255
     * @return the list of action IRIs
256
     */
257
    public List<IRI> getViewResultActionList() {
258
        return viewResultActionList;
×
259
    }
260

261
    public List<IRI> getViewEntryActionList() {
262
        return viewEntryActionList;
×
263
    }
264

265
    /**
266
     * Gets the Template for a given action IRI.
267
     *
268
     * @param actionIri the action IRI
269
     * @return the Template for the action IRI
270
     */
271
    public Template getTemplateForAction(IRI actionIri) {
272
        return actionTemplateMap.get(actionIri);
×
273
    }
274

275
    /**
276
     * Gets the template field for a given action IRI.
277
     *
278
     * @param actionIri the action IRI
279
     * @return the template field for the action IRI
280
     */
281
    public String getTemplateTargetFieldForAction(IRI actionIri) {
282
        return actionTemplateTargetFieldMap.get(actionIri);
×
283
    }
284

285
    public String getTemplatePartFieldForAction(IRI actionIri) {
286
        return actionTemplatePartFieldMap.get(actionIri);
×
287
    }
288

289
    public String getTemplateQueryMapping(IRI actionIri) {
290
        return actionTemplateQueryMappingMap.get(actionIri);
×
291
    }
292

293
    /**
294
     * Gets the label for a given action IRI.
295
     *
296
     * @param actionIri the action IRI
297
     * @return the label for the action IRI
298
     */
299
    public String getLabelForAction(IRI actionIri) {
300
        return labelMap.get(actionIri);
×
301
    }
302

303
    public boolean appliesTo(String resourceId, Set<IRI> classes) {
304
        for (IRI namespace : appliesToNamespaces) {
×
305
            if (resourceId.startsWith(namespace.stringValue())) return true;
×
306
        }
×
307
        if (classes != null) {
×
308
            for (IRI c : classes) {
×
309
                if (appliesToClasses.contains(c)) return true;
×
310
            }
×
311
        }
312
        return false;
×
313
    }
314

315
    /**
316
     * Checks if the ResourceView has target classes.
317
     *
318
     * @return true if the ResourceView has target classes, false otherwise
319
     */
320
    public boolean appliesToClasses() {
321
        return !appliesToClasses.isEmpty();
×
322
    }
323

324
    /**
325
     * Checks if the ResourceView has a specific target class.
326
     *
327
     * @param targetClass the target class IRI
328
     * @return true if the ResourceView has the target class, false otherwise
329
     */
330
    public boolean appliesToClass(IRI targetClass) {
331
        return appliesToClasses.contains(targetClass);
×
332
    }
333

334
    @Override
335
    public String toString() {
336
        return id;
×
337
    }
338

339
    /**
340
     * Gets the view type of the ResourceView.
341
     *
342
     * @return the view type mode IRI
343
     */
344
    public IRI getViewType() {
345
        return viewType;
×
346
    }
347

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