Skip to content

Commit

Permalink
QName and EName are now enums
Browse files Browse the repository at this point in the history
  • Loading branch information
dvreeze committed Apr 1, 2023
1 parent b185122 commit a0f75e1
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 47 deletions.
Expand Up @@ -43,8 +43,8 @@ object EQName:
def localPart: String = ename.localPart

override def toString: String = ename match
case common.EName(None, localPart) => s"Q{}$localPart"
case common.EName(Some(ns), localPart) => s"Q{$ns}$localPart"
case common.EName.WithoutNamespace(localPart) => s"Q{}$localPart"
case common.EName.WithNamespace(ns, localPart) => s"Q{$ns}$localPart"

object QName:

Expand Down
Expand Up @@ -17,6 +17,7 @@
package eu.cdevreeze.xpathparser.ast

import cats.data.NonEmptyVector
import eu.cdevreeze.xpathparser.queryapi.ElemApi
import eu.cdevreeze.xpathparser.queryapi.ElemLike

/**
Expand Down Expand Up @@ -51,7 +52,7 @@ import eu.cdevreeze.xpathparser.queryapi.ElemLike
* @author
* Chris de Vreeze
*/
sealed trait XPathElem extends ElemLike[XPathElem]:
sealed trait XPathElem extends ElemApi[XPathElem], ElemLike[XPathElem]:

/**
* Returns the (immediate) child elements of this element.
Expand Down
19 changes: 10 additions & 9 deletions shared/src/main/scala/eu/cdevreeze/xpathparser/common/EName.scala
Expand Up @@ -22,9 +22,9 @@ package eu.cdevreeze.xpathparser.common
* @author
* Chris de Vreeze
*/
final case class EName(namespaceUriOption: Option[String], localPart: String):
require(namespaceUriOption ne null) // scalastyle:off null
require(localPart ne null) // scalastyle:off null
enum EName(val namespaceUriOption: Option[String], val localPart: String):
case WithoutNamespace(override val localPart: String) extends EName(None, localPart)
case WithNamespace(namespace: String, override val localPart: String) extends EName(Some(namespace), localPart)

/** Given an optional prefix, creates a `QName` from this `EName` */
def toQName(prefixOption: Option[String]): QName =
Expand All @@ -41,11 +41,12 @@ final case class EName(namespaceUriOption: Option[String], localPart: String):

object EName:

/** Creates an `EName` from a namespaceUri and a localPart */
def apply(namespaceUri: String, localPart: String): EName = EName(Some(namespaceUri), localPart)
def apply(namespaceUriOption: Option[String], localPart: String): EName = namespaceUriOption match
case None => EName.WithoutNamespace(localPart)
case Some(ns) => EName.WithNamespace(ns, localPart)

/** Shorthand for `parse(s)` */
def apply(s: String): EName = parse(s)
/** Creates an `EName` from a namespaceUri and a localPart */
def apply(namespaceUri: String, localPart: String): EName = EName.WithNamespace(namespaceUri, localPart)

/**
* Parses a `String` into an `EName`. The `String` (after trimming) must conform to the `toString` format of an
Expand All @@ -59,8 +60,8 @@ object EName:
require(idx >= 2 && idx < st.length - 1, s"Opening brace not closed or at incorrect location in EName '${st}'")
val ns = st.substring(1, idx)
val localPart = st.substring(idx + 1)
EName(Some(ns), localPart)
EName.WithNamespace(ns, localPart)
else
require(st.indexOf("{") < 0, s"No opening brace allowed unless at the beginning in EName '${st}'")
require(st.indexOf("}") < 0, s"Closing brace without matching opening brace not allowed in EName '${st}'")
EName(None, st)
EName.WithoutNamespace(st)
49 changes: 16 additions & 33 deletions shared/src/main/scala/eu/cdevreeze/xpathparser/common/qname.scala
Expand Up @@ -22,47 +22,30 @@ package eu.cdevreeze.xpathparser.common
* @author
* Chris de Vreeze
*/
sealed trait QName extends Serializable:
enum QName(val prefixOption: Option[String], val localPart: String):
case Unprefixed(override val localPart: String) extends QName(None, localPart)
case Prefixed(prefix: String, override val localPart: String) extends QName(Some(prefix), localPart)

def localPart: String
def prefixOption: Option[String]

final case class UnprefixedName(override val localPart: String) extends QName:
require(localPart ne null) // scalastyle:off null

override def prefixOption: Option[String] = None

/** The `String` representation as it appears in XML, that is, the localPart */
override def toString: String = localPart

final case class PrefixedName(prefix: String, override val localPart: String) extends QName:
require(prefix ne null) // scalastyle:off null
require(localPart ne null) // scalastyle:off null

override def prefixOption: Option[String] = Some(prefix)

/** The `String` representation as it appears in XML. For example, <code>xs:schema</code> */
override def toString: String = s"${prefix}:${localPart}"
override def toString: String = this match
case Unprefixed(localPart) => localPart
case Prefixed(prefix, localPart) => s"$prefix:$localPart"

object QName:

/** Creates a `QName` from an optional prefix and a localPart */
def apply(prefixOption: Option[String], localPart: String): QName =
prefixOption
.map { pref =>
PrefixedName(pref, localPart)
Prefixed(pref, localPart)
}
.getOrElse(UnprefixedName(localPart))

/** Creates a `PrefixedName` from a prefix and a localPart */
def apply(prefix: String, localPart: String): QName = PrefixedName(prefix, localPart)
.getOrElse(Unprefixed(localPart))

/** Shorthand for `parse(s)` */
def apply(s: String): QName = parse(s)
/** Creates a `Prefixed` from a prefix and a localPart */
def apply(prefix: String, localPart: String): QName = Prefixed(prefix, localPart)

/**
* Parses a `String` into a `QName`. The `String` (after trimming) must conform to the `toString` format of a
* `PrefixedName` or `UnprefixedName`.
* `Prefixed` or `Unprefixed`.
*/
def parse(s: String): QName =
val st = s.trim
Expand All @@ -71,8 +54,8 @@ object QName:
require(arr.size <= 2, s"Expected at most 1 colon in QName '${st}'")

arr.size match
case 1 => UnprefixedName(st)
case 2 => PrefixedName(arr(0), arr(1))
case 1 => Unprefixed(st)
case 2 => Prefixed(arr(0), arr(1))
case _ => sys.error(s"Did not expect more than 1 colon in QName '${st}'")

/**
Expand All @@ -81,6 +64,6 @@ object QName:
* With this extractor one can pattern match on arbitrary QNames, and not just on prefixed or unprefixed names.
*/
def unapply(qname: QName): Option[(Option[String], String)] = qname match
case UnprefixedName(localPart) => Some((None, localPart))
case PrefixedName(prefix, localPart) => Some((Some(prefix), localPart))
case null => None
case Unprefixed(localPart) => Some((None, localPart))
case Prefixed(prefix, localPart) => Some((Some(prefix), localPart))
case null => None
Expand Up @@ -43,7 +43,6 @@ import eu.cdevreeze.xpathparser.ast.VarRef
import eu.cdevreeze.xpathparser.ast.VariableBinding
import eu.cdevreeze.xpathparser.ast.XPathElem
import eu.cdevreeze.xpathparser.ast.XPathExpr
import eu.cdevreeze.xpathparser.common.PrefixedName
import eu.cdevreeze.xpathparser.common.QName

/**
Expand Down Expand Up @@ -203,7 +202,7 @@ object EQNameUtil:
*/
val eqnameProducerFromXsQName: XPathElem => Option[Set[EQName]] =
case FunctionCall(
EQName.QName(PrefixedName("xs", "QName")),
EQName.QName(QName.Prefixed("xs", "QName")),
ArgumentList(IndexedSeq(ExprSingleArgument(StringLiteral(s))))
) =>
val qn = QName.parse(s)
Expand Down

0 comments on commit a0f75e1

Please sign in to comment.