1/* 2 * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23package org.netbeans.jemmy.operators; 24 25import java.awt.Component; 26import java.awt.Container; 27import java.awt.Dimension; 28import java.awt.List; 29import java.awt.event.ActionListener; 30import java.awt.event.ItemListener; 31import java.util.Hashtable; 32 33import org.netbeans.jemmy.ComponentChooser; 34import org.netbeans.jemmy.Outputable; 35import org.netbeans.jemmy.TestOut; 36import org.netbeans.jemmy.TimeoutExpiredException; 37import org.netbeans.jemmy.drivers.DriverManager; 38import org.netbeans.jemmy.drivers.MultiSelListDriver; 39 40/** 41 * <BR><BR>Timeouts used: <BR> 42 * ComponentOperator.WaitComponentTimeout - time to wait component displayed 43 * <BR> 44 * ComponentOperator.WaitComponentEnabledTimeout - time to wait component 45 * enabled <BR>. 46 * 47 * @see org.netbeans.jemmy.Timeouts 48 * 49 * @author Alexandre Iline (alexandre.iline@oracle.com) 50 * 51 */ 52public class ListOperator extends ComponentOperator 53 implements Outputable { 54 55 /** 56 * Identifier for a "item" properties. 57 * 58 * @see #getDump 59 */ 60 public static final String ITEM_PREFIX_DPROP = "Item"; 61 62 /** 63 * Identifier for a "selected item" property. 64 * 65 * @see #getDump 66 */ 67 public static final String SELECTED_ITEM_PREFIX_DPROP = "SelectedItem"; 68 69 private TestOut output; 70 private MultiSelListDriver driver; 71 72 /** 73 * Constructor. 74 * 75 * @param b a component 76 */ 77 public ListOperator(List b) { 78 super(b); 79 driver = DriverManager.getMultiSelListDriver(getClass()); 80 } 81 82 /** 83 * Constructs a ListOperator object. 84 * 85 * @param cont a container 86 * @param chooser a component chooser specifying searching criteria. 87 * @param index an index between appropriate ones. 88 */ 89 public ListOperator(ContainerOperator<?> cont, ComponentChooser chooser, int index) { 90 this((List) cont. 91 waitSubComponent(new ListFinder(chooser), 92 index)); 93 copyEnvironment(cont); 94 } 95 96 /** 97 * Constructs a ListOperator object. 98 * 99 * @param cont a container 100 * @param chooser a component chooser specifying searching criteria. 101 */ 102 public ListOperator(ContainerOperator<?> cont, ComponentChooser chooser) { 103 this(cont, chooser, 0); 104 } 105 106 /** 107 * Constructor. Waits item text first. Uses cont's timeout and output for 108 * waiting and to init operator. 109 * 110 * @param cont a container 111 * @param text Text of item which is currently selected. 112 * @param itemIndex Item index. 113 * @param index Ordinal component index. 114 * @throws TimeoutExpiredException 115 */ 116 public ListOperator(ContainerOperator<?> cont, String text, int itemIndex, int index) { 117 this((List) waitComponent(cont, 118 new ListByItemFinder(text, itemIndex, 119 cont.getComparator()), 120 index)); 121 copyEnvironment(cont); 122 } 123 124 /** 125 * Constructor. Waits component by selected item text first. Uses cont's 126 * timeout and output for waiting and to init operator. 127 * 128 * @param cont a container 129 * @param text Text of item which is currently selected. 130 * @param index Ordinal component index. 131 * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean) 132 * @throws TimeoutExpiredException 133 */ 134 public ListOperator(ContainerOperator<?> cont, String text, int index) { 135 this(cont, text, -1, index); 136 } 137 138 /** 139 * Constructor. Waits component in container first. Uses cont's timeout and 140 * output for waiting and to init operator. 141 * 142 * @param cont a container 143 * @param text Text of item which is currently selected. 144 * @see ComponentOperator#isCaptionEqual(String, String, boolean, boolean) 145 * @throws TimeoutExpiredException 146 */ 147 public ListOperator(ContainerOperator<?> cont, String text) { 148 this(cont, text, 0); 149 } 150 151 /** 152 * Constructor. Waits component in container first. Uses cont's timeout and 153 * output for waiting and to init operator. 154 * 155 * @param cont a container 156 * @param index Ordinal component index. 157 * @throws TimeoutExpiredException 158 */ 159 public ListOperator(ContainerOperator<?> cont, int index) { 160 this((List) waitComponent(cont, 161 new ListFinder(), 162 index)); 163 copyEnvironment(cont); 164 } 165 166 /** 167 * Constructor. Waits component in container first. Uses cont's timeout and 168 * output for waiting and to init operator. 169 * 170 * @param cont a container 171 * @throws TimeoutExpiredException 172 */ 173 public ListOperator(ContainerOperator<?> cont) { 174 this(cont, 0); 175 } 176 177 /** 178 * Searches List in container. 179 * 180 * @param cont Container to search component in. 181 * @param chooser org.netbeans.jemmy.ComponentChooser implementation. 182 * @param index Ordinal component index. 183 * @return List instance or null if component was not found. 184 */ 185 public static List findList(Container cont, ComponentChooser chooser, int index) { 186 return (List) findComponent(cont, new ListFinder(chooser), index); 187 } 188 189 /** 190 * Searches 0'th List in container. 191 * 192 * @param cont Container to search component in. 193 * @param chooser org.netbeans.jemmy.ComponentChooser implementation. 194 * @return List instance or null if component was not found. 195 */ 196 public static List findList(Container cont, ComponentChooser chooser) { 197 return findList(cont, chooser, 0); 198 } 199 200 @Override 201 public void setOutput(TestOut output) { 202 super.setOutput(output.createErrorOutput()); 203 this.output = output; 204 } 205 206 @Override 207 public TestOut getOutput() { 208 return output; 209 } 210 211 @Override 212 public void copyEnvironment(Operator anotherOperator) { 213 super.copyEnvironment(anotherOperator); 214 driver 215 = (MultiSelListDriver) DriverManager. 216 getDriver(DriverManager.MULTISELLIST_DRIVER_ID, 217 getClass(), 218 anotherOperator.getProperties()); 219 } 220 221 private int findItemIndex(String item, StringComparator comparator, int index) { 222 int count = 0; 223 for (int i = 0; i < getItemCount(); i++) { 224 if (comparator.equals(getItem(i), item)) { 225 if (count == index) { 226 return i; 227 } else { 228 count++; 229 } 230 } 231 } 232 return -1; 233 } 234 235 /** 236 * Searches an item index. 237 * 238 * @param item item text. 239 * @param index an ordinal index between appropriate ones. 240 * @return an index. 241 */ 242 public int findItemIndex(String item, int index) { 243 return findItemIndex(item, getComparator(), index); 244 } 245 246 /** 247 * Searches an item index. 248 * 249 * @param item item text. 250 * @return an index. 251 */ 252 public int findItemIndex(String item) { 253 return findItemIndex(item, 0); 254 } 255 256 private void selectItem(String item, StringComparator comparator, int index) { 257 selectItem(findItemIndex(item, comparator, index)); 258 } 259 260 /** 261 * Selects an item. 262 * 263 * @param item item text. 264 * @param index an ordinal index between appropriate ones. 265 */ 266 public void selectItem(String item, int index) { 267 selectItem(item, getComparator(), index); 268 } 269 270 /** 271 * Selects an item. 272 * 273 * @param item item text. 274 */ 275 public void selectItem(String item) { 276 selectItem(item, 0); 277 } 278 279 /** 280 * Selects an item. 281 * 282 * @param index an item index. 283 */ 284 public void selectItem(int index) { 285 output.printLine("Select " + Integer.toString(index) + "`th item in list\n : " 286 + toStringSource()); 287 output.printGolden("Select " + Integer.toString(index) + "`th item in list"); 288 driver.selectItem(this, index); 289 if (getVerification()) { 290 waitItemSelection(index, true); 291 } 292 } 293 294 /** 295 * Selects some items. 296 * 297 * @param from start selection index. 298 * @param to end selection index. 299 */ 300 public void selectItems(int from, int to) { 301 output.printLine("Select items from " + Integer.toString(from) 302 + "`th to " + Integer.toString(from) + "'th in list\n : " 303 + toStringSource()); 304 output.printGolden("Select items from " + Integer.toString(from) 305 + "`th to " + Integer.toString(from) + "'th"); 306 driver.selectItems(this, new int[]{from, to}); 307 if (getVerification()) { 308 waitItemsSelection(from, to, true); 309 } 310 } 311 312 /** 313 * Waits for items to be selected. 314 * 315 * @param from Start selection inex 316 * @param to End selection inex 317 * @param selected Selected (true) or unselected (false). 318 */ 319 public void waitItemsSelection(final int from, final int to, final boolean selected) { 320 getOutput().printLine("Wait items to be " 321 + (selected ? "" : "un") + "selected in component \n : " 322 + toStringSource()); 323 getOutput().printGolden("Wait items to be " 324 + (selected ? "" : "un") + "selected"); 325 waitState(new ComponentChooser() { 326 @Override 327 public boolean checkComponent(Component comp) { 328 int[] indices = getSelectedIndexes(); 329 for (int indice : indices) { 330 if (indice < from 331 || indice > to) { 332 return false; 333 } 334 } 335 return true; 336 } 337 338 @Override 339 public String getDescription() { 340 return ("Items has been " 341 + (selected ? "" : "un") + "selected"); 342 } 343 344 @Override 345 public String toString() { 346 return "ListOperator.waitItemsSelection.ComponentChooser{description = " + getDescription() + '}'; 347 } 348 }); 349 } 350 351 /** 352 * Waits for item to be selected. 353 * 354 * @param itemIndex an item index to be selected. 355 * @param selected Selected (true) or unselected (false). 356 */ 357 public void waitItemSelection(final int itemIndex, final boolean selected) { 358 waitItemsSelection(itemIndex, itemIndex, selected); 359 } 360 361 @Override 362 public Hashtable<String, Object> getDump() { 363 Hashtable<String, Object> result = super.getDump(); 364 addToDump(result, ITEM_PREFIX_DPROP, ((List) getSource()).getItems()); 365 addToDump(result, SELECTED_ITEM_PREFIX_DPROP, ((List) getSource()).getSelectedItems()); 366 return result; 367 } 368 369 //////////////////////////////////////////////////////// 370 //Mapping // 371 /** 372 * Maps {@code List.addActionListener(ActionListener)} through queue 373 */ 374 public void addActionListener(final ActionListener actionListener) { 375 runMapping(new MapVoidAction("addActionListener") { 376 @Override 377 public void map() { 378 ((List) getSource()).addActionListener(actionListener); 379 } 380 }); 381 } 382 383 /** 384 * Maps {@code List.addItemListener(ItemListener)} through queue 385 */ 386 public void addItemListener(final ItemListener itemListener) { 387 runMapping(new MapVoidAction("addItemListener") { 388 @Override 389 public void map() { 390 ((List) getSource()).addItemListener(itemListener); 391 } 392 }); 393 } 394 395 /** 396 * Maps {@code List.deselect(int)} through queue 397 */ 398 public void deselect(final int i) { 399 runMapping(new MapVoidAction("deselect") { 400 @Override 401 public void map() { 402 ((List) getSource()).deselect(i); 403 } 404 }); 405 } 406 407 /** 408 * Maps {@code List.getItem(int)} through queue 409 */ 410 public String getItem(final int i) { 411 return (runMapping(new MapAction<String>("getItem") { 412 @Override 413 public String map() { 414 return ((List) getSource()).getItem(i); 415 } 416 })); 417 } 418 419 /** 420 * Maps {@code List.getItemCount()} through queue 421 */ 422 public int getItemCount() { 423 return (runMapping(new MapIntegerAction("getItemCount") { 424 @Override 425 public int map() { 426 return ((List) getSource()).getItemCount(); 427 } 428 })); 429 } 430 431 /** 432 * Maps {@code List.getItems()} through queue 433 */ 434 public String[] getItems() { 435 return ((String[]) runMapping(new MapAction<Object>("getItems") { 436 @Override 437 public Object map() { 438 return ((List) getSource()).getItems(); 439 } 440 })); 441 } 442 443 /** 444 * Maps {@code List.getMinimumSize(int)} through queue 445 */ 446 public Dimension getMinimumSize(final int i) { 447 return (runMapping(new MapAction<Dimension>("getMinimumSize") { 448 @Override 449 public Dimension map() { 450 return ((List) getSource()).getMinimumSize(i); 451 } 452 })); 453 } 454 455 /** 456 * Maps {@code List.getPreferredSize(int)} through queue 457 */ 458 public Dimension getPreferredSize(final int i) { 459 return (runMapping(new MapAction<Dimension>("getPreferredSize") { 460 @Override 461 public Dimension map() { 462 return ((List) getSource()).getPreferredSize(i); 463 } 464 })); 465 } 466 467 /** 468 * Maps {@code List.getRows()} through queue 469 */ 470 public int getRows() { 471 return (runMapping(new MapIntegerAction("getRows") { 472 @Override 473 public int map() { 474 return ((List) getSource()).getRows(); 475 } 476 })); 477 } 478 479 /** 480 * Maps {@code List.getSelectedIndex()} through queue 481 */ 482 public int getSelectedIndex() { 483 return (runMapping(new MapIntegerAction("getSelectedIndex") { 484 @Override 485 public int map() { 486 return ((List) getSource()).getSelectedIndex(); 487 } 488 })); 489 } 490 491 /** 492 * Maps {@code List.getSelectedIndexes()} through queue 493 */ 494 public int[] getSelectedIndexes() { 495 return ((int[]) runMapping(new MapAction<Object>("getSelectedIndexes") { 496 @Override 497 public Object map() { 498 return ((List) getSource()).getSelectedIndexes(); 499 } 500 })); 501 } 502 503 /** 504 * Maps {@code List.getSelectedItem()} through queue 505 */ 506 public String getSelectedItem() { 507 return (runMapping(new MapAction<String>("getSelectedItem") { 508 @Override 509 public String map() { 510 return ((List) getSource()).getSelectedItem(); 511 } 512 })); 513 } 514 515 /** 516 * Maps {@code List.getSelectedItems()} through queue 517 */ 518 public String[] getSelectedItems() { 519 return ((String[]) runMapping(new MapAction<Object>("getSelectedItems") { 520 @Override 521 public Object map() { 522 return ((List) getSource()).getSelectedItems(); 523 } 524 })); 525 } 526 527 /** 528 * Maps {@code List.getSelectedObjects()} through queue 529 */ 530 public Object[] getSelectedObjects() { 531 return ((Object[]) runMapping(new MapAction<Object>("getSelectedObjects") { 532 @Override 533 public Object map() { 534 return ((List) getSource()).getSelectedObjects(); 535 } 536 })); 537 } 538 539 /** 540 * Maps {@code List.getVisibleIndex()} through queue 541 */ 542 public int getVisibleIndex() { 543 return (runMapping(new MapIntegerAction("getVisibleIndex") { 544 @Override 545 public int map() { 546 return ((List) getSource()).getVisibleIndex(); 547 } 548 })); 549 } 550 551 /** 552 * Maps {@code List.isIndexSelected(int)} through queue 553 */ 554 public boolean isIndexSelected(final int i) { 555 return (runMapping(new MapBooleanAction("isIndexSelected") { 556 @Override 557 public boolean map() { 558 return ((List) getSource()).isIndexSelected(i); 559 } 560 })); 561 } 562 563 /** 564 * Maps {@code List.isMultipleMode()} through queue 565 */ 566 public boolean isMultipleMode() { 567 return (runMapping(new MapBooleanAction("isMultipleMode") { 568 @Override 569 public boolean map() { 570 return ((List) getSource()).isMultipleMode(); 571 } 572 })); 573 } 574 575 /** 576 * Maps {@code List.makeVisible(int)} through queue 577 */ 578 public void makeVisible(final int i) { 579 runMapping(new MapVoidAction("makeVisible") { 580 @Override 581 public void map() { 582 ((List) getSource()).makeVisible(i); 583 } 584 }); 585 } 586 587 /** 588 * Maps {@code List.remove(int)} through queue 589 */ 590 public void remove(final int i) { 591 runMapping(new MapVoidAction("remove") { 592 @Override 593 public void map() { 594 ((List) getSource()).remove(i); 595 } 596 }); 597 } 598 599 /** 600 * Maps {@code List.remove(String)} through queue 601 */ 602 public void remove(final String string) { 603 runMapping(new MapVoidAction("remove") { 604 @Override 605 public void map() { 606 ((List) getSource()).remove(string); 607 } 608 }); 609 } 610 611 /** 612 * Maps {@code List.removeActionListener(ActionListener)} through queue 613 */ 614 public void removeActionListener(final ActionListener actionListener) { 615 runMapping(new MapVoidAction("removeActionListener") { 616 @Override 617 public void map() { 618 ((List) getSource()).removeActionListener(actionListener); 619 } 620 }); 621 } 622 623 /** 624 * Maps {@code List.removeAll()} through queue 625 */ 626 public void removeAll() { 627 runMapping(new MapVoidAction("removeAll") { 628 @Override 629 public void map() { 630 ((List) getSource()).removeAll(); 631 } 632 }); 633 } 634 635 /** 636 * Maps {@code List.removeItemListener(ItemListener)} through queue 637 */ 638 public void removeItemListener(final ItemListener itemListener) { 639 runMapping(new MapVoidAction("removeItemListener") { 640 @Override 641 public void map() { 642 ((List) getSource()).removeItemListener(itemListener); 643 } 644 }); 645 } 646 647 /** 648 * Maps {@code List.replaceItem(String, int)} through queue 649 */ 650 public void replaceItem(final String string, final int i) { 651 runMapping(new MapVoidAction("replaceItem") { 652 @Override 653 public void map() { 654 ((List) getSource()).replaceItem(string, i); 655 } 656 }); 657 } 658 659 /** 660 * Maps {@code List.select(int)} through queue 661 */ 662 public void select(final int i) { 663 runMapping(new MapVoidAction("select") { 664 @Override 665 public void map() { 666 ((List) getSource()).select(i); 667 } 668 }); 669 } 670 671 /** 672 * Maps {@code List.setMultipleMode(boolean)} through queue 673 */ 674 public void setMultipleMode(final boolean b) { 675 runMapping(new MapVoidAction("setMultipleMode") { 676 @Override 677 public void map() { 678 ((List) getSource()).setMultipleMode(b); 679 } 680 }); 681 } 682 683 //End of mapping // 684 //////////////////////////////////////////////////////// 685 /** 686 * Allows to find component by item text. 687 */ 688 public static class ListByItemFinder implements ComponentChooser { 689 690 String label; 691 int itemIndex; 692 StringComparator comparator; 693 694 /** 695 * Constructs ListByItemFinder. 696 * 697 * @param lb a text pattern 698 * @param ii item index to check. If equal to -1, selected item is 699 * checked. 700 * @param comparator specifies string comparision algorithm. 701 */ 702 public ListByItemFinder(String lb, int ii, StringComparator comparator) { 703 label = lb; 704 itemIndex = ii; 705 this.comparator = comparator; 706 } 707 708 /** 709 * Constructs ListByItemFinder. 710 * 711 * @param lb a text pattern 712 * @param ii item index to check. If equal to -1, selected item is 713 * checked. 714 */ 715 public ListByItemFinder(String lb, int ii) { 716 this(lb, ii, Operator.getDefaultStringComparator()); 717 } 718 719 @Override 720 public boolean checkComponent(Component comp) { 721 if (comp instanceof List) { 722 if (label == null) { 723 return true; 724 } 725 if (((List) comp).getItemCount() > itemIndex) { 726 int ii = itemIndex; 727 if (ii == -1) { 728 ii = ((List) comp).getSelectedIndex(); 729 if (ii == -1) { 730 return false; 731 } 732 } 733 return (comparator.equals(((List) comp).getItem(ii), 734 label)); 735 } 736 } 737 return false; 738 } 739 740 @Override 741 public String getDescription() { 742 return ("List with text \"" + label + "\" in " 743 + itemIndex + "'th item"); 744 } 745 746 @Override 747 public String toString() { 748 return "ListByItemFinder{" + "label=" + label + ", itemIndex=" + itemIndex + ", comparator=" + comparator + '}'; 749 } 750 } 751 752 /** 753 * Checks component type. 754 */ 755 public static class ListFinder extends Finder { 756 757 /** 758 * Constructs ListFinder. 759 * 760 * @param sf other searching criteria. 761 */ 762 public ListFinder(ComponentChooser sf) { 763 super(List.class, sf); 764 } 765 766 /** 767 * Constructs ListFinder. 768 */ 769 public ListFinder() { 770 super(List.class); 771 } 772 } 773} 774