com.revo.deployr.client.util.RDataUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.revo.deployr.client.util.RDataUtil.java

Source

/*
 * RDataUtil.java
 *
 * Copyright (C) 2010-2016, Microsoft Corporation
 *
 * This program is licensed to you under the terms of Version 2.0 of the
 * Apache License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) for more details.
 *
 */
package com.revo.deployr.client.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.revo.deployr.client.RDataException;
import com.revo.deployr.client.data.*;
import com.revo.deployr.client.data.impl.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

// import org.codehaus.jackson.map.ObjectMapper;

/**
 * RDataUtil provides support for the following:
 * <p/>
 * <br/><br/>
 * 1. Builds RData from JSON.
 * <br/>
 * 2. Builds JSON from RData.
 * <br/>
 * 3. Builds JSON from List<RData>.
 */
public class RDataUtil {

    private static Log log = LogFactory.getLog(RDataUtil.class);

    public static RData fromJSON(String name, Map json) {

        RData rData = null;

        String type = (json.get("type") != null) ? (String) json.get("type") : "primitive";

        log.debug("fromJSON: name=" + name + " type=" + type + " json=" + json);

        if (type.equalsIgnoreCase("primitive")) {
            rData = buildPrimitiveFromJSON(name, json);
        } else if (type.equalsIgnoreCase("vector")) {
            rData = buildVectorFromJSON(name, json);
        } else if (type.equalsIgnoreCase("matrix")) {
            rData = buildMatrixFromJSON(name, json);
        } else if (type.equalsIgnoreCase("list")) {
            rData = buildListFromJSON(name, json);
        } else if (type.equalsIgnoreCase("dataframe")) {
            rData = buildDataFrameFromJSON(name, json);
        } else if (type.equalsIgnoreCase("factor")) {
            rData = buildFactorFromJSON(name, json);
        } else if (type.equalsIgnoreCase("date")) {
            rData = buildDateFromJSON(name, json);
        } else {
            // Support RData without a corresponding
            // Phoenix encoding as can be
            // returned on a RSession listObjects call.
            rData = buildSummaryFromJSON(name, json);
        }

        return rData;
    }

    public static String toJSON(RData rData) throws RDataException {

        Map<String, Object> pMap = new HashMap<String, Object>();
        Map<String, Object> pValues = new HashMap<String, Object>();
        pValues.put("type", rData.getType());
        pValues.put("rclass", rData.getRclass());
        pValues.put("value", getValueForJSON(rData));

        /*
          * RData special cases needs additional properties in markup.
         */
        if (rData instanceof RDate) {
            RDate rDate = (RDate) rData;
            pValues.put("format", rDate.getFormat());
        } else if (rData instanceof RDateVector) {
            RDateVector rDateVector = (RDateVector) rData;
            pValues.put("format", rDateVector.getFormat());
        } else if (rData instanceof RFactor) {
            RFactor pFactor = (RFactor) rData;
            if (pFactor.getLevels() != null)
                pValues.put("levels", pFactor.getLevels());
            if (pFactor.getLabels() != null)
                pValues.put("labels", pFactor.getLabels());
            pValues.put("ordered", pFactor.isOrdered());
        }

        pMap.put(rData.getName(), pValues);

        ObjectMapper mapper = new ObjectMapper();
        StringWriter writer = new StringWriter();

        String json = null;

        try {
            mapper.writeValue(writer, pMap);
            json = writer.toString();
        } catch (Exception ex) {
            log.warn("toJSON: exception writing RData, name=" + rData.getName() + " type=" + rData.getType()
                    + " to JSON.", ex);
            throw new RDataException("RData can be not be parsed into JSON, ex=" + ex.getMessage());
        }

        log.debug("toJSON: returning=" + json);
        return json;
    }

