Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package net.acesinc.data.json.generator; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.StringWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.json.Json; import javax.json.stream.JsonGenerator; import javax.json.stream.JsonGeneratorFactory; import net.acesinc.data.json.generator.types.TypeHandler; import net.acesinc.data.json.generator.types.TypeHandlerFactory; import net.acesinc.data.json.util.JsonUtils; import org.apache.commons.math3.random.RandomDataGenerator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; /** * * @author andrewserff */ public class RandomJsonGenerator { private static final Logger log = LogManager.getLogger(RandomJsonGenerator.class); private SimpleDateFormat iso8601DF = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); private Map<String, Object> config; private static JsonGeneratorFactory factory = Json.createGeneratorFactory(null); private Map<String, Object> generatedValues; private JsonUtils jsonUtils; public RandomJsonGenerator(Map<String, Object> config) { this.config = config; jsonUtils = new JsonUtils(); } public String generateJson() { StringWriter w = new StringWriter(); javax.json.stream.JsonGenerator gen = factory.createGenerator(w); generatedValues = new LinkedHashMap<>(); processProperties(gen, config, ""); gen.flush(); return w.toString(); } public String generateFlattnedJson() throws IOException { String json = generateJson(); return jsonUtils.flattenJson(json); } public Map<String, Object> generateJsonMap() throws IOException { String json = generateJson(); ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(json, Map.class); } public List<Map<String, Object>> generateJsonList() throws IOException { String json = generateJson(); ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(json, List.class); } private javax.json.stream.JsonGenerator processProperties(javax.json.stream.JsonGenerator gen, Map<String, Object> props, String currentContext) { // Map<String, Object> outputValues = new LinkedHashMap<>(); for (String propName : props.keySet()) { Object value = props.get(propName); if (value == null) { // outputValues.put(propName, null); generatedValues.put(currentContext + propName, null); addValue(gen, propName, null); } else if (String.class.isAssignableFrom(value.getClass())) { String type = (String) value; if (type.startsWith("this.") || type.startsWith("cur.")) { String refPropName = null; if (type.startsWith("this.")) { refPropName = type.substring("this.".length(), type.length()); } else if (type.startsWith("cur.")) { refPropName = currentContext + type.substring("cur.".length(), type.length()); } Object refPropValue = generatedValues.get(refPropName); if (refPropValue != null) { addValue(gen, propName, refPropValue); } else { log.warn("Sorry, unable to reference property [ " + refPropName + " ]. Maybe it hasn't been generated yet?"); } } else { try { TypeHandler th = TypeHandlerFactory.getInstance().getTypeHandler(type, generatedValues, currentContext); if (th != null) { Object val = th.getNextRandomValue(); // outputValues.put(propName, val); generatedValues.put(currentContext + propName, val); addValue(gen, propName, val); } else { // log.debug("Unknown Type: [ " + type + " ] for prop [ " + propName + " ]. Attempting to echo literal value."); // outputValues.put(propName, type); generatedValues.put(currentContext + propName, type); addValue(gen, propName, type); } } catch (IllegalArgumentException iae) { log.warn("Error creating type [ " + type + " ]. Prop [ " + propName + " ] being ignored in output. Reason: " + iae.getMessage()); log.debug("Error creating type [ " + type + " ]. Prop [ " + propName + " ] being ignored in output.", iae); } } } else if (Map.class.isAssignableFrom(value.getClass())) { //nested object Map<String, Object> nestedProps = (Map<String, Object>) value; if (propName == null) { gen.writeStartObject(); } else { gen.writeStartObject(propName); } String newContext = ""; if (propName != null) { if (currentContext.isEmpty()) { newContext = propName + "."; } else { newContext = currentContext + propName + "."; } } processProperties(gen, nestedProps, newContext); gen.writeEnd(); } else if (List.class.isAssignableFrom(value.getClass())) { //array List<Object> listOfItems = (List<Object>) value; String newContext = ""; if (propName != null) { gen.writeStartArray(propName); if (currentContext.isEmpty()) { newContext = propName; } else { newContext = currentContext + propName; } } else { gen.writeStartArray(); } if (!listOfItems.isEmpty()) { //Check if this is a special function at the start of the array if (String.class.isAssignableFrom(listOfItems.get(0).getClass()) && ((String) listOfItems.get(0)).contains("(")) { //special function in array String name = (String) listOfItems.get(0); String specialFunc = null; String[] specialFuncArgs = {}; specialFunc = name.substring(0, name.indexOf("(")); String args = name.substring(name.indexOf("(") + 1, name.indexOf(")")); if (!args.isEmpty()) { specialFuncArgs = args.split(","); } switch (specialFunc) { case "repeat": { int timesToRepeat = 1; if (specialFuncArgs.length == 1) { timesToRepeat = Integer.parseInt(specialFuncArgs[0]); } else { timesToRepeat = new RandomDataGenerator().nextInt(0, 10); } List<Object> subList = listOfItems.subList(1, listOfItems.size()); for (int i = 0; i < timesToRepeat; i++) { processList(subList, gen, newContext); } break; } case "random": { //choose one of the items in the list at random List<Object> subList = listOfItems.subList(1, listOfItems.size()); Object item = subList.get(new RandomDataGenerator().nextInt(0, subList.size() - 1)); processItem(item, gen, newContext + "[0]"); break; } } } else { //it's not a special function, so just add it processList(listOfItems, gen, newContext); } } gen.writeEnd(); } else { //literals generatedValues.put(currentContext + propName, value); addValue(gen, propName, value); } } return gen; } protected void processList(List<Object> listOfItems, JsonGenerator gen, String currentContext) { for (int i = 0; i < listOfItems.size(); i++) { Object item = listOfItems.get(i); String newContext = currentContext + "[" + i + "]"; processItem(item, gen, newContext); } } protected void processItem(Object item, JsonGenerator gen, String currentContext) { if (String.class.isAssignableFrom(item.getClass())) { //literal string, just add it addValue(gen, null, (String) item); generatedValues.put(currentContext, (String) item); } else if (Map.class.isAssignableFrom(item.getClass())) { Map<String, Object> nestedProps = (Map<String, Object>) item; gen.writeStartObject(); processProperties(gen, nestedProps, currentContext + "."); gen.writeEnd(); } } private javax.json.stream.JsonGenerator addValue(javax.json.stream.JsonGenerator gen, String propName, Object val) { if (val == null) { gen.writeNull(propName); } else if (String.class.isAssignableFrom(val.getClass())) { if (propName != null) { gen.write(propName, (String) val); } else { gen.write((String) val); } } else if (Boolean.class.isAssignableFrom(val.getClass())) { gen.write(propName, (Boolean) val); } else if (Long.class.isAssignableFrom(val.getClass())) { gen.write(propName, (Long) val); } else if (Integer.class.isAssignableFrom(val.getClass())) { gen.write(propName, (Integer) val); } else if (Double.class.isAssignableFrom(val.getClass())) { gen.write(propName, (Double) val); } else if (Date.class.isAssignableFrom(val.getClass())) { gen.write(propName, iso8601DF.format((Date) val)); } return gen; } }