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

knowledgepixels / nanodash / 17837235071

18 Sep 2025 05:58PM UTC coverage: 13.87%. Remained the same
17837235071

push

github

tkuhn
chore: Remove serialVersionUIDs

443 of 4022 branches covered (11.01%)

Branch coverage included in aggregate %.

1133 of 7341 relevant lines covered (15.43%)

0.68 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/QueryResultTable.java
1
package com.knowledgepixels.nanodash.component;
2

3
import java.util.ArrayList;
4
import java.util.HashMap;
5
import java.util.Iterator;
6
import java.util.List;
7

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

32
import com.knowledgepixels.nanodash.ApiCache;
33
import com.knowledgepixels.nanodash.GrlcQuery;
34
import com.knowledgepixels.nanodash.Utils;
35
import com.knowledgepixels.nanodash.page.QueryPage;
36

37
/**
38
 * A table component that displays the results of a query.
39
 */
40
public class QueryResultTable extends Panel {
41

42
    private static final Logger logger = LoggerFactory.getLogger(QueryResultTable.class);
×
43

44
    private Model<String> errorMessages = Model.of("");
×
45
    private DataTable<ApiResponseEntry, String> table;
46
    private Label errorLabel;
47

48
    private QueryResultTable(String id, GrlcQuery q, ApiResponse response, boolean plain) {
49
        super(id);
×
50

51
        if (plain) {
×
52
            add(new Label("label").setVisible(false));
×
53
            add(new Label("morelink").setVisible(false));
×
54
        } else {
55
            add(new Label("label", q.getLabel()));
×
56
            add(new BookmarkablePageLink<Void>("morelink", QueryPage.class, new PageParameters().add("id", q.getNanopub().getUri())));
×
57
        }
58

59
        errorLabel = new Label("error-messages", errorMessages);
×
60
        errorLabel.setVisible(false);
×
61
        add(errorLabel);
×
62

63
        List<IColumn<ApiResponseEntry, String>> columns = new ArrayList<>();
×
64
        DataProvider dp;
65
        try {
66
            for (String h : response.getHeader()) {
×
67
                if (h.endsWith("_label")) continue;
×
68
                columns.add(new Column(h.replaceAll("_", " "), h));
×
69
            }
70
            dp = new DataProvider(response.getData());
×
71
            table = new DataTable<>("table", columns, dp, 20);
×
72
            table.setOutputMarkupId(true);
×
73
            table.addBottomToolbar(new AjaxNavigationToolbar(table));
×
74
            table.addBottomToolbar(new NoRecordsToolbar(table));
×
75
            table.addTopToolbar(new HeadersToolbar<String>(table, dp));
×
76
            add(table);
×
77
        } catch (Exception ex) {
×
78
            logger.error("Error creating table for query {}", q.getQueryId(), ex);
×
79
            add(new Label("table", "").setVisible(false));
×
80
            addErrorMessage(ex.getMessage());
×
81
        }
×
82
    }
×
83

84
    private void addErrorMessage(String errorMessage) {
85
        String s = errorMessages.getObject();
×
86
        if (s.isEmpty()) {
×
87
            s = "Error: " + errorMessage;
×
88
        } else {
89
            s += ", " + errorMessage;
×
90
        }
91
        errorMessages.setObject(s);
×
92
        errorLabel.setVisible(true);
×
93
        if (table != null) table.setVisible(false);
×
94
    }
×
95

96

97
    private class Column extends AbstractColumn<ApiResponseEntry, String> {
98

99
        private String key;
100

101
        public Column(String title, String key) {
×
102
            super(new Model<String>(title), key);
×
103
            this.key = key;
×
104
        }
×
105

106
        @Override
107
        public void populateItem(Item<ICellPopulator<ApiResponseEntry>> cellItem, String componentId, IModel<ApiResponseEntry> rowModel) {
108
            try {
109
                String value = rowModel.getObject().get(key);
×
110
                if (value.matches("https?://.+ .+")) {
×
111
                    List<Component> links = new ArrayList<>();
×
112
                    for (String v : value.split(" ")) {
×
113
                        links.add(new NanodashLink("component", v));
×
114
                    }
115
                    cellItem.add(new ComponentSequence(componentId, ", ", links));
×
116
                } else if (value.matches("https?://.+")) {
×
117
                    String label = rowModel.getObject().get(key + "_label");
×
118
                    cellItem.add(new NanodashLink(componentId, value, null, null, false, label));
×
119
                } else {
×
120
                    if (key.startsWith("pubkey")) {
×
121
                        cellItem.add(new Label(componentId, value).add(new AttributeAppender("style", "overflow-wrap: anywhere;")));
×
122
                    } else {
123
                        cellItem.add(new Label(componentId, value));
×
124
                    }
125
                }
126
            } catch (Exception ex) {
×
127
                logger.error("Failed to populate table column: ", ex);
×
128
                cellItem.add(new Label(componentId).setVisible(false));
×
129
                addErrorMessage(ex.getMessage());
×
130
            }
×
131
        }
×
132

133
    }
134

135

136
    private class DataProvider implements ISortableDataProvider<ApiResponseEntry, String> {
137

138
        private List<ApiResponseEntry> data = new ArrayList<>();
×
139
        private SingleSortState<String> sortState = new SingleSortState<>();
×
140

141
        public DataProvider() {
×
142
//                        sortState.setSort(new SortParam<String>("date", false));
143
        }
×
144

145
        public DataProvider(List<ApiResponseEntry> data) {
146
            this();
×
147
            this.data = data;
×
148
        }
×
149

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

159
        @Override
160
        public IModel<ApiResponseEntry> model(ApiResponseEntry object) {
161
            return new Model<ApiResponseEntry>(object);
×
162
        }
163

164
        @Override
165
        public long size() {
166
            return data.size();
×
167
        }
168

169
        @Override
170
        public ISortState<String> getSortState() {
171
            return sortState;
×
172
        }
173

174
        @Override
175
        public void detach() {
176
        }
×
177

178
    }
179

180
//    private class ApiResponseComparator implements Comparator<ApiResponseEntry>, Serializable {
181
//
182
//        private SortParam<String> sortParam;
183
//
184
//        public ApiResponseComparator(SortParam<String> sortParam) {
185
//            this.sortParam = sortParam;
186
//        }
187
//
188
//        @Override
189
//        public int compare(ApiResponseEntry o1, ApiResponseEntry o2) {
190
//            String p = sortParam.getProperty();
191
//            int result;
192
//            if (o1.get(p) == null && o2.get(p) == null) {
193
//                result = 0;
194
//            } else if (o1.get(p) == null) {
195
//                result = 1;
196
//            } else if (o2.get(p) == null) {
197
//                result = -1;
198
//            } else {
199
//                result = o1.get(p).compareTo(o2.get(p));
200
//            }
201
//            if (!sortParam.isAscending()) result = -result;
202
//            return result;
203
//        }
204
//
205
//    }
206

207
    /**
208
     * <p>createComponent.</p>
209
     *
210
     * @param markupId a {@link java.lang.String} object
211
     * @param queryId  a {@link java.lang.String} object
212
     * @param plain    a boolean
213
     * @return a {@link org.apache.wicket.Component} object
214
     */
215
    public static Component createComponent(final String markupId, final String queryId, boolean plain) {
216
        return createComponent(markupId, queryId, getParams(), plain);
×
217
    }
218

219
    /**
220
     * <p>createComponent.</p>
221
     *
222
     * @param markupId a {@link java.lang.String} object
223
     * @param queryId  a {@link java.lang.String} object
224
     * @param params   a {@link java.util.HashMap} object
225
     * @param plain    a boolean
226
     * @return a {@link org.apache.wicket.Component} object
227
     */
228
    public static Component createComponent(final String markupId, final String queryId, HashMap<String, String> params, boolean plain) {
229
        final GrlcQuery q = GrlcQuery.get(queryId);
×
230
        ApiResponse response = ApiCache.retrieveResponse(queryId, params);
×
231
        if (response != null) {
×
232
            return new QueryResultTable(markupId, q, response, plain);
×
233
        } else {
234
            return new ApiResultComponent(markupId, queryId, params) {
×
235

236
                @Override
237
                public Component getApiResultComponent(String markupId, ApiResponse response) {
238
                    return new QueryResultTable(markupId, q, response, plain);
×
239
                }
240

241
            };
242
        }
243
    }
244

245
    private static HashMap<String, String> getParams() {
246
        final HashMap<String, String> params = new HashMap<>();
×
247
        return params;
×
248
    }
249

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