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

lson.core_2.11.0.9.71.source-code.NamespaceName.scala Maven / Gradle / Ivy

The newest version!
//: ----------------------------------------------------------------------------
//: Copyright (C) 2017 Verizon.  All Rights Reserved.
//:
//:   Licensed under the Apache License, Version 2.0 (the "License");
//:   you may not use this file except in compliance with the License.
//:   You may obtain a copy of the License at
//:
//:       http://www.apache.org/licenses/LICENSE-2.0
//:
//:   Unless required by applicable law or agreed to in writing, software
//:   distributed under the License is distributed on an "AS IS" BASIS,
//:   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//:   See the License for the specific language governing permissions and
//:   limitations under the License.
//:
//: ----------------------------------------------------------------------------
package nelson

import scalaz._, Scalaz._
import scala.annotation.tailrec

/*
 * Represents a fully qualified namespace path, where 'dev' is the parent
 * to 'dev/sandbox'. When represented as a string it is delimited by '/'.
 * A NamespaceName is considered a root when it has no parent
 */
final case class NamespaceName(private val nel: NonEmptyList[String]) {
  def root: NamespaceName = NamespaceName(nel.head)
  def isRoot: Boolean = nel.tail.isEmpty
  def parent: Option[NamespaceName] = {
    if (isRoot) None
    else Some(NamespaceName(nel.head, nel.tail.dropRight(1)))
  }
  def asString: String = nel.tail.foldLeft(nel.head)((a,b) => s"$a/$b")

  def isSubordinate(other: NamespaceName): Boolean = {

    @tailrec
    def go(cur: NamespaceName): Boolean =
      if (cur == this) true
      else cur.parent match {
        case Some(p) => go(p)
        case None => false
      }

    other.parent.cata(p => go(p), false)
  }

  /*
   * Returns and ordered list of NamespaceName starting at the root
   */
  def hierarchy: List[NamespaceName] = {

    @tailrec
    def go(cur: NamespaceName, res: List[NamespaceName]): List[NamespaceName] = {
      cur.parent match {
        case Some(p) => go(p, cur :: res)
        case None => cur :: res
      }
    }

    go(this, Nil)
  }
}

object NamespaceName {

  def apply(root: String): NamespaceName = NamespaceName(NonEmptyList.nel(root, Nil))

  def apply(root: String, rest: List[String]): NamespaceName = NamespaceName(NonEmptyList.nel(root, rest))

  private val alphaNumHyphen = """[a-z][a-z-/]*[a-z]""".r
  def fromString(str: String): InvalidNamespaceName \/ NamespaceName = {
    if (!alphaNumHyphen.pattern.matcher(str).matches || str.contains("//"))
      -\/(InvalidNamespaceName(str))
    else {
      val sp = str.split('/')
      val len = sp.length
      if (len == 0)
        -\/(InvalidNamespaceName(str))
      else {
        val root = sp.head // length checked above
        val tail = sp.toList.takeRight(len - 1)
        \/-(NamespaceName(root, tail))
      }
    }
  }

  def fromList(ls: List[String]): InvalidNamespaceName \/ NamespaceName =
    fromString(ls.mkString("/"))

  implicit val NamespaceNameOrder: Order[NamespaceName] =
    Order[String].contramap[NamespaceName](_.asString)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy