/*
 * 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.functions;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.Logger;

import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.execute.FunctionContext;
import org.apache.geode.cache.partition.PartitionRegionHelper;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.Query;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.Struct;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.DefaultQuery;
import org.apache.geode.cache.query.internal.IndexTrackingQueryObserver;
import org.apache.geode.cache.query.internal.QueryObserver;
import org.apache.geode.cache.query.internal.QueryObserverHolder;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.internal.NanoTimer;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.PartitionedRegion;
import org.apache.geode.internal.cache.execute.InternalFunction;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.security.SecurityService;
import org.apache.geode.management.internal.cli.domain.DataCommandRequest;
import org.apache.geode.management.internal.cli.domain.DataCommandResult;
import org.apache.geode.management.internal.cli.domain.DataCommandResult.SelectResultRow;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.util.JsonUtil;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxInstance;
import org.apache.geode.util.internal.GeodeJsonMapper;

/**
 * @since GemFire 7.0
 */
public class DataCommandFunction implements InternalFunction {
  private static final Logger logger = LogService.getLogger();

  private static final long serialVersionUID = 1L;

  private boolean optimizeForWrite = false;

  private static final int NESTED_JSON_LENGTH = 20;

  @Override
  public String getId() {
    return DataCommandFunction.class.getName();
  }

  @Override
  public boolean hasResult() {
    return true;
  }

  @Override

  public boolean isHA() {
    return false;
  }

  /**
   * Read only function
   */
  @Override
  public boolean optimizeForWrite() {
    return optimizeForWrite;
  }

  public void setOptimizeForWrite(boolean optimizeForWrite) {
    this.optimizeForWrite = optimizeForWrite;
  }

  @Override
  public void execute(FunctionContext functionContext) {
    try {
      InternalCache cache =
          ((InternalCache) functionContext.getCache()).getCacheForProcessingClientRequests();
      DataCommandRequest request = (DataCommandRequest) functionContext.getArguments();
      if (logger.isDebugEnabled()) {
        logger.debug("Executing function : \n{}\n on member {}", request,
            System.getProperty("memberName"));
      }
      DataCommandResult result = null;
      if (request.isGet()) {
        result = get(request, cache);
      } else if (request.isLocateEntry()) {
        result = locateEntry(request, cache);
      } else if (request.isPut()) {
        result = put(request, cache);
      } else if (request.isRemove()) {
        result = remove(request, cache);
      } else if (request.isSelect()) {
        result = select(request, cache);
      }
      if (logger.isDebugEnabled()) {
        logger.debug("Result is {}", result);
      }
      functionContext.getResultSender().lastResult(result);
    } catch (Exception e) {
      logger.info("Exception occurred:", e);
      functionContext.getResultSender().sendException(e);
    }
  }

  public DataCommandResult remove(DataCommandRequest request, InternalCache cache) {
    String key = request.getKey();
    String keyClass = request.getKeyClass();
    String regionName = request.getRegionName();
    String removeAllKeys = request.getRemoveAllKeys();
    return remove(key, keyClass, regionName, removeAllKeys, cache);
  }

  public DataCommandResult get(DataCommandRequest request, InternalCache cache) {
    String key = request.getKey();
    String keyClass = request.getKeyClass();
    String valueClass = request.getValueClass();
    String regionName = request.getRegionName();
    Boolean loadOnCacheMiss = request.isLoadOnCacheMiss();
    return get(request.getPrincipal(), key, keyClass, valueClass, regionName, loadOnCacheMiss,
        cache);
  }

  public DataCommandResult locateEntry(DataCommandRequest request, InternalCache cache) {
    String key = request.getKey();
    String keyClass = request.getKeyClass();
    String valueClass = request.getValueClass();
    String regionName = request.getRegionName();
    boolean recursive = request.isRecursive();
    return locateEntry(key, keyClass, valueClass, regionName, recursive, cache);
  }

