package net.shrine.protocol import net.shrine.problem.{ProblemNotYetEncoded, LoggingProblemHandler, Problem, ProblemDigest} import scala.xml.{NodeBuffer, NodeSeq} import net.shrine.util.XmlUtil import net.shrine.serialization.XmlUnmarshaller import net.shrine.serialization.I2b2Unmarshaller import net.shrine.util.NodeSeqEnrichments import scala.util.Try import scala.util.control.NonFatal /** * @author Bill Simons * @since 4/25/11 * @see http://cbmi.med.harvard.edu * @see http://chip.org *

* NOTICE: This software comes with NO guarantees whatsoever and is * licensed as Lgpl Open Source * @see http://www.gnu.org/licenses/lgpl.html * * NB: Now a case class for structural equality */ final case class ErrorResponse(errorMessage: String,problemDigest:ProblemDigest) extends ShrineResponse { override protected def status: NodeSeq = { val buffer = new NodeBuffer buffer += { errorMessage } buffer += problemDigest.toXml } override protected def i2b2MessageBody = null import ErrorResponse.rootTagName override def toXml = { XmlUtil.stripWhitespace { val xml = XmlUtil.renameRootTag(rootTagName) { { errorMessage } {problemDigest.toXml} } xml } } } object ErrorResponse extends XmlUnmarshaller[ErrorResponse] with I2b2Unmarshaller[ErrorResponse] with HasRootTagName { val rootTagName = "errorResponse" //todo deprecate this one def apply(errorMessage:String,problem:Option[Problem] = None) = { new ErrorResponse(errorMessage,problem.fold{ val problem = ProblemNotYetEncoded(s"'$errorMessage'") LoggingProblemHandler.handleProblem(problem) //todo someday hook up to the proper problem handler hierarchy. problem.toDigest }(p => p.toDigest)) } def apply(problem:Problem) = { new ErrorResponse(problem.summary,problem.toDigest) } override def fromXml(xml: NodeSeq): ErrorResponse = { val messageXml = xml \ "message" //NB: Fail fast require(messageXml.nonEmpty) val problemDigest = ProblemDigest.fromXml(xml) ErrorResponse(XmlUtil.trim(messageXml),problemDigest) } override def fromI2b2(xml: NodeSeq): ErrorResponse = { import NodeSeqEnrichments.Strictness._ //todo what determines parseFormatA vs parseFormatB when written? It looks like our ErrorResponses use A. def parseFormatA: Try[ErrorResponse] = { for { statusXml <- xml withChild "response_header" withChild "result_status" withChild "status" resultStatusXml <- xml withChild "response_header" withChild "result_status" typeText <- statusXml attribute "type" if typeText == "ERROR" //NB: Fail fast{ statusMessage = XmlUtil.trim(statusXml) problemDigest = ProblemDigest.fromXml(resultStatusXml) } yield { ErrorResponse(statusMessage,problemDigest) } } def parseFormatB: Try[ErrorResponse] = { for { conditionXml <- xml withChild "message_body" withChild "response" withChild "status" withChild "condition" typeText <- conditionXml attribute "type" if typeText == "ERROR" statusMessage = XmlUtil.trim(conditionXml) } yield { ErrorResponse(statusMessage) } } parseFormatA.recoverWith { case NonFatal(e) => { e.printStackTrace() //todo log instead parseFormatB } }.get } /** * * * * * * Query result instance id 3126 not found * * * * */ }