Skip to content

Commit 64dac20

Browse files
rolaca11László Stahorszkih1dden-da3m0n
authored
feat: display value selector
* #81 add a displayExpression property, that allows a different display value to the one included in env variables * #81 fix test configuration * #81 enhancements based on review comments * #81 revert select option values to be the actual value * fix: parameter rebuild behaviour * refactor display value logic * bump version * remove no longer working tooltip Co-authored-by: László Stahorszki <[email protected]> Co-authored-by: h1dden-da3m0n <[email protected]>
1 parent f104328 commit 64dac20

File tree

16 files changed

+303
-109
lines changed

16 files changed

+303
-109
lines changed

.idea/codeStyles/Project.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
</parent>
1111

1212
<properties>
13-
<revision>1.4.3</revision>
13+
<revision>1.5.0</revision>
1414
<changelist>-SNAPSHOT</changelist>
1515
<!-- Baseline Jenkins version you use to build the plugin. Users must have this version or newer to run. -->
1616
<jenkins.version>2.263.4</jenkins.version>

src/main/java/io/jenkins/plugins/restlistparam/RestListParameterDefinition.java

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import com.cloudbees.plugins.credentials.common.StandardCredentials;
44
import hudson.Extension;
55
import hudson.model.Item;
6+
import io.jenkins.plugins.restlistparam.logic.ValueResolver;
7+
import io.jenkins.plugins.restlistparam.model.ValueItem;
68
import hudson.model.ParameterDefinition;
79
import hudson.model.ParameterValue;
810
import hudson.model.SimpleParameterDefinition;
@@ -21,7 +23,6 @@
2123
import org.kohsuke.stapler.*;
2224
import org.kohsuke.stapler.verb.POST;
2325

24-
import javax.annotation.CheckForNull;
2526
import javax.annotation.Nonnull;
2627
import java.util.Collections;
2728
import java.util.List;
@@ -36,23 +37,25 @@ public final class RestListParameterDefinition extends SimpleParameterDefinition
3637
private final String credentialId;
3738
private final MimeType mimeType;
3839
private final String valueExpression;
40+
private String displayExpression;
3941
private ValueOrder valueOrder;
4042
private String defaultValue;
4143
private String filter;
4244
private Integer cacheTime;
4345
private String errorMsg;
44-
private List<String> values;
46+
private List<ValueItem> values;
4547

4648
@DataBoundConstructor
4749
public RestListParameterDefinition(final String name,
4850
final String description,
4951
final String restEndpoint,
5052
final String credentialId,
5153
final MimeType mimeType,
52-
final String valueExpression)
54+
final String valueExpression,
55+
final String displayExpression)
5356
{
5457
this(name, description, restEndpoint, credentialId, mimeType, valueExpression,
55-
ValueOrder.NONE, ".*", config.getCacheTime(), "");
58+
displayExpression, ValueOrder.NONE, ".*", config.getCacheTime(), "");
5659
}
5760