  public DataCommandResult put(DataCommandRequest request, InternalCache cache) {
    String key = request.getKey();
    String value = request.getValue();
    boolean putIfAbsent = request.isPutIfAbsent();
    String keyClass = request.getKeyClass();
    String valueClass = request.getValueClass();
    String regionName = request.getRegionName();
    return put(key, value, putIfAbsent, keyClass, valueClass, regionName, cache);
  }

  public DataCommandResult select(DataCommandRequest request, InternalCache cache) {
    String query = request.getQuery();
    return select(cache, request.getPrincipal(), query);
  }

  /**
   * To catch trace output
   */
  public static class WrappedIndexTrackingQueryObserver extends IndexTrackingQueryObserver {

    @Override
    public void reset() {
      // NOOP
    }

    public void reset2() {
      super.reset();
    }
  }

  @SuppressWarnings("rawtypes")
  private DataCommandResult select(InternalCache cache, Object principal, String queryString) {

    if (StringUtils.isEmpty(queryString)) {
      return DataCommandResult.createSelectInfoResult(null, null, -1, null,
          CliStrings.QUERY__MSG__QUERY_EMPTY, false);
    }

    QueryService qs = cache.getQueryService();

    Query query = qs.newQuery(queryString);
    DefaultQuery tracedQuery = (DefaultQuery) query;
    WrappedIndexTrackingQueryObserver queryObserver = null;
    String queryVerboseMsg = null;
    long startTime = -1;
    if (tracedQuery.isTraced()) {
      startTime = NanoTimer.getTime();
      queryObserver = new WrappedIndexTrackingQueryObserver();
      QueryObserverHolder.setInstance(queryObserver);
    }
    List<SelectResultRow> list = new ArrayList<>();

    try {
      Object results = query.execute();
      if (tracedQuery.isTraced()) {
        queryVerboseMsg = getLogMessage(queryObserver, startTime, queryString);
        queryObserver.reset2();
      }
      if (results instanceof SelectResults) {
        select_SelectResults((SelectResults) results, principal, list, cache);
      } else {
        select_NonSelectResults(results, list);
      }
      return DataCommandResult.createSelectResult(queryString, list, queryVerboseMsg, null, null,
          true);

    } catch (FunctionDomainException | QueryInvocationTargetException | NameResolutionException
        | TypeMismatchException e) {
      logger.warn(e.getMessage(), e);
      return DataCommandResult.createSelectResult(queryString, null, queryVerboseMsg, e,
          e.getMessage(), false);
    } finally {
      if (queryObserver != null) {
        QueryObserverHolder.reset();
      }
    }
  }

  private void select_NonSelectResults(Object results, List<SelectResultRow> list) {
    if (logger.isDebugEnabled()) {
      logger.debug("BeanResults : Bean Results class is {}", results.getClass());
    }
    list.add(createSelectResultRow(results));
  }

  private void select_SelectResults(SelectResults selectResults, Object principal,
      List<SelectResultRow> list, InternalCache cache) {
    for (Object object : selectResults) {
      // Post processing
      object = cache.getSecurityService().postProcess(principal, null, null, object, false);

      list.add(createSelectResultRow(object));
    }
  }

  private SelectResultRow createSelectResultRow(Object object) {
    int rowType;
    if (object instanceof Struct) {
      rowType = DataCommandResult.ROW_TYPE_STRUCT_RESULT;
    } else if (JsonUtil.isPrimitiveOrWrapper(object.getClass())) {
      rowType = DataCommandResult.ROW_TYPE_PRIMITIVE;
    } else {
      rowType = DataCommandResult.ROW_TYPE_BEAN;
    }

    return new SelectResultRow(rowType, object);
  }

