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

knowledgepixels / nanodash / 17380144000

01 Sep 2025 02:12PM UTC coverage: 12.03% (+0.05%) from 11.978%
17380144000

push

github

ashleycaselli
refactor: replace printStackTrace with logger.error for better error handling

330 of 3850 branches covered (8.57%)

Branch coverage included in aggregate %.

958 of 6857 relevant lines covered (13.97%)

0.62 hits per line

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

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

3
import com.knowledgepixels.nanodash.ApiCache;
4
import com.knowledgepixels.nanodash.User;
5
import com.knowledgepixels.nanodash.Utils;
6
import com.knowledgepixels.nanodash.page.ReferenceTablePage;
7
import org.apache.wicket.Component;
8
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
9
import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState;
10
import org.apache.wicket.extensions.markup.html.repeater.data.table.*;
11
import org.apache.wicket.extensions.markup.html.repeater.util.SingleSortState;
12
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
13
import org.apache.wicket.markup.html.basic.Label;
14
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
15
import org.apache.wicket.markup.html.panel.Panel;
16
import org.apache.wicket.markup.repeater.Item;
17
import org.apache.wicket.model.IModel;
18
import org.apache.wicket.model.Model;
19
import org.apache.wicket.request.mapper.parameter.PageParameters;
20
import org.nanopub.Nanopub;
21
import org.nanopub.extra.services.ApiResponse;
22
import org.nanopub.extra.services.ApiResponseEntry;
23
import org.slf4j.Logger;
24
import org.slf4j.LoggerFactory;
25

26
import java.io.Serializable;
27
import java.util.*;
28

29
/**
30
 * A component that displays a data table of nanopublication references.
31
 */
