+ override def contextInitialized(servletContextEvent: ServletContextEvent): Unit = {
+ QepReceiver.start()
+ }
+
+ override def contextDestroyed(servletContextEvent: ServletContextEvent): Unit = {
+ QepReceiver.stop()
+ }
+}
+
case class UnexpectedMessageContentsTypeException(envelope: Envelope, queue: Queue) extends Exception(s"Could not interpret message with contents type of ${envelope.contentsType} from queue ${queue.name} from shrine version ${envelope.shrineVersion}")
case class ExceptionWhileReceivingMessage(queue:Queue, x:Throwable) extends AbstractProblem(ProblemSources.Qep) {
override val throwable = Some(x)
override def summary: String = s"The QEP encountered an exception while trying to receive a message from $queue"
override def description: String = s"The QEP encountered an exception while trying to receive a message from $queue on ${Thread.currentThread().getName}: ${x.getMessage}"
}
case class QepReceiverCouldNotDecodeMessage(messageString:String,queue:Queue, x:Throwable) extends AbstractProblem(ProblemSources.Qep) {
override val throwable = Some(x)
override def summary: String = s"The QEP could not decode a message from $queue"
override def description: String =
s"""The QEP encountered an exception while trying to decode a message from $queue on ${Thread.currentThread().getName}:
(response.status == StatusCodes.RequestTimeout))throw new CouldNotCreateQueueButOKToRetryException(response.status,response.entity.asString)
else throw new IllegalStateException(s"Response status is ${response.status}, not Created. Cannot make a queue from this response: ${response.entity.asString}") //todo more specific custom exception SHRINE-2213
}
}.transform({ s =>
Success(s)
},{throwable =>
throwable match {
case NonFatal(x) => error(s"Unable to create a Queue from '${response.entity.asString}' due to exception",throwable) //todo probably want to wrap more information into a new Throwable here SHRINE-2213
throw new IllegalStateException(s"Response status is ${response.status}, not OK or NotFound. Cannot make a Message from this response: ${response.entity.asString}")
}
}.transform({ s =>
- Success(s)
+ val hornetQMessage = s.map(msg => HornetQClientMessage(UUID.fromString(msg.id), msg.contents))
+ Success(hornetQMessage)
},{throwable =>
throwable match {
case NonFatal(x) => error(s"Unable to create a Message from '${response.entity.asString}' due to exception",throwable) //todo probably want to report a Problem here SHRINE-2216
case class HornetQMomServerErrorProblem(x:Throwable, function:String) extends AbstractProblem(ProblemSources.Hub) {
override val throwable = Some(x)
override val summary: String = "SHRINE cannot use HornetQMomWebApi due to a server error occurred in hornetQ."
override val description: String = s"HornetQ throws an exception while trying to $function," +
s" the server's response is: ${x.getMessage} from ${x.getClass}."
}
case class CannotUseHornetQMomWebApiProblem(x:Throwable) extends AbstractProblem(ProblemSources.Hub) {
override val throwable = Some(x)
override val summary: String = "SHRINE cannot use HornetQMomWebApi due to configuration in shrine.conf."
override val description: String = "If you intend for this node to serve as this SHRINE network's messaging hub " +
"set shrine.messagequeue.hornetQWebApi.enabled to true in your shrine.conf." +
" You do not want to do this unless you are the hub admin!"
}
+
+case class MessageDoesNotExistException(id: UUID) extends Exception(s"Cannot match given ${id.toString} to any Message in HornetQ server! Message does not exist!")
+
+case class MessageDoesNotExistInMapProblem(id: UUID) extends AbstractProblem(ProblemSources.Hub) {
+
+ override def summary: String = s"The client expected message $id, but the server did not find it and could not complete() the message."
+
+ override def description: String = s"The client expected message $id, but the server did not find it and could not complete() the message." +
+ s" Message either has never been received or already been completed!"
+}
+
+case class ExceptionWhileCleaningUpMessageProblem(timeOutInMillis: Long, x:Throwable) extends AbstractProblem(ProblemSources.Hub) {
+
+ override val throwable = Some(x)
+
+ override def summary: String = s"The Hub encountered an exception while trying to " +
+ s"cleanup messages that has been outstanding for more than $timeOutInMillis milliseconds"
+
+ override def description: String = s"The Hub encountered an exception while trying to " +
+ s"cleanup messages that has been received for more than $timeOutInMillis milliseconds " +
- implementation = "net.shrine.hornetqclient.HornetQMomWebClient" //Fully-qualified class name of the MessaageQueueService to use //todo when there are two real implemetnations, maybe leave this out
+ implementation = "net.shrine.hornetqclient.HornetQMomWebClient" //Fully-qualified class name of the MessaageQueueService to use //todo when there are two real implemetnations, maybe leave this default out
-case class NoSuchQueueExistsInHornetQ(proposedQueue: Queue) extends Exception(s"Given Queue ${proposedQueue.name} does not exist in HornetQ server! Please create the queue first!")
case class CouldNotCreateQueueButOKToRetryException(status:StatusCode,contents:String) extends Exception(s"Could not create a queue due to status code $status with message '$contents'")
val adapterNode = result.description.getOrElse(throw new IllegalStateException("description is empty, does not have an adapter node"))
val queryResultRow = QueryResultRow(networkQueryId,result)
val breakdowns: Iterable[QepQueryBreakdownResultsRow] = result.breakdowns.flatMap(QepQueryBreakdownResultsRow.breakdownRowsFor(networkQueryId,adapterNode,result.resultId,_))
val problem: Seq[QepProblemDigestRow] = result.problemDigest.map(p => QepProblemDigestRow(networkQueryId,adapterNode,p.codec,p.stampText,p.summary,p.description,p.detailsXml.toString,System.currentTimeMillis())).to[Seq]
implicit val queryStatusColumnType = MappedColumnType.base[QueryResult.StatusType,String] ({
statusType => statusType.name
},{
name => QueryResult.StatusType.valueOf(name).getOrElse(throw new IllegalStateException(s"$name is not one of ${QueryResult.StatusType.values.map(_.name).mkString(", ")}"))
})
class QepQueryResults(tag:Tag) extends Table[QueryResultRow](tag,"queryResults") {
shouldQuerySelf = false //true if there is an adapter at the hub , or just add a loopback address to downstreamNodes
}
adapter {
// create = true by default. False to not create an adapter.
// audit {
// collectAdapterAudit = true by default. False to not fill in the audit database
// database {
// dataSourceFrom = "JNDI" //Can be JNDI or testDataSource . Use testDataSource for tests, JNDI everywhere else
// jndiDataSourceName = "java:comp/env/jdbc/adapterAuditDB" //or leave out for tests
// slickProfileClassName = "slick.driver.MySQLDriver$" // Can be
// slick.driver.H2Driver$
// slick.driver.MySQLDriver$
// slick.driver.PostgresDriver$
// slick.driver.SQLServerDriver$
// slick.driver.JdbcDriver$
// freeslick.OracleProfile$
// freeslick.MSSQLServerProfile$
//
// (Yes, with the $ on the end)
// For testing without JNDI
// testDataSource {
//typical test settings for unit tests
//driverClassName = "org.h2.Driver"
//url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1" //H2 embedded in-memory for unit tests
//url = "jdbc:h2:~/stewardTest.h2" //H2 embedded on disk at ~/test
// }
// createTablesOnStart = false //for testing with H2 in memory, when not running unit tests. Set to false normally
// }
// obfuscation {
// binSize = 5 by default //Round to the nearest binSize. Use 1 for no effect (to match SHRINE 1.21 and earlier).
// sigma = 6.5 by default //Noise to inject. Use 0 for no effect. (Use 1.33 to match SHRINE 1.21 and earlier).
// clamp = 10 by default //Maximum ammount of noise to inject. (Use 3 to match SHRINE 1.21 and earlier).
// }
// adapterLockoutAttemptsThreshold = 0 by default // Number of allowed queries with the same actual result that can exist before a researcher is locked out of the adapter. In 1.24 the lockout code and this config value will be removed
// botDefense {
// countsAndMilliseconds = [ //to turn off, use an empty json list
// {count = 10, milliseconds = 60000}, //allow up to 10 queries in one minute by default
// {count = 200, milliseconds = 36000000} //allow up to 4 queries in 10 hours by default
// ]
// }
crcEndpoint {
//must be filled in url = "http://shrine-dev1.catalyst/i2b2/services/QueryToolService/"
}
setSizeObfuscation = true //must be set. false turns off obfuscation
adapterMappingsFileName = "AdapterMappings.xml"
maxSignatureAge {
minutes = 5 //must be longer than the hub's maxQueryWaitTime
}
immediatelyRunIncomingQueries = true //false to queue them
//delayResponse = "0 seconds" //time to delay before responding to a query. Should be 0 except for testing in shrine-qa
// slickProfileClassName = "slick.driver.MySQLDriver$" // Can be
// slick.driver.H2Driver$
// slick.driver.MySQLDriver$
// slick.driver.PostgresDriver$
// slick.driver.SQLServerDriver$
// slick.driver.JdbcDriver$
// freeslick.OracleProfile$
// freeslick.MSSQLServerProfile$
//
// (Yes, with the $ on the end)
// For testing without JNDI
// testDataSource {
//typical test settings for unit tests
//driverClassName = "org.h2.Driver"
//url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1" //H2 embedded in-memory for unit tests
//url = "jdbc:h2:~/stewardTest.h2" //H2 embedded on disk at ~/test
// }
// createTablesOnStart = false //for testing with H2 in memory, when not running unit tests. Set to false normally
// }
}
dashboard {
// gruntWatch = false //false for production, true for mvn tomcat7:run . Allows the client javascript and html files to be loaded via gruntWatch .
// happyBaseUrl = "https://localhost:6443/shrine/rest/happy" If the shine servlet is running on a different machime from the dashboard, change this URL to match
// statusBaseUrl = "https://localhost:6443/shrine/rest/internalstatus" If the shine servlet is running on a different machime from the dashboard, change this URL to match
// }
// status {
//permittedHostOfOrigin = "localhost" //If absent then get the host name via java.net.InetAddress.getLocalHost.getHostName . Override to control
}
//Get the older squerl-basd databases through JNDI (inside of tomcant, using tomcat's db connection pool) or directly via a db config here (for testing
squerylDataSource {
// database {
// dataSourceFrom = "JNDI" //Can be JNDI or testDataSource . Use testDataSource for tests, JNDI everywhere else
// jndiDataSourceName = "java:comp/env/jdbc/shrineDB" //or leave out for tests
// }
}
authenticate {
// realm = "SHRINE Researcher API" //todo figure out what this means. SHRINE-1978
usersource {
// domain = "i2b2demo" //you must provide your own domain
}
}
steward {
// createTopicsMode = Pending //Can be Pending, Approved, or TopcisIgnoredJustLog. Pending by default
//Pending - new topics start in the Pending state; researchers must wait for the Steward to approve them
//Approved - new topics start in the Approved state; researchers can use them immediately
//TopicsIgnoredJustLog - all queries are logged and approved; researchers don't need to create topics
emailDataSteward {
// sendAuditEmails = true //false to turn off the whole works of emailing the data steward
// interval = "1 day" //Audit researchers daily
// timeAfterMidnight = "6 hours" //Audit researchers at 6 am. If the interval is less than 1 day then this delay is ignored.
// maxQueryCountBetweenAudits = 30 //If a researcher runs more than this many queries since the last audit audit her
// minTimeBetweenAudits = "30 days" //If a researcher runs at least one query, audit those queries if this much time has passed
//You must provide the email address of the shrine node system admin, to handle bounces and invalid addresses
//from = "shrine-admin@example.com"
//You must provide the email address of the data steward
//to = "shrine-steward@example.com"
// subject = "Audit SHRINE researchers"
//The baseUrl for the data steward to be substituted in to email text. Must be supplied if it is used in the email text.
s += '<query_timing>SAMEINSTANCENUM</query_timing>\n';
s += '<specificity_scale>0</specificity_scale>\n';
}
for (var p = 0; p < panel_cnt; p++) {
s += '\t<panel>\n';
s += '\t\t<panel_number>' + (p+1) + '</panel_number>\n';
// date range constraints
if (panel_list[p].dateFrom) {
s += '\t\t<panel_date_from>'+panel_list[p].dateFrom.Year+'-'+padNumber(panel_list[p].dateFrom.Month,2)+'-'+padNumber(panel_list[p].dateFrom.Day,2)+'T00:00:00.000-05:00</panel_date_from>\n';
}
if (panel_list[p].dateTo) {
s += '\t\t<panel_date_to>'+panel_list[p].dateTo.Year+'-'+padNumber(panel_list[p].dateTo.Month,2)+'-'+padNumber(panel_list[p].dateTo.Day,2)+'T00:00:00.000-05:00</panel_date_to>\n';
}
s += "\t\t<panel_accuracy_scale>" + panel_list[p].relevance + "</panel_accuracy_scale>\n";
// Exclude constraint (invert flag)
if (panel_list[p].exclude) {
s += '\t\t<invert>1</invert>\n';
} else {
s += '\t\t<invert>0</invert>\n';
}
// Panel Timing
s += '\t\t<panel_timing>' + panel_list[p].timing + '</panel_timing>\n';
// Occurs constraint
s += '\t\t<total_item_occurrences>'+((panel_list[p].occurs*1)+1)+'</total_item_occurrences>\n';
// Concepts
for (i=0; i < panel_list[p].items.length; i++) {
var sdxData = panel_list[p].items[i];
s += '\t\t<item>\n';
switch(sdxData.sdxInfo.sdxType) {
case "QM":
s += '\t\t\t<item_key>masterid:' + sdxData.origData.id + '</item_key>\n';
s += '\t\t\t<item_name>' + sdxData.origData.title + '</item_name>\n';
s += '\t\t\t<tooltip>' + sdxData.origData.name + '</tooltip>\n';
s += '\t\t\t<item_is_synonym>false</item_is_synonym>\n';
s += '\t\t\t<hlevel>0</hlevel>\n';
break;
case "PRS":
s += '\t\t\t<item_key>patient_set_coll_id:' + sdxData.sdxInfo.sdxKeyValue + '</item_key>\n';
s += '\t\t\t<item_name>' + sdxData.sdxInfo.sdxDisplayName + '</item_name>\n';
s += '\t\t\t<tooltip>' + sdxData.sdxInfo.sdxDisplayName + '</tooltip>\n';
s += '\t\t\t<item_is_synonym>false</item_is_synonym>\n';
s += '\t\t\t<hlevel>0</hlevel>\n';
break;
case "ENS":
s += '\t\t\t<item_key>patient_set_enc_id:' + sdxData.sdxInfo.sdxKeyValue + '</item_key>\n';
s += '\t\t\t<item_name>' + sdxData.sdxInfo.sdxDisplayName + '</item_name>\n';
s += '\t\t\t<tooltip>' + sdxData.sdxInfo.sdxDisplayName + '</tooltip>\n';
s += '\t\t\t<item_is_synonym>false</item_is_synonym>\n';
s += '\t\t\t<hlevel>0</hlevel>\n';
break;
default:
if (sdxData.origData.isModifier) {
var modParent = sdxData.origData.parent;
var level = sdxData.origData.level;
var key = sdxData.origData.parent.key;
var name = (sdxData.origData.parent.name != null ? i2b2.h.Escape(sdxData.origData.parent.name) : i2b2.h.Escape(sdxData.origData.name)) ;
var tooltip = sdxData.origData.tooltip;
var itemicon = sdxData.origData.hasChildren;
while (modParent != null)
{
if (modParent.isModifier)
{
modParent = modParent.parent;
} else {
level = modParent.level;
key = modParent.key;
name = modParent.name;
tooltip = modParent.tooltip;
itemicon = modParent.hasChildren;
break;
}
}
s += '\t\t\t<hlevel>' + level + '</hlevel>\n';
s += '\t\t\t<item_key>' + key + '</item_key>\n';
s += '\t\t\t<item_name>' + name + '</item_name>\n';
s += '\t\t\t<item_key>' + sdxData.origData.key + '</item_key>\n';
s += '\t\t\t<tooltip>' + sdxData.origData.tooltip + '</tooltip>\n';
s += '\t\t\t<class>ENC</class>\n';
s += '\t\t\t<item_icon>' + sdxData.origData.hasChildren + '</item_icon>\n';
}
try {
var t = i2b2.h.XPath(sdxData.origData.xmlOrig,'descendant::synonym_cd/text()');
t = (t[0].nodeValue=="Y");
} catch(e) {
var t = "false";
}
s += '\t\t\t<item_is_synonym>'+t+'</item_is_synonym>\n';
if (sdxData.LabValues) {
//s += '\t\t\t<constrain_by_value>\n';
s += this.getValues( sdxData.LabValues);
}
break;
}
//TODO add contraint to the item in the future
/*
s += '\t\t\t<constrain_by_date>\n';
if (panel_list[p].dateFrom) {
s += '\t\t\t\t<date_from>'+panel_list[p].dateFrom.Year+'-'+padNumber(panel_list[p].dateFrom.Month,2)+'-'+padNumber(panel_list[p].dateFrom.Day,2)+'Z</date_from>\n';
}
if (panel_list[p].dateTo) {
s += '\t\t\t\t<date_to>'+panel_list[p].dateTo.Year+'-'+padNumber(panel_list[p].dateTo.Month,2)+'-'+padNumber(panel_list[p].dateTo.Day,2)+'Z</date_to>\n';
"<span class='no-print' style='font-family:Arial'><img src=\"js-i2b2/cells/CRC/assets/print.png\"/> <a href='javascript:window.print()' title='Click here to print the report.'>Print Report</a></span>"+
"<span class='no-print' style='font-family:Arial'><img src=\"js-i2b2/cells/CRC/assets/print.png\"/> <a href='javascript:window.print()' title='Click here to print the report.'>Print Report</a></span>"+