  @SuppressWarnings({"rawtypes"})
  public DataCommandResult remove(String key, String keyClass, String regionName,
      String removeAllKeys, InternalCache cache) {

    if (StringUtils.isEmpty(regionName)) {
      return DataCommandResult.createRemoveResult(key, null, null,
          CliStrings.REMOVE__MSG__REGIONNAME_EMPTY, false);
    }

    if (StringUtils.isEmpty(removeAllKeys) && (key == null)) {
      return DataCommandResult.createRemoveResult(null, null, null,
          CliStrings.REMOVE__MSG__KEY_EMPTY, false);
    }

    Region region = cache.getRegion(regionName);
    if (region == null) {
      return DataCommandResult.createRemoveInfoResult(key, null, null,
          CliStrings.format(CliStrings.REMOVE__MSG__REGION_NOT_FOUND, regionName), false);
    } else {
      if (removeAllKeys == null) {
        Object keyObject;
        try {
          keyObject = getClassObject(key, keyClass);
        } catch (ClassNotFoundException e) {
          return DataCommandResult.createRemoveResult(key, null, null,
              "ClassNotFoundException " + keyClass, false);
        } catch (IllegalArgumentException e) {
          return DataCommandResult.createRemoveResult(key, null, null,
              "Error in converting JSON " + e.getMessage(), false);
        }

        if (region.containsKey(keyObject)) {
          Object value = region.remove(keyObject);
          if (logger.isDebugEnabled()) {
            logger.debug("Removed key {} successfully", key);
          }
          Object array[] = getClassAndJson(value);
          DataCommandResult result =
              DataCommandResult.createRemoveResult(key, array[1], null, null, true);
          if (array[0] != null) {
            result.setValueClass((String) array[0]);
          }
          return result;
        } else {
          return DataCommandResult.createRemoveInfoResult(key, null, null,
              CliStrings.REMOVE__MSG__KEY_NOT_FOUND_REGION, false);
        }
      } else {
        DataPolicy policy = region.getAttributes().getDataPolicy();
        if (!policy.withPartitioning()) {
          region.clear();
          if (logger.isDebugEnabled()) {
            logger.debug("Cleared all keys in the region - {}", regionName);
          }
          return DataCommandResult.createRemoveInfoResult(key, null, null,
              CliStrings.format(CliStrings.REMOVE__MSG__CLEARED_ALL_CLEARS, regionName), true);
        } else {
          return DataCommandResult.createRemoveInfoResult(key, null, null,
              CliStrings.REMOVE__MSG__CLEARALL_NOT_SUPPORTED_FOR_PARTITIONREGION, false);
        }
      }
    }
  }

  @SuppressWarnings({"rawtypes"})
  public DataCommandResult get(Object principal, String key, String keyClass, String valueClass,
      String regionName, Boolean loadOnCacheMiss, InternalCache cache) {

    SecurityService securityService = cache.getSecurityService();

    if (StringUtils.isEmpty(regionName)) {
      return DataCommandResult.createGetResult(key, null, null,
          CliStrings.GET__MSG__REGIONNAME_EMPTY, false);
    }

    if (StringUtils.isEmpty(key)) {
      return DataCommandResult.createGetResult(key, null, null, CliStrings.GET__MSG__KEY_EMPTY,
          false);
    }

    Region region = cache.getRegion(regionName);

    if (region == null) {
      if (logger.isDebugEnabled()) {
        logger.debug("Region Not Found - {}", regionName);
      }
      return DataCommandResult.createGetResult(key, null, null,
          CliStrings.format(CliStrings.GET__MSG__REGION_NOT_FOUND, regionName), false);
    } else {
      Object keyObject;
      try {
        keyObject = getClassObject(key, keyClass);
      } catch (ClassNotFoundException e) {
        return DataCommandResult.createGetResult(key, null, null,
            "ClassNotFoundException " + keyClass, false);
      } catch (IllegalArgumentException e) {
        return DataCommandResult.createGetResult(key, null, null,
            "Error in converting JSON " + e.getMessage(), false);
      }

      boolean doGet = Boolean.TRUE.equals(loadOnCacheMiss);

      if (doGet || region.containsKey(keyObject)) {
        Object value = region.get(keyObject);

        // run it through post processor. region.get will return the deserialized object already, so
        // we don't need to
        // deserialize it anymore to pass it to the postProcessor
        value = securityService.postProcess(principal, regionName, keyObject, value, false);

        if (logger.isDebugEnabled()) {
          logger.debug("Get for key {} value {}", key, value);
        }
        Object array[] = getClassAndJson(value);
        if (value != null) {
          DataCommandResult result =
              DataCommandResult.createGetResult(key, array[1], null, null, true);
          if (array[0] != null) {
            result.setValueClass((String) array[0]);
          }
          return result;
        } else {
          return DataCommandResult.createGetResult(key, array[1], null, null, false);
        }
      } else {
        if (logger.isDebugEnabled()) {
          logger.debug("Key is not present in the region {}", regionName);
        }
        return DataCommandResult.createGetInfoResult(key, getClassAndJson(null)[1], null,
            CliStrings.GET__MSG__KEY_NOT_FOUND_REGION, false);
      }
    }
  }

