0
# Java Implementation
1
2
Enterprise-grade Java implementation with strong typing, comprehensive built-in types, annotation support, and extensive configuration options for robust BDD testing in Java ecosystems.
3
4
## Package Information
5
6
- **Maven Artifact**: `io.cucumber:cucumber-expressions:18.0.1`
7
- **Package**: `io.cucumber.cucumberexpressions`
8
- **Language**: Java 8+
9
- **API Stability**: Stable (marked with `@API(status = API.Status.STABLE)`)
10
11
## Core Imports
12
13
```java
14
import io.cucumber.cucumberexpressions.CucumberExpression;
15
import io.cucumber.cucumberexpressions.ParameterType;
16
import io.cucumber.cucumberexpressions.ParameterTypeRegistry;
17
import io.cucumber.cucumberexpressions.ExpressionFactory;
18
import io.cucumber.cucumberexpressions.CucumberExpressionGenerator;
19
import io.cucumber.cucumberexpressions.Argument;
20
import io.cucumber.cucumberexpressions.GeneratedExpression;
21
import io.cucumber.cucumberexpressions.Expression;
22
```
23
24
## Capabilities
25
26
### Expression Creation and Matching
27
28
Create and match Cucumber expressions with strong typing and comprehensive type hint support.
29
30
```java { .api }
31
/**
32
* Main class for parsing and matching Cucumber expressions
33
* Stable API - safe for production use
34
*/
35
@API(status = API.Status.STABLE)
36
public final class CucumberExpression implements Expression {
37
/**
38
* Create a new Cucumber expression
39
* @param expression The Cucumber expression string
40
* @param parameterTypeRegistry Registry containing parameter types
41
*/
42
CucumberExpression(String expression, ParameterTypeRegistry parameterTypeRegistry);
43
44
/**
45
* Match text against this expression and extract arguments
46
* @param text Text to match against the expression
47
* @param typeHints Optional type hints for anonymous parameters
48
* @return List of matched arguments or null if no match
49
*/
50
@Override
51
public List<Argument<?>> match(String text, Type... typeHints);
52
53
/**
54
* Get the original expression string
55
* @return The source expression
56
*/
57
@Override
58
public String getSource();
59
60
/**
61
* Get the compiled regular expression
62
* @return The regex pattern
63
*/
64
@Override
65
public Pattern getRegexp();
66
}
67
68
/**
69
* Common interface for all expression types
70
*/
71
@API(status = API.Status.STABLE)
72
public interface Expression {
73
/**
74
* Match text against this expression
75
* @param text Text to match
76
* @param typeHints Optional type hints for resolution
77
* @return List of arguments or null if no match
78
*/
79
List<Argument<?>> match(String text, Type... typeHints);
80
81
/**
82
* Get the source expression string
83
* @return Source string
84
*/
85
String getSource();
86
87
/**
88
* Get the compiled regular expression
89
* @return Regex pattern
90
*/
91
Pattern getRegexp();
92
}
93
```
94
95
**Usage Examples:**
96
97
```java
98
import io.cucumber.cucumberexpressions.*;
99
import java.util.List;
100
101
// Create registry with built-in parameter types
102
ParameterTypeRegistry registry = new ParameterTypeRegistry();
103
104
// Simple integer parameter
105
CucumberExpression expr1 = new CucumberExpression("I have {int} cucumbers", registry);
106
List<Argument<?>> args1 = expr1.match("I have 42 cucumbers");
107
if (args1 != null) {
108
Integer count = (Integer) args1.get(0).getValue();
109
System.out.println(count); // 42
110
}
111
112
// Multiple parameters with type safety
113
CucumberExpression expr2 = new CucumberExpression("User {word} has {int} items", registry);
114
List<Argument<?>> args2 = expr2.match("User alice has 42 items");
115
if (args2 != null) {
116
String username = (String) args2.get(0).getValue();
117
Integer itemCount = (Integer) args2.get(1).getValue();
118
System.out.println("User: " + username + ", Items: " + itemCount);
119
}
120
121
// Optional text
122
CucumberExpression expr3 = new CucumberExpression("I have {int} cucumber(s)", registry);
123
System.out.println(expr3.match("I have 1 cucumber") != null); // true
124
System.out.println(expr3.match("I have 5 cucumbers") != null); // true
125
126
// Alternative text
127
CucumberExpression expr4 = new CucumberExpression("I put it in my belly/stomach", registry);
128
System.out.println(expr4.match("I put it in my belly") != null); // true
129
System.out.println(expr4.match("I put it in my stomach") != null); // true
130
131
// String parameters (removes quotes)
132
CucumberExpression expr5 = new CucumberExpression("I say {string}", registry);
133
List<Argument<?>> args5 = expr5.match("I say \"hello world\"");
134
if (args5 != null) {
135
String message = (String) args5.get(0).getValue();
136
System.out.println(message); // "hello world" (without quotes)
137
}
138
139
// Type hints for anonymous parameters
140
CucumberExpression expr6 = new CucumberExpression("Value is {}", registry);
141
List<Argument<?>> args6 = expr6.match("Value is 42", Integer.class);
142
if (args6 != null) {
143
Integer value = (Integer) args6.get(0).getValue(); // Converted to Integer
144
System.out.println(value); // 42
145
}
146
```
147
148
### Parameter Type Definition
149
150
Define custom parameter types with strong typing, multiple constructor overloads, and transformer functions.
151
152
```java { .api }
153
/**
154
* Defines a parameter type with name, patterns, and transformer
155
* Stable API with comprehensive constructor overloads
156
*/
157
@API(status = API.Status.STABLE)
158
public final class ParameterType<T> implements Comparable<ParameterType<?>> {
159
/**
160
* Create parameter type with capture group transformer
161
* @param name Name used in expressions
162
* @param regexps List of regular expression patterns
163
* @param type Target class type
164
* @param transformer Function to transform capture groups
165
*/
166
public ParameterType(
167
String name,
168
List<String> regexps,
169
Class<T> type,
170
CaptureGroupTransformer<T> transformer
171
);
172
173
/**
174
* Create parameter type with simple transformer
175
* @param name Name used in expressions
176
* @param regexp Single regular expression pattern
177
* @param type Target class type
178
* @param transformer Function to transform single match
179
*/
180
public ParameterType(
181
String name,
182
String regexp,
183
Class<T> type,
184
Transformer<T> transformer
185
);
186
187
/**
188
* Create parameter type with all options
189
* @param name Name used in expressions
190
* @param regexps List of regular expression patterns
191
* @param type Target class type
192
* @param transformer Capture group transformer
193
* @param useForSnippets Whether to use for snippet generation
194
* @param preferForRegexpMatch Whether to prefer for regexp matches
195
*/
196
public ParameterType(
197
String name,
198
List<String> regexps,
199
Class<T> type,
200
CaptureGroupTransformer<T> transformer,
201
boolean useForSnippets,
202
boolean preferForRegexpMatch
203
);
204
205
// Many additional constructor overloads available...
206
207
/**
208
* Check if parameter type name is valid
209
* @param name Name to validate
210
* @throws CucumberExpressionException if invalid
211
*/
212
static void checkParameterTypeName(String name);
213
214
/**
215
* Test if parameter type name is valid
216
* @param name Name to test
217
* @return true if valid
218
*/
219
static boolean isValidParameterTypeName(String name);
220
221
/**
222
* Create anonymous parameter type for regexp matching
223
* @param regexp Regular expression pattern
224
* @return Anonymous parameter type
225
*/
226
static ParameterType<Object> createAnonymousParameterType(String regexp);
227
228
/**
229
* Create parameter type from enum class
230
* @param enumClass Enum class to create type for
231
* @return Parameter type for enum
232
*/
233
static <E extends Enum> ParameterType<E> fromEnum(final Class<E> enumClass);
234
235
/**
236
* Get parameter type name
237
* @return Name or null for anonymous types
238
*/
239
public String getName();
240
241
/**
242
* Get target type
243
* @return Java type
244
*/
245
public Type getType();
246
247
/**
248
* Get regular expression patterns
249
* @return List of regex strings
250
*/
251
public List<String> getRegexps();
252
253
/**
254
* Whether this type is preferred for regexp matches
255
* @return true if preferred
256
*/
257
public boolean preferForRegexpMatch();
258
259
/**
260
* Whether this type should be used for snippets
261
* @return true if used for snippets
262
*/
263
public boolean useForSnippets();
264
265
/**
266
* Whether regexp match provides strong type hint
267
* @return true if strong type hint
268
*/
269
public boolean useRegexpMatchAsStrongTypeHint();
270
271
/**
272
* Transform matched groups to target type
273
* @param groupValues List of matched strings
274
* @return Transformed value
275
* @throws Throwable if transformation fails
276
*/
277
T transform(List<String> groupValues) throws Throwable;
278
279
/**
280
* Compare parameter types for sorting
281
* @param o Other parameter type
282
* @return Comparison result
283
*/
284
@Override
285
public int compareTo(ParameterType<?> o);
286
287
/**
288
* Get parameter type weight for ranking
289
* @return Weight value
290
*/
291
public int weight();
292
}
293
294
/**
295
* Transformer for multiple capture groups
296
*/
297
@FunctionalInterface
298
public interface CaptureGroupTransformer<T> {
299
/**
300
* Transform capture group array to target type
301
* @param args Array of captured strings
302
* @return Transformed value
303
* @throws Throwable if transformation fails
304
*/
305
T transform(String[] args) throws Throwable;
306
}
307
308
/**
309
* Transformer for single capture group
310
*/
311
@FunctionalInterface
312
public interface Transformer<T> {
313
/**
314
* Transform single string to target type
315
* @param arg Captured string
316
* @return Transformed value
317
* @throws Throwable if transformation fails
318
*/
319
T transform(String arg) throws Throwable;
320
}
321
```
322
323
**Usage Examples:**
324
325
```java
326
import io.cucumber.cucumberexpressions.*;
327
import java.time.LocalDate;
328
import java.time.LocalDateTime;
329
import java.util.Arrays;
330
import java.math.BigDecimal;
331
332
// Simple enum parameter type
333
enum Priority {
334
LOW, MEDIUM, HIGH;
335
336
public static Priority fromString(String s) {
337
return valueOf(s.toUpperCase());
338
}
339
}
340
341
ParameterType<Priority> priorityType = new ParameterType<>(
342
"priority",
343
"low|medium|high",
344
Priority.class,
345
Priority::fromString
346
);
347
348
// Complex object with multiple capture groups
349
class User {
350
final String name;
351
final int age;
352
final String email;
353
354
User(String name, int age, String email) {
355
this.name = name;
356
this.age = age;
357
this.email = email;
358
}
359
360
@Override
361
public String toString() {
362
return String.format("User{name='%s', age=%d, email='%s'}", name, age, email);
363
}
364
}
365
366
ParameterType<User> userType = new ParameterType<>(
367
"user",
368
Arrays.asList("(\\w+):(\\d+):([^:]+)"),
369
User.class,
370
(String[] args) -> new User(args[0], Integer.parseInt(args[1]), args[2])
371
);
372
373
// Date parameter type with validation
374
ParameterType<LocalDate> dateType = new ParameterType<>(
375
"date",
376
Arrays.asList("(\\d{4})-(\\d{2})-(\\d{2})"),
377
LocalDate.class,
378
(String[] args) -> {
379
int year = Integer.parseInt(args[0]);
380
int month = Integer.parseInt(args[1]);
381
int day = Integer.parseInt(args[2]);
382
383
if (month < 1 || month > 12) {
384
throw new IllegalArgumentException("Invalid month: " + month);
385
}
386
if (day < 1 || day > 31) {
387
throw new IllegalArgumentException("Invalid day: " + day);
388
}
389
390
return LocalDate.of(year, month, day);
391
}
392
);
393
394
// Money parameter type with BigDecimal
395
class Money {
396
final BigDecimal amount;
397
final String currency;
398
399
Money(BigDecimal amount, String currency) {
400
this.amount = amount;
401
this.currency = currency;
402
}
403
404
@Override
405
public String toString() {
406
return amount + " " + currency;
407
}
408
}
409
410
ParameterType<Money> moneyType = new ParameterType<>(
411
"money",
412
"\\$([0-9]+(?:\\.[0-9]{2})?)\\s+(USD|EUR|GBP)",
413
Money.class,
414
(String[] args) -> new Money(new BigDecimal(args[0]), args[1])
415
);
416
417
// Register and use parameter types
418
ParameterTypeRegistry registry = new ParameterTypeRegistry();
419
registry.defineParameterType(priorityType);
420
registry.defineParameterType(userType);
421
registry.defineParameterType(dateType);
422
registry.defineParameterType(moneyType);
423
424
// Use in expressions
425
CucumberExpression priorityExpr = new CucumberExpression("Task has {priority} priority", registry);
426
List<Argument<?>> priorityArgs = priorityExpr.match("Task has high priority");
427
Priority p = (Priority) priorityArgs.get(0).getValue();
428
System.out.println(p); // HIGH
429
430
CucumberExpression userExpr = new CucumberExpression("Create {user}", registry);
431
List<Argument<?>> userArgs = userExpr.match("Create alice:25:alice@example.com");
432
User user = (User) userArgs.get(0).getValue();
433
System.out.println(user); // User{name='alice', age=25, email='alice@example.com'}
434
435
CucumberExpression dateExpr = new CucumberExpression("Meeting on {date}", registry);
436
List<Argument<?>> dateArgs = dateExpr.match("Meeting on 2023-12-25");
437
LocalDate date = (LocalDate) dateArgs.get(0).getValue();
438
System.out.println(date); // 2023-12-25
439
440
CucumberExpression moneyExpr = new CucumberExpression("Price is {money}", registry);
441
List<Argument<?>> moneyArgs = moneyExpr.match("Price is $29.99 USD");
442
Money money = (Money) moneyArgs.get(0).getValue();
443
System.out.println(money); // 29.99 USD
444
445
// Enum from class (automatic pattern generation)
446
ParameterType<Priority> autoEnumType = ParameterType.fromEnum(Priority.class);
447
registry.defineParameterType(autoEnumType);
448
System.out.println(autoEnumType.getRegexps()); // [LOW|MEDIUM|HIGH]
449
```
450
451
### Parameter Type Registry
452
453
Comprehensive registry with default parameter transformers and advanced lookup capabilities.
454
455
```java { .api }
456
/**
457
* Registry for managing parameter types with built-in type support
458
*/
459
@API(status = API.Status.STABLE)
460
public final class ParameterTypeRegistry implements DefinesParameterType {
461
/**
462
* Create new parameter type registry with built-in types
463
*/
464
public ParameterTypeRegistry();
465
466
/**
467
* Define new parameter type in registry
468
* @param parameterType Parameter type to register
469
*/
470
public <T> void defineParameterType(ParameterType<T> parameterType);
471
472
/**
473
* Look up parameter type by name
474
* @param typeName Name of parameter type
475
* @return Parameter type or null if not found
476
*/
477
public ParameterType<?> lookupByTypeName(String typeName);
478
479
/**
480
* Look up parameter type by regular expression
481
* @param parameterTypeRegexp Regex pattern to match
482
* @param expressionRegexp Full expression regex
483
* @param text Text being matched
484
* @return Matching parameter type or null
485
*/
486
public ParameterType<?> lookupByRegexp(
487
String parameterTypeRegexp,
488
Pattern expressionRegexp,
489
String text
490
);
491
492
/**
493
* Get default parameter transformer for type conversion
494
* @return Current default transformer
495
*/
496
public ParameterByTypeTransformer getDefaultParameterTransformer();
497
498
/**
499
* Set default parameter transformer for anonymous parameters
500
* @param defaultParameterTransformer Transformer to use
501
*/
502
public void setDefaultParameterTransformer(ParameterByTypeTransformer defaultParameterTransformer);
503
}
504
505
/**
506
* Interface for parameter type registration
507
*/
508
public interface DefinesParameterType {
509
/**
510
* Define parameter type
511
* @param parameterType Parameter type to define
512
*/
513
<T> void defineParameterType(ParameterType<T> parameterType);
514
}
515
516
/**
517
* Interface for transforming parameters by target type
518
*/
519
public interface ParameterByTypeTransformer {
520
/**
521
* Transform parameter to target type
522
* @param fromValue Source string value
523
* @param toValueType Target type
524
* @return Transformed value
525
* @throws Throwable if transformation fails
526
*/
527
Object transform(String fromValue, Type toValueType) throws Throwable;
528
}
529
```
530
531
**Usage Examples:**
532
533
```java
534
import io.cucumber.cucumberexpressions.*;
535
import java.lang.reflect.Type;
536
import java.time.LocalDateTime;
537
import java.time.format.DateTimeFormatter;
538
539
ParameterTypeRegistry registry = new ParameterTypeRegistry();
540
541
// Check built-in types
542
ParameterType<?> intType = registry.lookupByTypeName("int");
543
System.out.println(intType.getName()); // "int"
544
System.out.println(intType.getType()); // class java.lang.Integer
545
546
// Custom default parameter transformer
547
ParameterByTypeTransformer customTransformer = new ParameterByTypeTransformer() {
548
@Override
549
public Object transform(String fromValue, Type toValueType) throws Throwable {
550
if (toValueType == LocalDateTime.class) {
551
return LocalDateTime.parse(fromValue, DateTimeFormatter.ISO_LOCAL_DATE_TIME);
552
}
553
// Fallback to default behavior
554
return fromValue;
555
}
556
};
557
558
registry.setDefaultParameterTransformer(customTransformer);
559
560
// Now anonymous parameters can be converted to LocalDateTime
561
CucumberExpression expr = new CucumberExpression("Event at {}", registry);
562
List<Argument<?>> args = expr.match("Event at 2023-12-25T14:30:00", LocalDateTime.class);
563
if (args != null) {
564
LocalDateTime eventTime = (LocalDateTime) args.get(0).getValue();
565
System.out.println(eventTime); // 2023-12-25T14:30
566
}
567
568
// Define and verify custom type
569
ParameterType<String> customType = new ParameterType<>(
570
"uuid",
571
"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
572
String.class,
573
s -> s.toUpperCase()
574
);
575
576
registry.defineParameterType(customType);
577
ParameterType<?> retrieved = registry.lookupByTypeName("uuid");
578
System.out.println(retrieved == customType); // true
579
```
580
581
### Expression Factory
582
583
Factory for creating expressions with automatic type detection.
584
585
```java { .api }
586
/**
587
* Factory for creating expressions with automatic type detection
588
*/
589
@API(status = API.Status.STABLE)
590
public final class ExpressionFactory {
591
/**
592
* Create expression factory with parameter type registry
593
* @param parameterTypeRegistry Registry for parameter types
594
*/
595
public ExpressionFactory(ParameterTypeRegistry parameterTypeRegistry);
596
597
/**
598
* Create expression from string with automatic type detection
599
* @param expressionString Expression string or regex pattern
600
* @return Expression instance
601
*/
602
public Expression createExpression(String expressionString);
603
604
/**
605
* Create expression from Pattern
606
* @param pattern Regular expression pattern
607
* @return RegularExpression instance
608
*/
609
public Expression createExpression(Pattern pattern);
610
}
611
```
612
613
**Usage Examples:**
614
615
```java
616
import io.cucumber.cucumberexpressions.*;
617
import java.util.regex.Pattern;
618
619
ParameterTypeRegistry registry = new ParameterTypeRegistry();
620
ExpressionFactory factory = new ExpressionFactory(registry);
621
622
// Cucumber expression from string
623
Expression cucumberExpr = factory.createExpression("I have {int} items");
624
System.out.println(cucumberExpr.getClass().getSimpleName()); // "CucumberExpression"
625
626
// Regular expression from anchored string
627
Expression regexExpr = factory.createExpression("^I have (\\d+) items$");
628
System.out.println(regexExpr.getClass().getSimpleName()); // "RegularExpression"
629
630
// Regular expression from Pattern
631
Pattern pattern = Pattern.compile("^Count: (\\d+)$");
632
Expression patternExpr = factory.createExpression(pattern);
633
System.out.println(patternExpr.getClass().getSimpleName()); // "RegularExpression"
634
635
// Use expressions
636
List<Argument<?>> cucumberArgs = cucumberExpr.match("I have 42 items");
637
List<Argument<?>> regexArgs = regexExpr.match("I have 42 items");
638
639
Integer cucumberValue = (Integer) cucumberArgs.get(0).getValue(); // 42 as Integer
640
String regexValue = (String) regexArgs.get(0).getValue(); // "42" as String
641
```
642
643
### Expression Generation
644
645
Generate Cucumber expressions from example text with comprehensive metadata.
646
647
```java { .api }
648
/**
649
* Generates Cucumber expressions from example text
650
*/
651
@API(status = API.Status.STABLE)
652
public final class CucumberExpressionGenerator {
653
/**
654
* Create generator with parameter type registry
655
* @param parameterTypeRegistry Registry containing parameter types
656
*/
657
public CucumberExpressionGenerator(ParameterTypeRegistry parameterTypeRegistry);
658
659
/**
660
* Generate expressions from example text
661
* @param text Example text to analyze
662
* @return List of generated expressions ranked by specificity
663
*/
664
public List<GeneratedExpression> generateExpressions(String text);
665
}
666
667
/**
668
* Generated expression with comprehensive metadata
669
*/
670
@API(status = API.Status.STABLE)
671
public final class GeneratedExpression {
672
/**
673
* Create generated expression
674
* @param expressionTemplate Template with parameter placeholders
675
* @param parameterTypes List of parameter types in order
676
*/
677
public GeneratedExpression(String expressionTemplate, List<ParameterType<?>> parameterTypes);
678
679
/**
680
* Get generated expression source
681
* @return Expression string
682
*/
683
public String getSource();
684
685
/**
686
* Get parameter names for code generation
687
* @return List of parameter names
688
*/
689
public List<String> getParameterNames();
690
691
/**
692
* Get parameter information for IDE integration
693
* @return List of parameter information
694
*/
695
public List<ParameterInfo> getParameterInfos();
696
697
/**
698
* Get parameter types in declaration order
699
* @return List of parameter types
700
*/
701
public List<ParameterType<?>> getParameterTypes();
702
}
703
704
/**
705
* Parameter information for code generation and IDE support
706
*/
707
@API(status = API.Status.STABLE)
708
public final class ParameterInfo {
709
/**
710
* Get parameter type name for code generation
711
* @return Type name or null
712
*/
713
public String getType();
714
715
/**
716
* Get suggested parameter name
717
* @return Parameter name
718
*/
719
public String getName();
720
721
/**
722
* Get parameter occurrence count
723
* @return Number of occurrences
724
*/
725
public int getCount();
726
}
727
```
728
729
**Usage Examples:**
730
731
```java
732
import io.cucumber.cucumberexpressions.*;
733
import java.util.List;
734
735
ParameterTypeRegistry registry = new ParameterTypeRegistry();
736
CucumberExpressionGenerator generator = new CucumberExpressionGenerator(registry);
737
738
// Generate from simple text
739
List<GeneratedExpression> expressions = generator.generateExpressions("I have 42 items");
740
GeneratedExpression best = expressions.get(0);
741
System.out.println("Expression: " + best.getSource()); // "I have {int} items"
742
System.out.println("Parameter count: " + best.getParameterTypes().size()); // 1
743
744
// Generate step definition template
745
System.out.println("Step definition:");
746
System.out.println("@Given(\"" + best.getSource() + "\")");
747
StringBuilder params = new StringBuilder();
748
for (int i = 0; i < best.getParameterInfos().size(); i++) {
749
ParameterInfo info = best.getParameterInfos().get(i);
750
if (i > 0) params.append(", ");
751
params.append(getJavaType(info.getType())).append(" ").append(info.getName());
752
}
753
System.out.println("public void iHaveItems(" + params + ") {");
754
System.out.println(" // Implementation here");
755
System.out.println("}");
756
757
// Generate from complex text
758
List<GeneratedExpression> complex = generator.generateExpressions(
759
"User alice with age 25 has balance 123.45"
760
);
761
System.out.println("Generated options:");
762
for (int i = 0; i < Math.min(3, complex.size()); i++) {
763
GeneratedExpression expr = complex.get(i);
764
System.out.printf("%d. %s (%s)%n",
765
i + 1,
766
expr.getSource(),
767
expr.getParameterTypes().stream()
768
.map(pt -> pt.getName())
769
.collect(java.util.stream.Collectors.joining(", "))
770
);
771
}
772
773
private static String getJavaType(String paramTypeName) {
774
switch (paramTypeName) {
775
case "int": return "Integer";
776
case "float": return "Float";
777
case "double": return "Double";
778
case "string": return "String";
779
case "word": return "String";
780
default: return "Object";
781
}
782
}
783
```
784
785
### Argument Extraction
786
787
Extract matched arguments with strong typing and comprehensive metadata.
788
789
```java { .api }
790
/**
791
* Represents a matched argument with type safety
792
*/
793
@API(status = API.Status.STABLE)
794
public final class Argument<T> {
795
/**
796
* Create argument with group and parameter type
797
* @param group Matched group from regex
798
* @param parameterType Parameter type for transformation
799
*/
800
public Argument(Group group, ParameterType<T> parameterType);
801
802
/**
803
* Build arguments from matched groups
804
* @param group Root group from regex match
805
* @param parameterTypes Parameter types for transformation
806
* @return List of arguments
807
*/
808
static List<Argument<?>> build(Group group, List<ParameterType<?>> parameterTypes);
809
810
/**
811
* Get transformed value
812
* @return Transformed value
813
*/
814
public T getValue();
815
816
/**
817
* Get parameter type used for transformation
818
* @return Parameter type
819
*/
820
public ParameterType<T> getParameterType();
821
822
/**
823
* Get matched group information
824
* @return Group with position and text
825
*/
826
public Group getGroup();
827
}
828
829
/**
830
* Represents a matched group with position information
831
*/
832
public final class Group {
833
/**
834
* Get matched text value
835
* @return Matched string or null
836
*/
837
public String getValue();
838
839
/**
840
* Get start position in source text
841
* @return Start index
842
*/
843
public int getStart();
844
845
/**
846
* Get end position in source text
847
* @return End index
848
*/
849
public int getEnd();
850
851
/**
852
* Get child groups
853
* @return List of child groups
854
*/
855
public List<Group> getChildren();
856
}
857
```
858
859
**Usage Examples:**
860
861
```java
862
import io.cucumber.cucumberexpressions.*;
863
import java.util.List;
864
865
ParameterTypeRegistry registry = new ParameterTypeRegistry();
866
CucumberExpression expr = new CucumberExpression("User {word} has {int} items", registry);
867
868
List<Argument<?>> args = expr.match("User alice has 42 items");
869
if (args != null) {
870
// Type-safe value access
871
String username = (String) args.get(0).getValue(); // "alice"
872
Integer itemCount = (Integer) args.get(1).getValue(); // 42
873
874
// Parameter type information
875
System.out.println("First param type: " + args.get(0).getParameterType().getName()); // "word"
876
System.out.println("Second param type: " + args.get(1).getParameterType().getName()); // "int"
877
878
// Position information
879
Group usernameGroup = args.get(0).getGroup();
880
System.out.println("Username at: " + usernameGroup.getStart() + "-" + usernameGroup.getEnd());
881
System.out.println("Username value: '" + usernameGroup.getValue() + "'"); // "alice"
882
883
Group itemGroup = args.get(1).getGroup();
884
System.out.println("Item count at: " + itemGroup.getStart() + "-" + itemGroup.getEnd());
885
System.out.println("Item count value: '" + itemGroup.getValue() + "'"); // "42"
886
}
887
```
888
889
### Built-in Parameter Types
890
891
Comprehensive built-in parameter types with appropriate Java type conversion.
892
893
```java { .api }
894
// Built-in parameter types in Java implementation:
895
896
{int} // Converts to Integer (java.lang.Integer)
897
{byte} // Converts to Byte (java.lang.Byte)
898
{short} // Converts to Short (java.lang.Short)
899
{long} // Converts to Long (java.lang.Long)
900
{float} // Converts to Float (java.lang.Float)
901
{double} // Converts to Double (java.lang.Double)
902
{biginteger} // Converts to BigInteger (java.math.BigInteger)
903
{bigdecimal} // Converts to BigDecimal (java.math.BigDecimal)
904
{word} // Returns as String (single word)
905
{string} // Returns as String (removes quotes)
906
{} // Anonymous - uses ParameterByTypeTransformer
907
```
908
909
**Usage Examples:**
910
911
```java
912
import io.cucumber.cucumberexpressions.*;
913
import java.math.BigDecimal;
914
import java.math.BigInteger;
915
import java.util.List;
916
917
ParameterTypeRegistry registry = new ParameterTypeRegistry();
918
919
// Test all numeric built-in types
920
CucumberExpression expr = new CucumberExpression(
921
"Numbers: {byte} {short} {int} {long} {float} {double} {biginteger} {bigdecimal}",
922
registry
923
);
924
925
List<Argument<?>> args = expr.match("Numbers: 127 32767 42 9223372036854775807 3.14 2.718281828 12345678901234567890 123.456789");
926
927
if (args != null) {
928
Byte byteVal = (Byte) args.get(0).getValue();
929
Short shortVal = (Short) args.get(1).getValue();
930
Integer intVal = (Integer) args.get(2).getValue();
931
Long longVal = (Long) args.get(3).getValue();
932
Float floatVal = (Float) args.get(4).getValue();
933
Double doubleVal = (Double) args.get(5).getValue();
934
BigInteger bigIntVal = (BigInteger) args.get(6).getValue();
935
BigDecimal bigDecVal = (BigDecimal) args.get(7).getValue();
936
937
System.out.println("Byte: " + byteVal + " (" + byteVal.getClass().getSimpleName() + ")");
938
System.out.println("Short: " + shortVal + " (" + shortVal.getClass().getSimpleName() + ")");
939
System.out.println("Integer: " + intVal + " (" + intVal.getClass().getSimpleName() + ")");
940
System.out.println("Long: " + longVal + " (" + longVal.getClass().getSimpleName() + ")");
941
System.out.println("Float: " + floatVal + " (" + floatVal.getClass().getSimpleName() + ")");
942
System.out.println("Double: " + doubleVal + " (" + doubleVal.getClass().getSimpleName() + ")");
943
System.out.println("BigInteger: " + bigIntVal + " (" + bigIntVal.getClass().getSimpleName() + ")");
944
System.out.println("BigDecimal: " + bigDecVal + " (" + bigDecVal.getClass().getSimpleName() + ")");
945
}
946
```
947
948
### Integration with Java Testing Frameworks
949
950
Common patterns for integrating with JUnit, TestNG, and Cucumber-JVM.
951
952
```java
953
// Cucumber-JVM integration
954
import io.cucumber.java.en.Given;
955
import io.cucumber.java.en.When;
956
import io.cucumber.java.en.Then;
957
import io.cucumber.cucumberexpressions.*;
958
959
public class StepDefinitions {
960
private ParameterTypeRegistry registry = new ParameterTypeRegistry();
961
962
// Custom parameter type registration
963
@ParameterType("red|green|blue")
964
public Color color(String color) {
965
return Color.valueOf(color.toUpperCase());
966
}
967
968
// Step definitions using built-in types
969
@Given("I have {int} cucumbers")
970
public void iHaveCucumbers(Integer count) {
971
// count is already converted to Integer
972
assert count instanceof Integer;
973
}
974
975
@When("I eat {int} cucumber(s)")
976
public void iEatCucumbers(Integer count) {
977
// Handles both singular and plural
978
}
979
980
@Then("I should have {int} cucumber(s) left")
981
public void iShouldHaveCucumbersLeft(Integer count) {
982
// Assertion logic here
983
}
984
985
// Using custom parameter types
986
@Given("I have a {color} car")
987
public void iHaveColorCar(Color color) {
988
// color is converted using custom parameter type
989
assert color instanceof Color;
990
}
991
}
992
993
// JUnit 5 integration example
994
import org.junit.jupiter.api.Test;
995
import io.cucumber.cucumberexpressions.*;
996
997
class CucumberExpressionTest {
998
@Test
999
void testParameterExtraction() {
1000
ParameterTypeRegistry registry = new ParameterTypeRegistry();
1001
CucumberExpression expr = new CucumberExpression("User {word} has {int} items", registry);
1002
1003
List<Argument<?>> args = expr.match("User alice has 42 items");
1004
1005
assertThat(args).hasSize(2);
1006
assertThat(args.get(0).getValue()).isEqualTo("alice");
1007
assertThat(args.get(1).getValue()).isEqualTo(42);
1008
}
1009
}
1010
```
1011
1012
The Java implementation provides enterprise-grade robustness with comprehensive type safety, extensive built-in parameter types, and seamless integration with Java testing ecosystems while maintaining full API compatibility with the Cucumber Expressions specification.