I had implemented something similar for slugs, that after some time I make it work:
import models.dancePortPersistenceContext._
trait Slug[T <: Entity] {
def toSlugify: String
var slug: String = ""
def calculateSlug[S <: Entity : Manifest](): String = {
val tentativeSlug = slugify(toSlugify)
val regex = "^" + tentativeSlug + "(-[0-9]*)?$";
if (!slug.contains(tentativeSlug)) {
//Here the query
val result = query {
(entity: S with Slug[S]) =>
where(entity.slug regexp regex) select (entity.slug) orderBy (entity.slug desc) limit (1)
}
if (result.isEmpty) {
slug = tentativeSlug
} else {
val parts = result.head.split("-")
val lastPart = parts(parts.length - 1)
var lastSlugNumber = 1
if (lastPart.matches("\\d+"))
lastSlugNumber = lastPart.toInt + 1
slug = tentativeSlug + "-" + lastSlugNumber
}
}
slug
}
private def slugify(input: String): String = {
import java.text.Normalizer
Normalizer.normalize(input, Normalizer.Form.NFD)
.replaceAll("[^\\w\\s-]", "") // Remove all non-word, non-space or non-dash characters
.replace('-', ' ') // Replace dashes with spaces
.trim // Trim leading/trailing whitespace (including what used to be leading/trailing dashes)
.replaceAll("\\s+", "-") // Replace whitespace (including newlines and repetitions) with single dashes
.toLowerCase // Lowercase the final results
}
}
Then in an entity:
class OneEntity(var name: String = "") extends Entity with Slug[SchoolProfile] {
def onNameChange = on(_.name).change {
calculateSlug[SchoolProfile]()
}
override def toSlugify: String = name
}