/*
* This file is a part of EpnTAPClient.
* This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer.
* See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861
* Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie.
*
* This program is free software: you can
* redistribute it and/or modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation, either version 3 of the License, or (at your option) any later
* version. This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details. You should have received a copy of
* the GNU General Public License along with this program. If not, see
* .
*/
package eu.omp.irap.vespa.epntapclient;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import eu.omp.irap.vespa.votable.utils.CantSendQueryException;
import eu.omp.irap.vespa.votable.utils.Network;
import eu.omp.irap.vespa.votable.utils.StringJoiner;
/**
* @author N. Jourdane
*/
public class RequestCtrl {
/** The text in the query to replaced by the actual table name. */
private static final String KEYWORD_TABLE_NAME = "#tablename#";
/** The logger for the class RequestCtrl. */
private static final Logger LOGGER = Logger.getLogger(RequestCtrl.class.getName());
/** The query template to get granules. */
private static final String QUERY_TEMPLATE = "SELECT DISTINCT TOP %s %s FROM "
+ KEYWORD_TABLE_NAME + "%s";
/** The URL of the resolver used for the `target name` field. */
private static final String RESOLVER_URL = "http://voparis-registry.obspm.fr/ssodnet/1/autocomplete";
/** The names of the columns used in the SELECT keyword in the query. */
private List columnNames;
/** The maximum number of rows returned by the query. */
private int nbMaxResult;
/** The parameters fields for the request. */
private Map parameters = new HashMap<>();
/**
* The query to send, with the name of the table is replaced by {@link #KEYWORD_TABLE_NAME}.
*/
private String query;
/** Default constructor of RequestCtrl. */
public RequestCtrl() {
List newColumnNames = new ArrayList<>();
newColumnNames.add("target_name");
newColumnNames.add("target_class");
columnNames = newColumnNames;
nbMaxResult = 20;
}
/**
* Constructor of RequestCtrl.
*
* @param nbMaxResult The maximum number of rows returned by the query.
*/
public RequestCtrl(int nbMaxResult, List columnNames) {
this.nbMaxResult = nbMaxResult;
this.columnNames = columnNames;
}
/**
* The method used to get target names propositions by asking to the resolver.
*
* @param begining The beginning of the target_name.
* @return An array of Strings corresponding to the target names got.
* @throws CantSendQueryException Can not read the JSON file.
*/
public static String[] getTargetNames(String begining) throws CantSendQueryException {
Map params = new HashMap<>();
params.put("q", "\"" + begining + "\"");
String query = Network.buildGetRequest(RESOLVER_URL, params);
JsonObject root = Network.readJson(query);
int count = Integer.parseInt(root.get("count").toString());
String[] targetNames = new String[count];
JsonArray hits = root.getAsJsonArray("hits");
for (int i = 0; i < count; i++) {
JsonObject elmt = hits.get(i).getAsJsonObject();
targetNames[i] = elmt.get("name").toString().replace("\"", "");
}
return targetNames;
}
public List getColumnNames() {
return columnNames;
}
/**
* @return The maximum number of rows returned by the query.
*/
public int getNbMaxResult() {
return nbMaxResult;
}
/**
* Get the parameters.
*
* @return A map of couple .
*/
public Map getParameters() {
return parameters;
}
public String getQuery() {
return query;
}
public String getQuery(String tableName) {
return query.replace(KEYWORD_TABLE_NAME, tableName);
}
/**
* Remove a parameter from the query.
*
* @param paramName The name of the parameter to remove.
*/
public void removeParameter(String paramName) {
parameters.remove(paramName);
LOGGER.info("removed " + paramName);
}
public void setColumnNames(List columnNames) {
this.columnNames = columnNames;
}
/**
* Set the maximum number of rows returned by the query.
*
* @param nbRows The number of rows.
*/
public void setNbMaxResult(int nbRows) {
nbMaxResult = nbRows;
}
public void setQuery(String query) {
this.query = query;
}
/**
* Update a parameter in the query. If the parameter do not exists yet, create it.
*
* @param paramName The name of the parameter.
* @param paramValue The value of the parameter.
*/
public void updateParameter(String paramName, Object paramValue) {
parameters.put(paramName, paramValue);
LOGGER.info("updated " + paramName + ": " + paramValue);
}
/**
* Update the ADQL query, from the column names, the table name, the parameter values and the
* max results.
*/
public void updateQuery() {
StringJoiner addJoin = new StringJoiner(" AND ");
for (Map.Entry param : parameters.entrySet()) {
if (param.getValue() instanceof ArrayList) {
StringJoiner orJoin = new StringJoiner(" OR ");
@SuppressWarnings("unchecked")
List possibleValues = (List) param.getValue();
for (String possibleValue : possibleValues) {
orJoin.add(param.getKey() + " LIKE '" + possibleValue + "'");
}
addJoin.add("(" + orJoin + ")");
} else if (param.getValue() instanceof String) {
addJoin.add(param.getKey() + " LIKE '" + param.getValue() + "'");
} else {
addJoin.add(param.getKey() + " = " + param.getValue().toString());
}
}
String where = addJoin.isEmpty() ? "" : " WHERE " + addJoin;
query = String.format(QUERY_TEMPLATE, nbMaxResult, StringJoiner.join(columnNames), where);
}
}