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

3
import com.knowledgepixels.nanodash.ApiCache;
4
import org.apache.wicket.Component;
5
import org.apache.wicket.ajax.AbstractDefaultAjaxBehavior;
6
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
7
import org.apache.wicket.markup.html.basic.Label;
8
import org.apache.wicket.request.IRequestHandler;
9
import org.apache.wicket.request.cycle.RequestCycle;
10
import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
11
import org.nanopub.extra.services.ApiResponse;
12
import org.slf4j.Logger;
13
import org.slf4j.LoggerFactory;
14

15
import java.util.HashMap;
16

17
/**
18
 * A component that retrieves and displays the result of an API call.
19
 * It uses AjaxLazyLoadPanel to load the content lazily and shows a loading indicator while waiting for the response.
20
 */
21
public abstract class ApiResultComponent extends AjaxLazyLoadPanel<Component> {
22

23
    private static final long serialVersionUID = 1L;
24

25
    private final String queryName;
26
    private final HashMap<String, String> params;
27
    private boolean waitIconEnabled = true;
×
28
    private ApiResponse response = null;
×
29
    private String waitMessage = null;
×
30
    private String waitComponentHtml = null;
×
31
    private static final Logger logger = LoggerFactory.getLogger(ApiResultComponent.class);
×
32

33
    /**
34
     * Constructor for ApiResultComponent.
35
     *
36
     * @param id        the component id
37
     * @param queryName the name of the API query to be executed
38
     * @param params    a map of parameters to be passed to the API query
39
     */
40
    public ApiResultComponent(String id, String queryName, HashMap<String, String> params) {
41
        super(id);
×
42
        this.queryName = queryName;
×
43
        this.params = params;
×
44
    }
×
45

46
    /**
47
     * Constructor for ApiResultComponent with a single parameter.
48
     *
49
     * @param id         the component id
50
     * @param queryName  the name of the API query to be executed
51
     * @param paramKey   the key of the parameter to be passed to the API query
52
     * @param paramValue the value of the parameter to be passed to the API query
53
     */
54
    public ApiResultComponent(String id, String queryName, String paramKey, String paramValue) {
55
        this(id, queryName, getParams(paramKey, paramValue));
×
56
    }
×
57

58
    private static HashMap<String, String> getParams(String paramKey, String paramValue) {
59
        final HashMap<String, String> params = new HashMap<>();
×
60
        params.put(paramKey, paramValue);
×
61
        return params;
×
62
    }
63

64
    /**
65
     * Sets whether to show a loading icon while waiting for the API response.
66
     *
67
     * @param waitIconEnabled true to enable the wait icon, false to disable it
68
     */
69
    public void setWaitIconEnabled(boolean waitIconEnabled) {
70
        this.waitIconEnabled = waitIconEnabled;
×
71
    }
×
72

73
    /**
74
     * Sets a custom message to be displayed while waiting for the API response.
75
     *
76
     * @param waitMessage the message to display
77
     */
78
    public void setWaitMessage(String waitMessage) {
79
        this.waitMessage = waitMessage;
×
80
    }
×
81

82
    /**
83
     * Sets a custom HTML component to be displayed while waiting for the API response.
84
     *
85
     * @param waitComponentHtml the HTML string to display
86
     */
87
    public void setWaitComponentHtml(String waitComponentHtml) {
88
        this.waitComponentHtml = waitComponentHtml;
×
89
    }
×
90

91
    /**
92
     * {@inheritDoc}
93
     */
94
    @Override
95
    public Component getLazyLoadComponent(String markupId) {
96
        while (true) {
97
            if (!ApiCache.isRunning(queryName, params)) {
×
98
                try {
99
                    response = ApiCache.retrieveResponse(queryName, params);
×
100
                    if (response != null) break;
×
101
                } catch (Exception ex) {
×
102
                    return new Label(markupId, "<span class=\"negative\">API call failed.</span>").setEscapeModelStrings(false);
×
103
                }
×
104
            }
105
            try {
106
                Thread.sleep(100);
×
107
            } catch (InterruptedException ex) {
×
108
                logger.error("Interrupted while waiting for API response", ex);
×
109
            }
×
110
        }
111
        return getApiResultComponent(markupId, response);
×
112
    }
113

114
    /**
115
     * {@inheritDoc}
116
     */
117
    @Override
118
    public Component getLoadingComponent(String id) {
119
        if (!waitIconEnabled) {
×
120
            return new Label(id);
×
121
        } else if (waitComponentHtml != null) {
×
122
            return new Label(id, waitComponentHtml).setEscapeModelStrings(false);
×
123
        } else if (waitMessage != null) {
×
124
            return new Label(id, getWaitComponentHtml(waitMessage)).setEscapeModelStrings(false);
×
125
        } else {
126
            return super.getLoadingComponent(id);
×
127
        }
128
    }
129

130
    /**
131
     * {@inheritDoc}
132
     */
133
    @Override
134
    protected boolean isContentReady() {
135
        return response != null || !ApiCache.isRunning(queryName, params);
×
136
    }
137

138
    /**
139
     * Abstract method to be implemented by subclasses to provide the component that displays the API result.
140
     *
141
     * @param markupId the markup ID for the component
142
     * @param response the API response to display
143
     * @return a Component that displays the API result
144
     */
145
    // TODO Use lambda instead of abstract method?
146
    public abstract Component getApiResultComponent(String markupId, ApiResponse response);
147

148
    /**
149
     * Returns the HTML for a loading icon.
150
     *
151
     * @return a string containing the HTML for the loading icon
152
     */
153
    public static String getWaitIconHtml() {
154
        IRequestHandler handler = new ResourceReferenceRequestHandler(AbstractDefaultAjaxBehavior.INDICATOR);
×
155
        return "<img alt=\"Loading...\" src=\"" + RequestCycle.get().urlFor(handler) + "\"/>";
×
156
    }
157

158
    /**
159
     * Returns the HTML for a waiting message with an icon.
160
     *
161
     * @param waitMessage the message to display while waiting
162
     * @return a string containing the HTML for the waiting message
163
     */
164
    public static String getWaitComponentHtml(String waitMessage) {
165
        return "<p class=\"waiting\">" + waitMessage + " " + getWaitIconHtml() + "</p>";
×
166
    }
167

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