• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In
Build has been canceled!

knowledgepixels / nanodash / 17152489001

22 Aug 2025 10:10AM UTC coverage: 12.442% (-0.009%) from 12.451%
17152489001

push

github

tkuhn
Improve pubkey display

330 of 3766 branches covered (8.76%)

Branch coverage included in aggregate %.

977 of 6739 relevant lines covered (14.5%)

0.64 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 java.io.Serializable;
4
import java.util.ArrayList;
5
import java.util.Collections;
6
import java.util.Comparator;
7
import java.util.HashMap;
8
import java.util.Iterator;
9
import java.util.List;
10

11
import org.apache.wicket.Component;
12
import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
13
import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState;
14
import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
15
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
16
import org.apache.wicket.extensions.markup.html.repeater.data.table.HeadersToolbar;
17
import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
18
import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
19
import org.apache.wicket.extensions.markup.html.repeater.data.table.NavigationToolbar;
20
import org.apache.wicket.extensions.markup.html.repeater.data.table.NoRecordsToolbar;
21
import org.apache.wicket.extensions.markup.html.repeater.util.SingleSortState;
22
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
23
import org.apache.wicket.markup.html.basic.Label;
24
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
25
import org.apache.wicket.markup.html.panel.Panel;
26
import org.apache.wicket.markup.repeater.Item;
27
import org.apache.wicket.model.IModel;
28
import org.apache.wicket.model.Model;
29
import org.apache.wicket.request.mapper.parameter.PageParameters;
30
import org.nanopub.Nanopub;
31
import org.nanopub.extra.services.ApiResponse;
32
import org.nanopub.extra.services.ApiResponseEntry;
33

34
import com.knowledgepixels.nanodash.ApiCache;
35
import com.knowledgepixels.nanodash.User;
36
import com.knowledgepixels.nanodash.Utils;
37
import com.knowledgepixels.nanodash.page.ReferenceTablePage;
38

39
/**
40
 * A component that displays a data table of nanopublication references.
41
 */
42
public class ExploreDataTable extends Panel {
43

44
    private static final long serialVersionUID = 1L;
45

46
    private static final String refQueryName = "find-uri-references";
47

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

78

79
    private List<ApiResponseEntry> filterData(List<ApiResponseEntry> data, String nanopubUri, int limit) {
80
        List<ApiResponseEntry> filteredList = new ArrayList<>();
×
81
        Nanopub np = Utils.getAsNanopub(nanopubUri);
×
82
        if (np == null && limit == 0) return data;
×
83
        for (ApiResponseEntry e : data) {
×
84
            if (np == null || !nanopubUri.equals(e.get("np"))) {
×
85
                filteredList.add(e);
×
86
            }
87
            if (limit > 0 && limit == filteredList.size()) break;
×
88
        }
×
89
        return filteredList;
×
90
    }
91

92

93
    private class Column extends AbstractColumn<ApiResponseEntry, String> {
94

95
        private static final long serialVersionUID = 1L;
96

97
        private String key, current;
98

99
        /**
100
         * Constructor for a column in the data table.
101
         *
102
         * @param title   The title of the column.
103
         * @param key     The key used to retrieve data from ApiResponseEntry.
104
         * @param current The current value to highlight in the column.
105
         */
106
        public Column(String title, String key, String current) {
×
107
            super(new Model<String>(title), key);
×
108
            this.key = key;
×
109
            this.current = current;
×
110
        }
×
111

112
        @Override
113
        public void populateItem(Item<ICellPopulator<ApiResponseEntry>> cellItem, String componentId, IModel<ApiResponseEntry> rowModel) {
114
            String value = rowModel.getObject().get(key);
×
115
            if (value.equals(current)) {
×
116
                cellItem.add(new Label(componentId, "<strong>" + IriItem.getShortNameFromURI(value) + "</strong>").setEscapeModelStrings(false));
×
117
            } else if (value.matches("https?://.+")) {
×
118
                cellItem.add(new NanodashLink(componentId, value));
×
119
            } else {
120
                    if (key.equals("pubkey")) {
×
121
                            cellItem.add(new Label(componentId, User.getShortDisplayNameForPubkeyhash(null, Utils.createSha256HexHash(value))));
×
122
                    } else {
123
                            cellItem.add(new Label(componentId, value));
×
124
                    }
125
            }
126
        }
×
127

128
    }
129

130

131
    private class DataProvider implements ISortableDataProvider<ApiResponseEntry, String> {
132

133
        private static final long serialVersionUID = 1L;
134

135
        private List<ApiResponseEntry> data = new ArrayList<>();
×
136
        private SingleSortState<String> sortState = new SingleSortState<>();
×
137

138
        /**
139
         * Default constructor that initializes the sort state.
140
         */
141
        public DataProvider() {
×
142
            sortState.setSort(new SortParam<String>("date", false));
×
143
        }
×
144

145
        /**
146
         * Constructor that initializes the data provider with a list of ApiResponseEntry.
147
         *
148
         * @param data The list of ApiResponseEntry to be used in the data provider.
149
         */
150
        public DataProvider(List<ApiResponseEntry> data) {
151
            this();
×
152
            this.data = data;
×
153
        }
×
154

155
        @Override
156
        public Iterator<? extends ApiResponseEntry> iterator(long first, long count) {
157
            List<ApiResponseEntry> copy = new ArrayList<>(data);
×
158
            ApiResponseComparator comparator = new ApiResponseComparator(sortState.getSort());
×
159
            Collections.sort(copy, comparator);
×
160
            return Utils.subList(copy, first, first + count).iterator();
×
161
        }
162

163
        @Override
164
        public IModel<ApiResponseEntry> model(ApiResponseEntry object) {
165
            return new Model<ApiResponseEntry>(object);
×
166
        }
167

168
        @Override
169
        public long size() {
170
            return data.size();
×
171
        }
172

173
        @Override
174
        public ISortState<String> getSortState() {
175
            return sortState;
×
176
        }
177

178
        @Override
179
        public void detach() {
180
        }
×
181

182
    }
183

184
    private class ApiResponseComparator implements Comparator<ApiResponseEntry>, Serializable {
185

186
        private static final long serialVersionUID = 1L;
187
        private SortParam<String> sortParam;
188

189
        /**
190
         * Constructor that initializes the comparator with a sort parameter.
191
         *
192
         * @param sortParam The sort parameter defining the property and order for comparison.
193
         */
194
        public ApiResponseComparator(SortParam<String> sortParam) {
×
195
            this.sortParam = sortParam;
×
196
        }
×
197

198
        @Override
199
        public int compare(ApiResponseEntry o1, ApiResponseEntry o2) {
200
            String p = sortParam.getProperty();
×
201
            int result = o1.get(p).compareTo(o2.get(p));
×
202
            if (!sortParam.isAscending()) result = -result;
×
203
            return result;
×
204
        }
205

206
    }
207

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

223
                private static final long serialVersionUID = 1L;
224

225
                @Override
226
                public Component getApiResultComponent(String markupId, ApiResponse response) {
227
                    return new ExploreDataTable(markupId, ref, response, limit);
×
228
                }
229

230
            };
231
        }
232
    }
233

234
    private static HashMap<String, String> getParams(String ref) {
235
        final HashMap<String, String> params = new HashMap<>();
×
236
        params.put("ref", ref);
×
237
        return params;
×
238
    }
239

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