Skip to content

Commit

Permalink
CAMEL-10969: Use json-simple as json parser in JSonSchemaHelper inste…
Browse files Browse the repository at this point in the history
…ad of our own home-ground parser.
  • Loading branch information
davsclaus committed Sep 24, 2017
1 parent c3dcb77 commit 63963fa
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 145 deletions.
12 changes: 12 additions & 0 deletions camel-core/pom.xml
Expand Up @@ -43,6 +43,7 @@
org.apache.camel.tools.*;resolution:=optional, org.apache.camel.tools.*;resolution:=optional,
!org.apache.camel.*, !org.apache.camel.*,
!com.github.benmanes.caffeine.cache, !com.github.benmanes.caffeine.cache,
!org.json.simple,
${camel.osgi.import.defaults}, ${camel.osgi.import.defaults},
org.springframework.transaction;resolution:=optional, org.springframework.transaction;resolution:=optional,
org.apache.camel.spring.spi;resolution:=optional, org.apache.camel.spring.spi;resolution:=optional,
Expand Down Expand Up @@ -133,6 +134,11 @@
<groupId>com.github.ben-manes.caffeine</groupId> <groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId> <artifactId>caffeine</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.github.cliftonlabs</groupId>
<artifactId>json-simple</artifactId>
<version>2.1.2</version>
</dependency>


<!-- required dependencies by camel-core --> <!-- required dependencies by camel-core -->
<dependency> <dependency>
Expand Down Expand Up @@ -246,6 +252,7 @@
<plugins> <plugins>


<!-- shade caffeine cache for faster Camel and spi-annotations as needed by everybody --> <!-- shade caffeine cache for faster Camel and spi-annotations as needed by everybody -->
<!-- shade json-simple for parsing Camel component JSon schema files -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
Expand All @@ -259,6 +266,7 @@
<artifactSet> <artifactSet>
<includes> <includes>
<include>com.github.ben-manes.caffeine:caffeine</include> <include>com.github.ben-manes.caffeine:caffeine</include>
<include>com.github.cliftonlabs:json-simple</include>
<include>org.apache.camel:spi-annotations</include> <include>org.apache.camel:spi-annotations</include>
</includes> </includes>
<excludes> <excludes>
Expand All @@ -270,6 +278,10 @@
<pattern>com.github.benmanes.caffeine</pattern> <pattern>com.github.benmanes.caffeine</pattern>
<shadedPattern>org.apache.camel.com.github.benmanes.caffeine</shadedPattern> <shadedPattern>org.apache.camel.com.github.benmanes.caffeine</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>org.json.simple</pattern>
<shadedPattern>org.apache.camel.org.json.simple</shadedPattern>
</relocation>
</relocations> </relocations>
</configuration> </configuration>
</execution> </execution>
Expand Down
Expand Up @@ -22,14 +22,11 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public final class JSonSchemaHelper { import org.json.simple.JsonObject;
import org.json.simple.Jsoner;


// 0 = text, 1 = enum, 2 = boolean, 3 = integer or number public final class JSonSchemaHelper {
private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)");
private static final String QUOT = "&quot;";


