Skip to content

Commit 71423dc

Browse files
authored
Remove commons-collection4 from the project (#7561)
* Replace commons-collections4 CollectionUtils with JDK equivalents Two call sites used CollectionUtils.emptyIfNull() to guard against null collections before streaming. Both are replaced with explicit null checks: - VariableChannel.checkForVeto(): a stream-then-findAny-isPresent chain collapses to a single anyMatch() with a null guard. - VisionDisplay.getVision(): early return on null preserves the same empty-string output without constructing an empty collection. Step 1 of removing the commons-collections4 dependency. * Replace commons-collections4 IteratorUtils with JDK StreamSupport The single call site converted an Iterator into a List via IteratorUtils.toList(). Replaced with StreamSupport.stream() over a Spliterator wrapper of the Iterator and Stream.toList(), which is the idiomatic JDK pattern for the same conversion. Step 2 of removing the commons-collections4 dependency. * Replace commons-collections4 ListUtils and remove the dependency Four call sites in CDOMObjectUtilities used ListUtils.emptyIfNull() to guard a forEach against null. Replaced with explicit null checks: skip the iteration if the list is null, otherwise call forEach directly. This was the last remaining commons-collections4 import after the prior two commits removed CollectionUtils and IteratorUtils, so this change also drops the dependency from build.gradle and the requires clause from module-info.java. Step 3 of removing the commons-collections4 dependency. Saves ~880 KB from the runtime classpath. * Refactor veto mechanism: replace BiFunction with BiPredicate BiPredicate<T, T> is the specialized functional interface for boolean-returning two-argument functions, so call sites use .test() rather than .apply() and Sonar's "use the most specialized functional interface" warning goes away. Also tighten getVariableID() to return VariableID<T> instead of VariableID<?>. The veto API itself (VetoableReferenceFacade, addVetoToChannel) has no in-tree callers and PR #5577 (2019) proposed removing it. The original author (thpr) pushed back, asking that cdom/formula code not be changed without discussion since "it is rarely unused completely" — third-party plugins may rely on it. Keeping the API; only modernizing the signature. Signed-off-by: Vest <Vest@users.noreply.github.com> * Refactor ExportDialogController: simplify context creation and streamline UI logic Fix SonarLint errors/warnings. Signed-off-by: Vest <Vest@users.noreply.github.com> * Refactor CDOMObjectUtilities: streamline list handling with getSafeListFor Signed-off-by: Vest <Vest@users.noreply.github.com> --------- Signed-off-by: Vest <Vest@users.noreply.github.com>
1 parent 967e108 commit 71423dc

7 files changed

Lines changed: 31 additions & 61 deletions

File tree

build.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ dependencies {
231231
exclude group: 'xalan', module: 'serializer'
232232
}
233233
implementation 'net.sf.saxon:Saxon-HE:12.9'
234-
implementation 'org.apache.commons:commons-collections4:4.5.0'
235234
implementation 'org.scijava:jep:2.4.2'
236235
implementation 'org.freemarker:freemarker:2.3.34'
237236
implementation 'org.jdom:jdom2:2.0.6.1'
@@ -305,7 +304,7 @@ jar {
305304
jlink {
306305
options = ['--strip-debug', '--no-header-files', '--no-man-pages']
307306
forceMerge('PCGen-base', 'PCGen-Formula', 'jep', 'fop', 'Saxon-HE',
308-
'commons-lang3', 'commons-io', 'commons-collections4', 'spring',
307+
'commons-lang3', 'commons-io', 'spring',
309308
'freemarker', 'jdom2', 'argparse4j', 'xmlunit', 'controlsfx',
310309
'annotations', 'spotbugs', 'xmlresolver')
311310

code/src/java/module-info.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
requires org.apache.commons.lang3;
2626
requires org.apache.commons.io;
27-
requires org.apache.commons.collections4;
2827
requires freemarker;
2928
requires org.jdom2;
3029
requires net.sourceforge.argparse4j;

code/src/java/pcgen/cdom/base/CDOMObjectUtilities.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,9 @@
1717
*/
1818
package pcgen.cdom.base;
1919

20-
import java.util.List;
21-
2220
import pcgen.cdom.enumeration.ListKey;
2321
import pcgen.core.PlayerCharacter;
2422

25-
import org.apache.commons.collections4.ListUtils;
26-
2723
/**
2824
* CDOMObjectUtilities is a utility class designed to provide utility methods
2925
* when working with pcgen.cdom.base.CDOMObject Objects
@@ -71,8 +67,7 @@ public static void addAdds(CDOMObject cdo, PlayerCharacter pc)
7167
{
7268
return;
7369
}
74-
List<PersistentTransitionChoice<?>> addList = ListUtils.emptyIfNull(cdo.getListFor(ListKey.ADD));
75-
addList.forEach(tc -> driveChoice(cdo, tc, pc));
70+
cdo.getSafeListFor(ListKey.ADD).forEach(tc -> driveChoice(cdo, tc, pc));
7671
}
7772

7873
public static void removeAdds(CDOMObject cdo, PlayerCharacter pc)
@@ -81,8 +76,7 @@ public static void removeAdds(CDOMObject cdo, PlayerCharacter pc)
8176
{
8277
return;
8378
}
84-
List<PersistentTransitionChoice<?>> addList = ListUtils.emptyIfNull(cdo.getListFor(ListKey.ADD));
85-
addList.forEach(tc -> tc.remove(cdo, pc));
79+
cdo.getSafeListFor(ListKey.ADD).forEach(tc -> tc.remove(cdo, pc));
8680
}
8781

8882
public static void checkRemovals(CDOMObject cdo, PlayerCharacter pc)
@@ -91,8 +85,7 @@ public static void checkRemovals(CDOMObject cdo, PlayerCharacter pc)
9185
{
9286
return;
9387
}
94-
List<PersistentTransitionChoice<?>> removeList = ListUtils.emptyIfNull(cdo.getListFor(ListKey.REMOVE));
95-
removeList.forEach(tc -> driveChoice(cdo, tc, pc));
88+
cdo.getSafeListFor(ListKey.REMOVE).forEach(tc -> driveChoice(cdo, tc, pc));
9689
}
9790

9891
public static void restoreRemovals(CDOMObject cdo, PlayerCharacter pc)
@@ -101,8 +94,7 @@ public static void restoreRemovals(CDOMObject cdo, PlayerCharacter pc)
10194
{
10295
return;
10396
}
104-
List<PersistentTransitionChoice<?>> removeList = ListUtils.emptyIfNull(cdo.getListFor(ListKey.REMOVE));
105-
removeList.forEach(tc -> tc.remove(cdo, pc));
97+
cdo.getSafeListFor(ListKey.REMOVE).forEach(tc -> tc.remove(cdo, pc));
10698
}
10799

108100
private static <T> void driveChoice(CDOMObject cdo, TransitionChoice<T> tc, final PlayerCharacter pc)

code/src/java/pcgen/cdom/formula/VariableChannel.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,13 @@
2020
import java.util.ArrayList;
2121
import java.util.List;
2222
import java.util.Objects;
23-
import java.util.function.BiFunction;
23+
import java.util.function.BiPredicate;
2424

2525
import pcgen.base.formula.base.VariableID;
2626
import pcgen.base.solver.SolverManager;
2727
import pcgen.facade.util.AbstractReferenceFacade;
2828
import pcgen.facade.util.VetoableReferenceFacade;
2929

30-
import org.apache.commons.collections4.CollectionUtils;
31-
3230
/**
3331
* A VariableChannel provides a common mechanism for reading and writing to a
3432
* variable from a system external to the PCGen core.
@@ -66,7 +64,7 @@ public final class VariableChannel<T> extends AbstractReferenceFacade<T>
6664
/**
6765
* The list of functions allowed to veto changes to this variable channel.
6866
*/
69-
private List<BiFunction<T, T, Boolean>> vetoList = null;
67+
private final List<BiPredicate<T, T>> vetoList = new ArrayList<>(2);
7068

7169
/**
7270
* Constructs a new VariableChannel with the given SolverManager,
@@ -115,11 +113,7 @@ public void set(T object)
115113
private boolean checkForVeto(T proposedValue)
116114
{
117115
T oldValue = varStore.get(varID);
118-
return CollectionUtils.emptyIfNull(vetoList)
119-
.stream()
120-
.filter(f -> f.apply(oldValue, proposedValue))
121-
.findAny()
122-
.isPresent();
116+
return vetoList.stream().anyMatch(f -> f.test(oldValue, proposedValue));
123117
}
124118

125119
/**
@@ -172,18 +166,14 @@ public static <T> VariableChannel<T> construct(SolverManager manager,
172166
*
173167
* @return The VariableID for this VariableChannel
174168
*/
175-
public VariableID<?> getVariableID()
169+
public VariableID<T> getVariableID()
176170
{
177171
return varID;
178172
}
179173

180174
@Override
181-
public void addVetoToChannel(BiFunction<T, T, Boolean> function)
175+
public void addVetoToChannel(BiPredicate<T, T> function)
182176
{
183-
if (vetoList == null)
184-
{
185-
vetoList = new ArrayList<>(2);
186-
}
187177
vetoList.add(Objects.requireNonNull(function));
188178
}
189179

code/src/java/pcgen/core/display/VisionDisplay.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import pcgen.core.PlayerCharacter;
2727
import pcgen.core.Vision;
2828

29-
import org.apache.commons.collections4.CollectionUtils;
3029
import org.jetbrains.annotations.NotNull;
3130

3231
public final class VisionDisplay
@@ -42,7 +41,11 @@ public static String getVision(final PlayerCharacter aPC, CDOMObject cdo)
4241
{
4342
return "";
4443
}
45-
Collection<CDOMReference<Vision>> mods = CollectionUtils.emptyIfNull(cdo.getListMods(Vision.VISIONLIST));
44+
Collection<CDOMReference<Vision>> mods = cdo.getListMods(Vision.VISIONLIST);
45+
if (mods == null)
46+
{
47+
return "";
48+
}
4649

4750
StringJoiner visionString = new StringJoiner(";");
4851
mods.stream().flatMap(ref -> ref.getContainedObjects().stream()).map(v -> v.toString(aPC))

code/src/java/pcgen/facade/util/VetoableReferenceFacade.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,25 @@
1515
*/
1616
package pcgen.facade.util;
1717

18-
import java.util.function.BiFunction;
18+
import java.util.function.BiPredicate;
1919

2020
/**
2121
* A VetoableReferenceFacade is a WriteableReferenceFacade that allows functions to veto
2222
* changes to the underlying value
23-
*
23+
*
2424
* @param <T>
2525
* The format of object stored in this VetoableReferenceFacade
2626
*/
2727
public interface VetoableReferenceFacade<T> extends WriteableReferenceFacade<T>
2828
{
2929

3030
/**
31-
* Adds a BiFunction to determine if a change should be vetoed. Returning TRUE results
31+
* Adds a BiPredicate to determine if a change should be vetoed. Returning TRUE results
3232
* in an item being vetoed.
33-
*
33+
*
3434
* @param function
3535
* The function to be added to determine if a change will be vetoed
3636
*/
37-
void addVetoToChannel(BiFunction<T, T, Boolean> function);
37+
void addVetoToChannel(BiPredicate<T, T> function);
3838

3939
}

code/src/java/pcgen/gui3/dialog/ExportDialogController.java

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import java.util.Arrays;
2828
import java.util.List;
2929
import java.util.Optional;
30-
import java.util.stream.Collectors;
3130

3231
import javax.swing.JCheckBox;
3332

@@ -58,7 +57,6 @@
5857
import javafx.scene.control.ListView;
5958
import javafx.scene.control.ProgressBar;
6059
import javafx.stage.FileChooser;
61-
import org.apache.commons.collections4.IteratorUtils;
6260
import org.apache.commons.lang3.StringUtils;
6361

6462
/**
@@ -67,6 +65,8 @@
6765
*/
6866
public class ExportDialogController
6967
{
68+
private static final String EXPORT_DIALOG_CONTEXT = "ExportDialog";
69+
7070
@FXML
7171
private ComboBox<CharacterFacade> selectCharacterBox;
7272
@FXML
@@ -144,7 +144,7 @@ private static void doExportEntireParty(String sheetFilterPath, URI template, bo
144144
}
145145
else
146146
{
147-
PropertyContext context = UIPropertyContext.createContext("ExportDialog");
147+
PropertyContext context = UIPropertyContext.createContext(EXPORT_DIALOG_CONTEXT);
148148
context.setProperty(HTML_EXPORT_DIR_PROP, outFile.getParent());
149149
SettingsHandler.setSelectedPartyHTMLOutputSheet(templateAsFile.getAbsolutePath());
150150
BatchExporter.exportPartyToNonPDF(party, outFile, templateAsFile);
@@ -283,14 +283,7 @@ public void changed(final ObservableValue<? extends Boolean> observable,
283283
final Boolean newValue)
284284
{
285285
templateSelect.getSelectionModel().clearSelection();
286-
if (newValue == true)
287-
{
288-
selectCharacterBox.setDisable(true);
289-
}
290-
else
291-
{
292-
selectCharacterBox.setDisable(false);
293-
}
286+
selectCharacterBox.setDisable(newValue);
294287
refreshFiles(exportSheetType.getSelectionModel().getSelectedItem(), entireParty.isSelected());
295288
}
296289
}
@@ -302,20 +295,14 @@ public void changed(final ObservableValue<? extends URI> observable,
302295
final URI oldValue,
303296
final URI newValue)
304297
{
305-
if (newValue != null)
306-
{
307-
doExport.setDisable(false);
308-
} else
309-
{
310-
doExport.setDisable(true);
311-
}
298+
doExport.setDisable(newValue == null);
312299
}
313300
}
314301

315302
private void refreshFiles(ExportUtilities.SheetFilter sheetFilter, boolean exportParty)
316303
{
317304
URI[] validFiles = ExportUtilities.getValidFiles(allTemplates, sheetFilter, exportParty);
318-
List<URI> validFilesAsList = Arrays.stream(validFiles).collect(Collectors.toList());
305+
List<URI> validFilesAsList = Arrays.stream(validFiles).toList();
319306
ObservableList<URI> observableTemplates = FXCollections.observableList(validFilesAsList);
320307
templateSelect.itemsProperty().setValue(observableTemplates);
321308
}
@@ -327,7 +314,7 @@ public void changed(final ObservableValue<? extends ExportUtilities.SheetFilter>
327314
final ExportUtilities.SheetFilter oldValue,
328315
final ExportUtilities.SheetFilter newValue)
329316
{
330-
PropertyContext context = UIPropertyContext.createContext("ExportDialog");
317+
PropertyContext context = UIPropertyContext.createContext(EXPORT_DIALOG_CONTEXT);
331318
context.setProperty(UIPropertyContext.DEFAULT_OS_TYPE,
332319
exportSheetType.getSelectionModel().getSelectedItem().toString());
333320
refreshFiles(newValue, entireParty.isSelected());
@@ -345,19 +332,19 @@ private void doOnClose(final ActionEvent actionEvent)
345332
void initialize()
346333
{
347334
PartyFacade characters = CharacterManager.getCharacters();
348-
ObservableList<CharacterFacade> observableList =
349-
FXCollections.observableList(IteratorUtils.toList(characters.iterator()));
335+
ObservableList<CharacterFacade> observableList = FXCollections.observableArrayList();
336+
characters.forEach(observableList::add);
350337
selectCharacterBox.setItems(observableList);
351338
// todo: maybe select "current" character pcgenFrame.getSelectedCharacterRef() ???
352339
selectCharacterBox.getSelectionModel().select(0);
353340
entireParty.selectedProperty().addListener(new PartyCheckboxChangeListener());
354341
templateSelect.getSelectionModel().selectedItemProperty().addListener(new TemplateSelectionListener());
355342
List<ExportUtilities.SheetFilter> sheetFilterValues = Arrays.stream(
356-
ExportUtilities.SheetFilter.values()).collect(Collectors.toList());
343+
ExportUtilities.SheetFilter.values()).toList();
357344
exportSheetType.setItems(FXCollections.observableList(sheetFilterValues));
358345
exportSheetType.getSelectionModel().selectedItemProperty().addListener(new ExportSheetTypeSelectionListener());
359346
exportSheetType.getSelectionModel().select(0);
360-
PropertyContext context = UIPropertyContext.createContext("ExportDialog");
347+
PropertyContext context = UIPropertyContext.createContext(EXPORT_DIALOG_CONTEXT);
361348
String defaultOSType = context.getProperty(UIPropertyContext.DEFAULT_OS_TYPE);
362349
if (defaultOSType != null)
363350
{

0 commit comments

Comments
 (0)