5861
public RestListParameterDefinition(final String name,
@@ -61,6 +64,7 @@ public RestListParameterDefinition(final String name,
6164
final String credentialId,
6265
final MimeType mimeType,
6366
final String valueExpression,
67+
final String displayExpression,
6468
final ValueOrder valueOrder,
6569
final String filter,
6670
final Integer cacheTime,
@@ -71,6 +75,9 @@ public RestListParameterDefinition(final String name,
7175
this.mimeType = mimeType;
7276
this.valueExpression = valueExpression;
7377
this.credentialId = StringUtils.isNotBlank(credentialId) ? credentialId : "";
78+
if (mimeType == MimeType.APPLICATION_JSON) {
79+
this.displayExpression = StringUtils.isNotBlank(displayExpression) ? displayExpression : "$";
80+
}
7481
this.defaultValue = StringUtils.isNotBlank(defaultValue) ? defaultValue : "";
7582
this.valueOrder = valueOrder != null ? valueOrder : ValueOrder.NONE;
7683
this.filter = StringUtils.isNotBlank(filter) ? filter : ".*";
@@ -99,6 +106,18 @@ public String getFilter() {
99106
return filter;
100107
}
101108

109+
public String getDisplayExpression() {
110+
if (mimeType == MimeType.APPLICATION_JSON) {
111+
return StringUtils.isNotBlank(displayExpression) ? displayExpression : "$";
112+
}
113+
return "";
114+
}
115+
116+
@DataBoundSetter
117+
public void setDisplayExpression(final String displayExpression) {
118+
this.displayExpression = displayExpression;
119+
}
120+
102121
@DataBoundSetter
103122
public void setValueOrder(final ValueOrder valueOrder) {
104123
this.valueOrder = valueOrder;
@@ -139,15 +158,16 @@ public String getErrorMsg() {
139158
return errorMsg;
140159
}
141160

142-
public List<String> getValues() {
161+
public List<ValueItem> getValues() {
143162
Optional<StandardCredentials> credentials = CredentialsUtils.findCredentials(null, credentialId);
144163

145-
ResultContainer<List<String>> container = RestValueService.get(
164+
ResultContainer<List<ValueItem>> container = RestValueService.get(
146165
getRestEndpoint(),
147166
credentials.orElse(null),
148167
getMimeType(),
149168
getCacheTime(),
150169
getValueExpression(),
170+
getDisplayExpression(),
151171
getFilter(),
152172
getValueOrder());
153173

@@ -162,7 +182,8 @@ public ParameterDefinition copyWithDefaultValue(final ParameterValue defaultValu
162182
RestListParameterValue value = (RestListParameterValue) defaultValue;
163183
return new RestListParameterDefinition(
164184
getName(), getDescription(), getRestEndpoint(), getCredentialId(), getMimeType(),
165-
getValueExpression(), getValueOrder(), getFilter(), getCacheTime(), value.getValue());
185+
getValueExpression(), getDisplayExpression(), getValueOrder(), getFilter(), getCacheTime(),
186+
ValueResolver.parseDisplayValue(getMimeType(), value.getValue(), displayExpression));
166187
}
167188
else {
168189
return this;
@@ -172,16 +193,17 @@ public ParameterDefinition copyWithDefaultValue(final ParameterValue defaultValu
172193
@Override
173194
public ParameterValue createValue(final String value) {
174195
RestListParameterValue parameterValue = new RestListParameterValue(getName(), value, getDescription());
196+
175197
checkValue(parameterValue);
176198
return parameterValue;
177199
}
178200

179201
@Override
180-
@CheckForNull
181202
public ParameterValue createValue(final StaplerRequest req,
182203
final JSONObject jo)
183204
{
184205
RestListParameterValue value = req.bindJSON(RestListParameterValue.class, jo);
206+
185207
checkValue(value);
186208
return value;
187209
}
@@ -194,7 +216,14 @@ private void checkValue(final RestListParameterValue value) {
194216

195217
@Override
196218
public boolean isValid(ParameterValue value) {
197-
return values.contains(((RestListParameterValue) value).getValue());
219+
if(value == null || value.getValue() == null) {
220+
return false;
221+
}
222+
223+
return values.stream()
224+
.map(ValueItem::getValue)
225+
.filter(Objects::nonNull)
226+
.anyMatch(val -> value.getValue().equals(val));
198227
}
199228

200229
@Override
@@ -333,6 +362,7 @@ public FormValidation doTestConfiguration(@AncestorInPath final Item context,
333362
@QueryParameter final String credentialId,
334363
@QueryParameter final MimeType mimeType,
335364
@QueryParameter final String valueExpression,
365+
@QueryParameter final String displayExpression,
336366
@QueryParameter final String filter,
337367
@QueryParameter final ValueOrder valueOrder)
338368
{
@@ -357,24 +387,25 @@ public FormValidation doTestConfiguration(@AncestorInPath final Item context,
357387
return FormValidation.error(Messages.RLP_DescriptorImpl_ValidationErr_ExpressionEmpty());
358388
}
359389

360-
ResultContainer<List<String>> container = RestValueService.get(
390+
ResultContainer<List<ValueItem>> container = RestValueService.get(
361391
restEndpoint,
362392
credentials.orElse(null),
363393
mimeType,
364394
0,
365395
valueExpression,
396+
displayExpression,
366397
filter,
367398
valueOrder);
368399

369400
Optional<String> errorMsg = container.getErrorMsg();
370-
List<String> values = container.getValue();
401+
List<ValueItem> values = container.getValue();
371402
if (errorMsg.isPresent()) {
372403
return FormValidation.error(errorMsg.get());
373404
}
374405

375406
// values should NEVER be empty here
376407
// due to all the filtering and error handling done in the RestValueService
377-
return FormValidation.ok(Messages.RLP_DescriptorImpl_ValidationOk_ConfigValid(values.size(), values.get(0)));
408+
return FormValidation.ok(Messages.RLP_DescriptorImpl_ValidationOk_ConfigValid(values.size(), values.get(0).getDisplayValue()));
378409
}
379410
}
380411
}

src/main/java/io/jenkins/plugins/restlistparam/RestListParameterValue.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@
1818
public final class RestListParameterValue extends ParameterValue {
1919
@Exported(visibility = 4)
2020
@Restricted(NoExternalUse.class)
21-
public String value;
21+
private final String value;
2222

2323
@DataBoundConstructor
24-
public RestListParameterValue(String name,
25-
String value)
24+
public RestListParameterValue(final String name,
25+
final String value)
2626
{
2727
this(name, value, null);
2828
}
2929

30-
public RestListParameterValue(String name,
31-
String value,
32-
String description)
30+
public RestListParameterValue(final String name,
31+
final String value,
32+
final String description)
3333
{
3434
super(name, description);
3535
this.value = value;
@@ -87,7 +87,11 @@ public boolean equals(Object obj) {
8787

8888
@Override
8989
public String toString() {
90-
return "(RestListParameterValue) " + getName() + "='" + value + "'";
90+
return "{" +
91+
"\"type\": \"RestListParameterValue\", "+
92+
"\"name:\": \"" + getName() + "\", " +
93+
"\"value\": \"" + value + "\"" +
94+
"}";
9195
}
9296

9397
@Override

src/main/java/io/jenkins/plugins/restlistparam/logic/RestValueService.java

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.cloudbees.plugins.credentials.common.StandardUsernamePasswordCredentials;
55
import hudson.util.FormValidation;
66
import io.jenkins.plugins.restlistparam.Messages;
7+
import io.jenkins.plugins.restlistparam.model.ValueItem;
78
import io.jenkins.plugins.restlistparam.model.MimeType;
89
import io.jenkins.plugins.restlistparam.model.ResultContainer;
910
import io.jenkins.plugins.restlistparam.model.ValueOrder;
@@ -39,29 +40,31 @@ private RestValueService() {
3940
* This method uses its parameters to query a REST/Web endpoint to receive a {@link MimeType} response, which then
4041
* gets parsed with a supported Path expression to extract a list of string values.
4142
*
42-
* @param restEndpoint A http/https web address to the REST/Web endpoint
43-
* @param credentials The credentials required to access said endpoint
44-
* @param mimeType The MIME type of the expected REST/Web response
45-
* @param cacheTime Time for how long the REST response gets cached for in minutes
46-
* @param expression The Json-Path or xPath expression to filter the values
47-
* @param filter additional regex filter on any parsed values
48-
* @param order Set a {@link ValueOrder} to optionally reorder the values
43+
* @param restEndpoint A http/https web address to the REST/Web endpoint
44+
* @param credentials The credentials required to access said endpoint
45+
* @param mimeType The MIME type of the expected REST/Web response
46+
* @param cacheTime Time for how long the REST response gets cached for in minutes
47+
* @param valueExpression The Json-Path or xPath expression to filter the values
48+
* @param displayExpression The Json-Path or xPath expression to filter the display values
49+
* @param filter additional regex filter on any parsed values
50+
* @param order Set a {@link ValueOrder} to optionally reorder the values
4951
* @return A {@link ResultContainer} that capsules either the desired values or a user friendly error message.
5052
*/
51-
public static ResultContainer<List<String>> get(final String restEndpoint,
52-
final StandardCredentials credentials,
53-
final MimeType mimeType,
54-
final Integer cacheTime,
55-
final String expression,
56-
final String filter,
57-
final ValueOrder order)
53+
public static ResultContainer<List<ValueItem>> get(final String restEndpoint,
54+
final StandardCredentials credentials,
55+
final MimeType mimeType,
56+
final Integer cacheTime,
57+
final String valueExpression,
58+
final String displayExpression,
59+
final String filter,
60+
final ValueOrder order)
5861
{
59-
ResultContainer<List<String>> valueList = new ResultContainer<>(Collections.emptyList());
62+
ResultContainer<List<ValueItem>> valueList = new ResultContainer<>(Collections.emptyList());
6063
ResultContainer<String> rawValues = getValueStringFromRestEndpoint(restEndpoint, credentials, mimeType, cacheTime);
6164
Optional<String> rawValueError = rawValues.getErrorMsg();
6265

6366
if (!rawValueError.isPresent()) {
64-
valueList = convertToValuesList(mimeType, rawValues.getValue(), expression);
67+
valueList = convertToValuesList(mimeType, rawValues.getValue(), valueExpression, displayExpression);
6568
}
6669
else {
6770
valueList.setErrorMsg(rawValueError.get());
@@ -224,21 +227,23 @@ else if (credentials instanceof StringCredentials) {
224227
*
225228
* @param mimeType The {@link MimeType} of the {@code valueString}
226229
* @param valueString The value string to be parsed
227-
* @param expression The Json-Path or xPath expression to apply on the {@code valueString}
230+
* @param valueExpression The Json-Path or xPath expression to apply on the {@code valueString}
231+
* @param displayExpression Derives the value to be displayed to the user parsed by value expression
228232
* @return A {@link ResultContainer} capsuling the results of the applied expression or an error message
229233
*/
230-
private static ResultContainer<List<String>> convertToValuesList(final MimeType mimeType,
231-
final String valueString,
232-
final String expression)
234+
private static ResultContainer<List<ValueItem>> convertToValuesList(final MimeType mimeType,
235+
final String valueString,
236+
final String valueExpression,
237+
final String displayExpression)
233238
{
234-
ResultContainer<List<String>> container;
239+
ResultContainer<List<ValueItem>> container;
235240

236241
switch (mimeType) {
237242
case APPLICATION_JSON:
238-
container = ValueResolver.resolveJsonPath(valueString, expression);
243+
container = ValueResolver.resolveJsonPath(valueString, valueExpression, displayExpression);
239244
break;
240245
case APPLICATION_XML:
241-
container = ValueResolver.resolveXPath(valueString, expression);
246+
container = ValueResolver.resolveXPath(valueString, valueExpression, displayExpression);
242247
break;
243248
default:
244249
throw new IllegalStateException("Unexpected value: " + mimeType);
@@ -255,18 +260,18 @@ private static ResultContainer<List<String>> convertToValuesList(final MimeType
255260
* @param order The Order to apply (if any)
256261
* @return A {@link ResultContainer} capsuling a filtered string list or a user friendly error message
257262
*/
258-
private static ResultContainer<List<String>> filterAndSortValues(final List<String> values,
259-
final String filter,
260-
final ValueOrder order)
263+
private static ResultContainer<List<ValueItem>> filterAndSortValues(final List<ValueItem> values,
264+
final String filter,
265+
final ValueOrder order)
261266
{
262-
ResultContainer<List<String>> container = new ResultContainer<>(Collections.emptyList());
267+
ResultContainer<List<ValueItem>> container = new ResultContainer<>(Collections.emptyList());
263268

264269
try {
265-
List<String> updatedValues;
270+
List<ValueItem> updatedValues;
266271

267272
if (isFilterSet(filter) && !isOrderSet(order)) {
268273
updatedValues = values.stream()
269-
.filter(value -> value.matches(filter))
274+
.filter(value -> value.getValue().matches(filter))
270275
.collect(Collectors.toList());
271276
}
272277
else if (!isFilterSet(filter) && isOrderSet(order)) {
@@ -276,7 +281,7 @@ else if (!isFilterSet(filter) && isOrderSet(order)) {
276281
}
277282
else {
278283
updatedValues = values.stream()
279-
.filter(value -> value.matches(filter))
284+
.filter(value -> value.getValue().matches(filter))
280285
.sorted(order == ValueOrder.ASC ? Comparator.naturalOrder() : Comparator.reverseOrder())
281286
.collect(Collectors.toList());
282287
}

0 commit comments

Comments
 (0)