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

org.hyperscala.ui.dynamic.DynamicString.scala Maven / Gradle / Ivy

The newest version!
package org.hyperscala.ui.dynamic

import org.powerscala.IO
import java.io.File
import java.net.URL
import org.powerscala.log.Logging

/**
 * @author Matt Hicks 
 */
trait DynamicString {
  def name = DynamicString.name(this)
  def lastModified: Long
  def content: String
}

class DependentDynamicString protected[dynamic](dynamicString: DynamicString, val converter: String => String) extends DynamicString {
  private var originalContent: String = _
  private var converted: String = _

  def lastModified = dynamicString.lastModified
  def content = {
    checkUpdate()
    converted
  }

  protected def checkUpdate() = {
    val newContent = dynamicString.content
    if (newContent != originalContent) {
      converted = converter(newContent)
      originalContent = newContent
      refresh()
    }
  }

  protected def refresh() = {
  }
}

class GeneralDynamicString protected[dynamic](val contentFunction: () => String,
                                              val lastModifiedFunction: () => Long,
                                              val converter: String => String) extends DynamicString with Logging {
  private var _lastModified: Long = _
  private var _content: String = _

  refresh(force = true)

  def lastModified = {
    refresh()
    _lastModified
  }
  def content = {
    refresh()
    _content
  }

  def set(content: String, lastModified: Long = System.currentTimeMillis()) = synchronized {
    _content = content
    _lastModified = lastModified
    modified(content)
  }

  def refresh(force: Boolean = false): Unit = {
    val modified = lastModifiedFunction()
    if (force || modified > _lastModified) {
      val content = contentFunction()
      val converted = converter(content)
      set(converted, modified)
    }
  }

  protected def modified(content: String) = {}
}

object DynamicString {
  private var map = Map.empty[String, DynamicString]

  private def name(dynamicString: DynamicString) = map.collectFirst {
    case (name, ds) if ds == dynamicString => name
  }.getOrElse(throw new NullPointerException("Unable to find name for %s.".format(dynamicString)))

  def getOrSet[T <: DynamicString](name: String, creator: => T): T = synchronized {
    map.get(name) match {
      case Some(ds) => ds.asInstanceOf[T]
      case None => {
        val ds: T = creator
        map += name -> ds.asInstanceOf[DynamicString]
        ds
      }
    }
  }

  def remove(name: String) = synchronized {
    map -= name
  }

  def replace[T <: DynamicString](name: String, creator: => T): T = synchronized {
    val ds: T = creator
    map += name -> ds.asInstanceOf[DynamicString]
    ds
  }

  val defaultConverter = (s: String) => s

  def dependent(name: String, dynamicString: DynamicString, converter: String => String = defaultConverter) = {
    getOrSet[DynamicString](name, new DependentDynamicString(dynamicString, converter))
  }
  def static(name: String, content: String, converter: String => String = defaultConverter) = {
    getOrSet[DynamicString](name, new GeneralDynamicString(contentFunction(content), defaultLastModifyFunction, converter))
  }
  def dynamic(content: => String, converter: String => String = defaultConverter) = {
    new GeneralDynamicString(contentFunction(content), () => System.currentTimeMillis(), converter)
  }
  def file(name: String, file: File, converter: String => String = defaultConverter) = {
    getOrSet[DynamicString](name, new GeneralDynamicString(contentFunction(file), lastModifyFunction(file), converter))
  }
  def url(name: String, url: URL, checkLastModified: Boolean = false, converter: String => String = defaultConverter) = {
    getOrSet[DynamicString](name, new GeneralDynamicString(contentFunction(url), lastModifyFunction(url, checkLastModified), converter))
  }

  def contentFunction(content: => String) = () => content
  def contentFunction(file: File) = () => IO.copy(file)
  def contentFunction(url: URL) = () => IO.copy(url)

  val defaultLastModifyFunction = {
    val initial = System.currentTimeMillis()
    () => initial
  }
  def lastModifyFunction(file: File) = () => file.lastModified()
  def lastModifyFunction(url: URL, checkLastModified: Boolean = false) = if (checkLastModified) {
    () => IO.lastModified(url)
  } else {
    defaultLastModifyFunction
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy