Skip to content

Commit

Permalink
Updates to KML
Browse files Browse the repository at this point in the history
KML: Added maybeOpen to Document;
Renderers: added renderer6;
Extractors: added extractor60, etc.
  • Loading branch information
rchillyard committed Dec 3, 2022
1 parent b27355f commit e5de4b8
Show file tree
Hide file tree
Showing 6 changed files with 1,119 additions and 6 deletions.
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.5.5
sbt.version=1.7.1
11 changes: 8 additions & 3 deletions src/main/scala/com/phasmidsoftware/kmldoc/KML.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ case class KML_Binding(kml: KML, binding: NamespaceBinding)
* @param StyleMaps a sequence of StyleMap elements.
* @param Folders a sequence of Folder elements.
*/
case class Document(name: Text, description: Text, Styles: Seq[Style], StyleMaps: Seq[StyleMap], Folders: Seq[Folder])
case class Document(name: Text, maybeOpen: Option[Int], description: Text, Styles: Seq[Style], StyleMaps: Seq[StyleMap], Folders: Seq[Folder])

/**
* Case class to represent a Scale which is represented in XML as, for example: <scale>1.1</scale>
Expand All @@ -48,6 +48,7 @@ case class Icon(href: Text)
case class HotSpot(_x: Int, _xunits: String, _y: Int, _yunits: String)

case class IconStyle(scale: Scale, Icon: Icon, hotSpot: HotSpot)
//case class IconStyle(maybeScale: Option[Scale], Icon: Icon, hotSpot: HotSpot)

case class LabelStyle(scale: Scale)

Expand Down Expand Up @@ -117,6 +118,7 @@ object KmlExtractors extends Extractors {

implicit val extractorCoordinates: Extractor[Coordinates] = (node: Node) => Success(Coordinates.parse(node.text))
implicit val extractorScale: Extractor[Scale] = extractor10(Scale)
// implicit val extractMaybeScale: Extractor[Option[Scale]] = extractorOption
implicit val extractorIcon: Extractor[Icon] = extractor10(Icon)
implicit val extractorColor: Extractor[Color] = extractor10(Color)
implicit val extractorWidth: Extractor[Width] = extractor10(Width)
Expand Down Expand Up @@ -145,7 +147,8 @@ object KmlExtractors extends Extractors {
implicit val extractorMultiStyleMap: MultiExtractor[Seq[StyleMap]] = multiExtractor[StyleMap]
implicit val extractorMultiStyle: MultiExtractor[Seq[Style]] = multiExtractor[Style]
implicit val extractorMultiFolder: MultiExtractor[Seq[Folder]] = multiExtractor[Folder]
implicit val extractorDocument: Extractor[Document] = extractor23(Document)
implicit val extractMaybeOpen: Extractor[Option[Int]] = extractorOption
implicit val extractorDocument: Extractor[Document] = extractor33(Document)
implicit val extractorMultiDocument: MultiExtractor[Seq[Document]] = multiExtractor[Document]
implicit val extractorKml: Extractor[KML] = extractor01(KML)
implicit val extractorMultiKml: MultiExtractor[Seq[KML]] = multiExtractor[KML]
Expand All @@ -172,6 +175,7 @@ trait KmlRenderers extends Renderers {
import Renderers._

implicit val rendererScale: Renderable[Scale] = renderer1(Scale)
// implicit val rendererOptionScale: Renderable[Option[Scale]] = optionRenderer
implicit val rendererIcon: Renderable[Icon] = renderer1(Icon)
implicit val rendererColor: Renderable[Color] = renderer1(Color)
implicit val rendererWidth: Renderable[Width] = renderer1(Width)
Expand Down Expand Up @@ -204,7 +208,8 @@ trait KmlRenderers extends Renderers {
implicit val rendererFolders: Renderable[Seq[Folder]] = sequenceRenderer[Folder]
implicit val rendererStyles: Renderable[Seq[Style]] = sequenceRenderer[Style]
implicit val rendererStyleMaps: Renderable[Seq[StyleMap]] = sequenceRenderer[StyleMap]
implicit val rendererDocument: Renderable[Document] = renderer5(Document)
implicit val renderOptionOpen: Renderable[Option[Int]] = optionRenderer
implicit val rendererDocument: Renderable[Document] = renderer6(Document)
implicit val rendererDocuments: Renderable[Seq[Document]] = sequenceRenderer[Document]
implicit val rendererKml: Renderable[KML] = renderer1(KML)
implicit val rendererKml_Binding: Renderable[KML_Binding] = (t: KML_Binding, format: Format, stateR: StateR) =>
Expand Down
21 changes: 21 additions & 0 deletions src/main/scala/com/phasmidsoftware/render/Renderers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,27 @@ trait Renderers {
doNestedRender(format, stateR, wInner, wOuter, r.productElementName(4))
}

/**
* Method to create a renderer fpr a Product (e.g., case class) with five members.
*
* @param construct a function which takes a P0, P1, P2, P3, P4 and yields an R (this is usually the apply method of a case class).
* @tparam P0 the (Renderable) type of the first member of Product type R.
* @tparam P1 the (Renderable) type of the second member of Product type R.
* @tparam P2 the (Renderable) type of the third member of Product type R.
* @tparam P3 the (Renderable) type of the fourth member of Product type R.
* @tparam P4 the (Renderable) type of the fifth member of Product type R.
* @tparam R the (Renderable) type of Renderable to be returned (must be a Product).
* @return a function which takes an R, a Format, and a StateR as parameters and yields a Renderable[R].
*/
def renderer6[P0: Renderable, P1: Renderable, P2: Renderable, P3: Renderable, P4: Renderable, P5: Renderable, R <: Product : ClassTag](construct: (P0, P1, P2, P3, P4, P5) => R): Renderable[R] = (r: R, format: Format, stateR: StateR) => {
val objectOuter = r.productElement(5).asInstanceOf[P5]
val constructorInner: (P0, P1, P2, P3, P4) => R = construct(_, _, _, _, _, objectOuter)
val objectInner = constructorInner(r.productElement(0).asInstanceOf[P0], r.productElement(1).asInstanceOf[P1], r.productElement(2).asInstanceOf[P2], r.productElement(3).asInstanceOf[P3], r.productElement(4).asInstanceOf[P4])
val wInner = renderer5(constructorInner).render(objectInner, format.indent, stateR.recurse)
val wOuter = renderOuter(r, objectOuter, 4, format)
doNestedRender(format, stateR, wInner, wOuter, r.productElementName(4))
}

