org.apache.geode.management.internal.cli.domain.DataCommandResult.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.geode.management.internal.cli.domain.DataCommandResult.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.management.internal.cli.domain;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;

import org.apache.geode.DataSerializer;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.internal.cli.GfshParser;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.json.GfJsonException;
import org.apache.geode.management.internal.cli.json.GfJsonObject;
import org.apache.geode.management.internal.cli.result.CompositeResultData;
import org.apache.geode.management.internal.cli.result.CompositeResultData.SectionResultData;
import org.apache.geode.management.internal.cli.result.ResultBuilder;
import org.apache.geode.management.internal.cli.result.TabularResultData;
import org.apache.geode.management.internal.cli.util.JsonUtil;

/**
 * Domain object used for Data Commands Functions
 */
public class DataCommandResult implements Serializable {
    private static Logger logger = LogManager.getLogger();

    private static final long serialVersionUID = 1L;
    private String command;
    private Object putResult;
    private Object getResult;
    private List<SelectResultRow> selectResult;
    private String queryTraceString;

    public static final String QUERY_PAGE_START = "startCount";
    public static final String QUERY_PAGE_END = "endCount";
    public static final String QUERY_TRACE = "Query Trace";

    public static final String RESULT_FLAG = "Result";
    public static final String NUM_ROWS = "Rows";

    public static final String MISSING_VALUE = "<NULL>";

    // Aggregated Data.
    private List<KeyInfo> locateEntryLocations;
    private KeyInfo locateEntryResult;
    private boolean hasResultForAggregation;

    private Object removeResult;
    private Object inputKey;
    private Object inputValue;
    private Object inputQuery;
    private Throwable error;
    private String errorString;
    private String infoString;
    private String keyClass;
    private String valueClass;
    private int limit;
    private boolean operationCompletedSuccessfully; // used for validation purposes.

    public static final String NEW_LINE = GfshParser.LINE_SEPARATOR;

    public String toString() {
        StringBuilder sb = new StringBuilder();
        if (isGet()) {
            sb.append(" Type  : Get").append(NEW_LINE);
            sb.append(" Key  : ").append(inputKey).append(NEW_LINE);
            if (getResult != null) {
                sb.append(" ReturnValue Class : ").append(getResult.getClass()).append(NEW_LINE);
            }
            sb.append(" ReturnValue : ").append(getResult).append(NEW_LINE);
        } else if (isPut()) {
            sb.append(" Type  : Put");
            sb.append(" Key  : ").append(inputKey).append(NEW_LINE);
            if (putResult != null) {
                sb.append(" ReturnValue Class : ").append(putResult.getClass()).append(NEW_LINE);
            }
            sb.append(" ReturnValue  : ").append(putResult).append(NEW_LINE);
            sb.append(" Value  : ").append(inputValue).append(NEW_LINE);
        } else if (isRemove()) {
            sb.append(" Type  : Remove");
            sb.append(" Key  : ").append(inputKey).append(NEW_LINE);
            if (removeResult != null) {
                sb.append(" ReturnValue Class : ").append(removeResult.getClass()).append(NEW_LINE);
            }
            sb.append(" ReturnValue  : ").append(removeResult).append(NEW_LINE);
        } else if (isLocateEntry()) {
            sb.append(" Type  : Locate Entry");
            sb.append(" Key  : ").append(inputKey).append(NEW_LINE);
            // Assume here that this is aggregated result
            sb.append(" Results  : ").append(locateEntryResult).append(NEW_LINE);
            sb.append(" Locations  : ").append(locateEntryLocations).append(NEW_LINE);
        }
        if (errorString != null) {
            sb.append(" ERROR ").append(errorString);
        }
        return sb.toString();
    }

    public boolean isGet() {
        return CliStrings.GET.equals(command);
    }

    public boolean isPut() {
        return CliStrings.PUT.equals(command);
    }

    public boolean isRemove() {
        return CliStrings.REMOVE.equals(command);
    }

    public boolean isLocateEntry() {
        return CliStrings.LOCATE_ENTRY.equals(command);
    }

    public boolean isSelect() {
        return CliStrings.QUERY.equals(command);
    }

