2323import java .util .Collections ;
2424import java .util .List ;
2525import java .util .Locale ;
26- import java .util .Objects ;
2726
2827/**
2928 * This abstract class defining basic {@link Decision} used during shard
3029 * allocation process.
3130 *
3231 * @see AllocationDecider
3332 */
34- public abstract class Decision implements ToXContent , Writeable {
33+ public sealed interface Decision extends ToXContent , Writeable permits Decision . Single , Decision . Multi {
3534
36- public static final Decision ALWAYS = new Single (Type .YES );
37- public static final Decision YES = new Single (Type .YES );
38- public static final Decision NO = new Single (Type .NO );
39- public static final Decision THROTTLE = new Single (Type .THROTTLE );
35+ Single ALWAYS = new Single (Type .YES );
36+ Single YES = new Single (Type .YES );
37+ Single NO = new Single (Type .NO );
38+ Single THROTTLE = new Single (Type .THROTTLE );
4039
4140 /**
4241 * Creates a simple decision
@@ -46,40 +45,69 @@ public abstract class Decision implements ToXContent, Writeable {
4645 * @param explanationParams additional parameters for the decision
4746 * @return new {@link Decision} instance
4847 */
49- public static Decision single (Type type , @ Nullable String label , @ Nullable String explanation , @ Nullable Object ... explanationParams ) {
48+ static Decision single (Type type , @ Nullable String label , @ Nullable String explanation , @ Nullable Object ... explanationParams ) {
5049 return new Single (type , label , explanation , explanationParams );
5150 }
5251
53- public static Decision readFrom (StreamInput in ) throws IOException {
52+ static Decision readFrom (StreamInput in ) throws IOException {
5453 // Determine whether to read a Single or Multi Decision
5554 if (in .readBoolean ()) {
5655 Multi result = new Multi ();
5756 int decisionCount = in .readVInt ();
5857 for (int i = 0 ; i < decisionCount ; i ++) {
59- Decision s = readFrom (in );
60- result .decisions .add (s );
58+ var flag = in .readBoolean ();
59+ assert flag == false : "nested multi decision is not permitted" ;
60+ var single = readSingleFrom (in );
61+ result .decisions .add (single );
6162 }
6263 return result ;
6364 } else {
64- final Type type = Type .readFrom (in );
65- final String label = in .readOptionalString ();
66- final String explanation = in .readOptionalString ();
67- if (label == null && explanation == null ) {
68- return switch (type ) {
69- case YES -> YES ;
70- case THROTTLE -> THROTTLE ;
71- case NO -> NO ;
72- };
73- }
74- return new Single (type , label , explanation );
65+ return readSingleFrom (in );
66+ }
67+ }
68+
69+ private static Single readSingleFrom (StreamInput in ) throws IOException {
70+ final Type type = Type .readFrom (in );
71+ final String label = in .readOptionalString ();
72+ final String explanation = in .readOptionalString ();
73+ if (label == null && explanation == null ) {
74+ return switch (type ) {
75+ case YES -> YES ;
76+ case THROTTLE -> THROTTLE ;
77+ case NO -> NO ;
78+ };
7579 }
80+ return new Single (type , label , explanation );
7681 }
7782
83+ /**
84+ * Get the {@link Type} of this decision
85+ * @return {@link Type} of this decision
86+ */
87+ Type type ();
88+
89+ /**
90+ * Get the description label for this decision.
91+ */
92+ @ Nullable
93+ String label ();
94+
95+ /**
96+ * Get the explanation for this decision.
97+ */
98+ @ Nullable
99+ String getExplanation ();
100+
101+ /**
102+ * Return the list of all decisions that make up this decision
103+ */
104+ List <Decision > getDecisions ();
105+
78106 /**
79107 * This enumeration defines the
80108 * possible types of decisions
81109 */
82- public enum Type implements Writeable {
110+ enum Type implements Writeable {
83111 YES (1 ),
84112 THROTTLE (2 ),
85113 NO (0 );
@@ -110,45 +138,22 @@ public boolean higherThan(Type other) {
110138 return false ;
111139 } else if (other == NO ) {
112140 return true ;
113- } else if (other == THROTTLE && this == YES ) {
114- return true ;
115- }
116- return false ;
141+ } else return other == THROTTLE && this == YES ;
117142 }
118143
119- }
120-
121- /**
122- * Get the {@link Type} of this decision
123- * @return {@link Type} of this decision
124- */
125- public abstract Type type ();
126-
127- /**
128- * Get the description label for this decision.
129- */
130- @ Nullable
131- public abstract String label ();
132-
133- /**
134- * Get the explanation for this decision.
135- */
136- @ Nullable
137- public abstract String getExplanation ();
144+ /**
145+ * @return lowest decision by precedence NO->THROTTLE->YES
146+ */
147+ public static Type min (Type a , Type b ) {
148+ return a .higherThan (b ) ? b : a ;
149+ }
138150
139- /**
140- * Return the list of all decisions that make up this decision
141- */
142- public abstract List <Decision > getDecisions ();
151+ }
143152
144153 /**
145154 * Simple class representing a single decision
146155 */
147- public static class Single extends Decision implements ToXContentObject {
148- private final Type type ;
149- private final String label ;
150- private final String explanationString ;
151-
156+ record Single (Type type , String label , String explanationString ) implements Decision , ToXContentObject {
152157 /**
153158 * Creates a new {@link Single} decision of a given type
154159 * @param type {@link Type} of the decision
@@ -165,24 +170,13 @@ private Single(Type type) {
165170 * @param explanationParams A set of additional parameters
166171 */
167172 public Single (Type type , @ Nullable String label , @ Nullable String explanation , @ Nullable Object ... explanationParams ) {
168- this .type = type ;
169- this .label = label ;
170- if (explanationParams != null && explanationParams .length > 0 ) {
171- this .explanationString = String .format (Locale .ROOT , explanation , explanationParams );
172- } else {
173- this .explanationString = explanation ;
174- }
175- }
176-
177- @ Override
178- public Type type () {
179- return this .type ;
180- }
181-
182- @ Override
183- @ Nullable
184- public String label () {
185- return this .label ;
173+ this (
174+ type ,
175+ label ,
176+ explanationParams != null && explanationParams .length > 0
177+ ? String .format (Locale .ROOT , explanation , explanationParams )
178+ : explanation
179+ );
186180 }
187181
188182 @ Override
@@ -199,29 +193,6 @@ public String getExplanation() {
199193 return this .explanationString ;
200194 }
201195
202- @ Override
203- public boolean equals (Object object ) {
204- if (this == object ) {
205- return true ;
206- }
207-
208- if (object == null || getClass () != object .getClass ()) {
209- return false ;
210- }
211-
212- Decision .Single s = (Decision .Single ) object ;
213- return this .type == s .type && Objects .equals (label , s .label ) && Objects .equals (explanationString , s .explanationString );
214- }
215-
216- @ Override
217- public int hashCode () {
218- int result = type .hashCode ();
219- result = 31 * result + (label == null ? 0 : label .hashCode ());
220- String explanationStr = explanationString ;
221- result = 31 * result + (explanationStr == null ? 0 : explanationStr .hashCode ());
222- return result ;
223- }
224-
225196 @ Override
226197 public String toString () {
227198 if (explanationString != null ) {
@@ -254,17 +225,20 @@ public void writeTo(StreamOutput out) throws IOException {
254225 /**
255226 * Simple class representing a list of decisions
256227 */
257- public static class Multi extends Decision implements ToXContentFragment {
228+ record Multi ( List < Single > decisions ) implements Decision , ToXContentFragment {
258229
259- private final List <Decision > decisions = new ArrayList <>();
230+ public Multi () {
231+ this (new ArrayList <>());
232+ }
260233
261234 /**
262235 * Add a decision to this {@link Multi}decision instance
263236 * @param decision {@link Decision} to add
264237 * @return {@link Multi}decision instance with the given decision added
265238 */
266239 public Multi add (Decision decision ) {
267- decisions .add (decision );
240+ assert decision instanceof Single ;
241+ decisions .add ((Single ) decision );
268242 return this ;
269243 }
270244
@@ -300,26 +274,6 @@ public List<Decision> getDecisions() {
300274 return Collections .unmodifiableList (this .decisions );
301275 }
302276
303- @ Override
304- public boolean equals (final Object object ) {
305- if (this == object ) {
306- return true ;
307- }
308-
309- if (object == null || getClass () != object .getClass ()) {
310- return false ;
311- }
312-
313- final Decision .Multi m = (Decision .Multi ) object ;
314-
315- return this .decisions .equals (m .decisions );
316- }
317-
318- @ Override
319- public int hashCode () {
320- return 31 * decisions .hashCode ();
321- }
322-
323277 @ Override
324278 public String toString () {
325279 StringBuilder sb = new StringBuilder ();
0 commit comments