    public static String toJSON(List<RData> data) throws RDataException {

        Map<String, Object> pMap = new HashMap<String, Object>();

        for (RData rData : data) {

            Map<String, Object> pValues = new HashMap<String, Object>();
            pValues.put("type", rData.getType());
            pValues.put("rclass", rData.getRclass());
            pValues.put("value", getValueForJSON(rData));

            /*
             * RData special cases needs additional properties in markup.
             */
            if (rData instanceof RDate) {
                RDate rDate = (RDate) rData;
                pValues.put("format", rDate.getFormat());
            } else if (rData instanceof RDateVector) {
                RDateVector rDateVector = (RDateVector) rData;
                pValues.put("format", rDateVector.getFormat());
            } else if (rData instanceof RFactor) {
                RFactor pFactor = (RFactor) rData;
                if (pFactor.getLevels() != null)
                    pValues.put("levels", pFactor.getLevels());
                if (pFactor.getLabels() != null)
                    pValues.put("labels", pFactor.getLabels());
                pValues.put("ordered", pFactor.isOrdered());
            }

            pMap.put(rData.getName(), pValues);
        }

        ObjectMapper mapper = new ObjectMapper();
        StringWriter writer = new StringWriter();

        String json = null;

        try {
            mapper.writeValue(writer, pMap);
            json = writer.toString();
        } catch (Exception ex) {
            log.warn("toJSON: exception writing List<RData> to JSON.", ex);
            throw new RDataException("RData list can be not be parsed into JSON, ex=" + ex.getMessage());
        }

        log.debug("toJSON: List<RData> returning=" + json);
        return json;
    }

    private static RData buildPrimitiveFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");

