package org.sharegov.cirm.stats;
import mjson.Json;
/**
* SRCirmStatsDataReporter is a CirmDataProvider that can evaluate a serviceRequest Json for type and caseNumber (id).
* Calls inside CirmTransactions are automatically routed in a way, that data only is inserted into stats only on transaction success or failure,
* thereby ignoring retries.
*
* THREAD SAFE and fast (but mostly used in one thread only. e.g worker thread).
*
* @author Thomas Hilpold
*
*/
public class SRCirmStatsDataReporter extends CirmStatsDataReporter
{
public SRCirmStatsDataReporter(CirmStatistics stats, String component) {
super(stats, component);
}
/**
* Reports success to CirmStatistics, even inside of a CirmTransaction.
* In a CirmTransaction, the report will be delayed until CirmTransaction fails or succeeds.
* if type and/or casenum cannot be found, UNKNOWN will be set but no exception will be thrown.
* @param action
* @param serviceCaseJson with String properties (x|x."type"|x."bo")."type" and (x|x."type"|x."bo")."properties"."legacy:hasCaseNumber"
*/
public void succeeded(final String action, final Json serviceCaseJson) {
String type = safeDetermineType(serviceCaseJson);
String id = safeDetermineHasCaseNumber(serviceCaseJson);
super.succeeded(action, type, id);
}
/**
* Reports a failure to CirmStatistics, even inside of a CirmTransaction.
* In a CirmTransaction, the report will be delayed until CirmTransaction fails or succeeds.
*
* @param action
* @param serviceCaseJson with String properties (x|x."type"|x."bo")."type" and (x|x."type"|x."bo")."properties"."legacy:hasCaseNumber"
* @param exception
* @param failureMessage
*/
public void failed(final String action, final Json serviceCaseJson, final String exception, final String failureMessage) {
String type = safeDetermineType(serviceCaseJson);
String id = safeDetermineHasCaseNumber(serviceCaseJson);
super.failed(action, type, id, exception, failureMessage);
}
/**
* Returns the type property or CirmStatistics.UNKNOWN.
* @param serviceCaseJson
* @throws never an exception.
* @return
*/
public static String safeDetermineType(final Json serviceCaseJson) {
Json caseRoot;
try {
caseRoot = findCaseRoot(serviceCaseJson);
return caseRoot.at("type").asString();
} catch (Exception e) {
System.err.println("SRCirmStatsDataReporter was unable to determine type as String from " + serviceCaseJson);
return CirmStatistics.UNKNOWN;
}
}
/**
* Returns the ("properties").at("legacy:hasCaseNumber") property or CirmStatistics.UNKNOWN.
* jmsg.at("response").at("data")
* @param serviceCaseJson
* @throws never an exception.
* @return
*/
public static String safeDetermineHasCaseNumber(final Json serviceCaseJson) {
Json caseRoot;
try {
caseRoot = findCaseRoot(serviceCaseJson);
if (caseRoot.has("properties")) {
caseRoot = caseRoot.at("properties");
}
if (caseRoot.has("legacy:hasCaseNumber")) {
return caseRoot.at("legacy:hasCaseNumber").asString();
} else {
return caseRoot.at("hasCaseNumber").asString();
}
} catch (Exception e) {
System.err.println("SRCirmStatsDataReporter was unable to determine "
+ "properties.legacy:hasCaseNumber as String from " + serviceCaseJson);
return CirmStatistics.UNKNOWN;
}
}
/**
* Tries to return the case root (data or BO) for a serviceCaseJson, LE response or response JMSMessage.
* This method shows how many different json formats for a service case/message we must expect.
* @param serviceCaseOrJmsg
* @throws Exception if param null or non object
*/
static Json findCaseRoot(final Json serviceCaseOrJmsg) {
Json caseRoot = serviceCaseOrJmsg;
if (serviceCaseOrJmsg.has("response")
&& serviceCaseOrJmsg.at("response").has("data")
&& ( serviceCaseOrJmsg.at("response").at("data").has("type")
|| serviceCaseOrJmsg.at("response").at("data").has("case"))
) {
caseRoot = serviceCaseOrJmsg.at("response").at("data");
} else if (serviceCaseOrJmsg.has("bo")) {
caseRoot = serviceCaseOrJmsg.at("bo");
} else if (serviceCaseOrJmsg.has("data")) {
caseRoot = serviceCaseOrJmsg.at("data");
} else if (serviceCaseOrJmsg.has("originalMessage") && serviceCaseOrJmsg.at("originalMessage").has("data")) {
caseRoot = serviceCaseOrJmsg.at("originalMessage").at("data");
} else if (serviceCaseOrJmsg.has("originalMessage")
&& serviceCaseOrJmsg.at("originalMessage").has("response")
&& serviceCaseOrJmsg.at("originalMessage").at("response").has("bo")
&& serviceCaseOrJmsg.at("originalMessage").at("response").at("bo").isObject()
) {
caseRoot = serviceCaseOrJmsg.at("originalMessage").at("response").at("bo");
}
//else could not yet find caseRoot
//we might have case, data.case or response.data.case, so we'll investigate that:
if (serviceCaseOrJmsg.has("case")) caseRoot = serviceCaseOrJmsg.at("case");
return caseRoot;
}
}