View Javadoc

1   package com.atlassian.webtest.ui.keys;
2   
3   import com.google.common.base.Function;
4   import com.google.common.collect.ImmutableMap;
5   import com.google.common.collect.Lists;
6   import com.google.common.collect.Maps;
7   
8   import java.util.ArrayList;
9   import java.util.Arrays;
10  import java.util.Collection;
11  import java.util.EnumSet;
12  import java.util.List;
13  import java.util.Map;
14  import java.util.Set;
15  
16  import static com.google.common.base.Preconditions.checkNotNull;
17  
18  /**
19   * For easy and efficient instantiation of {@link KeySequence}s.
20   *
21   */
22  public final class KeySequenceBuilder implements KeyEventAware
23  {
24      private static final int ASCII_CACHE_START = 40;
25      private static final int ASCII_CACHE_END = 125;
26  
27      private static final Map<Character, CharacterKey> KEY_CACHE = createKeyCache();
28  
29      private static Map<Character, CharacterKey> createKeyCache()
30      {
31          Map<Character, CharacterKey> cache = Maps.newHashMap();
32          for (char ch= ASCII_CACHE_START; ch<=ASCII_CACHE_END; ch++)
33          {
34              cache.put(ch, new DefaultCharacterKey(ch));
35          }
36          return ImmutableMap.copyOf(cache);
37      }
38  
39      private final List<Key> keys = new ArrayList<Key>();
40      private final List<Character> charKeys = new ArrayList<Character>();
41      private final EnumSet<ModifierKey> pressed = EnumSet.noneOf(ModifierKey.class);
42      private EnumSet<KeyEventType> events = EnumSet.allOf(KeyEventType.class);
43      private TypeMode typeMode = TypeMode.DEFAULT;
44  
45      public KeySequenceBuilder()
46      {
47      }
48      
49      public KeySequenceBuilder(List<Key> keys)
50      {
51          this.keys.addAll(keys);
52      }
53      
54      public KeySequenceBuilder(Key... keys)
55      {
56          this(Arrays.asList(keys));
57      }
58  
59      public KeySequenceBuilder(String characterKeys)
60      {
61          append(characterKeys);
62      }
63  
64      public KeySequenceBuilder append(String characterKeys)
65      {
66          for (char ch : characterKeys.toCharArray())
67          {
68              keys.add(keyFor(ch));
69              charKeys.add(ch);
70          }
71          return this;
72      }
73  
74      public KeySequenceBuilder append(Key... keys)
75      {
76          this.keys.addAll(Arrays.asList(keys));
77          return this;
78      }
79  
80      public KeySequenceBuilder append(Collection<Key> keys)
81      {
82          this.keys.addAll(keys);
83          return this;
84      }
85  
86      public KeySequenceBuilder withPressed(ModifierKey key)
87      {
88          pressed.add(key);
89          return this;
90      }
91  
92      public KeySequenceBuilder keyEvents(KeyEventType... events)
93      {
94          this.events = toEnumSet(Arrays.asList(events));
95          return this;
96      }
97  
98      public KeySequenceBuilder keyEvents(Collection<KeyEventType> events)
99      {
100         this.events = toEnumSet(events);
101         return this;
102     }
103 
104     public Set<KeyEventType> keyEvents()
105     {
106         return events.clone();
107     }
108 
109     private EnumSet<KeyEventType> toEnumSet(Collection<KeyEventType> events)
110     {
111         return events.isEmpty() ? EnumSet.noneOf(KeyEventType.class) : EnumSet.copyOf(events);
112     }
113 
114     public KeySequenceBuilder typeMode(TypeMode typeMode)
115     {
116         this.typeMode = checkNotNull(typeMode);
117         return this;
118     }
119 
120     public int size()
121     {
122         return keys.size();
123     }
124 
125     public KeySequence build()
126     {
127         if (keys.size() == charKeys.size())
128         {
129             return new CharacterKeySequence(buildString(), typeMode, pressed, events);
130         }
131         if (specialKeysOnly(keys))
132         {
133             return new SpecialKeysSequence(toSpecialKeys(), typeMode, pressed, events);
134         }
135         return new DefaultKeySequence(keys, typeMode, pressed, events);
136     }
137 
138     private boolean specialKeysOnly(final List<Key> keys)
139     {
140         for (Key key : keys)
141         {
142             if (!SpecialKeys.class.isInstance(key))
143             {
144                 return false;
145             }
146         }
147         return true;
148     }
149 
150     private List<SpecialKeys> toSpecialKeys()
151     {
152         return Lists.transform(keys, new Function<Key,SpecialKeys>()
153         {
154             public SpecialKeys apply(Key input)
155             {
156                 return (SpecialKeys) input;
157             }
158         });
159     }
160 
161     private String buildString()
162     {
163         StringBuilder answer = new StringBuilder(charKeys.size());
164         for (Character character : charKeys)
165         {
166             answer.append(character);
167         }
168         return answer.toString();
169     }
170 
171 
172     static Key keyFor(char ch)
173     {
174         Key fromCache = KEY_CACHE.get(ch);
175         if (fromCache != null)
176         {
177             return fromCache;
178         }
179         else
180         {
181             return new DefaultCharacterKey(ch);
182         }
183     }
184 
185     
186 
187 }