/**
* Method to yield a renderer of Option[R].
*
Expand Down
149 changes: 149 additions & 0 deletions src/main/scala/com/phasmidsoftware/xml/Extractors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ trait Extractors {
case Failure(x) => Failure(x) // TESTME
}

/**
* Method to yield an Extractor which can choose from alternate extractors.
*
* TESTME
*
* @tparam R result type.
* @tparam P0 first extractor type.
* @tparam P1 second extractor type.
* @return an Extractor[R].
*/
def extractorAlt[R, P0 <: R : Extractor, P1 <: R : Extractor]: Extractor[R] =
(node: Node) => implicitly[Extractor[P0]].extract(node) orElse implicitly[Extractor[P1]].extract(node)

/**
* Extractor which will convert an Xml Node into a sequence of P objects where there is evidence of Extractor[P].
*
Expand Down Expand Up @@ -476,6 +489,130 @@ trait Extractors {
} yield t
case fs => Failure(XmlException(s"extractor5: insufficient field names: $fs"))
}

/**
* Extractor which will convert an Xml Node into an instance of a case class with six members.
*
* @param construct a function (P0,P1,P2,P3,P4,P5) => T, usually the apply method of a case class.
* @tparam P0 the (Extractor) type of the first member of the Product type T.
* @tparam P1 the (Extractor) type of the second member of the Product type T.
* @tparam P2 the (Extractor) type of the third member of the Product type T.
* @tparam P3 the (Extractor) type of the fourth member of the Product type T.
* @tparam P4 the (Extractor) type of the fifth member of the Product type T.
* @tparam P5 the (Extractor) type of the sixth member of the Product type T.
* @tparam T the underlying type of the result, a Product with five members.
* @return an Extractor[T] whose method extract will convert a Node into a T.
*/
def extractor60[P0: Extractor, P1: Extractor, P2: Extractor, P3: Extractor, P4: Extractor, P5: Extractor, T <: Product : ClassTag](construct: (P0, P1, P2, P3, P4, P5) => T, fields: Seq[String] = Nil): Extractor[T] =
(node: Node) =>
fieldNames(fields) match {
case member0 :: fs =>
for {
p0 <- extractField[P0](member0)(node)
t <- extractor50[P1, P2, P3, P4, P5, T](construct(p0, _, _, _, _, _), fs).extract(node)
} yield t
case fs => Failure(XmlException(s"extractor5: insufficient field names: $fs")) // TESTME
}