private JSonSchemaHelper() { private JSonSchemaHelper() {
} }
Expand All @@ -41,82 +38,62 @@ private JSonSchemaHelper() {
* @param json the json * @param json the json
* @return a list of all the rows, where each row is a set of key value pairs with metadata * @return a list of all the rows, where each row is a set of key value pairs with metadata
*/ */
@SuppressWarnings("unchecked")
public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) { public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
List<Map<String, String>> answer = new ArrayList<Map<String, String>>(); List<Map<String, String>> answer = new ArrayList<>();
if (json == null) { if (json == null) {
return answer; return answer;
} }


boolean found = false; // convert into a List<Map<String, String>> structure which is expected as output from this parser

JsonObject output = Jsoner.deserialize(json, new JsonObject());
// parse line by line for (String key : output.keySet()) {
String[] lines = json.split("\n"); Map row = output.getMap(key);
for (String line : lines) { if (key.equals(group)) {
// we need to find the group first if (parseProperties) {
if (!found) { // flattern each entry in the row with name as they key, and its value as the content (its a map also)
String s = line.trim(); for (Object obj : row.entrySet()) {
found = s.startsWith("\"" + group + "\":") && s.endsWith("{"); Map.Entry entry = (Map.Entry) obj;
continue; Map<String, String> newRow = new LinkedHashMap();
} newRow.put("name", entry.getKey().toString());


// we should stop when we end the group Map newData = transformMap((Map) entry.getValue());
if (line.equals(" },") || line.equals(" }")) { newRow.putAll(newData);
break; answer.add(newRow);
}

// need to safe encode \" so we can parse the line
line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"');

Map<String, String> row = new LinkedHashMap<String, String>();
Matcher matcher = PATTERN.matcher(line);

String key;
if (parseProperties) {
// when parsing properties the first key is given as name, so the first parsed token is the value of the name
key = "name";
} else {
key = null;
}
while (matcher.find()) {
if (key == null) {
key = matcher.group(1);
} else {
String value = matcher.group(1);
if (value != null) {
// its text based
value = value.trim();
// decode
value = value.replaceAll(QUOT, "\"");
value = decodeJson(value);
} }
if (value == null) { } else {
// not text then its maybe an enum? // flattern each entry in the row as a list of single Map<key, value> elements
value = matcher.group(2); Map newData = transformMap(row);
if (value != null) { for (Object obj : newData.entrySet()) {
// its an enum so strip out " and trim spaces after comma Map.Entry entry = (Map.Entry) obj;
value = value.replaceAll("\"", ""); Map<String, String> newRow = new LinkedHashMap<>();
value = value.replaceAll(", ", ","); newRow.put(entry.getKey().toString(), entry.getValue().toString());
value = value.trim(); answer.add(newRow);
}
}
if (value == null) {
// not text then its maybe a boolean?
value = matcher.group(3);
}
if (value == null) {
// not text then its maybe a integer?
value = matcher.group(4);
}
if (value != null) {
row.put(key, value);
} }
// reset
key = null;
} }
} }
if (!row.isEmpty()) { }
answer.add(row);
return answer;
}

private static Map<String, String> transformMap(Map jsonMap) {
Map<String, String> answer = new LinkedHashMap<>();

for (Object rowObj : jsonMap.entrySet()) {
Map.Entry rowEntry = (Map.Entry) rowObj;
// if its a list type then its an enum, and we need to parse it as a single line separated with comma
// to be backwards compatible
Object newValue = rowEntry.getValue();
if (newValue instanceof List) {
List list = (List) newValue;
CollectionStringBuffer csb = new CollectionStringBuffer(",");
for (Object line : list) {
csb.append(line);
}
newValue = csb.toString();
} }
answer.put(rowEntry.getKey().toString(), newValue.toString());
} }


return answer; return answer;
Expand Down
36 changes: 35 additions & 1 deletion platforms/camel-catalog/pom.xml
Expand Up @@ -34,7 +34,13 @@


<dependencies> <dependencies>


<!-- no dependency --> <!-- required dependencies by camel-catalog -->
<!-- which we shade into camel-catalog so its available for everybody out of the box -->
<dependency>
<groupId>com.github.cliftonlabs</groupId>
<artifactId>json-simple</artifactId>
<version>2.1.2</version>
</dependency>


<!-- testing --> <!-- testing -->
<dependency> <dependency>
Expand Down Expand Up @@ -162,6 +168,34 @@
</configuration> </configuration>
</plugin> </plugin>


<!-- shade caffeine cache for faster Camel and spi-annotations as needed by everybody -->
<!-- shade json-simple for parsing Camel component JSon schema files -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<artifactSet>
<includes>
<include>com.github.cliftonlabs:json-simple</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.json.simple</pattern>
<shadedPattern>org.apache.camel.org.json.simple</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>

<!-- generate and include all components in the catalog --> <!-- generate and include all components in the catalog -->
<plugin> <plugin>
<groupId>org.apache.camel</groupId> <groupId>org.apache.camel</groupId>
Expand Down
Expand Up @@ -22,14 +22,11 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public final class JSonSchemaHelper { import org.json.simple.JsonObject;
import org.json.simple.Jsoner;


// 0 = text, 1 = enum, 2 = boolean, 3 = integer or number public final class JSonSchemaHelper {
private static final Pattern PATTERN = Pattern.compile("\"(.+?)\"|\\[(.+)\\]|(true|false)|(-?\\d+\\.?\\d*)");
private static final String QUOT = "&quot;";


private JSonSchemaHelper() { private JSonSchemaHelper() {
} }
Expand All @@ -41,82 +38,62 @@ private JSonSchemaHelper() {
* @param json the json * @param json the json
* @return a list of all the rows, where each row is a set of key value pairs with metadata * @return a list of all the rows, where each row is a set of key value pairs with metadata
*/ */
@SuppressWarnings("unchecked")
public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) { public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
List<Map<String, String>> answer = new ArrayList<Map<String, String>>(); List<Map<String, String>> answer = new ArrayList<>();
if (json == null) { if (json == null) {
return answer; return answer;
} }


boolean found = false; // convert into a List<Map<String, String>> structure which is expected as output from this parser

JsonObject output = Jsoner.deserialize(json, new JsonObject());
// parse line by line for (String key : output.keySet()) {
String[] lines = json.split("\n"); Map row = output.getMap(key);
for (String line : lines) { if (key.equals(group)) {
// we need to find the group first if (parseProperties) {
if (!found) { // flattern each entry in the row with name as they key, and its value as the content (its a map also)
String s = line.trim(); for (Object obj : row.entrySet()) {
found = s.startsWith("\"" + group + "\":") && s.endsWith("{"); Map.Entry entry = (Map.Entry) obj;
continue; Map<String, String> newRow = new LinkedHashMap();
} newRow.put("name", entry.getKey().toString());


// we should stop when we end the group Map newData = transformMap((Map) entry.getValue());
if (line.equals(" },") || line.equals(" }")) { newRow.putAll(newData);
break; answer.add(newRow);
}

// need to safe encode \" so we can parse the line
line = line.replaceAll("\"\\\\\"\"", '"' + QUOT + '"');

Map<String, String> row = new LinkedHashMap<String, String>();
Matcher matcher = PATTERN.matcher(line);

String key;
if (parseProperties) {
// when parsing properties the first key is given as name, so the first parsed token is the value of the name
key = "name";
} else {
key = null;
}
while (matcher.find()) {
if (key == null) {
key = matcher.group(1);
} else {
String value = matcher.group(1);
if (value != null) {
// its text based
value = value.trim();
// decode
value = value.replaceAll(QUOT, "\"");
value = decodeJson(value);
} }
if (value == null) { } else {
// not text then its maybe an enum? // flattern each entry in the row as a list of single Map<key, value> elements
value = matcher.group(2); Map newData = transformMap(row);
if (value != null) { for (Object obj : newData.entrySet()) {
// its an enum so strip out " and trim spaces after comma Map.Entry entry = (Map.Entry) obj;
value = value.replaceAll("\"", ""); Map<String, String> newRow = new LinkedHashMap<>();
value = value.replaceAll(", ", ","); newRow.put(entry.getKey().toString(), entry.getValue().toString());
value = value.trim(); answer.add(newRow);
}
}
if (value == null) {
// not text then its maybe a boolean?
value = matcher.group(3);
}
if (value == null) {
// not text then its maybe a integer?
value = matcher.group(4);
}
if (value != null) {
row.put(key, value);
} }
// reset
key = null;
} }
} }
if (!row.isEmpty()) { }
answer.add(row);
return answer;
}

private static Map<String, String> transformMap(Map jsonMap) {
Map<String, String> answer = new LinkedHashMap<>();

for (Object rowObj : jsonMap.entrySet()) {
Map.Entry rowEntry = (Map.Entry) rowObj;
// if its a list type then its an enum, and we need to parse it as a single line separated with comma
// to be backwards compatible
Object newValue = rowEntry.getValue();
if (newValue instanceof List) {
List list = (List) newValue;
CollectionStringBuffer csb = new CollectionStringBuffer(",");
for (Object line : list) {
csb.append(line);
}
newValue = csb.toString();
} }
answer.put(rowEntry.getKey().toString(), newValue.toString());
} }


return answer; return answer;
Expand Down

0 comments on commit 63963fa

Please sign in to comment.