32
public class ExploreDataTable extends Panel {
33

34
    private static final long serialVersionUID = 1L;
35

36
    private static final String refQueryName = "find-uri-references";
37
    private static final Logger logger = LoggerFactory.getLogger(ExploreDataTable.class);
×
38

39
    private ExploreDataTable(String id, String ref, ApiResponse response, int limit) {
40
        super(id);
×
41
        List<IColumn<ApiResponseEntry, String>> columns = new ArrayList<>();
×
42
        DataProvider dp;
43
        try {
44
            columns.add(new Column("Nanopublication", "np", ref));
×
45
            columns.add(new Column("Part", "graphpred", ref));
×
46
            columns.add(new Column("Subject", "subj", ref));
×
47
            columns.add(new Column("Predicate", "pred", ref));
×
48
            columns.add(new Column("Object", "obj", ref));
×
49
            columns.add(new Column("Published By", "pubkey", ref));
×
50
            columns.add(new Column("Published On", "date", ref));
×
51
            dp = new DataProvider(filterData(response.getData(), ref, limit));
×
52
            DataTable<ApiResponseEntry, String> table = new DataTable<>("datatable", columns, dp, 100);
×
53
            table.addBottomToolbar(new NavigationToolbar(table));
×
54
            table.addBottomToolbar(new NoRecordsToolbar(table));
×
55
            table.addTopToolbar(new HeadersToolbar<String>(table, dp));
×
56
            add(table);
×
57
            add(new Label("message", "").setVisible(false));
×
58
            BookmarkablePageLink<Void> showAllLink = new BookmarkablePageLink<Void>("show-all", ReferenceTablePage.class, new PageParameters().add("id", ref));
×
59
            showAllLink.setVisible(limit > 0 && response.getData().size() > limit);
×
60
            add(showAllLink);
×
61
        } catch (Exception ex) {
×
62
            logger.error("Could not create data table for reference: {}", ref, ex);
×
63
            add(new Label("datatable", "").setVisible(false));
×
64
            add(new Label("message", "Could not load data table."));
×
65
            add(new Label("show-all").setVisible(false));
×
66
        }
×
67
    }
×
68

69

70
    private List<ApiResponseEntry> filterData(List<ApiResponseEntry> data, String nanopubUri, int limit) {
71
        List<ApiResponseEntry> filteredList = new ArrayList<>();
×
72
        Nanopub np = Utils.getAsNanopub(nanopubUri);
×
73
        if (np == null && limit == 0) return data;
×
74
        for (ApiResponseEntry e : data) {
×
75
            if (np == null || !nanopubUri.equals(e.get("np"))) {
×
76
                filteredList.add(e);
×
77
            }
78
            if (limit > 0 && limit == filteredList.size()) break;
×
79
        }
×
80
        return filteredList;
×
81
    }
82

83

84
    private class Column extends AbstractColumn<ApiResponseEntry, String> {
85

86
        private static final long serialVersionUID = 1L;
87

88
        private String key, current;
89

90
        /**
91
         * Constructor for a column in the data table.
92
         *
93
         * @param title   The title of the column.
94
         * @param key     The key used to retrieve data from ApiResponseEntry.
95
         * @param current The current value to highlight in the column.
96
         */
97
        public Column(String title, String key, String current) {
×
98
            super(new Model<String>(title), key);
×
99
            this.key = key;
×
100
            this.current = current;
×
101
        }
×
102

103
        @Override
104
        public void populateItem(Item<ICellPopulator<ApiResponseEntry>> cellItem, String componentId, IModel<ApiResponseEntry> rowModel) {
105
            String value = rowModel.getObject().get(key);
×
106
            if (value.equals(current)) {
×
107
                cellItem.add(new Label(componentId, "<strong>" + IriItem.getShortNameFromURI(value) + "</strong>").setEscapeModelStrings(false));
×
108
            } else if (value.matches("https?://.+")) {
×
109
                cellItem.add(new NanodashLink(componentId, value));
×
110
            } else {
111
                if (key.equals("pubkey")) {
×
112
                    cellItem.add(new Label(componentId, User.getShortDisplayNameForPubkeyhash(null, Utils.createSha256HexHash(value))));
×
113
                } else {
114
                    cellItem.add(new Label(componentId, value));
×
115
                }
116
            }
117
        }
×
118

119
    }
120

121

122
    private class DataProvider implements ISortableDataProvider<ApiResponseEntry, String> {
123

124
        private static final long serialVersionUID = 1L;
125

126
        private List<ApiResponseEntry> data = new ArrayList<>();
×
127
        private SingleSortState<String> sortState = new SingleSortState<>();
×
128

129
        /**
130
         * Default constructor that initializes the sort state.
131
         */
132
        public DataProvider() {
×
133
            sortState.setSort(new SortParam<String>("date", false));
×
134
        }
×
135

136
        /**
137
         * Constructor that initializes the data provider with a list of ApiResponseEntry.
138
         *
139
         * @param data The list of ApiResponseEntry to be used in the data provider.
140
         */
141
        public DataProvider(List<ApiResponseEntry> data) {
142
            this();
×
143
            this.data = data;
×
144
        }
×
145

146
        @Override
147
        public Iterator<? extends ApiResponseEntry> iterator(long first, long count) {
148
            List<ApiResponseEntry> copy = new ArrayList<>(data);
×
149
            ApiResponseComparator comparator = new ApiResponseComparator(sortState.getSort());
×
150
            copy.sort(comparator);
×
151
            return Utils.subList(copy, first, first + count).iterator();
×
152
        }
153

154
        @Override
155
        public IModel<ApiResponseEntry> model(ApiResponseEntry object) {
156
            return new Model<ApiResponseEntry>(object);
×
157
        }
158

159
        @Override
160
        public long size() {
161
            return data.size();
×
162
        }
163

164
        @Override
165
        public ISortState<String> getSortState() {
166
            return sortState;
×
167
        }
168

169
        @Override
170
        public void detach() {
171
        }
×
172

173
    }
174

175
    private class ApiResponseComparator implements Comparator<ApiResponseEntry>, Serializable {
176

177
        private static final long serialVersionUID = 1L;
178
        private SortParam<String> sortParam;
179

180
        /**
181
         * Constructor that initializes the comparator with a sort parameter.
182
         *
183
         * @param sortParam The sort parameter defining the property and order for comparison.
184
         */
185
        public ApiResponseComparator(SortParam<String> sortParam) {
×
186
            this.sortParam = sortParam;
×
187
        }
×
188

189
        @Override
190
        public int compare(ApiResponseEntry o1, ApiResponseEntry o2) {
191
            String p = sortParam.getProperty();
×
192
            int result = o1.get(p).compareTo(o2.get(p));
×
193
            if (!sortParam.isAscending()) result = -result;
×
194
            return result;
×
195
        }
196

197
    }
198

199
    /**
200
     * Creates a new ExploreDataTable component.
201
     *
202
     * @param markupId the Wicket markup ID for the component
203
     * @param ref      the reference URI to be displayed in the table
204
     * @param limit    the maximum number of entries to display in the table; if 0, all entries are shown
205
     * @return a new ExploreDataTable component or an ApiResultComponent if the data is not cached
206
     */
207
    public static Component createComponent(final String markupId, final String ref, int limit) {
208
        ApiResponse response = ApiCache.retrieveResponse(refQueryName, getParams(ref));
×
209
        if (response != null) {
×
210
            return new ExploreDataTable(markupId, ref, response, limit);
×
211
        } else {
212
            return new ApiResultComponent(markupId, refQueryName, getParams(ref)) {
×
213

214
                private static final long serialVersionUID = 1L;
215

216
                @Override
217
                public Component getApiResultComponent(String markupId, ApiResponse response) {
218
                    return new ExploreDataTable(markupId, ref, response, limit);
×
219
                }
220

221
            };
222
        }
223
    }
224

225
    private static HashMap<String, String> getParams(String ref) {
226
        final HashMap<String, String> params = new HashMap<>();
×
227
        params.put("ref", ref);
×
228
        return params;
×
229
    }
230

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