Summary
The SimpleSelector and CompoundSelector will be deprecated for removal to allow for future enhancements (see #JDK-8322964), and a new method will be introduced in their superclass Selector to cover a gap in the Selector API.
Problem
SimpleSelector and CompoundSelector have several hard to reach public methods intended for use by FX internals. Hard to reach because the only way to access them is to obtain a Selector (which is their superclass, and intended to be public) and then cast to a more specific type.
This casting happens only in two places, in FX itself and in Scene Builder. Scene Builder is basically working around what could be considered a gap in the API of Selector (obtaining the style class names of a selector lacks API on Selector but it is available after casting to a specific type).
The problem with this construction is this setup makes the SimpleSelector and CompoundSelector classes hard to evolve, because technically they're public API, but were never intended as such. This is corroborated by the fact they cannot be constructed directly (package private constructor), have public methods that are of questionable value for users, and are not directly accepted or returned as types anywhere in the rest of FX (only Selector is ever referred to).
The motivation to improve this is a recent potential performance optimization described in https://bugs.openjdk.org/browse/JDK-8322964 -- this would require a new public method in SimpleSelector, which then unfortunately would become part of the exported API. To avoid this and to allow for the optimization in a future release, we are taking the steps to move these classes to internal packages. We're not doing this lightly, similar discussions were held in the past when other problems were addressed related to the selector classes.
Solution
The full solution will consist of several parts. The first part being to deprecate the SimpleSelector and CompoundSelector classes for removal, and to address the gap in the API of Selector by introducing a new method named getStyleClassNames to allow Scene Builder easy access to these without needing to cast to a specific type.
The next step, to be performed in the next release, is to make the Selector superclass sealed permitting only the (moved to internal) types SimpleSelector and CompoundSelector. Although Selector is not final, it has a package private constructor allowing this to be done in a binary compatible fashion.
As part of this process, some of the code in SimpleSelector and CompoundSelector that is accessing package private state in javafx.css will be moved directly to Selector.
The full process for this next step was discussed here: https://github.com/openjdk/jfx/pull/1316#discussion_r1451738916
Specification
CompoundSelector changes:
--- a/modules/javafx.graphics/src/main/java/javafx/css/CompoundSelector.java
+++ b/modules/javafx.graphics/src/main/java/javafx/css/CompoundSelector.java
@@ -60,7 +62,9 @@ import java.util.Set;
* <code>Combinator.DESCENDANT</code>.
*
* @since 9
+ * @deprecated This class was exposed erroneously and will be removed in a future version
*/
+@Deprecated(since = "23", forRemoval = true)
final public class CompoundSelector extends Selector {
private final List<SimpleSelector> selectors;
@@ -97,6 +101,14 @@ final public class CompoundSelector extends Selector {
: Collections.EMPTY_LIST;
}
+ @Override
+ public Set<String> getStyleClassNames() {
+ return selectors.stream()
+ .map(Selector::getStyleClassNames)
+ .flatMap(Collection::stream)
+ .collect(Collectors.toUnmodifiableSet());
+ }
+
@Override public Match createMatch() {
final PseudoClassState allPseudoClasses = new PseudoClassState();
int idCount = 0;
Selector changes:
--- a/modules/javafx.graphics/src/main/java/javafx/css/Selector.java
+++ b/modules/javafx.graphics/src/main/java/javafx/css/Selector.java
@@ -91,6 +91,15 @@ abstract public class Selector {
return ordinal;
}
+ /**
+ * Gets the immutable set of style class names of this Selector.
+ *
+ * @return an immutable set with style class names, never {@code null},
+ * or contains {@code null}s, but can be empty
+ * @since 23
+ */
+ public abstract Set<String> getStyleClassNames();
+
/**
* Creates a {@code Match}.
*
SimpleSelector changes:
--- a/modules/javafx.graphics/src/main/java/javafx/css/SimpleSelector.java
+++ b/modules/javafx.graphics/src/main/java/javafx/css/SimpleSelector.java
@@ -49,7 +50,9 @@ import static javafx.geometry.NodeOrientation.RIGHT_TO_LEFT;
* A simple selector which behaves according to the CSS standard.
*
* @since 9
+ * @deprecated This class was exposed erroneously and will be removed in a future version
*/
+@Deprecated(since = "23", forRemoval = true)
final public class SimpleSelector extends Selector {
/**
@@ -192,6 +195,13 @@ final public class SimpleSelector extends Selector {
}
+ @Override
+ public Set<String> getStyleClassNames() {
+ return styleClassSet.stream()
+ .map(StyleClass::getStyleClassName)
+ .collect(Collectors.toUnmodifiableSet());
+ }
+
@Override public Match createMatch() {
final int idCount = (matchOnId) ? 1 : 0;
int styleClassCount = styleClassSet.size();
- csr of
-
JDK-8324182 Deprecate for removal SimpleSelector and CompoundSelector classes
-
- Resolved
-