00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 package com.realtime.crossfire.jxclient.skin.io;
00023
00024 import com.realtime.crossfire.jxclient.gui.button.GUISelectable;
00025 import com.realtime.crossfire.jxclient.gui.commandlist.GUICommand;
00026 import com.realtime.crossfire.jxclient.gui.commands.AccountCreateCharacterCommand;
00027 import com.realtime.crossfire.jxclient.gui.commands.AccountCreateCommand;
00028 import com.realtime.crossfire.jxclient.gui.commands.AccountLinkCharacterCommand;
00029 import com.realtime.crossfire.jxclient.gui.commands.AccountLoginCommand;
00030 import com.realtime.crossfire.jxclient.gui.commands.AccountPasswordCommand;
00031 import com.realtime.crossfire.jxclient.gui.commands.AccountPlayCharacterCommand;
00032 import com.realtime.crossfire.jxclient.gui.commands.CommandType;
00033 import com.realtime.crossfire.jxclient.gui.commands.ConnectCommand;
00034 import com.realtime.crossfire.jxclient.gui.commands.DialogCloseCommand;
00035 import com.realtime.crossfire.jxclient.gui.commands.DialogOpenCommand;
00036 import com.realtime.crossfire.jxclient.gui.commands.DialogToggleCommand;
00037 import com.realtime.crossfire.jxclient.gui.commands.DisconnectCommand;
00038 import com.realtime.crossfire.jxclient.gui.commands.ExecSelectionCommand;
00039 import com.realtime.crossfire.jxclient.gui.commands.ExecuteElementCommand;
00040 import com.realtime.crossfire.jxclient.gui.commands.HideCommand;
00041 import com.realtime.crossfire.jxclient.gui.commands.MetaCommand;
00042 import com.realtime.crossfire.jxclient.gui.commands.MoveSelectionCommand;
00043 import com.realtime.crossfire.jxclient.gui.commands.PrintCommand;
00044 import com.realtime.crossfire.jxclient.gui.commands.QuitCommand;
00045 import com.realtime.crossfire.jxclient.gui.commands.ScrollCommand;
00046 import com.realtime.crossfire.jxclient.gui.commands.ScrollListCommand;
00047 import com.realtime.crossfire.jxclient.gui.commands.ScrollNeverCommand;
00048 import com.realtime.crossfire.jxclient.gui.commands.ScrollNextCommand;
00049 import com.realtime.crossfire.jxclient.gui.commands.ScrollResetCommand;
00050 import com.realtime.crossfire.jxclient.gui.commands.SelectCommand;
00051 import com.realtime.crossfire.jxclient.gui.commands.ShowCommand;
00052 import com.realtime.crossfire.jxclient.gui.commands.StartCommand;
00053 import com.realtime.crossfire.jxclient.gui.commands.ToggleCommand;
00054 import com.realtime.crossfire.jxclient.gui.gui.AbstractGUIElement;
00055 import com.realtime.crossfire.jxclient.gui.gui.ActivatableGUIElement;
00056 import com.realtime.crossfire.jxclient.gui.gui.GUIElement;
00057 import com.realtime.crossfire.jxclient.gui.item.GUIItem;
00058 import com.realtime.crossfire.jxclient.gui.list.GUIItemList;
00059 import com.realtime.crossfire.jxclient.gui.list.GUIList;
00060 import com.realtime.crossfire.jxclient.gui.scrollable.GUIScrollable;
00061 import com.realtime.crossfire.jxclient.gui.textinput.CommandCallback;
00062 import com.realtime.crossfire.jxclient.gui.textinput.CommandExecutor;
00063 import com.realtime.crossfire.jxclient.gui.textinput.ExecuteCommandCommand;
00064 import com.realtime.crossfire.jxclient.gui.textinput.GUIText;
00065 import com.realtime.crossfire.jxclient.guistate.GuiStateManager;
00066 import com.realtime.crossfire.jxclient.items.FloorView;
00067 import com.realtime.crossfire.jxclient.queue.CommandQueue;
00068 import com.realtime.crossfire.jxclient.server.crossfire.CrossfireServerConnection;
00069 import com.realtime.crossfire.jxclient.settings.Macros;
00070 import com.realtime.crossfire.jxclient.skin.skin.Dialogs;
00071 import com.realtime.crossfire.jxclient.skin.skin.JXCSkinCache;
00072 import com.realtime.crossfire.jxclient.skin.skin.JXCSkinException;
00073 import com.realtime.crossfire.jxclient.util.NumberParser;
00074 import java.awt.Component;
00075 import java.io.IOException;
00076 import java.io.LineNumberReader;
00077 import org.jetbrains.annotations.NotNull;
00078 import org.jetbrains.annotations.Nullable;
00079
00085 public class CommandParser {
00086
00090 @NotNull
00091 private final Dialogs dialogs;
00092
00096 @NotNull
00097 private final FloorView floorView;
00098
00102 @NotNull
00103 private final JXCSkinCache<AbstractGUIElement> definedGUIElements;
00104
00111 public CommandParser(@NotNull final Dialogs dialogs, @NotNull final FloorView floorView, @NotNull final JXCSkinCache<AbstractGUIElement> definedGUIElements) {
00112 this.dialogs = dialogs;
00113 this.floorView = floorView;
00114 this.definedGUIElements = definedGUIElements;
00115 }
00116
00133 @NotNull
00134 public GUICommand parseCommandArgs(@NotNull final Args args, @Nullable final AbstractGUIElement element, @NotNull final String command, @NotNull final GuiStateManager guiStateManager, @NotNull final CommandExecutor commandExecutor, @NotNull final LineNumberReader lnr, @NotNull final CommandQueue commandQueue, @NotNull final CrossfireServerConnection crossfireServerConnection, @NotNull final CommandCallback commandCallback, @NotNull final Macros macros) throws IOException, JXCSkinException {
00135 if (command.equals("SHOW")) {
00136 return parseShow(element);
00137 } else if (command.equals("HIDE")) {
00138 return parseHide(element);
00139 } else if (command.equals("TOGGLE")) {
00140 return parseToggle(element);
00141 } else if (command.equals("PRINT")) {
00142 return parsePrint(element);
00143 } else if (command.equals("QUIT")) {
00144 return parseQuit(element, commandCallback);
00145 } else if (command.equals("CONNECT")) {
00146 return parseConnect(element, guiStateManager);
00147 } else if (command.equals("DISCONNECT")) {
00148 return parseDisconnect(element, guiStateManager);
00149 } else if (command.equals("GUI_META")) {
00150 return parseGuiMeta(element, guiStateManager);
00151 } else if (command.equals("GUI_START")) {
00152 return parseGuiStart(element, guiStateManager);
00153 } else if (command.equals("GUI_EXECUTE_ELEMENT")) {
00154 return parseGuiExecuteElement(element);
00155 } else if (command.equals("DIALOG_OPEN")) {
00156 return parseDialogOpen(args, element, commandCallback);
00157 } else if (command.equals("DIALOG_TOGGLE")) {
00158 return parseDialogToggle(args, element, commandCallback);
00159 } else if (command.equals("DIALOG_CLOSE")) {
00160 return parseDialogClose(args, element, commandCallback);
00161 } else if (command.equals("GUI_EXECUTE_COMMAND")) {
00162 return parseGuiExecuteCommand(args, element, commandExecutor, lnr, macros);
00163 } else if (command.equals("EXEC_SELECTION")) {
00164 return parseExecSelection(args, element, commandQueue, crossfireServerConnection);
00165 } else if (command.equals("MOVE_SELECTION")) {
00166 return parseMoveSelection(args, element);
00167 } else if (command.equals("SCROLL_LIST")) {
00168 return parseScrollList(args, element);
00169 } else if (command.equals("SCROLL") || command.equals("SCROLL_NEVER")) {
00170 return parseScroll(args, element, command.equals("SCROLL"));
00171 } else if (command.equals("SCROLL_RESET")) {
00172 return parseScrollReset(element);
00173 } else if (command.equals("MOVE_FOCUS")) {
00174 return parseMoveFocus(args, element);
00175 } else if (command.equals("ACCOUNT_LOGIN")) {
00176 return parseAccountLogin(element, commandCallback);
00177 } else if (command.equals("ACCOUNT_CREATE")) {
00178 return parseAccountCreate(element, commandCallback);
00179 } else if (command.equals("ACCOUNT_PLAY")) {
00180 return parseAccountPlay(element, commandCallback);
00181 } else if (command.equals("ACCOUNT_LINK")) {
00182 return parseAccountLink(element, commandCallback);
00183 } else if (command.equals("ACCOUNT_CREATE_CHARACTER")) {
00184 return parseAccountCreateCharacter(element, commandCallback);
00185 } else if (command.equals("ACCOUNT_PASSWORD")) {
00186 return parseAccountPassword(element, commandCallback);
00187 } else if (command.equals("SELECT")) {
00188 return parseSelect(args, element);
00189 } else {
00190 throw new JXCSkinException("unknown command '"+command+"'");
00191 }
00192 }
00193
00200 @NotNull
00201 private static GUICommand parseShow(@Nullable final Component element) throws IOException {
00202 if (element == null) {
00203 throw new IOException("<element> is required");
00204 }
00205
00206 return new ShowCommand(element);
00207 }
00208
00215 @NotNull
00216 private static GUICommand parseHide(@Nullable final Component element) throws IOException {
00217 if (element == null) {
00218 throw new IOException("<element> is required");
00219 }
00220
00221 return new HideCommand(element);
00222 }
00223
00230 @NotNull
00231 private static GUICommand parseToggle(@Nullable final Component element) throws IOException {
00232 if (element == null) {
00233 throw new IOException("<element> is required");
00234 }
00235
00236 return new ToggleCommand(element);
00237 }
00238
00245 @NotNull
00246 private static GUICommand parsePrint(@Nullable final GUIElement element) throws IOException {
00247 if (element != null) {
00248 throw new IOException("<element> is not allowed");
00249 }
00250
00251 return new PrintCommand();
00252 }
00253
00261 @NotNull
00262 private static GUICommand parseQuit(@Nullable final GUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00263 if (element != null) {
00264 throw new IOException("<element> is not allowed");
00265 }
00266
00267 return new QuitCommand(commandCallback);
00268 }
00269
00277 @NotNull
00278 private static GUICommand parseConnect(@Nullable final GUIElement element, @NotNull final GuiStateManager guiStateManager) throws IOException {
00279 if (element == null) {
00280 throw new IOException("<element> is required");
00281 }
00282
00283 if (!(element instanceof GUIText)) {
00284 throw new IOException("'"+element+"' must be an input field");
00285 }
00286
00287 return new ConnectCommand(guiStateManager, (GUIText)element);
00288 }
00289
00297 @NotNull
00298 private static GUICommand parseDisconnect(@Nullable final GUIElement element, @NotNull final GuiStateManager guiStateManager) throws IOException {
00299 if (element != null) {
00300 throw new IOException("<element> is not allowed");
00301 }
00302
00303 return new DisconnectCommand(guiStateManager);
00304 }
00305
00313 @NotNull
00314 private static GUICommand parseGuiMeta(@Nullable final GUIElement element, @NotNull final GuiStateManager guiStateManager) throws IOException {
00315 if (element != null) {
00316 throw new IOException("<element> is not allowed");
00317 }
00318
00319 return new MetaCommand(guiStateManager);
00320 }
00321
00329 @NotNull
00330 private static GUICommand parseGuiStart(@Nullable final GUIElement element, @NotNull final GuiStateManager guiStateManager) throws IOException {
00331 if (element != null) {
00332 throw new IOException("<element> is not allowed");
00333 }
00334
00335 return new StartCommand(guiStateManager);
00336 }
00337
00344 @NotNull
00345 private static GUICommand parseGuiExecuteElement(@Nullable final GUIElement element) throws IOException {
00346 if (element == null) {
00347 throw new IOException("<element> is required");
00348 }
00349
00350 if (!(element instanceof GUIItem)) {
00351 throw new IOException("'"+element+"' must be an item element");
00352 }
00353
00354 return new ExecuteElementCommand((GUIItem)element);
00355 }
00356
00365 @NotNull
00366 private GUICommand parseDialogOpen(@NotNull final Args args, @Nullable final GUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00367 if (element != null) {
00368 throw new IOException("<element> is not allowed");
00369 }
00370
00371 return new DialogOpenCommand(commandCallback, dialogs.addDialog(args.get()));
00372 }
00373
00382 @NotNull
00383 private GUICommand parseDialogToggle(@NotNull final Args args, @Nullable final GUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00384 if (element != null) {
00385 throw new IOException("<element> is not allowed");
00386 }
00387
00388 return new DialogToggleCommand(commandCallback, dialogs.addDialog(args.get()));
00389 }
00390
00399 @NotNull
00400 private GUICommand parseDialogClose(@NotNull final Args args, @Nullable final GUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00401 if (element != null) {
00402 throw new IOException("<element> is not allowed");
00403 }
00404
00405 return new DialogCloseCommand(commandCallback, dialogs.addDialog(args.get()));
00406 }
00407
00418 @NotNull
00419 private static GUICommand parseGuiExecuteCommand(@NotNull final Args args, @Nullable final GUIElement element, @NotNull final CommandExecutor commandExecutor, @NotNull final LineNumberReader lnr, @NotNull final Macros macros) throws IOException {
00420 if (element != null) {
00421 throw new IOException("<element> is not allowed");
00422 }
00423
00424 final String commandString = ParseUtils.parseText(args, lnr);
00425 return new ExecuteCommandCommand(commandExecutor, commandString, macros);
00426 }
00427
00437 @NotNull
00438 private GUICommand parseExecSelection(@NotNull final Args args, @Nullable final GUIElement element, @NotNull final CommandQueue commandQueue, @NotNull final CrossfireServerConnection crossfireServerConnection) throws IOException {
00439 final CommandType commandType = NumberParser.parseEnum(CommandType.class, args.get(), "command name");
00440
00441 if (element == null) {
00442 throw new IOException("<element> is required");
00443 }
00444
00445 if (!(element instanceof GUIItemList)) {
00446 throw new IOException("'"+element+"' must be an item list");
00447 }
00448
00449 return new ExecSelectionCommand((GUIItemList)element, commandType, crossfireServerConnection, floorView, commandQueue);
00450 }
00451
00459 @NotNull
00460 private static GUICommand parseMoveSelection(@NotNull final Args args, @Nullable final GUIElement element) throws IOException {
00461 final int diffLines = ExpressionParser.parseInt(args.get());
00462 final int diffElements = ExpressionParser.parseInt(args.get());
00463 if (diffLines == 0 && diffElements == 0) {
00464 throw new IOException("Invalid zero scroll distance");
00465 }
00466
00467 if (element == null) {
00468 throw new IOException("<element> is required");
00469 }
00470
00471 if (!(element instanceof GUIList)) {
00472 throw new IOException("'"+element+"' must be a list");
00473 }
00474
00475 return new MoveSelectionCommand((GUIList)element, diffLines, diffElements);
00476 }
00477
00485 @NotNull
00486 private static GUICommand parseScrollList(@NotNull final Args args, @Nullable final GUIElement element) throws IOException {
00487 final int distance = ExpressionParser.parseInt(args.get());
00488 if (distance == 0) {
00489 throw new IOException("Invalid zero scroll distance");
00490 }
00491
00492 if (element == null) {
00493 throw new IOException("<element> is required");
00494 }
00495
00496 if (!(element instanceof GUIScrollable)) {
00497 throw new IOException("'"+element+"' must be a scrollable");
00498 }
00499
00500 return new ScrollListCommand((GUIScrollable)element, distance);
00501 }
00502
00512 @NotNull
00513 private static GUICommand parseScroll(@NotNull final Args args, @Nullable final GUIElement element, final boolean isScroll) throws IOException {
00514 final int distance = ExpressionParser.parseInt(args.get());
00515 if (distance == 0) {
00516 throw new IOException("Invalid zero scroll distance");
00517 }
00518
00519 if (element == null) {
00520 throw new IOException("<element> is required");
00521 }
00522
00523 if (!(element instanceof GUIScrollable)) {
00524 throw new IOException("'"+element+"' must be a scrollable element");
00525 }
00526
00527 return isScroll ? new ScrollCommand(distance, (GUIScrollable)element) : new ScrollNeverCommand(distance, (GUIScrollable)element);
00528 }
00529
00536 @NotNull
00537 private static GUICommand parseScrollReset(@Nullable final GUIElement element) throws IOException {
00538 if (element == null) {
00539 throw new IOException("<element> is required");
00540 }
00541
00542 if (!(element instanceof GUIScrollable)) {
00543 throw new IOException("'"+element+"' must be a scrollable element");
00544 }
00545
00546 return new ScrollResetCommand((GUIScrollable)element);
00547 }
00548
00557 @NotNull
00558 private GUICommand parseMoveFocus(@NotNull final Args args, @Nullable final GUIElement element) throws IOException, JXCSkinException {
00559 final Object nextElement = definedGUIElements.lookup(args.get());
00560 if (!(nextElement instanceof ActivatableGUIElement)) {
00561 throw new IOException("'"+args.getPrev()+"' cannot become active");
00562 }
00563
00564 final int apply = args.hasMore() ? ExpressionParser.parseInt(args.get()) : 0;
00565 if (apply != 0 && apply != 1) {
00566 throw new IOException("<apply> must be 0 or 1");
00567 }
00568
00569 if (element == null) {
00570 throw new IOException("<element> is required");
00571 }
00572
00573 if (!(element instanceof ActivatableGUIElement)) {
00574 throw new IOException("'"+element+"' cannot become active");
00575 }
00576
00577 return new ScrollNextCommand((ActivatableGUIElement)nextElement, (ActivatableGUIElement)element, apply != 0);
00578 }
00579
00587 @NotNull
00588 private static GUICommand parseAccountLogin(@Nullable final AbstractGUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00589 if (element == null) {
00590 throw new IOException("<element> is required");
00591 }
00592
00593 return new AccountLoginCommand(commandCallback, element);
00594 }
00595
00603 @NotNull
00604 private static GUICommand parseAccountCreate(@Nullable final AbstractGUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00605 if (element == null) {
00606 throw new IOException("<element> is required");
00607 }
00608
00609 return new AccountCreateCommand(commandCallback, element);
00610 }
00611
00619 @NotNull
00620 private static GUICommand parseAccountPlay(@Nullable final AbstractGUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00621 if (element == null) {
00622 throw new IOException("<element> is required");
00623 }
00624
00625 return new AccountPlayCharacterCommand(commandCallback, element);
00626 }
00627
00635 @NotNull
00636 private static GUICommand parseAccountLink(@Nullable final AbstractGUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00637 if (element == null) {
00638 throw new IOException("<element> is required");
00639 }
00640
00641 return new AccountLinkCharacterCommand(commandCallback, element);
00642 }
00643
00651 @NotNull
00652 private static GUICommand parseAccountCreateCharacter(@Nullable final AbstractGUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00653 if (element == null) {
00654 throw new IOException("<element> is required");
00655 }
00656
00657 return new AccountCreateCharacterCommand(commandCallback, element);
00658 }
00659
00667 @NotNull
00668 private static GUICommand parseAccountPassword(@Nullable final AbstractGUIElement element, @NotNull final CommandCallback commandCallback) throws IOException {
00669 if (element == null) {
00670 throw new IOException("<element> is required");
00671 }
00672
00673 return new AccountPasswordCommand(commandCallback, element);
00674 }
00675
00683 @NotNull
00684 private static GUICommand parseSelect(@NotNull final Args args, @Nullable final GUIElement element) throws IOException {
00685 final boolean selected = NumberParser.parseBoolean(args.get());
00686
00687 if (element == null) {
00688 throw new IOException("<element> is required");
00689 }
00690
00691 if (!(element instanceof GUISelectable)) {
00692 throw new IOException("'"+element+"' must be a selectable element");
00693 }
00694
00695 return new SelectCommand((GUISelectable)element, selected);
00696 }
00697
00698 }