0
# Utilities and Support Classes
1
2
The Utilities module provides essential helper classes and functions for common operations including parameter validation, string manipulation, file handling, version management, and other utility functions used throughout PMD Core.
3
4
## Capabilities
5
6
### Assertion Utilities
7
8
Parameter validation and assertion utilities for defensive programming and error handling.
9
10
```java { .api }
11
/**
12
* Utility methods for parameter validation and assertions.
13
* Provides consistent error messages and null checking across PMD.
14
*/
15
public final class AssertionUtil {
16
17
/**
18
* Check parameter is not null and return it
19
* @param paramName Name of parameter for error message
20
* @param param Parameter value to check
21
* @return The parameter value if not null
22
* @throws IllegalArgumentException if parameter is null
23
*/
24
static <T> T requireParamNotNull(String paramName, T param);
25
26
/**
27
* Check collection contains no null values
28
* @param paramName Name of parameter for error message
29
* @param collection Collection to validate
30
* @throws IllegalArgumentException if collection contains null elements
31
*/
32
static <T> void requireContainsNoNullValue(String paramName, Collection<T> collection);
33
34
/**
35
* Create "unreachable code" assertion error
36
* @return AssertionError indicating code should not be reached
37
*/
38
static AssertionError shouldNotReachHere();
39
40
/**
41
* Create "unreachable code" assertion error with message
42
* @param message Descriptive message for the error
43
* @return AssertionError with custom message
44
*/
45
static AssertionError shouldNotReachHere(String message);
46
47
/**
48
* Create "unreachable code" assertion error with message and cause
49
* @param message Descriptive message for the error
50
* @param cause Underlying cause of the error
51
* @return AssertionError with message and cause
52
*/
53
static AssertionError shouldNotReachHere(String message, Throwable cause);
54
}
55
```
56
57
**Usage Examples:**
58
59
```java
60
import net.sourceforge.pmd.util.AssertionUtil;
61
import java.util.List;
62
import java.util.Arrays;
63
64
// Using assertion utilities in methods
65
public class ValidationExample {
66
67
public void processData(String name, List<String> items, Object config) {
68
// Validate required parameters
69
name = AssertionUtil.requireParamNotNull("name", name);
70
items = AssertionUtil.requireParamNotNull("items", items);
71
config = AssertionUtil.requireParamNotNull("config", config);
72
73
// Validate collection contents
74
AssertionUtil.requireContainsNoNullValue("items", items);
75
76
// Process with confidence that parameters are valid
77
processValidatedData(name, items, config);
78
}
79
80
private void processValidatedData(String name, List<String> items, Object config) {
81
// Implementation assumes all parameters are non-null
82
System.out.printf("Processing %s with %d items%n", name, items.size());
83
}
84
85
public String handleDifferentCases(int caseType) {
86
switch (caseType) {
87
case 1:
88
return "Case 1";
89
case 2:
90
return "Case 2";
91
case 3:
92
return "Case 3";
93
default:
94
// This should never happen based on our design
95
throw AssertionUtil.shouldNotReachHere(
96
"Unexpected case type: " + caseType);
97
}
98
}
99
100
public void demonstrateErrorHandling() {
101
try {
102
processData(null, Arrays.asList("a", "b"), new Object());
103
} catch (IllegalArgumentException e) {
104
System.err.println("Expected error: " + e.getMessage());
105
}
106
107
try {
108
processData("test", Arrays.asList("a", null, "c"), new Object());
109
} catch (IllegalArgumentException e) {
110
System.err.println("Expected error: " + e.getMessage());
111
}
112
113
try {
114
handleDifferentCases(99); // Invalid case
115
} catch (AssertionError e) {
116
System.err.println("Unreachable code error: " + e.getMessage());
117
}
118
}
119
}
120
121
// Using in custom rule implementation
122
public class CustomRuleExample extends AbstractRule {
123
124
@Override
125
public void apply(List<? extends Node> nodes, RuleContext ctx) {
126
// Validate inputs
127
nodes = AssertionUtil.requireParamNotNull("nodes", nodes);
128
ctx = AssertionUtil.requireParamNotNull("ctx", ctx);
129
AssertionUtil.requireContainsNoNullValue("nodes", nodes);
130
131
// Safe to proceed with analysis
132
for (Node node : nodes) {
133
analyzeNode(node, ctx);
134
}
135
}
136
137
private void analyzeNode(Node node, RuleContext ctx) {
138
// Implementation can assume node and ctx are non-null
139
if (node.getNumChildren() == 0) {
140
ctx.addViolation(node, "Empty node found");
141
}
142
}
143
}
144
```
145
146
### String Utilities
147
148
String manipulation utilities for common text processing operations.
149
150
```java { .api }
151
/**
152
* String manipulation utilities for common text operations.
153
* Provides null-safe methods for string validation and processing.
154
*/
155
public final class StringUtil {
156
157
/**
158
* Check if string is null or empty
159
* @param str String to check
160
* @return true if string is null or has length 0
161
*/
162
static boolean isEmpty(String str);
163
164
/**
165
* Check if string is not null and not empty
166
* @param str String to check
167
* @return true if string is not null and has length > 0
168
*/
169
static boolean isNotEmpty(String str);
170
171
/**
172
* Check if string is null, empty, or contains only whitespace
173
* @param str String to check
174
* @return true if string is null, empty, or whitespace-only
175
*/
176
static boolean isBlank(String str);
177
178
/**
179
* Check if string has non-whitespace content
180
* @param str String to check
181
* @return true if string contains non-whitespace characters
182
*/
183
static boolean isNotBlank(String str);
184
185
/**
186
* Quote string for MessageFormat (escape single quotes)
187
* @param msg String to quote for MessageFormat usage
188
* @return String with single quotes escaped
189
*/
190
static String quoteMessageFormat(String msg);
191
192
/**
193
* Replace all occurrences of substring
194
* @param original Source string
195
* @param find Substring to find
196
* @param replacement Replacement string
197
* @return String with all occurrences replaced
198
*/
199
static String replaceString(String original, String find, String replacement);
200
201
/**
202
* Split string by character separator
203
* @param str String to split
204
* @param separator Character to split on
205
* @return List of split parts (empty list if input is null/empty)
206
*/
207
static List<String> split(String str, char separator);
208
}
209
```
210
211
**Usage Examples:**
212
213
```java
214
import net.sourceforge.pmd.util.StringUtil;
215
import java.util.List;
216
217
// Using string utilities
218
public class StringProcessingExample {
219
220
public void validateInput(String userInput) {
221
if (StringUtil.isEmpty(userInput)) {
222
throw new IllegalArgumentException("Input cannot be empty");
223
}
224
225
if (StringUtil.isBlank(userInput)) {
226
System.out.println("Warning: Input is only whitespace");
227
return;
228
}
229
230
// Process valid input
231
processValidInput(userInput.trim());
232
}
233
234
public void processConfiguration(String configValue) {
235
// Check for meaningful content
236
if (StringUtil.isNotBlank(configValue)) {
237
System.out.printf("Processing config: '%s'%n", configValue);
238
239
// Split configuration values
240
List<String> parts = StringUtil.split(configValue, ',');
241
System.out.printf("Configuration has %d parts:%n", parts.size());
242
243
for (int i = 0; i < parts.size(); i++) {
244
String part = parts.get(i).trim();
245
if (StringUtil.isNotEmpty(part)) {
246
System.out.printf(" Part %d: %s%n", i + 1, part);
247
}
248
}
249
} else {
250
System.out.println("No configuration provided");
251
}
252
}
253
254
public String formatMessage(String template, String userValue) {
255
// Prepare message for MessageFormat
256
String quotedTemplate = StringUtil.quoteMessageFormat(template);
257
258
// Replace placeholder with actual value
259
return StringUtil.replaceString(quotedTemplate, "{value}", userValue);
260
}
261
262
public void demonstrateStringOperations() {
263
// Test empty/blank detection
264
testString(null, "null string");
265
testString("", "empty string");
266
testString(" ", "whitespace string");
267
testString("hello", "normal string");
268
269
// Test splitting
270
String csvData = "apple,banana,cherry,date";
271
List<String> fruits = StringUtil.split(csvData, ',');
272
System.out.printf("CSV '%s' split into: %s%n", csvData, fruits);
273
274
// Test replacement
275
String original = "Hello {name}, welcome to {place}!";
276
String replaced = StringUtil.replaceString(original, "{name}", "Alice");
277
replaced = StringUtil.replaceString(replaced, "{place}", "PMD");
278
System.out.printf("Template: %s%nResult: %s%n", original, replaced);
279
280
// Test MessageFormat quoting
281
String messageTemplate = "Don't use 'System.out.println'";
282
String quoted = StringUtil.quoteMessageFormat(messageTemplate);
283
System.out.printf("Original: %s%nQuoted: %s%n", messageTemplate, quoted);
284
}
285
286
private void testString(String str, String description) {
287
System.out.printf("%s:%n", description);
288
System.out.printf(" isEmpty: %b%n", StringUtil.isEmpty(str));
289
System.out.printf(" isNotEmpty: %b%n", StringUtil.isNotEmpty(str));
290
System.out.printf(" isBlank: %b%n", StringUtil.isBlank(str));
291
System.out.printf(" isNotBlank: %b%n", StringUtil.isNotBlank(str));
292
}
293
294
private void processValidInput(String input) {
295
System.out.printf("Processing valid input: '%s'%n", input);
296
}
297
}
298
299
// Using in rule message formatting
300
public class MessageFormattingExample {
301
302
public void formatRuleMessage(String template, Object... args) {
303
// Quote template for MessageFormat
304
String quotedTemplate = StringUtil.quoteMessageFormat(template);
305
306
// Format with arguments
307
String message = MessageFormat.format(quotedTemplate, args);
308
System.out.println("Formatted message: " + message);
309
}
310
311
public void processRuleViolation(RuleViolation violation) {
312
String description = violation.getDescription();
313
314
if (StringUtil.isNotBlank(description)) {
315
// Clean up the description
316
description = description.trim();
317
318
// Remove PMD-specific markers if present
319
description = StringUtil.replaceString(description, "PMD:", "");
320
description = description.trim();
321
322
System.out.printf("Clean violation: %s%n", description);
323
}
324
}
325
}
326
```
327
328
### Version Management
329
330
Version information and utilities for PMD versioning and compatibility checking.
331
332
```java { .api }
333
/**
334
* PMD version information and utilities.
335
* Provides access to current version and version-related operations.
336
*/
337
public final class PMDVersion {
338
339
/**
340
* Current PMD version string
341
*/
342
public static final String VERSION;
343
344
/**
345
* Get next expected major version
346
* @return Next major version string
347
*/
348
static String getNextMajorRelease();
349
350
/**
351
* Check if current version is unknown
352
* @return true if version information is not available
353
*/
354
static boolean isUnknown();
355
356
/**
357
* Check if current version is a snapshot build
358
* @return true if version contains snapshot indicators
359
*/
360
static boolean isSnapshot();
361
362
/**
363
* Get full version string with metadata
364
* @return Complete version string including build information
365
*/
366
static String getFullVersionName();
367
}
368
```
369
370
**Usage Examples:**
371
372
```java
373
import net.sourceforge.pmd.PMDVersion;
374
375
// Working with version information
376
public class VersionExample {
377
378
public void displayVersionInfo() {
379
System.out.println("PMD Version Information:");
380
System.out.printf(" Current version: %s%n", PMDVersion.VERSION);
381
System.out.printf(" Full version: %s%n", PMDVersion.getFullVersionName());
382
System.out.printf(" Next major: %s%n", PMDVersion.getNextMajorRelease());
383
System.out.printf(" Is snapshot: %b%n", PMDVersion.isSnapshot());
384
System.out.printf(" Is unknown: %b%n", PMDVersion.isUnknown());
385
}
386
387
public void checkCompatibility(String requiredVersion) {
388
String currentVersion = PMDVersion.VERSION;
389
390
if (PMDVersion.isUnknown()) {
391
System.out.println("Warning: PMD version is unknown");
392
return;
393
}
394
395
if (PMDVersion.isSnapshot()) {
396
System.out.println("Note: Using snapshot version - features may be unstable");
397
}
398
399
// Simple version comparison (real implementation would be more sophisticated)
400
if (currentVersion.equals(requiredVersion)) {
401
System.out.printf("✓ Version %s matches requirement%n", currentVersion);
402
} else {
403
System.out.printf("⚠ Version %s does not match requirement %s%n",
404
currentVersion, requiredVersion);
405
}
406
}
407
408
public void generateBuildInfo() {
409
System.out.println("Build Information:");
410
System.out.printf("PMD Core %s%n", PMDVersion.getFullVersionName());
411
412
if (PMDVersion.isSnapshot()) {
413
System.out.println("This is a development build - not for production use");
414
} else {
415
System.out.println("This is a release build");
416
}
417
}
418
}
419
```
420
421
### Rendering Utilities
422
423
Extended rendering system with comprehensive output format support including XML, HTML, JSON, CSV, and specialized formats.
424
425
```java { .api }
426
/**
427
* Extensible rendering framework for formatting analysis reports.
428
* Provides multiple output formats with customizable properties.
429
*/
430
public interface Renderer extends PropertySource {
431
432
/**
433
* Get renderer name/identifier
434
* @return Unique name for the renderer
435
*/
436
String getName();
437
438
/**
439
* Set renderer name
440
* @param name Unique identifier for renderer
441
*/
442
void setName(String name);
443
444
/**
445
* Get renderer description
446
* @return Human-readable description of renderer purpose
447
*/
448
String getDescription();
449
450
/**
451
* Set renderer description
452
* @param description Description of renderer functionality
453
*/
454
void setDescription(String description);
455
456
/**
457
* Get default file extension for output
458
* @return File extension without dot (e.g., "xml", "html")
459
*/
460
String defaultFileExtension();
461
462
/**
463
* Check if suppressed violations are shown
464
* @return true if renderer includes suppressed violations
465
*/
466
boolean isShowSuppressedViolations();
467
468
/**
469
* Set whether to show suppressed violations
470
* @param show true to include suppressed violations in output
471
*/
472
void setShowSuppressedViolations(boolean show);
473
474
/**
475
* Set output writer for rendering
476
* @param writer Writer for formatted output
477
*/
478
void setWriter(Writer writer);
479
480
/**
481
* Set report file path (alternative to setWriter)
482
* @param reportFile Path to output file
483
*/
484
void setReportFile(String reportFile);
485
486
/**
487
* Create analysis listener for receiving events
488
* @return GlobalAnalysisListener that forwards to this renderer
489
*/
490
GlobalAnalysisListener newListener();
491
492
/**
493
* Start rendering process
494
*/
495
void start();
496
497
/**
498
* End rendering process
499
*/
500
void end();
501
502
/**
503
* Flush any buffered output
504
*/
505
void flush();
506
}
507
```
508
509
## Types
510
511
```java { .api }
512
/**
513
* File identifier and metadata
514
*/
515
interface FileId {
516
517
/**
518
* Get absolute file path
519
* @return Absolute path to the file
520
*/
521
String getAbsolutePath();
522
523
/**
524
* Get display name for reports
525
* @return User-friendly file name for display
526
*/
527
String getDisplayName();
528
529
/**
530
* Get file URI
531
* @return URI representation of file location
532
*/
533
URI getUri();
534
535
/**
536
* Create FileId from path-like string
537
* @param pathLike String representing file path
538
* @return FileId instance
539
*/
540
static FileId fromPathLikeString(String pathLike);
541
542
/**
543
* Create FileId from Path object
544
* @param path Path object representing file
545
* @return FileId instance
546
*/
547
static FileId fromPath(Path path);
548
}
549
550
/**
551
* Text document representation
552
*/
553
interface TextDocument {
554
555
/**
556
* Get complete document text
557
* @return Full text content
558
*/
559
String getText();
560
561
/**
562
* Get text for specific region
563
* @param region TextRegion to extract
564
* @return Text content for region
565
*/
566
String getText(TextRegion region);
567
568
/**
569
* Get line content by number
570
* @param lineNumber One-based line number
571
* @return Content of specified line
572
*/
573
String getLine(int lineNumber);
574
575
/**
576
* Get total line count
577
* @return Number of lines in document
578
*/
579
int getLineCount();
580
581
/**
582
* Get file identifier
583
* @return FileId for this document
584
*/
585
FileId getFileId();
586
}
587
588
/**
589
* Collection utilities for common operations
590
*/
591
final class CollectionUtil {
592
593
/**
594
* Create immutable list from array
595
* @param items Array elements
596
* @return Unmodifiable List containing elements
597
*/
598
static <T> List<T> listOf(T... items);
599
600
/**
601
* Check if collection is null or empty
602
* @param collection Collection to check
603
* @return true if collection is null or empty
604
*/
605
static boolean isEmpty(Collection<?> collection);
606
607
/**
608
* Get first element of list
609
* @param list List to query
610
* @return First element or null if empty
611
*/
612
static <T> T first(List<T> list);
613
614
/**
615
* Get last element of list
616
* @param list List to query
617
* @return Last element or null if empty
618
*/
619
static <T> T last(List<T> list);
620
}
621
622
/**
623
* I/O utilities for file operations
624
*/
625
final class IOUtil {
626
627
/**
628
* Read entire file as string
629
* @param file File to read
630
* @param charset Character encoding to use
631
* @return File contents as string
632
*/
633
static String readFileToString(File file, Charset charset) throws IOException;
634
635
/**
636
* Write string to file
637
* @param file Target file
638
* @param content Content to write
639
* @param charset Character encoding to use
640
*/
641
static void writeStringToFile(File file, String content, Charset charset) throws IOException;
642
643
/**
644
* Close resource quietly (ignoring exceptions)
645
* @param closeable Resource to close
646
*/
647
static void closeQuietly(Closeable closeable);
648
649
/**
650
* Copy input stream to output stream
651
* @param input Source stream
652
* @param output Target stream
653
* @return Number of bytes copied
654
*/
655
static long copy(InputStream input, OutputStream output) throws IOException;
656
}
657
658
/**
659
* Date/time utilities for timestamps
660
*/
661
final class DateTimeUtil {
662
663
/**
664
* Format timestamp for reports
665
* @param timestamp Timestamp to format
666
* @return Formatted timestamp string
667
*/
668
static String formatTimestamp(long timestamp);
669
670
/**
671
* Get current timestamp
672
* @return Current system time in milliseconds
673
*/
674
static long getCurrentTimestamp();
675
676
/**
677
* Parse ISO date string
678
* @param dateString ISO-formatted date
679
* @return Parsed timestamp
680
*/
681
static long parseISODate(String dateString);
682
}
683
684
/**
685
* System utilities for environment access
686
*/
687
final class SystemUtil {
688
689
/**
690
* Get system property with default
691
* @param key Property key
692
* @param defaultValue Default if property not set
693
* @return Property value or default
694
*/
695
static String getSystemProperty(String key, String defaultValue);
696
697
/**
698
* Check if running on Windows
699
* @return true if Windows operating system
700
*/
701
static boolean isWindows();
702
703
/**
704
* Get available processor count
705
* @return Number of available processors
706
*/
707
static int getAvailableProcessors();
708
709
/**
710
* Get total system memory
711
* @return Total memory in bytes
712
*/
713
static long getTotalMemory();
714
}
715
716
/**
717
* Mathematical utilities for calculations
718
*/
719
final class MathUtil {
720
721
/**
722
* Calculate percentage
723
* @param part Numerator value
724
* @param total Denominator value
725
* @return Percentage (0-100)
726
*/
727
static double percentage(long part, long total);
728
729
/**
730
* Clamp value to range
731
* @param value Value to clamp
732
* @param min Minimum allowed value
733
* @param max Maximum allowed value
734
* @return Clamped value within range
735
*/
736
static int clamp(int value, int min, int max);
737
738
/**
739
* Check if number is in range (inclusive)
740
* @param value Value to check
741
* @param min Minimum value
742
* @param max Maximum value
743
* @return true if value is within range
744
*/
745
static boolean inRange(int value, int min, int max);
746
}
747
```