app/models/FCInfo.scala (55 lines of code) (raw):
package models
import io.circe.generic.auto._
import io.circe.syntax._
import io.circe.parser.decode
import scala.xml.{Elem, NodeSeq}
object FCDomain extends ((String,Option[String],Option[String], Option[String],Int)=>FCDomain) {
private def getAttrOption(xml:NodeSeq, attr:String) = {
val raw = xml \@ attr
if(raw==""){
None
} else {
Some(raw)
}
}
def fromXml(xml:NodeSeq):Either[String, FCDomain] = try {
if(!xml.head.label.startsWith("Domain")) throw new RuntimeException(s"expected a Domain line, got ${xml.head.label}")
Right(new FCDomain(
xml.head.label,
getAttrOption(xml,"Speed"),
getAttrOption(xml,"Status"),
getAttrOption(xml,"WWN"),
(xml \@ "lunCount").toInt
))
} catch {
case ex:Throwable=>
Left(ex.toString)
}
}
case class FCDomain(name:String, speed:Option[String],status:Option[String], portWWN:Option[String], lunCount:Int)
object FCInfo extends((Seq[FCDomain], String)=>FCInfo) {
def fromXml(xml:NodeSeq):Either[String,FCInfo] = try {
val domains = xml.head.child.map({
case e: Elem =>
if(e.label.startsWith("Domain")){
Some(FCDomain.fromXml(e))
} else {
None
}
case _=>
None
}).collect({
case Some(dom)=>dom
})
val failedDoms = domains.collect({case Left(err)=>err})
if(failedDoms.nonEmpty){
Left(s"Could not parse FC domains: $failedDoms")
} else {
Right(new FCInfo(domains.collect({case Right(dom)=>dom}), xml \@"Product"))
}
} catch {
case ex:Throwable=>
Left(ex.toString)
}
}
case class FCInfo(domains: Seq[FCDomain], productName: String)