Clover Coverage Report - FEST Swing 1.2
Coverage timestamp: Tue Jun 1 2010 15:19:25 PDT
../../../../img/srcFileCovDistChart10.png 0% of files have more coverage
56   213   30   3.73
20   113   0.54   15
15     2  
1    
 
  KeyStrokeMappingsParser       Line # 76 56 0% 30 3 96.7% 0.96703297
 
No Tests
 
1    /*
2    * Created on Mar 12, 2010
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5    * the License. You may obtain a copy of the License at
6    *
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10    * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11    * specific language governing permissions and limitations under the License.
12    *
13    * Copyright @2010 the original author or authors.
14    */
15    package org.fest.swing.keystroke;
16   
17    import static java.lang.Thread.currentThread;
18    import static org.fest.reflect.core.Reflection.staticField;
19    import static org.fest.swing.keystroke.KeyStrokeMapping.mapping;
20    import static org.fest.swing.keystroke.KeyStrokeMappingProvider.NO_MASK;
21    import static org.fest.util.Closeables.close;
22    import static org.fest.util.Strings.*;
23   
24    import java.awt.event.InputEvent;
25    import java.awt.event.KeyEvent;
26    import java.io.*;
27    import java.util.*;
28   
29    import org.fest.reflect.exception.ReflectionError;
30    import org.fest.swing.exception.ParsingException;
31    import org.fest.util.VisibleForTesting;
32   
33    /**
34    * Understands creation of <code>{@link KeyStrokeMapping}</code>s by parsing a text file.
35    * <p>
36    * Mappings for the following characters:
37    * <ul>
38    * <li>Backspace</li>
39    * <li>Delete</li>
40    * <li>Enter</li>
41    * <li>Escape</li>
42    * <li>Tab</li>
43    * </ul>
44    * will be automatically added and should <strong>not</strong> be included to the file to parse.
45    * </p>
46    * <p>
47    * The following is an example of a mapping file:
48    *
49    * <pre>
50    * a, A, NO_MASK
51    * A, A, SHIFT_MASK
52    * COMMA, COMMA, NO_MASK
53    * </pre>
54    *
55    * Each line represents a character-keystroke mapping where each value is separated by a comma.
56    * <p>
57    * The first value represents the character to map. For example 'a' or 'A'. Since each field is separated by a comma, to
58    * map the ',' character we need to specify the text "COMMA."
59    * </p>
60    * <p>
61    * The second value represents the key code, which should be the name of a key code from <code>{@link KeyEvent}</code>
62    * without the prefix "VK_". For example, if the key code is <code>{@link KeyEvent#VK_COMMA}</code> we just need to
63    * specify "COMMA".
64    * </p>
65    * <p>
66    * The third value represents any modifiers to use, which should be the name of a modifier from
67    * <code>{@link InputEvent}</code>. For example, if the modifier to use is <code>{@link InputEvent#SHIFT_MASK}</code> we
68    * need to specify "SHIFT_MASK". If no modifiers are necessary, we just specify "NO_MASK".
69    * </p>
70    *
71    * @author Olivier DOREMIEUX
72    * @author Alex Ruiz
73    *
74    * @since 1.2
75    */
 