  @SuppressWarnings({"unchecked", "rawtypes"})
  public DataCommandResult locateEntry(String key, String keyClass, String valueClass,
      String regionPath, boolean recursive, InternalCache cache) {

    if (StringUtils.isEmpty(regionPath)) {
      return DataCommandResult.createLocateEntryResult(key, null, null,
          CliStrings.LOCATE_ENTRY__MSG__REGIONNAME_EMPTY, false);
    }

    if (StringUtils.isEmpty(key)) {
      return DataCommandResult.createLocateEntryResult(key, null, null,
          CliStrings.LOCATE_ENTRY__MSG__KEY_EMPTY, false);
    }
    List<Region> listOfRegionsStartingWithRegionPath = new ArrayList<>();

    if (recursive) {
      // Recursively find the keys starting from the specified region path.
      List<String> regionPaths = getAllRegionPaths(cache, true);
      for (String path : regionPaths) {
        if (path.startsWith(regionPath) || path.startsWith(Region.SEPARATOR + regionPath)) {
          Region targetRegion = cache.getRegion(path);
          listOfRegionsStartingWithRegionPath.add(targetRegion);
        }
      }
      if (listOfRegionsStartingWithRegionPath.size() == 0) {
        if (logger.isDebugEnabled()) {
          logger.debug("Region Not Found - {}", regionPath);
        }
        return DataCommandResult.createLocateEntryResult(key, null, null,
            CliStrings.format(CliStrings.REMOVE__MSG__REGION_NOT_FOUND, regionPath), false);
      }
    } else {
      Region region = cache.getRegion(regionPath);
      if (region == null) {
        if (logger.isDebugEnabled()) {
          logger.debug("Region Not Found - {}", regionPath);
        }
        return DataCommandResult.createLocateEntryResult(key, null, null,
            CliStrings.format(CliStrings.REMOVE__MSG__REGION_NOT_FOUND, regionPath), false);
      } else {
        listOfRegionsStartingWithRegionPath.add(region);
      }
    }

    Object keyObject;
    try {
      keyObject = getClassObject(key, keyClass);
    } catch (ClassNotFoundException e) {
      logger.error(e.getMessage(), e);
      return DataCommandResult.createLocateEntryResult(key, null, null,
          "ClassNotFoundException " + keyClass, false);
    } catch (IllegalArgumentException e) {
      logger.error(e.getMessage(), e);
      return DataCommandResult.createLocateEntryResult(key, null, null,
          "Error in converting JSON " + e.getMessage(), false);
    }

    Object value;
    DataCommandResult.KeyInfo keyInfo;
    keyInfo = new DataCommandResult.KeyInfo();
    DistributedMember member = cache.getDistributedSystem().getDistributedMember();
    keyInfo.setHost(member.getHost());
    keyInfo.setMemberId(member.getId());
    keyInfo.setMemberName(member.getName());

    for (Region region : listOfRegionsStartingWithRegionPath) {
      if (region instanceof PartitionedRegion) {
        // Following code is adaptation of which.java of old Gfsh
        PartitionedRegion pr = (PartitionedRegion) region;
        Region localRegion = PartitionRegionHelper.getLocalData(region);
        value = localRegion.get(keyObject);
        if (value != null) {
          DistributedMember primaryMember =
              PartitionRegionHelper.getPrimaryMemberForKey(region, keyObject);
          int bucketId = pr.getKeyInfo(keyObject).getBucketId();
          boolean isPrimary = member == primaryMember;
          keyInfo.addLocation(new Object[] {region.getFullPath(), true, getClassAndJson(value)[1],
              isPrimary, "" + bucketId});
        } else {
          if (logger.isDebugEnabled()) {
            logger.debug("Key is not present in the region {}", regionPath);
          }
          return DataCommandResult.createLocateEntryInfoResult(key, null, null,
              CliStrings.LOCATE_ENTRY__MSG__KEY_NOT_FOUND_REGION, false);
        }
      } else {
        if (region.containsKey(keyObject)) {
          value = region.get(keyObject);
          if (logger.isDebugEnabled()) {
            logger.debug("Get for key {} value {} in region {}", key, value, region.getFullPath());
          }
          if (value != null) {
            keyInfo.addLocation(
                new Object[] {region.getFullPath(), true, getClassAndJson(value)[1], false, null});
          } else {
            keyInfo.addLocation(new Object[] {region.getFullPath(), false, null, false, null});
          }
        } else {
          if (logger.isDebugEnabled()) {
            logger.debug("Key is not present in the region {}", regionPath);
          }
          keyInfo.addLocation(new Object[] {region.getFullPath(), false, null, false, null});
        }
      }
    }

    if (keyInfo.hasLocation()) {
      return DataCommandResult.createLocateEntryResult(key, keyInfo, null, null, true);
    } else {
      return DataCommandResult.createLocateEntryInfoResult(key, null, null,
          CliStrings.LOCATE_ENTRY__MSG__KEY_NOT_FOUND_REGION, false);
    }
  }

