Skip to content

Commit

Permalink
Add object-oriented mr Hyde
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil-adam committed Jan 15, 2020
1 parent 13a99bc commit e491e7c
Show file tree
Hide file tree
Showing 35 changed files with 658 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package pl.writeonly.scala.hyde.common.states

trait State {
def showResult(): Unit

def showStep(): Unit

def isEmptyNextInternalUrls: Boolean
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package pl.writeonly.scala.hyde.common.states.api

import pl.writeonly.scala.hyde.common.states.State
import pl.writeonly.scala.hyde.common.url.typed.InternalUrls
import pl.writeonly.scala.hyde.common.url.urls._
import scalaz.Scalaz._

abstract class AbstractAPIState(data: UrlsWithThrowableList) extends State {

protected type HP

protected final type SET = Set[HP]

type NextState

override def showStep(): Unit = data.showStep()

def showResult(): Unit = data.showResult()

def isEmptyNextInternalUrls: Boolean = data.isEmptyNextInternalUrls

override def toString: String = data.toString

protected final def newState(set: SET): NextState = set |> nextData |> nextState

protected def nextData(set: SET): UrlsWithThrowableList

protected def nextState(data: UrlsWithThrowableList): NextState

protected def nextUrls: InternalUrls = data.nextUrls

def throwableList: ThrowableList = data.throwableList
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pl.writeonly.scala.hyde.common.states.notexception

import pl.writeonly.scala.hyde.sourcepage.InternalUrlTo

trait AbstractFunctionState extends AbstractNewSetState {

protected final def newSet: SET = nextUrls.map(impureFunction)

protected def impureFunction: HPFromInternalUrl

protected type HPFromInternalUrl = InternalUrlTo[HP]

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package pl.writeonly.scala.hyde.common.states.notexception

trait AbstractNewSetState extends AbstractNextState {

final def next: AbstractNextState = newState(newSet)

protected def newSet: SET
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package pl.writeonly.scala.hyde.common.states.notexception

import scala.annotation.tailrec

import pl.writeonly.scala.hyde.common.states.api.AbstractAPIState

trait AbstractNextState extends AbstractAPIState {

def next: NextState

type NextState = AbstractNextState
}

object AbstractNextState {
@tailrec
def run(state: AbstractNextState): AbstractNextState = if (state.isEmptyNextInternalUrls) state else run(state.next)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pl.writeonly.scala.hyde.common.states.notexception

import pl.writeonly.scala.hyde.common.url.Domain
import scalaz.Scalaz._

trait AbstractNextStateObject {

final def apply(domain: String): AbstractNextState = fromDomain(new Domain(domain)) |> AbstractNextState.run

protected def fromDomain(implicit d: Domain): AbstractNextState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package pl.writeonly.scala.hyde.common.states.oo

import scala.annotation.tailrec

import pl.writeonly.scala.hyde.common.states.State
import pl.writeonly.scala.hyde.common.url._
import pl.writeonly.scala.hyde.common.url.urls._
import pl.writeonly.scala.hyde.sourcepage.oo.InternalUrlToSourcePage
import scalaz.Scalaz._

abstract class AbstractOOState(urls: Urls)(implicit d: Domain) extends State {

final def next: AbstractOOState = getWrappedUrlSet |> NewUrls.apply |> urls.next |> nextState

final def getWrappedUrlSet: WrappedUrlSet =
urls.nextInternalUrls
.map(impureFunction)
.flatMap(_.getWrappedUrlSet)

override final def showResult(): Unit = urls.showResult()

override final def showStep(): Unit = urls.showStep()

override final def isEmptyNextInternalUrls: Boolean = urls.isEmptyNextInternalUrls

protected def nextState(urls: Urls): AbstractOOState

protected def impureFunction: InternalUrlToSourcePage
}

object AbstractOOState {
@tailrec
def run(state: AbstractOOState): AbstractOOState = if (state.isEmptyNextInternalUrls) state else run(state.next)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package pl.writeonly.scala.hyde.common.states.oo

import pl.writeonly.scala.hyde.common.url.Domain
import scalaz.Scalaz._

trait AbstractOOStateObject {

final def apply(domain: String): AbstractOOState = fromDomain(new Domain(domain)) |> AbstractOOState.run

def fromDomain(implicit d: Domain): AbstractOOState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pl.writeonly.scala.hyde.common.url

import pl.writeonly.scala.hyde.common.url.typed._

class Domain(domain: WrappedUrl) {

def this(url: String) = this(new WrappedUrl(url))

println("domain " + toString)

override def toString: String = domain.toString

def toInternalUrl: InternalUrl = InternalUrl(domain)(this)

def toInternalUrl(url: WrappedUrl): InternalUrl = new InternalUrl(domain.append(url))

def isInternalUrl(url: WrappedUrl): Boolean = url.isInternalUrl(domain)

def toWrappedUrl: WrappedUrl = domain
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package pl.writeonly.scala.hyde.common.url

import java.net._

import pl.writeonly.scala.hyde.common.url.exception._
import pl.writeonly.scala.hyde.common.url.typed._

final case class WrappedUrl(private val url: String) extends Ordered[WrappedUrl] {

override def toString: String = url

override def compare(that: WrappedUrl): Int = url.compareTo(that.url)

def append(that: WrappedUrl): WrappedUrl = new WrappedUrl(url + that.url)

def toURL: URL = new URL(url)

def toURI: URI = URI.create(url)

def toException(e: Throwable): UrlException = new UrlException(url, e)

def toNonInternalException: NonInternalUrlException = new NonInternalUrlException(url)

def toNonRelativeException: NonRelativeUrlException = new NonRelativeUrlException(url)

def isRelativeUrl: Boolean = url.startsWith("/")

def isInternalUrl(implicit d: Domain): Boolean = d.isInternalUrl(this)

def isInternalUrl(d: WrappedUrl): Boolean = url.startsWith(d.url)

def toInternalUrl(implicit d: Domain): InternalUrl = InternalUrl(this)

def makeInternalUrl(implicit d: Domain): InternalUrl = d.toInternalUrl(this)

def toExternalUrl: ExternalUrl = new ExternalUrl(this)

def getType(implicit d: Domain): Symbol = url match {
case _ if isInternalUrl => WrappedUrl.Internal
case _ if isRelativeUrl => WrappedUrl.Relative
case _ => WrappedUrl.External
}
}

object WrappedUrl {
val Internal = 'internal
val Relative = 'relative
val External = 'external
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package pl.writeonly.scala.hyde.common.url.exception

class NonInternalUrlException(url: String) extends IllegalArgumentException(url)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package pl.writeonly.scala.hyde.common.url.exception

class NonRelativeUrlException(url: String) extends IllegalArgumentException(url)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package pl.writeonly.scala.hyde.common.url.exception

class UrlException(url: String, e: Throwable) extends IllegalArgumentException(url, e)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package pl.writeonly.scala.hyde.common

import scala.collection.immutable.SortedSet

package object url {
type WrappedUrls = SortedSet[WrappedUrl]

type WrappedUrlSet = Set[WrappedUrl]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package pl.writeonly.scala.hyde.common.url.typed

import pl.writeonly.scala.hyde.common.url._

final class ExternalUrl(private val url: WrappedUrl) extends Ordered[ExternalUrl] {

def toInternalUrl(implicit d: Domain): InternalUrl = InternalUrl(url)

override def compare(that: ExternalUrl): Int = url.compareTo(that.url)

override def toString: String = url.toString
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package pl.writeonly.scala.hyde.common.url.typed

import java.net.URL

import pl.writeonly.scala.hyde.common.url._
import pl.writeonly.scala.hyde.common.url.exception.UrlException

final class InternalUrl(private val url: WrappedUrl) extends Ordered[InternalUrl] {

override def compare(that: InternalUrl): Int = url.compare(that.url)

override def toString: String = url.toString

def toException(e: Throwable): UrlException = url.toException(e)

def toURL: URL = url.toURL
}

object InternalUrl {

@SuppressWarnings(Array("org.wartremover.warts.Throw"))
def apply(url: WrappedUrl)(implicit d: Domain): InternalUrl =
if (url.isInternalUrl) new InternalUrl(url) else throw url.toNonInternalException
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package pl.writeonly.scala.hyde.common.url.typed

import pl.writeonly.scala.hyde.common.url._

final class RelativeUrl private (val url: WrappedUrl) {
def toInternalUrl(implicit d: Domain): InternalUrl = InternalUrl(url)

override def toString: String = url.toString
}

object RelativeUrl {

def isRelativeUrl(url: WrappedUrl): Boolean = url.isRelativeUrl

@SuppressWarnings(Array("org.wartremover.warts.Throw"))
def apply(url: WrappedUrl): RelativeUrl =
if (url.isRelativeUrl) new RelativeUrl(url) else throw url.toNonRelativeException

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package pl.writeonly.scala.hyde.common.url

import scala.collection.immutable.SortedSet

package object typed {
type RelationUrls = SortedSet[RelativeUrl]
type InternalUrls = SortedSet[InternalUrl]
type ExternalUrls = SortedSet[ExternalUrl]

type RelationUrlSet = Set[RelativeUrl]
type InternalUrlSet = Set[InternalUrl]
type ExternalUrlSet = Set[ExternalUrl]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package pl.writeonly.scala.hyde.common.url.urls

import pl.writeonly.scala.hyde.common.url._
import pl.writeonly.scala.hyde.common.url.typed._

class NewUrls private (val newExternalUrls: ExternalUrlSet, val newInternalUrls: InternalUrlSet)

object NewUrls {
type GroupedUrlMap = Map[Symbol, WrappedUrlSet]

def apply(wrappedUrlSet: WrappedUrlSet)(implicit d: Domain): NewUrls = {
val grouped: GroupedUrlMap = wrappedUrlSet.groupBy(_.getType)

val newExternalUrls: ExternalUrlSet = grouped.getOrElse(WrappedUrl.External, Set.empty).map(_.toExternalUrl)

val relativeUrls1: InternalUrlSet = grouped.getOrElse(WrappedUrl.Relative, Set.empty).map(_.makeInternalUrl)

val internalUrls: InternalUrlSet = grouped.getOrElse(WrappedUrl.Internal, Set.empty).map(_.toInternalUrl)

val newInternalUrls: InternalUrlSet = internalUrls ++ relativeUrls1

new NewUrls(newExternalUrls, newInternalUrls)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package pl.writeonly.scala.hyde.common.url.urls

import scala.collection.immutable._

import pl.writeonly.scala.hyde.common.url.Domain
import pl.writeonly.scala.hyde.common.url.typed._
import slogging.LazyLogging

class Urls(count: Int, val externalUrls: ExternalUrls, val internalUrls: InternalUrls, val nextInternalUrls: InternalUrls) {

def next(newUrls: NewUrls): Urls =
new Urls(
count + 1,
externalUrls ++ newUrls.newExternalUrls,
internalUrls ++ nextInternalUrls,
SortedSet(newUrls.newInternalUrls.filter(isNewInternalUrl).toSeq: _*)
)

def showStep(): Unit = {
Urls.showHeader("count: " + count.toString)
Urls.showPart(details = false, "externalUrls", externalUrls)
Urls.showPart(details = false, "internalUrls", internalUrls)
Urls.showPart(details = false, "nextInternalUrls", nextInternalUrls)
nextInternalUrls.foreach(Urls.showString)
}

def showResult(): Unit = {
Urls.showPart(details = true, "externalUrls", externalUrls)
Urls.showPart(details = true, "internalUrls", internalUrls)
Urls.showPart(details = true, "nextInternalUrls", nextInternalUrls)
}

private def isNewInternalUrl(internalUrl: InternalUrl): Boolean =
!internalUrls.contains(internalUrl) && !nextInternalUrls.contains(internalUrl)

def isEmptyNextInternalUrls: Boolean = nextInternalUrls.isEmpty
}

object Urls extends LazyLogging {

def showPartThrowableList(details: Boolean, x: String, xs: Iterable[Throwable]): Unit = {
showHeader(x + " size: " + xs.size.toString)
if (details) xs.foreach(x => logger.error(x.getMessage, x.getCause))
}

def showPart(details: Boolean, x: String, xs: Iterable[AnyRef]): Unit = {
showHeader(x + " size: " + xs.size.toString)
if (details) xs.foreach(showString)
}

private def showHeader(x: String): Unit = {
(1 to 80).foreach(_ => print("'"))
println("")
println(x)
}

private def showString(x: AnyRef): Unit = println(x)

def fromDomain(implicit d: Domain): Urls =
new Urls(0, SortedSet.empty, SortedSet.empty, SortedSet(d.toInternalUrl))
}
Loading

0 comments on commit e491e7c

Please sign in to comment.