    public List<SelectResultRow> getSelectResult() {
        return selectResult;
    }

    public static DataCommandResult createGetResult(Object inputKey, Object value, Throwable error,
            String errorString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.GET;
        result.inputKey = inputKey;
        result.getResult = value;
        result.error = error;
        result.errorString = errorString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createGetInfoResult(Object inputKey, Object value, Throwable error,
            String infoString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.GET;
        result.inputKey = inputKey;
        result.getResult = value;
        result.error = error;
        result.infoString = infoString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createLocateEntryResult(Object inputKey, KeyInfo locationResult,
            Throwable error, String errorString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.LOCATE_ENTRY;
        result.inputKey = inputKey;

        if (flag) {
            result.hasResultForAggregation = true;
        }

        result.locateEntryResult = locationResult;

        result.error = error;
        result.errorString = errorString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createLocateEntryInfoResult(Object inputKey, KeyInfo locationResult,
            Throwable error, String infoString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.LOCATE_ENTRY;
        result.inputKey = inputKey;

        if (flag) {
            result.hasResultForAggregation = true;
        }

        result.locateEntryResult = locationResult;

        result.error = error;
        result.infoString = infoString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createPutResult(Object inputKey, Object value, Throwable error,
            String errorString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.PUT;
        result.inputKey = inputKey;
        result.putResult = value;
        result.error = error;
        result.errorString = errorString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createPutInfoResult(Object inputKey, Object value, Throwable error,
            String infoString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.PUT;
        result.inputKey = inputKey;
        result.putResult = value;
        result.error = error;
        result.infoString = infoString;
        return result;
    }

    public static DataCommandResult createRemoveResult(Object inputKey, Object value, Throwable error,
            String errorString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.REMOVE;
        result.inputKey = inputKey;
        result.removeResult = value;
        result.error = error;
        result.errorString = errorString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createRemoveInfoResult(Object inputKey, Object value, Throwable error,
            String infoString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.REMOVE;
        result.inputKey = inputKey;
        result.removeResult = value;
        result.error = error;
        result.infoString = infoString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createSelectResult(Object inputQuery, List<SelectResultRow> value,
            String queryTraceString, Throwable error, String errorString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.QUERY;
        result.inputQuery = inputQuery;
        result.queryTraceString = queryTraceString;
        result.selectResult = value;
        result.error = error;
        result.errorString = errorString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public static DataCommandResult createSelectInfoResult(Object inputQuery, List<SelectResultRow> value,
            int limit, Throwable error, String infoString, boolean flag) {
        DataCommandResult result = new DataCommandResult();
        result.command = CliStrings.QUERY;
        result.inputQuery = inputQuery;
        result.limit = limit;
        result.selectResult = value;
        result.error = error;
        result.infoString = infoString;
        result.operationCompletedSuccessfully = flag;
        return result;
    }

    public String getCommand() {
        return command;
    }

    public void setCommand(String command) {
        this.command = command;
    }

    public Object getPutResult() {
        return putResult;
    }

    public void setPutResult(Object putResult) {
        this.putResult = putResult;
    }

    public Object getGetResult() {
        return getResult;
    }

    public void setGetResult(Object getResult) {
        this.getResult = getResult;
    }

    public Object getRemoveResult() {
        return removeResult;
    }

    public void setRemoveResult(Object removeResult) {
        this.removeResult = removeResult;
    }

    public Object getInputKey() {
        return inputKey;
    }

    public void setInputKey(Object inputKey) {
        this.inputKey = inputKey;
    }

    public Object getInputValue() {
        return inputValue;
    }

    public void setInputValue(Object inputValue) {
        this.inputValue = inputValue;
    }

    public Throwable getErorr() {
        return error;
    }

    public void setErorr(Throwable erorr) {
        this.error = erorr;
    }

    public String getErrorString() {
        return errorString;
    }

    public void setErrorString(String errorString) {
        this.errorString = errorString;
    }

    public String getInfoString() {
        return infoString;
    }

    public void setInfoString(String infoString) {
        this.infoString = infoString;
    }

    public String getKeyClass() {
        return keyClass;
    }

    public void setKeyClass(String keyClass) {
        this.keyClass = keyClass;
    }

    public String getValueClass() {
        return valueClass;
    }

    public void setValueClass(String valueClass) {
        this.valueClass = valueClass;
    }

    public List<KeyInfo> getLocateEntryLocations() {
        return locateEntryLocations;
    }

    public void setLocateEntryLocations(List<KeyInfo> locateEntryLocations) {
        this.locateEntryLocations = locateEntryLocations;
    }

    public Result toCommandResult() {

        if (StringUtils.isEmpty(keyClass)) {
            keyClass = "java.lang.String";
        }

        if (StringUtils.isEmpty(valueClass)) {
            valueClass = "java.lang.String";
        }

        if (errorString != null) {
            CompositeResultData data = ResultBuilder.createCompositeResultData();
            SectionResultData section = data.addSection();
            section.addData("Message", errorString);
            section.addData(RESULT_FLAG, operationCompletedSuccessfully);
            return ResultBuilder.buildResult(data);
        }

        CompositeResultData data = ResultBuilder.createCompositeResultData();
        SectionResultData section = data.addSection();
        TabularResultData table = section.addTable();

        section.addData(RESULT_FLAG, operationCompletedSuccessfully);
        if (infoString != null) {
            section.addData("Message", infoString);
        }

        if (isGet()) {
            toCommandResult_isGet(section, table);
        } else if (isLocateEntry()) {
            toCommandResult_isLocate(section, table);
        } else if (isPut()) {
            toCommandResult_isPut(section, table);
        } else if (isRemove()) {
            toCommandResult_isRemove(section, table);
        }
        return ResultBuilder.buildResult(data);
    }

    private void toCommandResult_isGet(SectionResultData section, TabularResultData table) {
        section.addData("Key Class", getKeyClass());
        if (!isDeclaredPrimitive(keyClass)) {
            addJSONStringToTable(table, inputKey);
        } else {
            section.addData("Key", inputKey);
        }

        section.addData("Value Class", getValueClass());
        if (!isDeclaredPrimitive(valueClass)) {
            addJSONStringToTable(table, getResult);
        } else {
            section.addData("Value", getResult);
        }
    }

    private void toCommandResult_isLocate(SectionResultData section, TabularResultData table) {

        section.addData("Key Class", getKeyClass());
        if (!isDeclaredPrimitive(keyClass)) {
            addJSONStringToTable(table, inputKey);
        } else {
            section.addData("Key", inputKey);
        }

        if (locateEntryLocations != null) {
            TabularResultData locationTable = section.addTable();

            int totalLocations = 0;

            for (KeyInfo info : locateEntryLocations) {
                List<Object[]> locations = info.getLocations();

                if (locations != null) {
                    if (locations.size() == 1) {
                        Object array[] = locations.get(0);
                        boolean found = (Boolean) array[1];
                        if (found) {
                            totalLocations++;
                            boolean primary = (Boolean) array[3];
                            String bucketId = (String) array[4];
                            locationTable.accumulate("MemberName", info.getMemberName());
                            locationTable.accumulate("MemberId", info.getMemberId());
                            if (bucketId != null) {// PR
                                if (primary) {
                                    locationTable.accumulate("Primary", "*Primary PR*");
                                } else {
                                    locationTable.accumulate("Primary", "No");
                                }
                                locationTable.accumulate("BucketId", bucketId);
                            }
                        }
                    } else {
                        for (Object[] array : locations) {
                            String regionPath = (String) array[0];
                            boolean found = (Boolean) array[1];
                            if (found) {
                                totalLocations++;
                                boolean primary = (Boolean) array[3];
                                String bucketId = (String) array[4];
                                locationTable.accumulate("MemberName", info.getMemberName());
                                locationTable.accumulate("MemberId", info.getMemberId());
                                locationTable.accumulate("RegionPath", regionPath);
                                if (bucketId != null) {// PR
                                    if (primary) {
                                        locationTable.accumulate("Primary", "*Primary PR*");
                                    } else {
                                        locationTable.accumulate("Primary", "No");
                                    }
                                    locationTable.accumulate("BucketId", bucketId);
                                }
                            }
                        }
                    }
                }
            }
            section.addData("Locations Found", totalLocations);
        } else {
            section.addData("Location Info ", "Could not find location information");
        }
    }

    private void toCommandResult_isPut(SectionResultData section, TabularResultData table) {
        section.addData("Key Class", getKeyClass());

        if (!isDeclaredPrimitive(keyClass)) {
            addJSONStringToTable(table, inputKey);
        } else {
            section.addData("Key", inputKey);
        }

        section.addData("Value Class", getValueClass());
        if (!isDeclaredPrimitive(valueClass)) {
            addJSONStringToTable(table, putResult);
        } else {
            section.addData("Old Value", putResult);
        }

    }

    private void toCommandResult_isRemove(SectionResultData section, TabularResultData table) {
        if (inputKey != null) {// avoids printing key when remove ALL is called
            section.addData("Key Class", getKeyClass());
            if (!isDeclaredPrimitive(keyClass)) {
                addJSONStringToTable(table, inputKey);
            } else {
                section.addData("Key", inputKey);
            }
        }
    }

    /**
     * This method returns result when flag interactive=false i.e. Command returns result in one go
     * and does not goes through steps waiting for user input. Method returns CompositeResultData
     * instead of Result as Command Step is required to add NEXT_STEP information to guide
     * executionStrategy to route it through final step.
     */
    public CompositeResultData toSelectCommandResult() {
        if (errorString != null) {
            CompositeResultData data = ResultBuilder.createCompositeResultData();
            SectionResultData section = data.addSection();
            section.addData("Message", errorString);
            section.addData(RESULT_FLAG, operationCompletedSuccessfully);
            return data;
        } else {
            CompositeResultData data = ResultBuilder.createCompositeResultData();
            SectionResultData section = data.addSection();
            TabularResultData table = section.addTable();
            section.addData(RESULT_FLAG, operationCompletedSuccessfully);
            if (infoString != null) {
                section.addData("Message", infoString);
            }
            if (inputQuery != null) {
                if (this.limit > 0) {
                    section.addData("Limit", this.limit);
                }
                if (this.selectResult != null) {
                    section.addData(NUM_ROWS, this.selectResult.size());
                    if (this.queryTraceString != null) {
                        section.addData("Query Trace", this.queryTraceString);
                    }
                    buildTable(table, 0, selectResult.size());
                }
            }
            return data;
        }
    }

    private int buildTable(TabularResultData table, int startCount, int endCount) {
        // Three steps:
        // 1a. Convert each row object to a Json object.
        // 1b. Build a list of keys that are used for each object
        // 2. Pad MISSING_VALUE into Json objects for those data that are missing any particular key
        // 3. Build the table from these Json objects.

        // 1.
        int lastRowExclusive = Math.min(selectResult.size(), endCount + 1);
        List<SelectResultRow> paginatedRows = selectResult.subList(startCount, lastRowExclusive);

        List<GfJsonObject> tableRows = new ArrayList<>();
        List<GfJsonObject> rowsWithRealJsonObjects = new ArrayList<>();
        Set<String> columns = new HashSet<>();

        for (SelectResultRow row : paginatedRows) {
            GfJsonObject object = new GfJsonObject();
            try {
                if (row.value == null || MISSING_VALUE.equals(row.value)) {
                    object.put("Value", MISSING_VALUE);
                } else if (row.type == ROW_TYPE_PRIMITIVE) {
                    object.put(RESULT_FLAG, row.value);
                } else {
                    object = buildGfJsonFromRawObject(row.value);
                    rowsWithRealJsonObjects.add(object);
                    object.keys().forEachRemaining(columns::add);
                }
                tableRows.add(object);
            } catch (GfJsonException e) {
                JSONObject errJson = new JSONObject().put("Value",
                        "Error getting bean properties " + e.getMessage());
                tableRows.add(new GfJsonObject(errJson, false));
            }
        }

        // 2.
        for (GfJsonObject tableRow : rowsWithRealJsonObjects) {
            for (String key : columns) {
                if (!tableRow.has(key)) {
                    try {
                        tableRow.put(key, MISSING_VALUE);
                    } catch (GfJsonException e) {
                        logger.warn("Ignored GfJsonException:", e);
                    }
                }
            }
        }

        // 3.
        for (GfJsonObject jsonObject : tableRows) {
            addJSONObjectToTable(table, jsonObject);
        }

        return paginatedRows.size();
    }

    private boolean isDeclaredPrimitive(String keyClass2) {
        try {
            Class klass = ClassPathLoader.getLatest().forName(keyClass2);
            return JsonUtil.isPrimitiveOrWrapper(klass);
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    private Object getDomainValue(Object value) {
        if (value instanceof String) {
            String str = (String) value;
            if (str.contains("{") && str.contains("}")) {// small filter to see if its json string
                try {
                    JSONObject json = new JSONObject(str);
                    return json.get("type-class");
                } catch (Exception e) {
                    return str;
                }
            } else {
                return str;
            }
        }
        return value;
    }

    public Object getInputQuery() {
        return inputQuery;
    }

    public void setInputQuery(Object inputQuery) {
        this.inputQuery = inputQuery;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

    public static class KeyInfo implements /* Data */ Serializable {

        private String memberId;
        private String memberName;
        private String host;
        private int pid;

        // Indexes : regionName = 0, found=1, value=2 primary=3 bucketId=4
        private ArrayList<Object[]> locations = null;

        public void addLocation(Object[] locationArray) {
            if (this.locations == null) {
                locations = new ArrayList<>();
            }

            locations.add(locationArray);
        }

        public List<Object[]> getLocations() {
            return locations;
        }

        public String getMemberId() {
            return memberId;
        }

        public void setMemberId(String memberId) {
            this.memberId = memberId;
        }

        public String getMemberName() {
            return memberName;
        }

        public void setMemberName(String memberName) {
            this.memberName = memberName;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public int getPid() {
            return pid;
        }

        public void setPid(int pid) {
            this.pid = pid;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("{ Member : ").append(host).append("(").append(memberId).append(") , ");
            for (Object[] array : locations) {
                boolean primary = (Boolean) array[3];
                String bucketId = (String) array[4];
                sb.append(" [ Primary : ").append(primary).append(" , BucketId : ").append(bucketId).append(" ]");
            }
            sb.append(" }");
            return sb.toString();
        }

        public boolean hasLocation() {
            if (locations == null) {
                return false;
            } else {
                for (Object[] array : locations) {
                    boolean found = (Boolean) array[1];
                    if (found) {
                        return true;
                    }
                }
            }
            return false;
        }

        // @Override
        public void toData(DataOutput out) throws IOException {
            DataSerializer.writeString(memberId, out);
            DataSerializer.writeString(memberName, out);
            DataSerializer.writeString(host, out);
            DataSerializer.writePrimitiveInt(pid, out);
            DataSerializer.writeArrayList(locations, out);

        }

        // @Override
        public void fromData(DataInput in) throws IOException, ClassNotFoundException {
            memberId = DataSerializer.readString(in);
            memberName = DataSerializer.readString(in);
            host = DataSerializer.readString(in);
            pid = DataSerializer.readPrimitiveInt(in);
            locations = DataSerializer.readArrayList(in);
        }
    }

    public static final int ROW_TYPE_STRUCT_RESULT = 100;
    public static final int ROW_TYPE_BEAN = 200;
    public static final int ROW_TYPE_PRIMITIVE = 300;

    public static class SelectResultRow implements Serializable {
        private static final long serialVersionUID = 1L;
        private int type;
        private Object value;

        public SelectResultRow(int type, Object value) {
            this.type = type;
            this.value = value;
        }

        public int getType() {
            return type;
        }

        public void setType(int type) {
            this.type = type;
        }

        public Object getValue() {
            return value;
        }

        public void setValue(Object value) {
            this.value = value;
        }

    }

    public void aggregate(DataCommandResult result) {
        /* Right now only called for LocateEntry */
        if (!isLocateEntry()) {
            return;
        }

        if (this.locateEntryLocations == null) {
            locateEntryLocations = new ArrayList<>();
        }

        if (result == null) {// self-transform result from single to aggregate when numMember==1
            if (this.locateEntryResult != null) {
                locateEntryLocations.add(locateEntryResult);
            }
            return;
        }

        if (result.errorString != null && !result.errorString.equals(errorString)) {
            // append errorString only if differs
            errorString = result.errorString + " " + errorString;
        }

        // append message only when it differs for negative results
        if (!operationCompletedSuccessfully && result.infoString != null && !result.infoString.equals(infoString)) {
            infoString = result.infoString;
        }

        if (result.hasResultForAggregation) {
            this.operationCompletedSuccessfully = true;
            infoString = result.infoString;
            if (result.locateEntryResult != null) {
                locateEntryLocations.add(result.locateEntryResult);
            }
        }
    }

    private void addJSONObjectToTable(TabularResultData table, GfJsonObject object) {
        Iterator<String> keys;

        keys = object.keys();
        while (keys.hasNext()) {
            String k = keys.next();
            // filter out meta-field type-class used to identify java class of json object
            if (!"type-class".equals(k)) {
                Object value = object.get(k);

                if (value != null) {
                    table.accumulate(k, getDomainValue(value));
                }
            }
        }
    }

    private GfJsonObject buildGfJsonFromRawObject(Object object) throws GfJsonException {
        GfJsonObject jsonObject;
        if (String.class.equals(object.getClass())) {
            jsonObject = new GfJsonObject(sanitizeJsonString((String) object));
        } else {
            jsonObject = new GfJsonObject(object, true);
        }

        return jsonObject;
    }

    private String sanitizeJsonString(String s) {
        // InputString in JSON Form but with round brackets
        String newString = s.replaceAll("'", "\"");
        if (newString.charAt(0) == '(') {
            int len = newString.length();
            newString = "{" + newString.substring(1, len - 1) + "}";
        }
        return newString;
    }

    private void addJSONStringToTable(TabularResultData table, Object object) {
        if (object == null || MISSING_VALUE.equals(object)) {
            table.accumulate("Value", MISSING_VALUE);
        } else {
            try {
                GfJsonObject jsonObject = buildGfJsonFromRawObject(object);
                addJSONObjectToTable(table, jsonObject);
            } catch (Exception e) {
                table.accumulate("Value", "Error getting bean properties " + e.getMessage());
            }
        }
    }

    // @Override
    public void toData(DataOutput out) throws IOException {
        DataSerializer.writeString(command, out);
        out.writeUTF(command);
        DataSerializer.writeObject(putResult, out);
        DataSerializer.writeObject(getResult, out);
        DataSerializer.writeObject(locateEntryResult, out);
        DataSerializer.writeArrayList((ArrayList<?>) locateEntryLocations, out);
        DataSerializer.writeBoolean(hasResultForAggregation, out);
        DataSerializer.writeObject(removeResult, out);
        DataSerializer.writeObject(inputKey, out);
        DataSerializer.writeObject(inputValue, out);
        DataSerializer.writeObject(error, out);
        DataSerializer.writeString(errorString, out);
        DataSerializer.writeString(infoString, out);
        DataSerializer.writeString(keyClass, out);
        DataSerializer.writeString(valueClass, out);
        DataSerializer.writeBoolean(operationCompletedSuccessfully, out);
    }

    // @Override
    public void fromData(DataInput in) throws IOException, ClassNotFoundException {
        command = DataSerializer.readString(in);
        putResult = DataSerializer.readObject(in);
        getResult = DataSerializer.readObject(in);
        locateEntryLocations = DataSerializer.readArrayList(in);
        locateEntryResult = DataSerializer.readObject(in);
        hasResultForAggregation = DataSerializer.readBoolean(in);
        removeResult = DataSerializer.readObject(in);
        inputKey = DataSerializer.readObject(in);
        inputValue = DataSerializer.readObject(in);
        error = DataSerializer.readObject(in);
        errorString = DataSerializer.readString(in);
        infoString = DataSerializer.readString(in);
        keyClass = DataSerializer.readString(in);
        valueClass = DataSerializer.readString(in);
        operationCompletedSuccessfully = DataSerializer.readBoolean(in);
    }

}