  @SuppressWarnings({"rawtypes"})
  public DataCommandResult put(String key, String value, boolean putIfAbsent, String keyClass,
      String valueClass, String regionName, InternalCache cache) {

    if (StringUtils.isEmpty(regionName)) {
      return DataCommandResult.createPutResult(key, null, null,
          CliStrings.PUT__MSG__REGIONNAME_EMPTY, false);
    }

    if (StringUtils.isEmpty(key)) {
      return DataCommandResult.createPutResult(key, null, null, CliStrings.PUT__MSG__KEY_EMPTY,
          false);
    }

    if (StringUtils.isEmpty(value)) {
      return DataCommandResult.createPutResult(key, null, null, CliStrings.PUT__MSG__VALUE_EMPTY,
          false);
    }

    Region region = cache.getRegion(regionName);
    if (region == null) {
      return DataCommandResult.createPutResult(key, null, null,
          CliStrings.format(CliStrings.PUT__MSG__REGION_NOT_FOUND, regionName), false);
    } else {
      Object keyObject;
      Object valueObject;
      try {
        keyObject = getClassObject(key, keyClass);
      } catch (ClassNotFoundException e) {
        return DataCommandResult.createPutResult(key, null, null,
            "ClassNotFoundException " + keyClass, false);
      } catch (IllegalArgumentException e) {
        return DataCommandResult.createPutResult(key, null, null,
            "Error in converting JSON " + e.getMessage(), false);
      }

      try {
        valueObject = getClassObject(value, valueClass);
      } catch (ClassNotFoundException e) {
        return DataCommandResult.createPutResult(key, null, null,
            "ClassNotFoundException " + valueClass, false);
      }
      Object returnValue;
      if (putIfAbsent && region.containsKey(keyObject)) {
        returnValue = region.get(keyObject);
      } else {
        returnValue = region.put(keyObject, valueObject);
      }
      Object array[] = getClassAndJson(returnValue);
      DataCommandResult result = DataCommandResult.createPutResult(key, array[1], null, null, true);
      if (array[0] != null) {
        result.setValueClass((String) array[0]);
      }
      return result;
    }
  }