/**
* Extractor which will convert an Xml Node into an instance of a case class with five members.
*
* TESTME
*
* @param construct a function (P0,P1,P2,P3,P4) => T, usually the apply method of a case class.
* @tparam PE0 the (Extractor) type of the first member of the Product type T.
* @tparam PE1 the (Extractor) type of the second member of the Product type T.
* @tparam PE2 the (Extractor) type of the third member of the Product type T.
* @tparam PE3 the (Extractor) type of the fourth member of the Product type T.
* @tparam PM0 the (MultiExtractor) type of the fourth member of the Product type T.
* @tparam PM1 the (MultiExtractor) type of the fifth member of the Product type T.
* @tparam T the underlying type of the result, a Product with five members.
* @return an Extractor[T] whose method extract will convert a Node into a T.
*/
def extractor42[PE0: Extractor, PE1: Extractor, PE2: Extractor, PE3: Extractor, PM0: MultiExtractor, PM1: MultiExtractor, T <: Product : ClassTag](construct: (PE0, PE1, PE2, PE3, PM0, PM1) => T, fields: Seq[String] = Nil): Extractor[T] =
(node: Node) =>
fieldNames(fields) match {
case member0 :: fs =>
for {
p0 <- extractField[PE0](member0)(node)
t <- extractor32[PE1, PE2, PE3, PM0, PM1, T](construct(p0, _, _, _, _, _), fs).extract(node)
} yield t
case fs => Failure(XmlException(s"extractor5: insufficient field names: $fs"))
}

/**
* Extractor which will convert an Xml Node into an instance of a case class with five members.
*
* @param construct a function (P0,P1,P2,P3,P4) => T, usually the apply method of a case class.
* @tparam PE0 the (Extractor) type of the first member of the Product type T.
* @tparam PE1 the (Extractor) type of the second member of the Product type T.
* @tparam PE2 the (MultiExtractor) type of the third member of the Product type T.
* @tparam PM0 the (MultiExtractor) type of the fourth member of the Product type T.
* @tparam PM1 the (MultiExtractor) type of the fifth member of the Product type T.
* @tparam T the underlying type of the result, a Product with five members.
* @return an Extractor[T] whose method extract will convert a Node into a T.
*/
def extractor33[PE0: Extractor, PE1: Extractor, PE2: Extractor, PM0: MultiExtractor, PM1: MultiExtractor, PM2: MultiExtractor, T <: Product : ClassTag](construct: (PE0, PE1, PE2, PM0, PM1, PM2) => T, fields: Seq[String] = Nil): Extractor[T] =
(node: Node) =>
fieldNames(fields) match {
case member0 :: fs =>
for {
p0 <- extractField[PE0](member0)(node)
t <- extractor23[PE1, PE2, PM0, PM1, PM2, T](construct(p0, _, _, _, _, _), fs).extract(node)
} yield t
case fs => Failure(XmlException(s"extractor5: insufficient field names: $fs")) // TESTME
}

