com.mapr.data.sputnik.RandomJsonGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.mapr.data.sputnik.RandomJsonGenerator.java

Source

/*
 * 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 com.mapr.data.sputnik;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mapr.data.sputnik.types.TypeHandler;
import com.mapr.data.sputnik.types.TypeHandlerFactory;
import com.mapr.data.sputnik.util.JsonUtils;
import com.mapr.data.sputnik.util.RandomDataGen;

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 org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 *
 * 
 */
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 JsonGeneratorFactory factory = Json.createGeneratorFactory(null);
    private Map<String, Object> generatedValues;
    private JsonUtils jsonUtils;
    private RandomDataGen rdg;

    public RandomJsonGenerator(Map<String, Object> config) {
        this.config = config;
        this.rdg = RandomDataGen.getInstance();
        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 if (specialFuncArgs.length == 2) {
                                int low = Integer.parseInt(specialFuncArgs[0]);
                                int high = Integer.parseInt(specialFuncArgs[1]);
                                timesToRepeat = rdg.randInt(low, high);
                            } else {
                                timesToRepeat = rdg.randInt(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(rdg.randInt(0, subList.size() - 1));
                            processItem(item, gen, newContext + "[0]");
                            break;
                        }
                        case "array": {
                            String largs = name.substring(name.indexOf("(") + 1, name.lastIndexOf(")"));
                            String dtype = largs.substring(0, largs.indexOf(")") + 1);
                            String[] arrayArgs = StringUtils
                                    .strip(largs.substring(largs.indexOf(")") + 1).trim(), ",").split(",");
                            int min = Integer.parseInt(arrayArgs[0]);
                            int max = Integer.parseInt(arrayArgs[1]);
                            min = min > max || min == max ? 0 : min;
                            try {
                                Map<String, Object> vals = new LinkedHashMap<String, Object>();
                                for (int i = min; i < max; i++) {
                                    TypeHandler th = TypeHandlerFactory.getInstance().getTypeHandler(dtype, vals,
                                            currentContext);
                                    if (th != null) {
                                        Object val = th.getNextRandomValue();
                                        addValue(gen, null, val);
                                    } else {
                                        addValue(gen, null, dtype);
                                    }
                                }
                            } catch (IllegalArgumentException iae) {
                                log.warn("Error creating type [ " + dtype + " ]. Prop [ " + propName
                                        + " ] being ignored in output.  Reason: " + iae.getMessage());
                                log.debug("Error creating type [ " + dtype + " ]. Prop [ " + propName
                                        + " ] being ignored in output.", iae);
                            }
                            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;
    }

}