76    public class KeyStrokeMappingsParser {
77   
78    private static final Map<String, Character> SPECIAL_MAPPINGS = new HashMap<String, Character>();
79   
 
80  3 toggle static {
81  3 SPECIAL_MAPPINGS.put("COMMA", ',');
82    }
83   
84    /**
85    * Creates a <code>{@link KeyStrokeMappingProvider}</code> containing all the character-keystroke mappings specified
86    * in the file with the given name.
87    * <p>
88    * <strong>Note:</strong> This attempts to read the file using
89    * <code>{@link ClassLoader#getResourceAsStream(String)}</code>.
90    * </p>
91    * @param file the name of the file to parse.
92    * @return the created {@code KeyStrokeMappingProvider}.
93    * @throws NullPointerException if the given name is <code>null</code>.
94    * @throws IllegalArgumentException if the given name is empty.
95    * @throws ParsingException if any error occurs during parsing.
96    * @see #parse(File)
97    */
 
98  4 toggle public KeyStrokeMappingProvider parse(String file) {
99  4 validate(file);
100  2 try {
101  2 return parse(fileAsStream(file));
102    } catch (IOException e) {
103  0 throw new ParsingException(concat("An I/O error ocurred while parsing file ", file), e);
104    }
105    }
106   
 
107  4 toggle private void validate(String file) {
108  4 if (file == null)
109  1 throw new NullPointerException("The name of the file to parse should not be null");
110  3 if (isEmpty(file))
111  1 throw new IllegalArgumentException("The name of the file to parse should not be an empty string");
112    }
113   
 
114  2 toggle private InputStream fileAsStream(String file) {
115  2 InputStream stream = currentThread().getContextClassLoader().getResourceAsStream(file);
116  1 if (stream == null) throw new ParsingException(concat("Unable to open file ", file));
117  1 return stream;
118    }
119   
120    /**
121    * Creates a <code>{@link KeyStrokeMappingProvider}</code> containing all the character-keystroke mappings specified
122    * in the given file.
123    * @param file the file to parse.
124    * @return the created {@code KeyStrokeMappingProvider}.
125    * @throws NullPointerException if the given file is <code>null</code>.
126    * @throws IllegalArgumentException if the given file does not represent an existing file.
127    * @throws ParsingException if any error occurs during parsing.
128    */
 
129  3 toggle public KeyStrokeMappingProvider parse(File file) {
130  3 validate(file);
131  1 try {
132  1 return parse(fileAsStream(file));
133    } catch (IOException e) {
134  0 throw new ParsingException(concat("An I/O error ocurred while parsing file ", file), e);
135    }
136    }
137   
 
138  3 toggle private void validate(File file) {
139  3 if (file == null)
140  1 throw new NullPointerException("The file to parse should not be null");
141  2 if (!file.isFile())
142  1 throw new IllegalArgumentException(concat("The file ", file.getPath(), " is not an existing file"));
143    }
144   
 
145  1 toggle private InputStream fileAsStream(File file) {
146  1 try {
147  1 return new FileInputStream(file);
148    } catch (FileNotFoundException e) {
149  0 throw new ParsingException(concat("The file ", file.getPath(), " was not found"), e);
150    }
151    }
152   
 
153  2 toggle private KeyStrokeMappingProvider parse(InputStream input) throws IOException {
154  2 List<KeyStrokeMapping> mappings = new ArrayList<KeyStrokeMapping>();
155  2 BufferedReader reader = new BufferedReader(new InputStreamReader(input));
156  2 try {
157  2 String line = reader.readLine();
158  6 while(line != null) {
159  4 mappings.add(mappingFrom(line));
160  4 line = reader.readLine();
161    }
162  2 return new ParsedKeyStrokeMappingProvider(mappings);
163    } finally {
164  2 close(reader);
165    }
166    }
167   
 
168  13 toggle @VisibleForTesting
169    KeyStrokeMapping mappingFrom(String line) {
170  13 String[] parts = split(line);
171  1 if (parts.length != 3) throw notConformingWithPatternError(line);
172  12 char character = characterFrom(parts[0].trim());
173  11 int keyCode = keyCodeFrom(parts[1].trim());
174  10 int modifiers = modifiersFrom(parts[2].trim());
175  9 return mapping(character, keyCode, modifiers);
176    }
177   
 
178  13 toggle private static String[] split(String line) {
179  13 return line.trim().split(",");
180    }
181   
 
182  1 toggle private static ParsingException notConformingWithPatternError(String line) {
183  1 return new ParsingException(concat(
184    "Line ", quote(line), " does not conform with pattern '{char}, {keycode}, {modifiers}'"));
185    }
186   
 
187  12 toggle private static char characterFrom(String s) {
188  4 if (SPECIAL_MAPPINGS.containsKey(s)) return SPECIAL_MAPPINGS.get(s);
189  7 if (s.length() == 1) return s.charAt(0);
190  1 throw new ParsingException(concat("The text ", quote(s) , " should have a single character"));
191    }
192   
 
193  11 toggle private static int keyCodeFrom(String s) {
194  11 try {
195  11 return staticField(keyCodeNameFrom(s)).ofType(int.class).in(KeyEvent.class).get();
196    } catch (ReflectionError e) {
197  1 throw new ParsingException(concat("Unable to retrieve key code from text ", quote(s)), e.getCause());
198    }
199    }
200   
 
201  11 toggle private static String keyCodeNameFrom(String s) {
202  11 return concat("VK_", s);
203    }
204   
 
205  10 toggle private static int modifiersFrom(String s) {
206  7 if ("NO_MASK".equals(s)) return NO_MASK;
207  3 try {
208  3 return staticField(s).ofType(int.class).in(InputEvent.class).get();
209    } catch (ReflectionError e) {
210  1 throw new ParsingException(concat("Unable to retrieve modifiers from text ", quote(s)), e.getCause());
211    }
212    }
213    }