/************************************************************************
* Copyright (c) 2014-2016 IoT-Solutions e.U.
*
* Licensed 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 iot.jcypher.query;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.json.JsonArray;
import javax.json.JsonObject;
import org.neo4j.driver.v1.StatementResult;
import iot.jcypher.database.IDBAccess;
import iot.jcypher.graph.GrNode;
import iot.jcypher.graph.GrPath;
import iot.jcypher.graph.GrRelation;
import iot.jcypher.graph.Graph;
import iot.jcypher.query.result.JcError;
import iot.jcypher.query.result.util.ResultHandler;
import iot.jcypher.query.values.JcBoolean;
import iot.jcypher.query.values.JcCollection;
import iot.jcypher.query.values.JcNode;
import iot.jcypher.query.values.JcNumber;
import iot.jcypher.query.values.JcPath;
import iot.jcypher.query.values.JcPrimitive;
import iot.jcypher.query.values.JcRelation;
import iot.jcypher.query.values.JcString;
import iot.jcypher.query.values.JcValue;
public class JcQueryResult {
private JsonObject jsonResult;
private List<JcError> generalErrors;
private List<JcError> dbErrors;
private ResultHandler resultHandler;
public JcQueryResult(JsonObject jsonResult, int queryIndex, IDBAccess dbAccess) {
super();
this.jsonResult = jsonResult;
this.resultHandler = new ResultHandler(jsonResult, queryIndex, dbAccess);
}
public JcQueryResult(StatementResult statementResult, IDBAccess dbAccess) {
this.resultHandler = new ResultHandler(statementResult, dbAccess);
}
/**
* @return the JsonObject representing the query result. Is null when BOLT protocol is used.
*/
public JsonObject getJsonResult() {
return jsonResult;
}
/**
* @param node
* @return an unmodifiable list of nodes (i.e a result column)
*/
public List<GrNode> resultOf(JcNode node) {
return this.resultHandler.getNodes(node);
}
/**
* @param relation
* @return an unmodifiable list of relations (i.e a result column)
*/
public List<GrRelation> resultOf(JcRelation relation) {
return this.resultHandler.getRelations(relation);
}
/**
* Note: After locally modifying the graph the result may be inconsistent with the changes
* @param path
* @return an unmodifiable list of paths (i.e a result column)
*/
public List<GrPath> resultOf(JcPath path) {
return this.resultHandler.getPaths(path);
}
public List<BigDecimal> resultOf(JcNumber number) {
return this.resultHandler.getNumbers(number);
}
public List<String> resultOf(JcString string) {
return this.resultHandler.getStrings(string);
}
public List<Boolean> resultOf(JcBoolean bool) {
return this.resultHandler.getBooleans(bool);
}
public List<List<?>> resultOf(JcCollection collection) {
return this.resultHandler.getCollections(collection);
}
public List<?> resultOf(JcValue val) {
return this.resultHandler.getObjects(val);
}
/**
* answer a list of literal maps containing result values for the given keys
* @param key a variable number of keys which are used to calculate result-values to fill the resulting maps
* @return a list of LiteralMap(s)
*/
public LiteralMapList resultMapListOf(JcPrimitive... key) {
List<List<?>> results = new ArrayList<List<?>>();
LiteralMapList ret = new LiteralMapList();
int size = -1;
ResultHandler.includeNullValues.set(Boolean.TRUE);
try {
for (JcPrimitive k : key) {
List<?> r = this.resultOf(k);
if (size == -1)
size = r.size();
results.add(r);
for (int i = 0; i < r.size(); i++) {
LiteralMap map;
if (i > ret.size() - 1) {
map = new LiteralMap();
ret.add(map);
} else
map = ret.get(i);
map.put(k, r.get(i));
}
}
} finally {
ResultHandler.includeNullValues.remove();
}
return ret;
}
public Graph getGraph() {
return this.resultHandler.getGraph();
}
/**
* @return a list of general errors (e.g. connection errors).
*/
public List<JcError> getGeneralErrors() {
if (this.generalErrors == null)
this.generalErrors = new ArrayList<JcError>();
return this.generalErrors;
}
/**
* @return a list of database errors
* <br/>(the database was successfully accessed, but the query produced error(s)).
*/
public List<JcError> getDBErrors() {
if (this.dbErrors == null) {
this.dbErrors = new ArrayList<JcError>();
JsonObject obj = getJsonResult();
if (obj != null) {
JsonArray errs = obj.getJsonArray("errors");
int size = errs.size();
for (int i = 0; i < size; i++) {
JsonObject err = errs.getJsonObject(i);
String info = null;
if (err.containsKey("info"))
info = err.getString("info");
this.dbErrors.add(new JcError(err.getString("code"),
err.getString("message"), info));
}
}
}
return this.dbErrors;
}
/**
* Add a general (system) error
* @param generalError
*/
public void addGeneralError(JcError generalError) {
getGeneralErrors().add(generalError);
}
/**
* @return true, if the query result contains any error(s).
*/
public boolean hasErrors() {
return !this.getGeneralErrors().isEmpty() || !this.getDBErrors().isEmpty();
}
ResultHandler getResultHandler() {
return this.resultHandler;
}
}