/**
* Extractor which will convert an Xml Node into an instance of a case class with five members.
*
* TESTME
*
* @param construct a function (P0,P1,P2,P3,P4) => T, usually the apply method of a case class.
* @tparam PE0 the (Extractor) type of the first member of the Product type T.
* @tparam P1 the (MultiExtractor) type of the second member of the Product type T.
* @tparam P2 the (MultiExtractor) type of the third member of the Product type T.
* @tparam P3 the (MultiExtractor) type of the fourth member of the Product type T.
* @tparam P4 the (MultiExtractor) type of the fifth member of the Product type T.
* @tparam T the underlying type of the result, a Product with five members.
* @return an Extractor[T] whose method extract will convert a Node into a T.
*/
def extractor24[PE0: Extractor, PE1: Extractor, P1: MultiExtractor, P2: MultiExtractor, P3: MultiExtractor, P4: MultiExtractor, T <: Product : ClassTag](construct: (PE0, PE1, P1, P2, P3, P4) => T, fields: Seq[String] = Nil): Extractor[T] =
(node: Node) =>
fieldNames(fields) match {
case member0 :: fs =>
for {
p0 <- extractField[PE0](member0)(node)
t <- extractor14[PE1, P1, P2, P3, P4, T](construct(p0, _, _, _, _, _), fs).extract(node)
} yield t
case fs => Failure(XmlException(s"extractor5: insufficient field names: $fs"))
}

/**
* Extractor which will convert an Xml Node into an instance of a case class with five members.
*
* TESTME
*
* @param construct a function (P0,P1,P2,P3,P4) => T, usually the apply method of a case class.
* @tparam P0 the (MultiExtractor) type of the first member of the Product type T.
* @tparam P1 the (MultiExtractor) type of the second member of the Product type T.
* @tparam P2 the (MultiExtractor) type of the third member of the Product type T.
* @tparam P3 the (MultiExtractor) type of the fourth member of the Product type T.
* @tparam P4 the (MultiExtractor) type of the fifth member of the Product type T.
* @tparam T the underlying type of the result, a Product with five members.
* @return an Extractor[T] whose method extract will convert a Node into a T.
*/
def extractor06[P0: MultiExtractor, P1: MultiExtractor, P2: MultiExtractor, P3: MultiExtractor, P4: MultiExtractor, P5: MultiExtractor, T <: Product : ClassTag](construct: (P0, P1, P2, P3, P4, P5) => T, fields: Seq[String] = Nil): Extractor[T] =
(node: Node) =>
fieldNames(fields) match {
case member0 :: fs =>
for {
p0 <- extractChildren[P0](node, member0)
t <- extractor05[P1, P2, P3, P4, P5, T](construct(p0, _, _, _, _, _), fs).extract(node)
} yield t
case fs => Failure(XmlException(s"extractor5: insufficient field names: $fs"))
}

}

/**
Expand Down Expand Up @@ -683,13 +820,25 @@ object Extractors {
* @tparam T the type to be constructed.
*/
trait Extractor[T] {
self =>

/**
* Method to convert a Node into a Try[T].
*
* @param node a Node.
* @return a Try[T].
*/
def extract(node: Node): Try[T]

/**
* Method to combine this Extractor[T] with alt as a disjunctive expression.
*
* TESTME
*
* @param alt an alternative Extractor which will be invoked if this Extractor fails.
* @return an Extractor based on this and alt.
*/
def |(alt: Extractor[T]): Extractor[T] = (node: Node) => self.extract(node) orElse alt.extract(node)
}

/**
Expand Down
Loading

0 comments on commit e5de4b8

Please sign in to comment.