All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sandinh.soap.SOAP.scala Maven / Gradle / Ivy

The newest version!
package com.sandinh.soap

import scala.language.implicitConversions
import scala.xml.{Elem, NamespaceBinding}
import com.sandinh.xml._
import org.slf4j.LoggerFactory

object SOAP extends SOAP

trait SOAP {
  def toSoap[T](t: T, ns: NamespaceBinding = SoapNS)(implicit w: XmlWriter[T]): xml.Elem =
    DefaultImplicits.SoapEnvelopeWriter[T](w).write(SoapEnvelope(t)(ns), xml.NodeSeq.Empty).asInstanceOf[Elem]

  def fromSOAP[T](x: xml.NodeSeq)(implicit r: XmlReader[T]): Option[T] =
    DefaultImplicits.SoapEnvelopeReader[T](r).read(x) match {
      case Some(SoapEnvelope(t)) => Some(t)
      case None                  => None
    }

  val SoapNS = NamespaceBinding("soapenv", "http://schemas.xmlsoap.org/soap/envelope/", xml.TopScope)
  val SoapNS12 = NamespaceBinding("soapenv", "http://www.w3.org/2003/05/soap-envelope", xml.TopScope)
}

case class SoapEnvelope[T](t: T)(implicit _namespace: NamespaceBinding = SOAP.SoapNS) {
  def namespace = _namespace
}

case class SoapFault[T](
  faultcode:   String,
  faultstring: String,
  faultactor:  String,
  detail:      T
)

object SoapFault {
  object FaultCode {
    /** Found an invalid namespace for the SOAP Envelope element */
    val VersionMismatch = "SOAP-ENV:VersionMismatch"
    /** An immediate child element of the Header element, with the mustUnderstand attribute set to "1", was not understood */
    val MustUnderstand = "SOAP-ENV:MustUnderstand"
    /** The message was incorrectly formed or contained incorrect information */
    val Client = "SOAP-ENV:Client"
    /** There was a problem with the server so the message could not proceed */
    val Server = "SOAP-ENV:Server"
  }
}

object DefaultImplicits extends DefaultSOAPFormatters with BasicReaders with SpecialReaders with BasicWriters with SpecialWriters

trait DefaultSOAPFormatters {
  private lazy val logger = LoggerFactory getLogger getClass.getName

  implicit def SoapEnvelopeReader[T](implicit reader: XmlReader[T]): XmlReader[SoapEnvelope[T]] = new XmlReader[SoapEnvelope[T]] {
    def read(x: xml.NodeSeq): Option[SoapEnvelope[T]] = {
      x.collectFirst { case x: xml.Elem if x.label == "Envelope" => x }
        .flatMap { env =>
          (env \ "Body").headOption.flatMap { body =>
            reader.read(body).map { t =>
              SoapEnvelope(t)(env.scope)
            }
          }
        }
    }
  }

  implicit def SoapEnvelopeWriter[T](implicit fmt: XmlWriter[T]): XmlWriter[SoapEnvelope[T]] = new XmlWriter[SoapEnvelope[T]] {
    /** @param base not used */
    def write(st: SoapEnvelope[T], base: xml.NodeSeq) = {
      val env =
        
          
          { Xml.toXml(st.t) }
        
      env.copy(scope = st.namespace)
    }
  }

  implicit def SoapFaultReader[T](implicit fmt: XmlReader[T], strR: XmlReader[String]): XmlReader[SoapFault[T]] = new XmlReader[SoapFault[T]] {
    def read(x: xml.NodeSeq): Option[SoapFault[T]] = {
      val envelope = x \\ "Fault"
      envelope.headOption.flatMap[SoapFault[T]]({ elt =>
        (
          strR.read(elt \ "faultcode"), strR.read(elt \ "faultstring"), strR.read(elt \ "faultactor"), fmt.read(elt \ "detail")
        ) match {
            case (None, _, _, _) =>
              logger.debug("Code part missing in SOAP Fault"); None
            case (_, None, _, _) =>
              logger.debug("Message part missing in SOAP Fault"); None
            case (_, _, None, _) =>
              logger.debug("Actor part missing in SOAP Fault"); None
            case (_, _, _, None) =>
              logger.debug("Detail part missing in SOAP Fault"); None
            case (Some(code), Some(msg), Some(actor), Some(detail)) => Some(SoapFault(code, msg, actor, detail))
            case _ => None
          }
      })
    }
  }

  implicit def SoapFaultWriter[T](implicit fmt: XmlWriter[T]): XmlWriter[SoapFault[T]] = new XmlWriter[SoapFault[T]] {
    def write(fault: SoapFault[T], base: xml.NodeSeq) =
      
        { fault.faultcode }
        { fault.faultstring }
        { fault.faultactor }
        { Xml.toXml(fault.detail) }
      
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy