Skip to content

Commit

Permalink
fix escaping and unescaping of EXI4JSON keys
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpeintner committed Aug 24, 2016
1 parent 7bb8a8c commit 87b4dc1
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 15 deletions.
49 changes: 44 additions & 5 deletions src/main/java/com/siemens/ct/exi/json/EXIforJSONGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,8 @@ protected String escapeKey(String key) {
// --> Conflict with existing EXI4JSON global schema element name
key = String.valueOf(EXI4JSONConstants.ESCAPE_START_CHARACTER)
+ String.valueOf(EXI4JSONConstants.ESCAPE_END_CHARACTER) + key;
} else {
key = escapeNCNamePlus(key);
}

// TODO represent '_' itself
Expand Down Expand Up @@ -421,24 +423,61 @@ public static String escapeNCNamePlus(String name) {
// first character (special)
if (isLetter(c)) {
// OK
if (sb != null) {
sb.append(c);
}
} else if (c == '_') {
// valid NCName, but needs to be escaped for EXI4JSON

// NOT OK: valid NCName, but needs to be escaped for EXI4JSON
if (sb == null) {
sb = new StringBuilder();
}
sb.append("_95.");
} else {
// NOT OK
if (sb == null) {
sb = new StringBuilder();
}
sb.append(EXI4JSONConstants.ESCAPE_START_CHARACTER);
// Is this a UTF-16 surrogate pair?
if (Character.isHighSurrogate(c)) {
// use code-point and increment loop count (2 char's)
sb.append((int)name.codePointAt(i++));
} else {
sb.append((int)c);
}
sb.append(EXI4JSONConstants.ESCAPE_END_CHARACTER);
}
} else {
// rest of the characters

if (isNCNameChar(c)) {
// OK
if(c == '_') {
// update
// NOT OK: valid NCName, but needs to be escaped for EXI4JSON
if (sb == null) {
sb = new StringBuilder();
sb.append(name, 0, i);
}
sb.append("_95.");
} else {
// OK
if (sb != null) {
sb.append(c);
}
}
} else {
// Not OK, fix
if (sb == null) {
sb = new StringBuilder();
sb.append(name, 0, i);
}
sb.append(EXI4JSONConstants.ESCAPE_START_CHARACTER);
// Is this a UTF-16 surrogate pair?
if (Character.isHighSurrogate(c)) {
// use code-point and increment loop count (2 char's)
sb.append((int)name.codePointAt(i++));
} else {
sb.append((int)c);
}
sb.append(EXI4JSONConstants.ESCAPE_END_CHARACTER);
}
}
}
Expand Down
36 changes: 33 additions & 3 deletions src/main/java/com/siemens/ct/exi/json/EXIforJSONParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -320,14 +320,44 @@ protected void parseV2(InputStream isEXI4JSON, OutputStream osJSON) throws EXIEx
}

protected String unescapeKey(String key) {
StringBuilder sb = null;

// conflicting names
if(key.length() > 2 && key.charAt(0) == EXI4JSONConstants.ESCAPE_START_CHARACTER && key.charAt(1) == EXI4JSONConstants.ESCAPE_END_CHARACTER) {
key = key.substring(2);
} else {
// check whether there is an escape character
int i = 0;
while(i < key.length()) {
char c = key.charAt(i);
if(c == EXI4JSONConstants.ESCAPE_START_CHARACTER) {
int endIndex = key.indexOf(EXI4JSONConstants.ESCAPE_END_CHARACTER, i);
if(endIndex <= 0) {
throw new RuntimeException("Unexpected Escape Key: " + key);
} else {
int cp = Integer.parseInt(key.substring(i+1, endIndex));
if(sb == null) {
sb = new StringBuilder();
sb.append(key, 0, i);
}
sb.appendCodePoint(cp);
i += (endIndex-i);
}
} else {
// ok
if(sb != null) {
sb.append(c);
}
}
i++;
}
}
// TODO represent '_' itself
// TODO Conflict with NCName character(s)

return key;
if(sb == null) {
return key;
} else {
return sb.toString();
}
}

// public static void main(String[] args) throws EXIException, IOException {
Expand Down
47 changes: 40 additions & 7 deletions src/test/java/com/siemens/ct/exi/json/JSONDataTestsV2.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,14 @@ public void testEscapeKey1() throws EXIException, IOException, JSONException {
String key = EXI4JSONConstants.LOCALNAME_NUMBER; // "number"
EXIforJSONGenerator e4jGenerator = new EXIforJSONGenerator();
String ekey = e4jGenerator.escapeKey(key);

assertFalse(key.equals(ekey));
assertTrue((String.valueOf(EXI4JSONConstants.ESCAPE_START_CHARACTER)+String.valueOf(EXI4JSONConstants.ESCAPE_END_CHARACTER)+EXI4JSONConstants.LOCALNAME_NUMBER).equals(ekey));

assertTrue((String.valueOf(EXI4JSONConstants.ESCAPE_START_CHARACTER)
+ String.valueOf(EXI4JSONConstants.ESCAPE_END_CHARACTER) + EXI4JSONConstants.LOCALNAME_NUMBER)
.equals(ekey));

EXIforJSONParser e4jParser = new EXIforJSONParser();
String ukey = e4jParser.unescapeKey(ekey);

assertTrue(ukey.equals(key));
}

Expand All @@ -91,8 +92,10 @@ public void testEscapeKey2() throws EXIException, IOException, JSONException {

assertFalse(key.equals(ekey));
assertTrue("a_32.number".equals(ekey));

// TODO

EXIforJSONParser e4jParser = new EXIforJSONParser();
String ukey = e4jParser.unescapeKey(ekey);
assertTrue(ukey.equals(key));
}

@Test
Expand All @@ -103,8 +106,12 @@ public void testEscapeKey3() throws EXIException, IOException, JSONException {

assertFalse(key.equals(ekey));
assertTrue("_95.foo".equals(ekey));

EXIforJSONParser e4jParser = new EXIforJSONParser();
String ukey = e4jParser.unescapeKey(ekey);
assertTrue(ukey.equals(key));
}

@Test
public void testEscapeKey4() throws EXIException, IOException, JSONException {
String key = "foo_.A";
Expand All @@ -113,6 +120,32 @@ public void testEscapeKey4() throws EXIException, IOException, JSONException {

assertFalse(key.equals(ekey));
assertTrue("foo_95..A".equals(ekey));

EXIforJSONParser e4jParser = new EXIforJSONParser();
String ukey = e4jParser.unescapeKey(ekey);
assertTrue(ukey.equals(key));
}

@Test
public void testEscapeKey5() throws EXIException, IOException, JSONException {
// High surrogate pair
byte[] data = { 0, 0x41, // A
(byte) 0xD8, 1, // High surrogate
(byte) 0xDC, 2, // Low surrogate
0, 0x42, // B
};

String key = new String(data, "UTF-16");

EXIforJSONGenerator e4jGenerator = new EXIforJSONGenerator();
String ekey = e4jGenerator.escapeKey(key);

assertFalse(key.equals(ekey));
assertTrue("A_66562.B".equals(ekey));

EXIforJSONParser e4jParser = new EXIforJSONParser();
String ukey = e4jParser.unescapeKey(ekey);
assertTrue(ukey.equals(key));
}

}

0 comments on commit 87b4dc1

Please sign in to comment.