assertj-swing
assertj-swing copied to clipboard
none-ASCII chars for key stroke mapping classes are not transferred correctly when clone from github
Issue by DaveBrad from Tuesday Jan 29, 2013 at 10:29 GMT Originally opened as https://github.com/alexruiz/fest-swing-1.x/issues/5
I've cloned from https://github.com/alexruiz/fest-swing-1.x.git into Netbeans (and a standalone directory to further confirm issue) and find errors against some files: [see below]
Also below is code to convert a key mapping file non-ASCII char to a numeric representation in hopes this will be useful in saving you time to create the update. It processes the whole Java file and saves it into a new file (saved).
Problem
org.fest.swing.keystroke. KeyStrokeMappingProvider_de.java KeyStrokeMappingProvider_fr.java KeyStrokeMappingProvider_mac_fr-FR.java
The issue appears to be with git doing something to the special characters for key stroke mappings that use none ASCII chars. Below is an example where the encoding is damaged (********** marked) when I git clone the repository. I've also cloned to a standalone (command line used) directory on windows 7 wijh the same problem.
Doing a compare to downloaded zip files of Fest-Swing1.2 and looking at the sources.jar you can see what the special characters are. If I copy/paste the affected lines from the sources.jar to the NetBeans Ide the special characters show correctly and okay.
I've googled git for UTF and encoding issues and only found issues pertaining to file names with UTF-8.
Do you have any idea as to the cause and a possible fix?
(Ideally, for key stroke mappings character shouldn't be used, but utf code values should be for none ASCII chars [as is pointed out by discussion on UTF-8/internationlization advocates]).
Thx anyone
Git cloned source
KeyStrokeMappingProvider_de.java
public Collection<KeyStrokeMapping> keyStrokeMappings() { List<KeyStrokeMapping> mappings = new ArrayList<KeyStrokeMapping>(120); mappings.addAll(defaultMappings()); mappings.add(mapping('0', VK_0, NO_MASK)); mappings.add(mapping('=', VK_0, SHIFT_MASK)); mappings.add(mapping('}', VK_0, ALT_GRAPH_MASK)); mappings.add(mapping('1', VK_1, NO_MASK)); mappings.add(mapping('!', VK_1, SHIFT_MASK)); mappings.add(mapping('2', VK_2, NO_MASK)); mappings.add(mapping('"', VK_2, SHIFT_MASK)); mappings.add(mapping('�', VK_2, ALT_GRAPH_MASK)); ************ mappings.add(mapping('3', VK_3, NO_MASK)); mappings.add(mapping('�', VK_3, SHIFT_MASK)); ************* mappings.add(mapping('�', VK_0, ALT_GRAPH_MASK)); ************* mappings.add(mapping('4', VK_4, NO_MASK)); mappings.add(mapping('$', VK_4, SHIFT_MASK)); mappings.add(mapping('5', VK_5, NO_MASK)); mappings.add(mapping('%', VK_5, SHIFT_MASK));
sources.jar code
public Collection<KeyStrokeMapping> keyStrokeMappings() { List<KeyStrokeMapping> mappings = new ArrayList<KeyStrokeMapping>(120); mappings.addAll(defaultMappings());
mappings.add(mapping('0', VK_0, NO_MASK)); mappings.add(mapping('=', VK_0, SHIFT_MASK)); mappings.add(mapping('}', VK_0, ALT_GRAPH_MASK)); mappings.add(mapping('1', VK_1, NO_MASK)); mappings.add(mapping('!', VK_1, SHIFT_MASK)); mappings.add(mapping('2', VK_2, NO_MASK)); mappings.add(mapping('"', VK_2, SHIFT_MASK)); mappings.add(mapping('²', VK_2, ALT_GRAPH_MASK)); *** correct mappings.add(mapping('3', VK_3, NO_MASK)); mappings.add(mapping('§', VK_3, SHIFT_MASK)); *** correct mappings.add(mapping('³', VK_0, ALT_GRAPH_MASK)); *** correct mappings.add(mapping('4', VK_4, NO_MASK)); mappings.add(mapping('$', VK_4, SHIFT_MASK)); mappings.add(mapping('5', VK_5, NO_MASK)); mappings.add(mapping('%', VK_5, SHIFT_MASK));
Solution for issue:
Code below will process a key mapping file and replace non-ascii chars with the code: (char)178
package Iso8859JavaProcessor.main;
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.ArrayList;
import javax.swing.JFileChooser;
/**
-
Class to convert ISO-8859-1 characters to numeric values for a format of
-
FEST-Swing KeyMappingProvider class java code. The whole file is input and
-
then output to another file with the conversion of only the special chars
-
changed.
-
-
For example:
-
mappings.add(mapping('²', VK_2, ALT_GRAPH_MASK));
-
converted to
-
mappings.add(mapping((char)178, VK_2, ALT_GRAPH_MASK));
-
the super-script 2 is an ALT+178
-
-
Via FileChooser provide an "OPEN" input file and then provide a "SAVE" output
-
file (different path). / public class ProcessingKeyMapperFESTSwing { /* encoding for processing file on read and any non-ASCII special chars */ private static String encodingCode = "ISO-8859-1";
/**
- convert the char in the quotes to a numeric
- mappings.add(mapping('?', VK_G, NO_MASK)); ->
- mappings.add(mapping((char)178, VK_G, NO_MASK)); // 178 -> ?
- NB: ? is a special char representation for comment purposes
-
*/ static String conversionFormat = "%s(char)%d%s";
/**
-
Main for application run.
-
@param args
-
arguments not used
*/ public static void main(String[] args) {
// perform the input file chooser JFileChooser inputFileChooser = new JFileChooser();
int returnVal = inputFileChooser.showOpenDialog(null);
// if the item is approved then may set the path for processing if (returnVal == JFileChooser.APPROVE_OPTION) {
File source = new File(inputFileChooser.getSelectedFile().getPath());
String filePathInput = source.getAbsolutePath();
if (filePathInput != null) { // process for the output file path JFileChooser outputFileChooser = new JFileChooser();
int returnValOutput = outputFileChooser.showSaveDialog(null); // if the item is approved then may set the path for processing if (returnValOutput == JFileChooser.APPROVE_OPTION) { File destination = new File(outputFileChooser .getSelectedFile().getPath()); String fileNameOut = destination.getAbsolutePath(); if (!fileNameOut.equals(filePathInput)) { processFile(filePathInput, fileNameOut); } else { System.out .println("input file and output file paths may not be the same"); } }
} } }
/**
-
Processing the input file to convert special chars to numeric values
-
(like ALT+178 for superscript 2).
-
@param inputFilePath
-
path of the input file
-
@param outFilePath
-
path of the output file
*/ public static void processFile(String inputFilePath, String outFilePath) {
ArrayList<String> codeArr = new ArrayList<String>();
readFile(inputFilePath, codeArr);
if (!checkFESTFile(codeArr)) { System.out .println("File is not considered a FEST key mapping file"); System.exit(99999); } KeyMappingJavaFile keyMappingJavaFile = new KeyMappingJavaFile();
keyMappingJavaFile.addCodeArr(codeArr);
keyMappingJavaFile.convertStrings();
ArrayList<String> outputArr = keyMappingJavaFile.outputStrings();
writeFile(outFilePath, outputArr); }
/**
-
Check if the source code being processed is in fact a FEST key stroke
-
mapping Java class code.
-
-
This is a best guess arrangement, where the code is on one line. If the
-
one line is commented this test does not work.
-
@param codeArr
-
code array of the file to convert
-
@return true is matches basic conditions */ private static boolean checkFESTFile(ArrayList<String> codeArr) { // ASSUMPTION all on the same line String festTest = "implements KeyStrokeMappingProvider";
for (String codeLine : codeArr) { if (codeLine.contains(festTest)) { return true; } } return false; }
/**
-
Read a string/text file and place the input into an array list.
-
@param fileFullPath
-
absolute file path
-
@param lineBuf
-
the array list line buffer
-
@return true if successful */ private static boolean readFile(String fileFullPath, ArrayList<String> lineBuf) { // this will read a file and store the lines into an array for // processing lineBuf.clear();
BufferedReader inputStream = null; try { FileInputStream fis = new FileInputStream(fileFullPath); InputStreamReader isr = new InputStreamReader(fis, encodingCode);
inputStream = new BufferedReader(isr);
// this inputs each line String input; while ((input = inputStream.readLine()) != null) { // copy the input into an array for processing at leisure lineBuf.add(input); } inputStream.close();
} catch (FileNotFoundException e) { return false;
} catch (IOException e) { e.printStackTrace(); return false; } return true; }
/**
-
Create a write a file to the file-path with the data provided and
-
processing and object array that contains strings. (The object array
-
array may be either a String[] or Object[]-of-string and will work.)
-
-
The public overlays for this action support string[] and
-
ArrayList<String> as input parameters. The design of this code
-
avoids/minimizes the conversion of either overlay to this method's
-
parameter using an ArrayCopy or other copying routines; thus providing a
-
better memory management architecture.)
-
@param filePath
-
absolute file path
-
@param lineOutArr
-
string array to write
-
@return true if successful */ private static boolean writeFile(String filePath, ArrayList<String> lineOutArr) { // the data should be in an array for writing PrintWriter outputStream = null;
try { FileOutputStream fos = new FileOutputStream(filePath); OutputStreamWriter osr = new OutputStreamWriter(fos, encodingCode);
outputStream = new PrintWriter(osr);
for (String strObj : lineOutArr) { outputStream.println(strObj); } outputStream.close(); outputStream = null;
} catch (IOException e) { e.printStackTrace(); return false; } finally { if (outputStream != null) { outputStream.close(); } } return true; } }
/**
-
Key mapping provider java code file to be processed. */ class KeyMappingJavaFile {
/** the lines of code array as input */ ArrayList<KeyMappingLineOfCode> fileLineOfCodeArr = new ArrayList<KeyMappingLineOfCode>();
/**
- add a line of code to the array
- @param lineStr
-
*/ public void addLine(String lineStr) { this.fileLineOfCodeArr.add(new KeyMappingLineOfCode(lineStr)); }string of line to add
/**
- add an array of lines of code to the object
- @param codeArr
-
*/ public void addCodeArr(ArrayList<String> codeArr) { for (String s : codeArr) { addLine(s); } }array list of code lines
/**
- Convert the input code lines that meet a special format into the special
- character needs necessary for compiling independent of Unicode chars in
- single quotes.
-
- mappings.add(mapping('g', VK_G, NO_MASK)); */ public void convertStrings() { for (KeyMappingLineOfCode k : this.fileLineOfCodeArr) { k.convertString4Output(); } }
/**
-
Output the converted strings for processing into an array list of
-
strings.
-
@return array list of strings */ public ArrayList<String> outputStrings() { ArrayList<String> outputArr = new ArrayList<String>();
for (KeyMappingLineOfCode k : this.fileLineOfCodeArr) { outputArr.add(k.outputConvertedString()); } return outputArr; } }
/**
-
Key mapping line of code for a single line with an input line and after
-
conversion an output line.
-
*/ class KeyMappingLineOfCode {
/** string for input of code line */ String inputLineStr;
/** string for output of code line */ String outputLineStr;
/**
- Create an object for a single line of code.
- @param inputCodeLine
-
*/ KeyMappingLineOfCode(String inputCodeLine) { this.inputLineStr = inputCodeLine; }line of code string
/**
-
Convert the input code line that meets a special format into the special
-
character needs necessary for compiling independent of Unicode chars in
-
single quotes.
-
-
mappings.add(mapping('g', VK_G, NO_MASK)); -> mappings.add(mapping('g', VK_G, NO_MASK));
-
mappings.add(mapping('?', VK_G, NO_MASK)); -> mappings.add(mapping(178, VK_G, NO_MASK));
-
-
- a 1st single-quote indicates a line needs to be checked for conversion
-
- if the char in the single-quotes is not an ASCII, assume a UTF special
-
character and convert to a numeric value instead of a '?' value
-
*/ public void convertString4Output() { CharsetEncoder asciiEncoder = Charset.forName("US-ASCII").newEncoder();
// assumptions only one single-quote in a line for mapping // // find the first single quote in the string int singleQuoteIdx = this.inputLineStr.indexOf("'");
// copy-line-as-is is a boolean that is set if a // line is not-a-line for conversion // // a conversion line would be consider to be: // - has a single-quote // - the char after the quote is non-ASCII // // mappings.add(mapping('?', VK_G, NO_MASK)); // // NB: ? is a special char representation for comment purposes // boolean copyLineAsIs = true;
if (singleQuoteIdx > -1) { // have a single-quote char c2Test = this.inputLineStr.charAt(singleQuoteIdx + 1);
// this is a boolean to force all conversions to be // applied to a numeric value. DEBUG testing arrangement. boolean alwaysNonAscii = false;
if (c2Test != '') { int d = (int) c2Test;
// if this is an ASCII char then the code line has no conversion // needed to be done if (!asciiEncoder.canEncode(c2Test) || alwaysNonAscii) { // convert the char in the quotes to a numeric // // mappings.add(mapping('?', VK_G, NO_MASK)); // -> mappings.add(mapping((char)178, VK_G, NO_MASK)); // // 178 -> ? // // NB: ? is a special char representation for comment // purposes // this.outputLineStr = String.format( ProcessingKeyMapperFESTSwing.conversionFormat, this.inputLineStr.substring(0, singleQuoteIdx), d, this.inputLineStr.substring(singleQuoteIdx + 3)); } else { // no conversion but the numeric maybe useful this.outputLineStr = this.inputLineStr; } // add a comment that provides the numeric and character // side-by-side this.outputLineStr = String.format("%s // %d .. %c", this.outputLineStr, d, c2Test); copyLineAsIs = false;
} } // retain lines as the same due to no conversion need if (copyLineAsIs) { this.outputLineStr = this.inputLineStr; } }
/**
-
Output the line in its converted form (maybe not have been converted).
-
@return string for new line */ public String outputConvertedString() { System.out.println(this.outputLineStr);
return this.outputLineStr; } }