  @SuppressWarnings({"rawtypes", "unchecked"})
  private Object getClassObject(String string, String klassString)
      throws ClassNotFoundException, IllegalArgumentException {
    if (StringUtils.isEmpty(klassString)) {
      return string;
    }
    Class klass = ClassPathLoader.getLatest().forName(klassString);

    if (klass.equals(String.class)) {
      return string;
    }

    Object resultObject;
    try {
      ObjectMapper mapper = GeodeJsonMapper.getMapper();
      resultObject = mapper.readValue(string, klass);
    } catch (IOException e) {
      throw new IllegalArgumentException(
          "Failed to convert input key to " + klassString + " Msg : " + e.getMessage());
    }

    return resultObject;
  }

  private Object[] getClassAndJson(Object obj) {
    Object[] array = new Object[2];

    if (obj == null) {
      array[0] = null;
      array[1] = null;
      return array;
    }

    array[0] = obj.getClass().getCanonicalName();

    if (obj instanceof PdxInstance) {
      array[1] = JSONFormatter.toJSON((PdxInstance) obj);
      return array;
    }

    ObjectMapper mapper = new ObjectMapper();
    try {
      array[1] = mapper.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
      array[1] = e.getMessage();
    }

    return array;
  }

  /**
   * Returns a sorted list of all region full paths found in the specified cache.
   *
   * @param cache The cache to search.
   * @param recursive recursive search for sub-regions
   * @return Returns a sorted list of all region paths defined in the distributed system.
   */
  @SuppressWarnings({"rawtypes", "unchecked"})
  public static List getAllRegionPaths(InternalCache cache, boolean recursive) {
    ArrayList list = new ArrayList();
    if (cache == null) {
      return list;
    }

    // get a list of all root regions
    Set<Region<?, ?>> regions = cache.rootRegions();

    for (Region rootRegion : regions) {
      String regionPath = rootRegion.getFullPath();

      Region region = cache.getRegion(regionPath);
      list.add(regionPath);
      Set<Region> subregionSet = region.subregions(true);
      if (recursive) {
        for (Region aSubregionSet : subregionSet) {
          list.add(aSubregionSet.getFullPath());
        }
      }
    }
    Collections.sort(list);
    return list;
  }

  public static String getLogMessage(QueryObserver observer, long startTime, String query) {
    String usedIndexesString = null;
    float time = 0.0f;

    if (startTime > 0L) {
      time = (NanoTimer.getTime() - startTime) / 1.0e6f;
    }

    if (observer != null && observer instanceof IndexTrackingQueryObserver) {
      IndexTrackingQueryObserver indexObserver = (IndexTrackingQueryObserver) observer;
      Map usedIndexes = indexObserver.getUsedIndexes();
      indexObserver.reset();
      StringBuffer buf = new StringBuffer();
      buf.append(" indexesUsed(");
      buf.append(usedIndexes.size());
      buf.append(")");
      if (usedIndexes.size() > 0) {
        buf.append(":");
        for (Iterator itr = usedIndexes.entrySet().iterator(); itr.hasNext();) {
          Map.Entry entry = (Map.Entry) itr.next();
          buf.append(entry.getKey().toString()).append(entry.getValue());
          if (itr.hasNext()) {
            buf.append(",");
          }
        }
      }
      usedIndexesString = buf.toString();
    } else if (DefaultQuery.QUERY_VERBOSE) {
      usedIndexesString = " indexesUsed(NA due to other observer in the way: "
          + observer.getClass().getName() + ")";
    }

    return String.format("Query Executed%s%s", startTime > 0L ? " in " + time + " ms;" : ";",
        usedIndexesString != null ? usedIndexesString : "");
  }

}