        log.debug("buildPrimitiveFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " json=" + json);

        if (json.containsKey("value")) {

            Object value = json.get("value");

            log.debug("buildPrimitiveFromJSON: name=" + name + " has value=" + value);

            if ("character".equalsIgnoreCase(rclass)) {
                rData = new RStringImpl(name, value == null ? null : (String) value);
            } else if ("numeric".equalsIgnoreCase(rclass)) {
                rData = new RNumericImpl(name, value == null ? null : (Double) value);
            } else if ("logical".equalsIgnoreCase(rclass)) {
                rData = new RBooleanImpl(name, value == null ? null : (Boolean) value);
            }

            if (rData == null) {

                if (value instanceof Integer) {
                    rData = new RNumericImpl(name, ((Integer) value).doubleValue());
                } else if (value instanceof Double) {
                    rData = new RNumericImpl(name, (Double) value);
                } else if (value instanceof String) {
                    rData = new RStringImpl(name, (String) value);
                } else if (value instanceof Boolean) {
                    rData = new RBooleanImpl(name, (Boolean) value);
                } else {
                    // Indeterminate type, skip here to treat as RDataNA.
                }
            }
        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        if (rData == null) {
            rData = new RDataNAImpl(name, "vector");
        }

        log.debug("buildPrimitiveFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildVectorFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");
        String format = (String) json.get("format");

        log.debug("buildVectorFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " format=" + format
                + " json=" + json);

        if (format != null) {

            if (json.containsKey("value")) {

                List value = (List) json.get("value");
                log.debug("buildVectorFromJSON: name=" + name + " format=" + format + " has value=" + value);
                Iterator iter = value.iterator();

                List<Date> dates = new ArrayList<Date>();

                SimpleDateFormat sdf = new SimpleDateFormat(format);

                while (iter.hasNext()) {

                    Object found = iter.next();
                    if (found instanceof String) {

                        try {
                            Date date = sdf.parse((String) found);
                            dates.add(date);
                        } catch (Exception ex) {
                            log.debug(
                                    "buildVectorFromJSON: date sdf.parse format=${format} adding NULL because ex=${ex}");
                            ex.printStackTrace();
                            dates.add(null);
                        }
                    } else {
                        dates.add(null);
                    }
                }

                rData = new RDateVectorImpl(name, dates, format, rclass);
            }

        } else if (json.containsKey("value")) {

            List value = (List) json.get("value");

            log.debug("buildVectorFromJSON: name=" + name + " has value=" + value);

            if ("character".equalsIgnoreCase(rclass)) {
                rData = new RStringVectorImpl(name, value);
            } else if ("numeric".equalsIgnoreCase(rclass)) {
                rData = new RNumericVectorImpl(name, value);
            } else if ("logical".equalsIgnoreCase(rclass)) {
                rData = new RBooleanVectorImpl(name, value);
            }

            if (rData == null) {
                Iterator iter = value.iterator();

                // Loop to determine the "type" of context in the JSON vector.
                while (iter.hasNext()) {

                    Object found = iter.next();

                    if (found instanceof Integer) {
                        rData = new RNumericVectorImpl(name, value);
                    } else if (found instanceof Double) {
                        rData = new RNumericVectorImpl(name, value);
                    } else if (found instanceof String) {
                        rData = new RStringVectorImpl(name, value);
                    } else if (found instanceof Boolean) {
                        rData = new RBooleanVectorImpl(name, value);
                    } else {
                        // Indeterminate type, skip here allowing other value in vector to determine type.
                    }

                    if (rData != null)
                        break;
                }
            }

        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        if (rData == null) {
            rData = new RDataNAImpl(name, "vector");
        }

        log.debug("buildVectorFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildMatrixFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");

        log.debug("buildMatrixFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " json=" + json);

        if (json.containsKey("value")) {

            List value = (List) json.get("value");

            log.debug("buildMatrixFromJSON: name=" + name + " value=" + value);

            Iterator rows = value.iterator();

            // Loop to determine the "type" of context in the JSON matrix.
            while (rows.hasNext()) {

                List rowList = (List) rows.next();

                Iterator rowIterator = rowList.iterator();

                while (rowIterator.hasNext()) {

                    Object entry = rowIterator.next();

                    if (entry instanceof Integer) {
                        rData = new RNumericMatrixImpl(name, value);
                    } else if (entry instanceof Double) {
                        rData = new RNumericMatrixImpl(name, value);
                    } else if (entry instanceof String) {
                        rData = new RStringMatrixImpl(name, value);
                    } else if (entry instanceof Boolean) {
                        rData = new RBooleanMatrixImpl(name, value);
                    } else {
                        // Indeterminate type, skip here allowing other value in matrix to determine type.
                    }

                    if (rData != null)
                        break;
                }

                if (rData != null)
                    break;
            }

        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        if (rData == null) {
            rData = new RDataNAImpl(name, "matrix");
        }

        log.debug("buildMatrixFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildListFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");

        log.debug("buildListFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " json=" + json);

        if (json.containsKey("value")) {

            List<Map> values = (List<Map>) json.get("value");

            List<RData> listData = new ArrayList();

            for (Map entry : values) {

                // Recursively build RList from JSON.
                String entryName = (String) entry.get("name");
                RData dataItem = fromJSON(entryName, entry);
                listData.add(dataItem);
            }

            rData = new RListImpl(name, listData);

        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        log.debug("buildListFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildDataFrameFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");

        log.debug("buildDataFrameFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " json=" + json);

        if (json.containsKey("value")) {

            List<Map> values = (List<Map>) json.get("value");

            List<RData> frameData = new ArrayList();

            for (Map entry : values) {

                // Recursively build RDataFrame from JSON.
                String entryName = (String) entry.get("name");
                RData dataItem = fromJSON(entryName, entry);
                frameData.add(dataItem);
            }

            rData = new RDataFrameImpl(name, frameData);

        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        log.debug("buildDataFrameFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildFactorFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");

        log.debug("buildFactorFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " json=" + json);

        if (json.containsKey("value")) {

            List value = (List) json.get("value");
            List levels = (List) json.get("levels");
            List labels = (List) json.get("labels");
            boolean ordered = (Boolean) json.get("ordered");
            rData = new RFactorImpl(name, value, levels, labels, ordered, rclass);

        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        log.debug("buildFactorFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildDateFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");

        log.debug("buildDateFromJSON: name=" + name + " type=" + type + " rclass=" + rclass + " json=" + json);

        if (json.containsKey("value")) {

            String value = (String) json.get("value");
            String format = (String) json.get("format");

            if (value != null) {
                SimpleDateFormat sdf = new SimpleDateFormat(format);

                try {
                    Date date = sdf.parse(value);
                    rData = new RDateImpl(name, date, format, rclass);
                } catch (ParseException pex) {
                    rData = new RDataImpl(name, type, rclass);
                    log.warn("buildDateFromJSON: bad date results in NA, RDataImpl=" + rData);
                }
            } else {
                rData = new RDateImpl(name, null, format, rclass);
            }

        } else {

            rData = new RDataImpl(name, type, rclass);
        }

        log.debug("buildDateFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    private static RData buildSummaryFromJSON(String name, Map json) {

        RData rData = null;

        String type = (String) json.get("type");
        String rclass = (String) json.get("rclass");
        rData = new RDataImpl(name, type, rclass);
        log.debug("buildSummaryFromJSON: name=" + name + " returning=" + rData);
        return rData;
    }

    /**
     * Facilitate the building of valid Phoenix JSON.
     */
    private static Object getValueForJSON(RData rData) {

        if (rData instanceof RNumeric) {
            return ((RNumeric) rData).getValue();
        } else if (rData instanceof RString) {
            return ((RString) rData).getValue();
        } else if (rData instanceof RBoolean) {
            return ((RBoolean) rData).getValue();
        } else if (rData instanceof RNumericVector) {
            return ((RNumericVector) rData).getValue();
        } else if (rData instanceof RStringVector) {
            return ((RStringVector) rData).getValue();
        } else if (rData instanceof RDateVector) {
            RDateVector rDateVector = (RDateVector) rData;
            SimpleDateFormat sdf = new SimpleDateFormat(rDateVector.getFormat());
            List<Date> dates = rDateVector.getValue();
            List<String> dateValues = new ArrayList<String>();
            Iterator iter = dates.iterator();
            while (iter.hasNext()) {
                Date date = (Date) iter.next();
                String dateString = null;
                try {
                    dateString = sdf.format(date);
                } catch (Exception ex) {
                }
                dateValues.add(dateString);
            }
            return dateValues;
        } else if (rData instanceof RBooleanVector) {
            return ((RBooleanVector) rData).getValue();
        } else if (rData instanceof RNumericMatrix) {
            return ((RNumericMatrix) rData).getValue();
        } else if (rData instanceof RStringMatrix) {
            return ((RStringMatrix) rData).getValue();
        } else if (rData instanceof RBooleanMatrix) {
            return ((RBooleanMatrix) rData).getValue();
        } else if (rData instanceof RList) {
            RListImpl pList = (RListImpl) rData;
            List<Map> pListItems = new ArrayList<Map>();
            for (RData pChild : pList.getValue()) {
                pListItems.add(mapPDataValues(pChild, true));
            }
            return pListItems;
        } else if (rData instanceof RDataFrame) {
            RDataFrame pFrame = (RDataFrame) rData;
            List<Map> pFrameItems = new ArrayList<Map>();
            for (RData pChild : pFrame.getValue()) {
                pFrameItems.add(mapPDataValues(pChild, true));
            }
            return pFrameItems;
        } else if (rData instanceof RFactor) {
            return ((RFactor) rData).getValue();
        } else if (rData instanceof RDate) {
            RDate rDate = (RDate) rData;
            String format = rDate.getFormat();
            Date date = rDate.getValue();
            SimpleDateFormat sdf = new SimpleDateFormat(rDate.getFormat());
            String dateString = null;
            try {
                dateString = sdf.format(date);
            } catch (Exception ex) {
            }
            return dateString;
        } else
            return null;
    }

    /**
     * Facilitate the building of valid Phoenix JSON.
     */
    private static Map mapPDataValues(RData rData) {
        return mapPDataValues(rData, false);
    }

    private static Map mapPDataValues(RData rData, boolean mapForOrderedCollection) {
        Map<String, Object> pValues = new HashMap<String, Object>();
        if (mapForOrderedCollection)
            pValues.put("name", rData.getName());
        pValues.put("type", rData.getType());
        pValues.put("rclass", rData.getRclass());
        pValues.put("value", getValueForJSON(rData));

        if (rData instanceof RDate) {
            RDate rDate = (RDate) rData;
            pValues.put("format", rDate.getFormat());
        } else if (rData instanceof RDateVector) {
            RDateVector rDateVector = (RDateVector) rData;
            pValues.put("format", rDateVector.getFormat());
        } else if (rData instanceof RFactor) {
            RFactor pFactor = (RFactor) rData;
            if (pFactor.getLevels() != null)
                pValues.put("levels", pFactor.getLevels());
            if (pFactor.getLabels() != null)
                pValues.put("labels", pFactor.getLabels());
            pValues.put("ordered", pFactor.isOrdered());
        }

        return pValues;
    }
}