2323import java .util .Collections ;
2424import java .util .List ;
2525import java .util .Locale ;
26- import java .util .Objects ;
2726
2827/**
29- * This abstract class defining basic {@link Decision} used during shard
30- * allocation process.
28+ * A {@link Decision} used during shard allocation process.
3129 *
3230 * @see AllocationDecider
3331 */
34- public abstract class Decision implements ToXContent , Writeable {
32+ public sealed interface Decision extends ToXContent , Writeable permits Decision . Single , Decision . Multi {
3533
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 );
34+ Single ALWAYS = new Single (Type .YES );
35+ Single YES = new Single (Type .YES );
36+ Single NO = new Single (Type .NO );
37+ Single THROTTLE = new Single (Type .THROTTLE );
4038
4139 /**
4240 * Creates a simple decision
@@ -46,40 +44,69 @@ public abstract class Decision implements ToXContent, Writeable {
4644 * @param explanationParams additional parameters for the decision
4745 * @return new {@link Decision} instance
4846 */
49- public static Decision single (Type type , @ Nullable String label , @ Nullable String explanation , @ Nullable Object ... explanationParams ) {
47+ static Decision single (Type type , @ Nullable String label , @ Nullable String explanation , @ Nullable Object ... explanationParams ) {
5048 return new Single (type , label , explanation , explanationParams );
5149 }
5250
53- public static Decision readFrom (StreamInput in ) throws IOException {
51+ static Decision readFrom (StreamInput in ) throws IOException {
5452 // Determine whether to read a Single or Multi Decision
5553 if (in .readBoolean ()) {
5654 Multi result = new Multi ();
5755 int decisionCount = in .readVInt ();
5856 for (int i = 0 ; i < decisionCount ; i ++) {
59- Decision s = readFrom (in );
60- result .decisions .add (s );
57+ var flag = in .readBoolean ();
58+ assert flag == false : "nested multi decision is not permitted" ;
59+ var single = readSingleFrom (in );
60+ result .decisions .add (single );
6161 }
6262 return result ;
6363 } 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 );
64+ return readSingleFrom (in );
65+ }
66+ }
67+
68+ private static Single readSingleFrom (StreamInput in ) throws IOException {
69+ final Type type = Type .readFrom (in );
70+ final String label = in .readOptionalString ();
71+ final String explanation = in .readOptionalString ();
72+ if (label == null && explanation == null ) {
73+ return switch (type ) {
74+ case YES -> YES ;
75+ case THROTTLE -> THROTTLE ;
76+ case NO -> NO ;
77+ };
7578 }
79+ return new Single (type , label , explanation );
7680 }
7781
82+ /**
83+ * Get the {@link Type} of this decision
84+ * @return {@link Type} of this decision
85+ */
86+ Type type ();
87+
88+ /**
89+ * Get the description label for this decision.
90+ */
91+ @ Nullable
92+ String label ();
93+
94+ /**
95+ * Get the explanation for this decision.
96+ */
97+ @ Nullable
98+ String getExplanation ();
99+
100+ /**
101+ * Return the list of all decisions that make up this decision
102+ */
103+ List <Decision > getDecisions ();
104+
78105 /**
79106 * This enumeration defines the
80107 * possible types of decisions
81108 */
82- public enum Type implements Writeable {
109+ enum Type implements Writeable {
83110 YES (1 ),
84111 THROTTLE (2 ),
85112 NO (0 );
@@ -110,45 +137,22 @@ public boolean higherThan(Type other) {
110137 return false ;
111138 } else if (other == NO ) {
112139 return true ;
113- } else if (other == THROTTLE && this == YES ) {
114- return true ;
115- }
116- return false ;
140+ } else return other == THROTTLE && this == YES ;
117141 }
118142
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 ();
143+ /**
144+ * @return lowest decision by precedence NO->THROTTLE->YES
145+ */
146+ public static Type min (Type a , Type b ) {
147+ return a .higherThan (b ) ? b : a ;
148+ }
138149
139- /**
140- * Return the list of all decisions that make up this decision
141- */
142- public abstract List <Decision > getDecisions ();
150+ }
143151
144152 /**
145153 * Simple class representing a single decision
146154 */
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-
155+ record Single (Type type , String label , String explanationString ) implements Decision , ToXContentObject {
152156 /**
153157 * Creates a new {@link Single} decision of a given type
154158 * @param type {@link Type} of the decision
@@ -165,24 +169,13 @@ private Single(Type type) {
165169 * @param explanationParams A set of additional parameters
166170 */
167171 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 ;
172+ this (
173+ type ,
174+ label ,
175+ explanationParams != null && explanationParams .length > 0
176+ ? String .format (Locale .ROOT , explanation , explanationParams )
177+ : explanation
178+ );
186179 }
187180
188181 @ Override
@@ -199,29 +192,6 @@ public String getExplanation() {
199192 return this .explanationString ;
200193 }
201194
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-
225195 @ Override
226196 public String toString () {
227197 if (explanationString != null ) {
@@ -254,17 +224,20 @@ public void writeTo(StreamOutput out) throws IOException {
254224 /**
255225 * Simple class representing a list of decisions
256226 */
257- public static class Multi extends Decision implements ToXContentFragment {
227+ record Multi ( List < Single > decisions ) implements Decision , ToXContentFragment {
258228
259- private final List <Decision > decisions = new ArrayList <>();
229+ public Multi () {
230+ this (new ArrayList <>());
231+ }
260232
261233 /**
262234 * Add a decision to this {@link Multi}decision instance
263235 * @param decision {@link Decision} to add
264236 * @return {@link Multi}decision instance with the given decision added
265237 */
266238 public Multi add (Decision decision ) {
267- decisions .add (decision );
239+ assert decision instanceof Single ;
240+ decisions .add ((Single ) decision );
268241 return this ;
269242 }
270243
@@ -300,26 +273,6 @@ public List<Decision> getDecisions() {
300273 return Collections .unmodifiableList (this .decisions );
301274 }
302275
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-
323276 @ Override
324277 public String toString () {
325278 StringBuilder sb = new StringBuilder ();
0 commit comments