/
OrderAction.java
414 lines (379 loc) · 14.5 KB
/
OrderAction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
/*
* Copyright 2015-2018 Austin Keener & Michael Ritter & Florian Spieß
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.dv8tion.jda.core.requests.restaction.order;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.requests.Request;
import net.dv8tion.jda.core.requests.Response;
import net.dv8tion.jda.core.requests.RestAction;
import net.dv8tion.jda.core.requests.Route;
import net.dv8tion.jda.core.utils.Checks;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Extension of {@link net.dv8tion.jda.core.requests.RestAction RestAction} - Type: Void
* that allows to modify the order of entities provided as an {@link java.util.ArrayList ArrayList}.
* <br>This action contains a List or entities for the specified type {@code T} which
* can be moved within the bounds but not removed, nor can any new entities be added.
*
* @param <T>
* The entity type for the {@link java.util.List List} of entities
* contained in the OrderAction's orderList
* @param <M>
* The extension implementing the abstract operations of this OrderAction,
* this will be important for chaining convenience as it returns the specific
* implementation rather than a mask of this class. It allows us to implement
* chaining operations in this class instead of having to implement it in every
* inheriting class!
*
* @since 3.0
*/
public abstract class OrderAction<T, M extends OrderAction<T, M>> extends RestAction<Void>
{
protected final JDA api;
protected final List<T> orderList;
protected final boolean ascendingOrder;
protected int selectedPosition = -1;
/**
* Creates a new OrderAction instance
*
* @param api
* JDA instance which is associated with the entities contained
* in the order list
* @param route
* The {@link net.dv8tion.jda.core.requests.Route.CompiledRoute CompiledRoute}
* which is provided to the {@link RestAction#RestAction(JDA, Route.CompiledRoute, okhttp3.RequestBody) RestAction Constructor}
*/
public OrderAction(JDA api, Route.CompiledRoute route)
{
this(api, true, route);
}
/**
* Creates a new OrderAction instance
*
* @param api
* JDA instance which is associated with the entities contained
* in the order list
* @param ascendingOrder
* Whether or not the order of items should be ascending
* @param route
* The {@link net.dv8tion.jda.core.requests.Route.CompiledRoute CompiledRoute}
* which is provided to the {@link RestAction#RestAction(JDA, Route.CompiledRoute, okhttp3.RequestBody) RestAction Constructor}
*/
public OrderAction(JDA api, boolean ascendingOrder, Route.CompiledRoute route)
{
super(api, route);
this.api = api;
this.orderList = new ArrayList<>();
this.ascendingOrder = ascendingOrder;
}
/**
* The corresponding JDA instance for the entities of
* this OrderAction instance
*
* @return The corresponding JDA instance
*/
public JDA getJDA()
{
return api;
}
/**
* Immutable List representing the currently selected order
* of entities in this OrderAction instance
*
* @return Immutable List representing the current order
*/
public List<T> getCurrentOrder()
{
return Collections.unmodifiableList(orderList);
}
/**
* Selects a new current entity at the specified index
* <br>This index is in correlation to the {@link #getCurrentOrder() current order}
*
* @param selectedPosition
* The index for the new position that will be in focus for all modification
* operations
*
* @throws java.lang.IllegalArgumentException
* If the provided position is out-of-bounds
*
* @return The current OrderAction sub-implementation instance
*
* @see #getSelectedPosition()
* @see #getSelectedEntity()
*/
public M selectPosition(int selectedPosition)
{
Checks.notNegative(selectedPosition, "Provided selectedPosition");
Checks.check(selectedPosition < orderList.size(), "Provided selectedPosition is too big and is out of bounds. selectedPosition: " + selectedPosition);
this.selectedPosition = selectedPosition;
return (M) this;
}
/**
* Selects a new current entity based on the index of
* the specified entity in the {@link #getCurrentOrder() current order}
* <br>This is a convenience function that uses {@link #selectPosition(int)} internally
*
* @param selectedEntity
* The entity for the new position that will be in focus for all modification
* operations
*
* @return The current OrderAction sub-implementation instance
*
* @see #selectPosition(int)
* @see #getSelectedPosition()
* @see #getSelectedEntity()
*/
public M selectPosition(T selectedEntity)
{
Checks.notNull(selectedEntity, "Channel");
validateInput(selectedEntity);
return selectPosition(orderList.indexOf(selectedEntity));
}
/**
* The currently selected position
* that is in focus for all modification operations of this OrderAction instance
*
* @return The currently selected index, or -1 if no position has been selected yet
*/
public int getSelectedPosition()
{
return selectedPosition;
}
/**
* The entity which is currently at the {@link #getSelectedPosition() selected position}
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
*
* @return The currently selected entity
*/
public T getSelectedEntity()
{
if (selectedPosition == -1)
throw new IllegalStateException("No position has been selected yet");
return orderList.get(selectedPosition);
}
/**
* Moves the currently selected entity {@code amount} positions <b>UP</b>
* in order by pushing all entities down by one position.
*
* @param amount
* The amount of positions that should be moved
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* @throws java.lang.IllegalArgumentException
* If the specified amount would cause the entity to go out-of-bounds
*
* @return The current OrderAction sub-implementation instance
*
* @see #moveTo(int)
*/
public M moveUp(int amount)
{
Checks.notNegative(amount, "Provided amount");
if (selectedPosition == -1)
throw new IllegalStateException("Cannot move until an item has been selected. Use #selectPosition first.");
if (ascendingOrder)
{
Checks.check(selectedPosition - amount >= 0,
"Amount provided to move up is too large and would be out of bounds." +
"Selected position: " + selectedPosition + " Amount: " + amount + " Largest Position: " + orderList.size());
}
else
{
Checks.check(selectedPosition + amount < orderList.size(),
"Amount provided to move up is too large and would be out of bounds." +
"Selected position: " + selectedPosition + " Amount: " + amount + " Largest Position: " + orderList.size());
}
if (ascendingOrder)
return moveTo(selectedPosition - amount);
else
return moveTo(selectedPosition + amount);
}
/**
* Moves the currently selected entity {@code amount} positions <b>DOWN</b>
* in order by pushing all entities up by one position.
*
* @param amount
* The amount of positions that should be moved
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* @throws java.lang.IllegalArgumentException
* If the specified amount would cause the entity to go out-of-bounds
*
* @return The current OrderAction sub-implementation instance
*
* @see #moveTo(int)
*/
public M moveDown(int amount)
{
Checks.notNegative(amount, "Provided amount");
if (selectedPosition == -1)
throw new IllegalStateException("Cannot move until an item has been selected. Use #selectPosition first.");
if (ascendingOrder)
{
Checks.check(selectedPosition + amount < orderList.size(),
"Amount provided to move down is too large and would be out of bounds." +
"Selected position: " + selectedPosition + " Amount: " + amount + " Largest Position: " + orderList.size());
}
else
{
Checks.check(selectedPosition - amount >= orderList.size(),
"Amount provided to move down is too large and would be out of bounds." +
"Selected position: " + selectedPosition + " Amount: " + amount + " Largest Position: " + orderList.size());
}
if (ascendingOrder)
return moveTo(selectedPosition + amount);
else
return moveTo(selectedPosition - amount);
}
/**
* Moves the currently selected entity to the specified
* position (0 based index). All entities are moved in the
* direction of the left <i>hole</i> to fill the gap.
*
* @param position
* The new not-negative position for the currently selected entity
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* @throws java.lang.IllegalArgumentException
* If the specified position is out-of-bounds
*
* @return The current OrderAction sub-implementation instance
*
* @see #moveDown(int)
* @see #moveUp(int)
*/
public M moveTo(int position)
{
Checks.notNegative(position, "Provided position");
Checks.check(position < orderList.size(), "Provided position is too big and is out of bounds.");
T selectedItem = orderList.remove(selectedPosition);
orderList.add(position, selectedItem);
return (M) this;
}
/**
* Swaps the currently selected entity with the entity located
* at the specified position. No other entities are affected by this operation.
*
* @param swapPosition
* 0 based index of target position
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* @throws java.lang.IllegalArgumentException
* If the specified position is out-of-bounds
*
* @return The current OrderAction sub-implementation instance
*/
public M swapPosition(int swapPosition)
{
Checks.notNegative(swapPosition, "Provided swapPosition");
Checks.check(swapPosition < orderList.size(), "Provided swapPosition is too big and is out of bounds. swapPosition: "
+ swapPosition);
T selectedItem = orderList.get(selectedPosition);
T swapItem = orderList.get(swapPosition);
orderList.set(swapPosition, selectedItem);
orderList.set(selectedPosition, swapItem);
return (M) this;
}
/**
* Swaps the currently selected entity with the specified entity.
* No other entities are affected by this operation.
*
* @param swapEntity
* Target entity to switch positions with
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* @throws java.lang.IllegalArgumentException
* If the specified position is out-of-bounds,
* or if the target entity is {@code null} or not
* available in this order action implementation
*
* @return The current OrderAction sub-implementation instance
*
* @see #swapPosition(int)
*/
public M swapPosition(T swapEntity)
{
Checks.notNull(swapEntity, "Provided swapEntity");
validateInput(swapEntity);
return swapPosition(orderList.indexOf(swapEntity));
}
/**
* Reverses the {@link #getCurrentOrder() current order} by using
* {@link java.util.Collections#reverse(java.util.List) Collections.reverse(orderList)}
*
* @return The current OrderAction sub-implementation instance
*
* @see java.util.Collections#reverse(java.util.List)
*/
public M reverseOrder()
{
Collections.reverse(this.orderList);
return (M) this;
}
/**
* Shuffles the {@link #getCurrentOrder() current order} by using
* {@link java.util.Collections#shuffle(java.util.List) Collections.shuffle(orderList)}
*
* @return The current OrderAction sub-implementation instance
*
* @see java.util.Collections#shuffle(java.util.List)
*/
public M shuffleOrder()
{
Collections.shuffle(this.orderList);
return (M) this;
}
/**
* Sorts the {@link #getCurrentOrder() current order} based on
* the specified {@link java.util.Comparator Comparator}.
* <br>Using {@link java.util.ArrayList#sort(java.util.Comparator) ArrayList.sort(comparator)}
*
* @param comparator
* Comparator used to sort the current order
*
* @throws java.lang.IllegalArgumentException
* If the specified comparator is {@code null}
*
* @return The current OrderAction sub-implementation instance
*
* @see java.util.ArrayList#sort(java.util.Comparator)
*/
public M sortOrder(final Comparator<T> comparator)
{
Checks.notNull(comparator, "Provided comparator");
this.orderList.sort(comparator);
return (M) this;
}
@Override
protected void handleResponse(Response response, Request<Void> request)
{
if (response.isOk())
request.onSuccess(null);
else
request.onFailure(response);
}
protected abstract void validateInput(T entity);
}