diff --git a/.travis.yml b/.travis.yml
index 3e1785403f..633598801e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,8 +3,8 @@ dist: trusty
sudo: false
scala:
- 2.11.12
- - 2.12.10
- - 2.13.1
+ - 2.12.11
+ - 2.13.2
cache:
directories:
- '$HOME/node_modules'
@@ -15,16 +15,16 @@ jdk:
- openjdk8
matrix:
include:
- - scala: 2.12.10
+ - scala: 2.12.11
jdk: openjdk11
env: DISABLE_PUBLISH=true
- - scala: 2.12.10
+ - scala: 2.12.11
jdk: openjdk12
env: DISABLE_PUBLISH=true
- - scala: 2.13.1
+ - scala: 2.13.2
jdk: openjdk11
env: DISABLE_PUBLISH=true
- - scala: 2.13.1
+ - scala: 2.13.2
jdk: openjdk12
env: DISABLE_PUBLISH=true
script: ./travis.sh
diff --git a/build.sbt b/build.sbt
index b16f06c942..1add661794 100644
--- a/build.sbt
+++ b/build.sbt
@@ -9,8 +9,8 @@ startYear in ThisBuild := Some(2006)
organizationName in ThisBuild := "WorldWide Conferencing, LLC"
val scala211Version = "2.11.12"
-val scala212Version = "2.12.10"
-val scala213Version = "2.13.1"
+val scala212Version = "2.12.11"
+val scala213Version = "2.13.2"
val crossUpTo212 = Seq(scala212Version, scala211Version)
val crossUpTo213 = scala213Version +: crossUpTo212
@@ -18,7 +18,9 @@ val crossUpTo213 = scala213Version +: crossUpTo212
scalaVersion in ThisBuild := scala212Version
crossScalaVersions in ThisBuild := crossUpTo212 // default everyone to 2.12 for now
-libraryDependencies in ThisBuild ++= Seq(specs2, specs2Matchers, specs2Mock, scalacheck, scalatest)
+libraryDependencies in ThisBuild ++= Seq(specs2, specs2Matchers, specs2Mock, scalacheck, scalactic, scalatest)
+
+scalacOptions in ThisBuild ++= Seq("-deprecation")
// Settings for Sonatype compliance
pomIncludeRepository in ThisBuild := { _ => false }
@@ -77,7 +79,7 @@ lazy val markdown =
.settings(
description := "Markdown Parser",
parallelExecution in Test := false,
- libraryDependencies ++= Seq(scalatest, junit, scala_xml, scala_parser)
+ libraryDependencies ++= Seq(scalatest, scalatest_junit, scala_xml, scala_parser)
)
.settings(crossScalaVersions := crossUpTo213)
@@ -160,7 +162,7 @@ lazy val webkit =
specs2MatchersProv,
jetty6,
jwebunit,
- mockito_all,
+ mockito_scalatest,
jquery,
jasmineCore,
jasmineAjax
@@ -216,7 +218,7 @@ lazy val persistence: Seq[ProjectReference] =
lazy val db =
persistenceProject("db")
.dependsOn(util, webkit)
- .settings(libraryDependencies += mockito_all)
+ .settings(libraryDependencies += mockito_scalatest)
.settings(crossScalaVersions := crossUpTo213)
lazy val proto =
@@ -238,6 +240,7 @@ lazy val mapper =
)
}
)
+ .settings(crossScalaVersions := crossUpTo213)
lazy val record =
persistenceProject("record")
diff --git a/core/markdown/src/test/scala/net/liftweb/markdown/BaseParsersTest.scala b/core/markdown/src/test/scala/net/liftweb/markdown/BaseParsersTest.scala
index 64fb96dcb0..ccc0e12efe 100644
--- a/core/markdown/src/test/scala/net/liftweb/markdown/BaseParsersTest.scala
+++ b/core/markdown/src/test/scala/net/liftweb/markdown/BaseParsersTest.scala
@@ -19,7 +19,7 @@ package net.liftweb.markdown
* Christoph Henkelmann http://henkelmann.eu/
*/
-import org.scalatest.junit.JUnitRunner
+import org.scalatestplus.junit.JUnitRunner
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import collection.SortedMap
@@ -71,4 +71,4 @@ class BaseParsersTest extends FlatSpec with Matchers with BaseParsers{
an [IllegalArgumentException] should be thrownBy(apply(p, "<"))
}
-}
\ No newline at end of file
+}
diff --git a/core/markdown/src/test/scala/net/liftweb/markdown/BlockParsersTest.scala b/core/markdown/src/test/scala/net/liftweb/markdown/BlockParsersTest.scala
index 4d239139c8..15ff828e11 100644
--- a/core/markdown/src/test/scala/net/liftweb/markdown/BlockParsersTest.scala
+++ b/core/markdown/src/test/scala/net/liftweb/markdown/BlockParsersTest.scala
@@ -20,7 +20,7 @@ package net.liftweb.markdown
*/
import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
+import org.scalatestplus.junit.JUnitRunner
import org.scalatest.{Matchers,FlatSpec}
import scala.xml.{Group, NodeSeq}
diff --git a/core/markdown/src/test/scala/net/liftweb/markdown/InlineParsersTest.scala b/core/markdown/src/test/scala/net/liftweb/markdown/InlineParsersTest.scala
index acd2378c5f..96c69ccd45 100644
--- a/core/markdown/src/test/scala/net/liftweb/markdown/InlineParsersTest.scala
+++ b/core/markdown/src/test/scala/net/liftweb/markdown/InlineParsersTest.scala
@@ -22,7 +22,7 @@ package net.liftweb.markdown
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
+import org.scalatestplus.junit.JUnitRunner
/**
* Tests Inline Parsing, i.e. emphasis , strong text, links, escapes etc.
diff --git a/core/markdown/src/test/scala/net/liftweb/markdown/LineParsersTest.scala b/core/markdown/src/test/scala/net/liftweb/markdown/LineParsersTest.scala
index 4ab214944a..968635d740 100644
--- a/core/markdown/src/test/scala/net/liftweb/markdown/LineParsersTest.scala
+++ b/core/markdown/src/test/scala/net/liftweb/markdown/LineParsersTest.scala
@@ -21,7 +21,7 @@ package net.liftweb.markdown
import org.scalatest.{Matchers,FlatSpec}
import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
+import org.scalatestplus.junit.JUnitRunner
/**
* tests parsing of individual lines
diff --git a/core/markdown/src/test/scala/net/liftweb/markdown/LineTokenizerTest.scala b/core/markdown/src/test/scala/net/liftweb/markdown/LineTokenizerTest.scala
index e22b667f21..6399f797b7 100644
--- a/core/markdown/src/test/scala/net/liftweb/markdown/LineTokenizerTest.scala
+++ b/core/markdown/src/test/scala/net/liftweb/markdown/LineTokenizerTest.scala
@@ -21,7 +21,7 @@ package net.liftweb.markdown
import org.scalatest.{Matchers,FlatSpec}
import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
+import org.scalatestplus.junit.JUnitRunner
/**
* Tests the Line Tokenizer that prepares input for parsing.
diff --git a/core/markdown/src/test/scala/net/liftweb/markdown/TransformerTest.scala b/core/markdown/src/test/scala/net/liftweb/markdown/TransformerTest.scala
index 3e7d29baf5..b0a613e3fb 100644
--- a/core/markdown/src/test/scala/net/liftweb/markdown/TransformerTest.scala
+++ b/core/markdown/src/test/scala/net/liftweb/markdown/TransformerTest.scala
@@ -21,7 +21,7 @@ package net.liftweb.markdown
import org.scalatest.{Matchers,FlatSpec}
import org.junit.runner.RunWith
-import org.scalatest.junit.JUnitRunner
+import org.scalatestplus.junit.JUnitRunner
/**
* Tests the behavior of the complete parser, i.e. all parsing steps together.
diff --git a/persistence/db/src/test/scala/net/liftweb/db/DBSpec.scala b/persistence/db/src/test/scala/net/liftweb/db/DBSpec.scala
index dab759ad4c..29aae14f61 100644
--- a/persistence/db/src/test/scala/net/liftweb/db/DBSpec.scala
+++ b/persistence/db/src/test/scala/net/liftweb/db/DBSpec.scala
@@ -19,12 +19,10 @@ package db
import org.specs2.mutable.Specification
import org.specs2.mock.Mockito
-import org.mockito.Matchers._
-import net.liftweb.common._
-import net.liftweb.db._
-import net.liftweb.util.DefaultConnectionIdentifier
-import net.liftweb.util.ControlHelpers._
+import common._
+import util.DefaultConnectionIdentifier
+import util.ControlHelpers._
import java.sql._
@@ -35,8 +33,8 @@ class DBSpec extends Specification with Mockito {
def f(success: Boolean): Unit
}
- def dBVendor(connection: Connection) = new ProtoDBVendor {
- def createOne = {
+ def dBVendor(connection: Connection): ProtoDBVendor = new ProtoDBVendor {
+ def createOne: Box[Connection] = {
connection.createStatement returns mock[PreparedStatement]
Full(connection)
}
diff --git a/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/FieldFinder.scala b/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/FieldFinder.scala
new file mode 100644
index 0000000000..7736b1c190
--- /dev/null
+++ b/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/FieldFinder.scala
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006-2011 WorldWide Conferencing, LLC
+ *
+ * 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 net.liftweb
+package mapper
+
+import scala.reflect.{ClassTag, classTag}
+
+class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: common.Logger) {
+
+ import java.lang.reflect._
+
+ logger.debug("Created FieldFinder for " + classTag[T].runtimeClass)
+
+ def isMagicObject(m: Method): Boolean = m.getReturnType.getName.endsWith("$" + m.getName + "$") && m.getParameterTypes.length == 0
+
+ def typeFilter: Class[_] => Boolean = classTag[T].runtimeClass.isAssignableFrom
+
+ /**
+ * Find the magic mapper fields on the superclass
+ */
+ def findMagicFields(onMagic: AnyRef, startingClass: Class[_]): List[Method] = {
+ // If a class name ends in $module, it's a subclass created for scala object instances
+ def deMod(in: String): String =
+ if (in.endsWith("$module")) in.substring(0, in.length - 7)
+ else in
+
+ // find the magic fields for the given superclass
+ def findForClass(clz: Class[_]): List[Method] = clz match {
+ case null => Nil
+ case c =>
+ // get the names of fields that represent the type we want
+
+ val fields = Map(c.getDeclaredFields
+ .filter { f =>
+ val ret = typeFilter(f.getType)
+ logger.trace("typeFilter(" + f.getType + "); T=" + classTag[T].runtimeClass)
+ ret
+ }
+ .map(f => (deMod(f.getName), f)): _*)
+
+ logger.trace("fields: " + fields)
+
+ // this method will find all the super classes and super-interfaces
+ def getAllSupers(clz: Class[_]): List[Class[_]] = clz match {
+ case null => Nil
+ case c =>
+ c :: c.getInterfaces.toList.flatMap(getAllSupers) :::
+ getAllSupers(c.getSuperclass)
+ }
+
+ // does the method return an actual instance of an actual class that's
+ // associated with this Mapper class
+ def validActualType(meth: Method): Boolean = {
+ try {
+ // invoke the method
+ meth.invoke(onMagic) match {
+ case null =>
+ logger.debug("Not a valid mapped field: %s".format(meth.getName))
+ false
+ case inst =>
+ // do we get a T of some sort back?
+ if (!typeFilter(inst.getClass)) false
+ else {
+ // find out if the class name of the actual thing starts
+ // with the name of this class or some superclass...
+ // basically, is an inner class of this class
+ getAllSupers(clz).exists(c => inst.getClass.getName.startsWith(c.getName))
+ }
+ }
+
+ } catch {
+ case e: Exception =>
+ logger.debug("Not a valid mapped field: %s, got exception: %s".format(meth.getName, e))
+ false
+ }
+ }
+
+ // find all the declared methods
+ val meths = c.getDeclaredMethods.toList.
+ filter(_.getParameterTypes.length == 0). // that take no parameters
+ filter(m => Modifier.isPublic(m.getModifiers)). // that are public
+ filter(m => fields.contains(m.getName) && // that are associated with private fields
+ fields(m.getName).getType == m.getReturnType).
+ filter(validActualType) // and have a validated type
+
+ meths ::: findForClass(clz.getSuperclass)
+ }
+
+ findForClass(startingClass).distinct
+ }
+
+ lazy val accessorMethods = findMagicFields(metaMapper, metaMapper.getClass.getSuperclass)
+}
diff --git a/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/ManyToMany.scala b/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/ManyToMany.scala
new file mode 100644
index 0000000000..441612eceb
--- /dev/null
+++ b/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/ManyToMany.scala
@@ -0,0 +1,217 @@
+package net.liftweb
+package mapper
+
+import common.{Empty, Full}
+
+import scala.annotation.tailrec
+
+/**
+ * Add this trait to a Mapper to add support for many-to-many relationships
+ *
+ * @author nafg
+ */
+trait ManyToMany extends BaseKeyedMapper {
+ this: KeyedMapper[_, _] =>
+
+ private[this] type K = TheKeyType
+ private[this] type T = KeyedMapperType
+
+ private var manyToManyFields: List[MappedManyToMany[_,_,_]] = Nil
+
+ /**
+ * An override for save to propagate the save to all children
+ * of this parent.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ abstract override def save: Boolean = {
+ super.save && manyToManyFields.forall(_.save)
+ }
+
+ /**
+ * An override for delete_! to propogate the deletion to all children
+ * of this parent.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ abstract override def delete_! : Boolean = {
+ super.delete_! &&
+ manyToManyFields.forall( _.delete_!)
+ }
+
+
+ /**
+ * This is the base class to extend for fields that track many-to-many relationships.
+ * @param joinMeta The singleton of the join table
+ * @param thisField The foreign key in the join table that refers to this mapper's primaryKey.
+ * @param otherField The foreign key in the join table that refers to the other mapper's primaryKey
+ * @param otherMeta The singleton of the other mapper
+ * @param qp Any QueryParams to limit entries in the join table (other than matching thisField to primaryKey)
+ * To limit children based on fields in the other table (not the join table), it is currently necessary
+ * to point the join mapper to a view which pulls the join table's fields as well as fields of the other table.
+ */
+ class MappedManyToMany[O<:Mapper[O], K2, T2 <: KeyedMapper[K2,T2]](
+ val joinMeta: MetaMapper[O],
+ thisField: MappedForeignKey[K,O,_ <: KeyedMapper[_,_]],
+ val otherField: MappedForeignKey[K2, O, T2],
+ val otherMeta: MetaMapper[T2],
+ val qp: QueryParam[O]*) extends scala.collection.mutable.Buffer[T2] {
+
+ def otherFK[A](join: O)(f: MappedForeignKey[K2,O,T2] => A): A =
+ otherField.actualField(join) match { case mfk: MappedForeignKey[K2,O,T2] => f(mfk) }
+
+ protected def children: List[T2] = joins.flatMap(otherFK(_)(_.obj))
+
+ protected var _joins: List[O] = _
+
+ /**
+ * Get the list of instances of joinMeta
+ */
+ def joins: List[O] = _joins // read only to the public
+ protected var removedJoins: List[O] = Nil
+
+ refresh
+ manyToManyFields ::= this
+
+ protected def isJoinForChild(e: T2)(join: O): Boolean = otherField.actualField(join).get == e.primaryKeyField.get
+
+ protected def joinForChild(e: T2): Option[O] = joins.find(isJoinForChild(e))
+
+ protected def own(e: T2): O = {
+ joinForChild(e).fold {
+ removedJoins
+ // first check if we can recycle a removed join
+ .find(otherField.actualField(_).get == e.primaryKeyField)
+ .fold{
+ val newJoin = joinMeta.create
+ thisField.actualField(newJoin) match {
+ case mfk: MappedForeignKey[K, O, T] => mfk.set(primaryKeyField.get.asInstanceOf[K])
+ }
+ otherFK(newJoin)(_.apply(e))
+ newJoin
+ }{ removedJoin =>
+ removedJoins = removedJoins filter removedJoin.ne
+ removedJoin // well, noLongerRemovedJoin...
+ }
+ }(join => join)
+ }
+
+ protected def unown(e: T2): Option[O] =
+ joinForChild(e).map{ join =>
+ removedJoins = join :: removedJoins
+ val o = otherField.actualField(join)
+ o.set(o.defaultValue)
+ thisField.actualField(join) match { case mfk => mfk set mfk.defaultValue }
+ join
+ }
+
+ /**
+ * Get the List backing this Buffer.
+ */
+ def all: List[T2] = children
+
+ def length: Int = children.length
+
+ def iterator: Iterator[T2] = children.iterator
+
+ protected def childAt(n: Int): T2 = children(n)
+ def apply(n: Int): T2 = childAt(n)
+ def indexOf(e: T2): Int = children.indexWhere(e.eq)
+
+ def insertAll(n: Int, traversable: Traversable[T2]) {
+ val ownedJoins = traversable map own
+ val n2 = joins.indexWhere(isJoinForChild(children(n)))
+ val before = joins.take(n2)
+ val after = joins.drop(n2)
+
+ _joins = before ++ ownedJoins ++ after
+ }
+
+ def +=:(elem: T2): MappedManyToMany.this.type = {
+ _joins ::= own(elem)
+ this
+ }
+
+ def +=(elem: T2): MappedManyToMany.this.type = {
+ _joins ++= List(own(elem))
+ this
+ }
+
+ def update(n: Int, newelem: T2): Unit = {
+ unown(childAt(n)) match {
+ case Some(join) =>
+ val n2 = joins.indexOf(join)
+ val (before, after) = (joins.take(n2), joins.drop(n2+1))
+ _joins = before ++ List(own(newelem)) ++ after
+ case None =>
+ }
+ }
+
+ def remove(n: Int): T2 = {
+ val child = childAt(n)
+ unown(child).foreach(join => _joins = joins filterNot join.eq)
+ child
+ }
+
+ override def remove(idx: Int, count: Int): Unit = {
+ if (count > 0) {
+ @tailrec
+ def loop(c: Int, a: List[T2]): List[T2] =
+ if (c == 0) childAt(idx) :: a
+ else loop(c - 1, childAt(idx + c) :: a)
+
+ val joins0 = loop(count - 1, Nil) flatMap unown
+ _joins = joins filterNot joins0.contains
+ }
+ }
+
+ def clear(): Unit = {
+ children foreach unown
+ _joins = Nil
+ }
+
+ /**
+ * Discard the cached state of this MappedManyToMany's children and reinitialize it from the database
+ */
+ def refresh: List[T2] = {
+ val by = new Cmp[O, TheKeyType](thisField, OprEnum.Eql, Full(primaryKeyField.get.asInstanceOf[K]), Empty, Empty)
+
+ _joins = joinMeta.findAll( (by :: qp.toList): _*)
+ all
+ }
+
+ /**
+ * Save the state of this MappedManyToMany to the database.
+ * This will do the following:
+ * 1) Prune join table instances whose "child" foreign key's value is its defaultValue, i.e., -1
+ * 2) Set all join table instances' "parent" foreign key
+ * 3) Delete all join table instances whose child instance was removed
+ * 4) Save all child instances
+ * 5) If step 3 succeeds save all join instances
+ * 6) Return true if steps 2-4 all returned true; otherwise false
+ */
+ def save: Boolean = {
+ _joins = joins.filter { join =>
+ otherFK(join)(f => f.get != f.defaultValue)
+ }
+ _joins foreach {
+ thisField.actualField(_).asInstanceOf[MappedForeignKey[K,O,X] forSome {type X <: KeyedMapper[K,X]}] set ManyToMany.this.primaryKeyField.get.asInstanceOf[K]
+ }
+
+ removedJoins.forall {_.delete_!} & ( // continue saving even if deleting fails
+ children.forall(_.save) &&
+ joins.forall(_.save)
+ )
+ }
+
+ /**
+ * Deletes all join rows, including those
+ * marked for removal.
+ * Returns true if both succeed, otherwise false
+ */
+ def delete_! : Boolean = {
+ removedJoins.forall(_.delete_!) &
+ joins.forall(_.delete_!)
+ }
+ }
+}
diff --git a/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/OneToMany.scala b/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/OneToMany.scala
new file mode 100644
index 0000000000..b959516f7d
--- /dev/null
+++ b/persistence/mapper/src/main/scala-2.11/net/liftweb/mapper/OneToMany.scala
@@ -0,0 +1,284 @@
+/*
+ * Copyright 2006-2011 WorldWide Conferencing, LLC
+ *
+ * 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 net.liftweb
+package mapper
+
+
+private[mapper] object RecursiveType {
+ val rec: { type R0 <: Mapper[R0] } = null
+ type Rec = rec.R0
+}
+import net.liftweb.mapper.RecursiveType._
+
+/**
+ * Add this trait to a Mapper for managed one-to-many support
+ * For example: class Contact extends LongKeyedMapper[Contact] with OneToMany[Long, Contact] { ... }
+ * @tparam K the type of the primary key
+ * @tparam T the mapper type
+ * @author nafg
+ */
+trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
+
+ private[mapper] lazy val oneToManyFields: List[MappedOneToManyBase[Rec]] = {
+ new FieldFinder[MappedOneToManyBase[Rec]](
+ getSingleton,
+ net.liftweb.common.Logger(classOf[OneToMany[K,T]])
+ ).accessorMethods map (_.invoke(this).asInstanceOf[MappedOneToManyBase[Rec]])
+ }
+
+ /**
+ * An override for save to propagate the save to all children
+ * of this parent.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ override def save: Boolean = {
+ val ret = super.save &&
+ oneToManyFields.forall(_.save)
+ ret
+ }
+
+ /**
+ * An override for delete_! to propagate the deletion
+ * to all children of one-to-many fields implementing Cascade.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ override def delete_! : Boolean = DB.use(connectionIdentifier){ _ =>
+ if(oneToManyFields.forall{(_: MappedOneToManyBase[_ <: Mapper[_]]) match {
+ case f: Cascade[_] => f.delete_!
+ case _ => true
+ }
+ })
+ super.delete_!
+ else {
+ DB.rollback(connectionIdentifier)
+ false
+ }
+ }
+
+
+ /**
+ * This implicit allows a MappedForeignKey to be used as foreignKey function.
+ * Returns a function that takes a Mapper and looks up the actualField of field on the Mapper.
+ */
+ implicit def foreignKey[K, O<:Mapper[O], T<:KeyedMapper[K,T]](field: MappedForeignKey[K,O,T]): O=>MappedForeignKey[K,O,T] =
+ field.actualField(_).asInstanceOf[MappedForeignKey[K,O,T]]
+
+ /**
+ * Simple OneToMany support for children from the same table
+ */
+ class MappedOneToMany[O <: Mapper[O]](meta: MetaMapper[O], foreign: MappedForeignKey[K,O,T], qp: QueryParam[O]*)
+ extends MappedOneToManyBase[O](
+ ()=>{
+ val ret = meta.findAll(By(foreign, primaryKeyField.get) :: qp.toList : _*)
+ for(child <- ret) {
+ foreign.actualField(child).asInstanceOf[MappedForeignKey[K,O,T]].primeObj(net.liftweb.common.Full(OneToMany.this : T))
+ }
+ ret
+ },
+ foreign
+ )
+
+ /**
+ * This is the base class to use for fields that represent one-to-many or parent-child relationships.
+ * Maintains a list of children, tracking pending additions and deletions, and
+ * keeping their foreign key pointed to this mapper.
+ * Implements Buffer, so the children can be managed as one.
+ * Most users will use MappedOneToMany, however to support children from multiple tables
+ * it is necessary to use MappedOneToManyBase.
+ * @param reloadFunc A function that returns a sequence of children from storage.
+ * @param foreign A function that gets the MappedForeignKey on the child that refers to this parent
+ */
+ class MappedOneToManyBase[O <: Mapper[_]](val reloadFunc: () => Seq[O],
+ val foreign: O => MappedForeignKey[K,_,T]) extends scala.collection.mutable.Buffer[O] {
+ private var inited = false
+ private var _delegate: List[O] = _
+ /**
+ * children that were added before the parent was ever saved
+ */
+ private var unlinked: List[O] = Nil
+ protected def delegate: List[O] = {
+ if(!inited) {
+ refresh()
+ inited = true
+ }
+ _delegate
+ }
+ protected def delegate_=(d: List[O]): Unit = _delegate = d
+
+ /**
+ * Takes ownership of e. Sets e's foreign key to our primary key
+ */
+ protected def own(e: O): O = {
+ val f0 = foreign(e).asInstanceOf[Any]
+ f0 match {
+ case f: MappedLongForeignKey[O,T] with MappedForeignKey[K,_,T] =>
+ f.apply(OneToMany.this)
+ case f: MappedForeignKey[K,_,T] =>
+ f.set(OneToMany.this.primaryKeyField.get)
+ }
+ if(!OneToMany.this.saved_?)
+ unlinked ::= e
+ e
+ }
+ /**
+ * Relinquishes ownership of e. Resets e's foreign key to its default value.
+ */
+ protected def unown(e: O): O = {
+ val f = foreign(e)
+ f.set(f.defaultValue)
+ unlinked = unlinked filter {e.ne}
+ e
+ }
+ /**
+ * Returns the backing List
+ */
+ def all: List[O] = delegate
+
+ // 2.8: return this
+ def +=(elem: O): MappedOneToManyBase.this.type = {
+ delegate = delegate ++ List(own(elem))
+ this
+ }
+ // 2.7
+ //def readOnly = all
+ def length: Int = delegate.length
+ // 2.7
+ //def elements = delegate.elements
+ // 2.8
+ def iterator: Iterator[O] = delegate.iterator
+
+ def apply(n: Int): O = delegate(n)
+
+ // 2.7
+ /* def +:(elem: O) = {
+ delegate ::= own(elem)
+ this
+ } */
+ // 2.8
+ def +=:(elem: O): MappedOneToManyBase.this.type = {
+ delegate ::= own(elem)
+ this
+ }
+
+ override def indexOf[B >: O](e: B): Int = delegate.indexWhere(e.asInstanceOf[AnyRef].eq)
+
+ // 2.7
+ // def insertAll(n: Int, iter: Iterable[O]) {
+ // 2.8
+ def insertAll(n: Int, iter: Traversable[O]) {
+ val (before, after) = delegate.splitAt(n)
+ iter foreach own
+ delegate = before ++ iter ++ after
+ }
+
+ def update(n: Int, newelem: O): Unit = {
+ unown(delegate(n))
+ delegate = delegate.take(n) ++ List(own(newelem)) ++ delegate.drop(n+1)
+ }
+
+ def remove(n: Int): O = {
+ val e = unown(delegate(n))
+ delegate = delegate.filterNot(e.eq)
+ e
+ }
+
+ def clear(): Unit = {
+ while(delegate.nonEmpty)
+ remove(0)
+ }
+
+ /**
+ * Reloads the children from storage.
+ * NOTE: This may leave children in an inconsistent state.
+ * It is recommended to call save or clear() before calling refresh.
+ */
+ def refresh(): Unit = {
+ delegate = reloadFunc().toList
+ if(saved_?)
+ unlinked = Nil
+ else
+ unlinked = _delegate
+ }
+
+ /**
+ * Saves this "field," i.e., all the children it represents.
+ * Returns false as soon as save on a child returns false.
+ * Returns true if all children were saved successfully.
+ */
+ def save: Boolean = {
+ unlinked foreach {u =>
+ val f = foreign(u)
+ if(f.obj.map(_ eq OneToMany.this) openOr true) // obj is Empty or this
+ f.apply(OneToMany.this)
+ }
+ unlinked = Nil
+ delegate = delegate.filter {e =>
+ foreign(e).get == OneToMany.this.primaryKeyField.get ||
+ foreign(e).obj.map(_ eq OneToMany.this).openOr(false) // obj is this but not Empty
+ }
+ delegate.forall(_.save)
+ }
+
+ override def toString: String = {
+ val c = getClass.getSimpleName
+ val l = c.lastIndexOf("$")
+ c.substring(c.lastIndexOf("$",l-1)+1, l) + delegate.mkString("[",", ","]")
+ }
+ }
+
+ /**
+ * Adds behavior to delete orphaned fields before save.
+ */
+ trait Owned[O<:Mapper[_]] extends MappedOneToManyBase[O] {
+ var removed: List[O] = Nil
+ override def unown(e: O) = {
+ removed = e :: removed
+ super.unown(e)
+ }
+ override def own(e: O) = {
+ removed = removed filter {e.ne}
+ super.own(e)
+ }
+ override def save: Boolean = {
+ val unowned = removed.filter{ e =>
+ val f = foreign(e)
+ f.get == f.defaultValue
+ }
+ unowned foreach {_.delete_!}
+ super.save
+ }
+ }
+
+ /**
+ * Trait that indicates that the children represented
+ * by this field should be deleted when the parent is deleted.
+ */
+ trait Cascade[O<:Mapper[_]] extends MappedOneToManyBase[O] {
+ def delete_! : Boolean = {
+ delegate.forall { e =>
+ if(foreign(e).get ==
+ OneToMany.this.primaryKeyField.get) {
+ e.delete_!
+ }
+ else
+ true // doesn't constitute a failure
+ }
+ }
+ }
+}
diff --git a/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/FieldFinder.scala b/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/FieldFinder.scala
new file mode 100644
index 0000000000..7736b1c190
--- /dev/null
+++ b/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/FieldFinder.scala
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006-2011 WorldWide Conferencing, LLC
+ *
+ * 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 net.liftweb
+package mapper
+
+import scala.reflect.{ClassTag, classTag}
+
+class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: common.Logger) {
+
+ import java.lang.reflect._
+
+ logger.debug("Created FieldFinder for " + classTag[T].runtimeClass)
+
+ def isMagicObject(m: Method): Boolean = m.getReturnType.getName.endsWith("$" + m.getName + "$") && m.getParameterTypes.length == 0
+
+ def typeFilter: Class[_] => Boolean = classTag[T].runtimeClass.isAssignableFrom
+
+ /**
+ * Find the magic mapper fields on the superclass
+ */
+ def findMagicFields(onMagic: AnyRef, startingClass: Class[_]): List[Method] = {
+ // If a class name ends in $module, it's a subclass created for scala object instances
+ def deMod(in: String): String =
+ if (in.endsWith("$module")) in.substring(0, in.length - 7)
+ else in
+
+ // find the magic fields for the given superclass
+ def findForClass(clz: Class[_]): List[Method] = clz match {
+ case null => Nil
+ case c =>
+ // get the names of fields that represent the type we want
+
+ val fields = Map(c.getDeclaredFields
+ .filter { f =>
+ val ret = typeFilter(f.getType)
+ logger.trace("typeFilter(" + f.getType + "); T=" + classTag[T].runtimeClass)
+ ret
+ }
+ .map(f => (deMod(f.getName), f)): _*)
+
+ logger.trace("fields: " + fields)
+
+ // this method will find all the super classes and super-interfaces
+ def getAllSupers(clz: Class[_]): List[Class[_]] = clz match {
+ case null => Nil
+ case c =>
+ c :: c.getInterfaces.toList.flatMap(getAllSupers) :::
+ getAllSupers(c.getSuperclass)
+ }
+
+ // does the method return an actual instance of an actual class that's
+ // associated with this Mapper class
+ def validActualType(meth: Method): Boolean = {
+ try {
+ // invoke the method
+ meth.invoke(onMagic) match {
+ case null =>
+ logger.debug("Not a valid mapped field: %s".format(meth.getName))
+ false
+ case inst =>
+ // do we get a T of some sort back?
+ if (!typeFilter(inst.getClass)) false
+ else {
+ // find out if the class name of the actual thing starts
+ // with the name of this class or some superclass...
+ // basically, is an inner class of this class
+ getAllSupers(clz).exists(c => inst.getClass.getName.startsWith(c.getName))
+ }
+ }
+
+ } catch {
+ case e: Exception =>
+ logger.debug("Not a valid mapped field: %s, got exception: %s".format(meth.getName, e))
+ false
+ }
+ }
+
+ // find all the declared methods
+ val meths = c.getDeclaredMethods.toList.
+ filter(_.getParameterTypes.length == 0). // that take no parameters
+ filter(m => Modifier.isPublic(m.getModifiers)). // that are public
+ filter(m => fields.contains(m.getName) && // that are associated with private fields
+ fields(m.getName).getType == m.getReturnType).
+ filter(validActualType) // and have a validated type
+
+ meths ::: findForClass(clz.getSuperclass)
+ }
+
+ findForClass(startingClass).distinct
+ }
+
+ lazy val accessorMethods = findMagicFields(metaMapper, metaMapper.getClass.getSuperclass)
+}
diff --git a/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/ManyToMany.scala b/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/ManyToMany.scala
new file mode 100644
index 0000000000..441612eceb
--- /dev/null
+++ b/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/ManyToMany.scala
@@ -0,0 +1,217 @@
+package net.liftweb
+package mapper
+
+import common.{Empty, Full}
+
+import scala.annotation.tailrec
+
+/**
+ * Add this trait to a Mapper to add support for many-to-many relationships
+ *
+ * @author nafg
+ */
+trait ManyToMany extends BaseKeyedMapper {
+ this: KeyedMapper[_, _] =>
+
+ private[this] type K = TheKeyType
+ private[this] type T = KeyedMapperType
+
+ private var manyToManyFields: List[MappedManyToMany[_,_,_]] = Nil
+
+ /**
+ * An override for save to propagate the save to all children
+ * of this parent.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ abstract override def save: Boolean = {
+ super.save && manyToManyFields.forall(_.save)
+ }
+
+ /**
+ * An override for delete_! to propogate the deletion to all children
+ * of this parent.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ abstract override def delete_! : Boolean = {
+ super.delete_! &&
+ manyToManyFields.forall( _.delete_!)
+ }
+
+
+ /**
+ * This is the base class to extend for fields that track many-to-many relationships.
+ * @param joinMeta The singleton of the join table
+ * @param thisField The foreign key in the join table that refers to this mapper's primaryKey.
+ * @param otherField The foreign key in the join table that refers to the other mapper's primaryKey
+ * @param otherMeta The singleton of the other mapper
+ * @param qp Any QueryParams to limit entries in the join table (other than matching thisField to primaryKey)
+ * To limit children based on fields in the other table (not the join table), it is currently necessary
+ * to point the join mapper to a view which pulls the join table's fields as well as fields of the other table.
+ */
+ class MappedManyToMany[O<:Mapper[O], K2, T2 <: KeyedMapper[K2,T2]](
+ val joinMeta: MetaMapper[O],
+ thisField: MappedForeignKey[K,O,_ <: KeyedMapper[_,_]],
+ val otherField: MappedForeignKey[K2, O, T2],
+ val otherMeta: MetaMapper[T2],
+ val qp: QueryParam[O]*) extends scala.collection.mutable.Buffer[T2] {
+
+ def otherFK[A](join: O)(f: MappedForeignKey[K2,O,T2] => A): A =
+ otherField.actualField(join) match { case mfk: MappedForeignKey[K2,O,T2] => f(mfk) }
+
+ protected def children: List[T2] = joins.flatMap(otherFK(_)(_.obj))
+
+ protected var _joins: List[O] = _
+
+ /**
+ * Get the list of instances of joinMeta
+ */
+ def joins: List[O] = _joins // read only to the public
+ protected var removedJoins: List[O] = Nil
+
+ refresh
+ manyToManyFields ::= this
+
+ protected def isJoinForChild(e: T2)(join: O): Boolean = otherField.actualField(join).get == e.primaryKeyField.get
+
+ protected def joinForChild(e: T2): Option[O] = joins.find(isJoinForChild(e))
+
+ protected def own(e: T2): O = {
+ joinForChild(e).fold {
+ removedJoins
+ // first check if we can recycle a removed join
+ .find(otherField.actualField(_).get == e.primaryKeyField)
+ .fold{
+ val newJoin = joinMeta.create
+ thisField.actualField(newJoin) match {
+ case mfk: MappedForeignKey[K, O, T] => mfk.set(primaryKeyField.get.asInstanceOf[K])
+ }
+ otherFK(newJoin)(_.apply(e))
+ newJoin
+ }{ removedJoin =>
+ removedJoins = removedJoins filter removedJoin.ne
+ removedJoin // well, noLongerRemovedJoin...
+ }
+ }(join => join)
+ }
+
+ protected def unown(e: T2): Option[O] =
+ joinForChild(e).map{ join =>
+ removedJoins = join :: removedJoins
+ val o = otherField.actualField(join)
+ o.set(o.defaultValue)
+ thisField.actualField(join) match { case mfk => mfk set mfk.defaultValue }
+ join
+ }
+
+ /**
+ * Get the List backing this Buffer.
+ */
+ def all: List[T2] = children
+
+ def length: Int = children.length
+
+ def iterator: Iterator[T2] = children.iterator
+
+ protected def childAt(n: Int): T2 = children(n)
+ def apply(n: Int): T2 = childAt(n)
+ def indexOf(e: T2): Int = children.indexWhere(e.eq)
+
+ def insertAll(n: Int, traversable: Traversable[T2]) {
+ val ownedJoins = traversable map own
+ val n2 = joins.indexWhere(isJoinForChild(children(n)))
+ val before = joins.take(n2)
+ val after = joins.drop(n2)
+
+ _joins = before ++ ownedJoins ++ after
+ }
+
+ def +=:(elem: T2): MappedManyToMany.this.type = {
+ _joins ::= own(elem)
+ this
+ }
+
+ def +=(elem: T2): MappedManyToMany.this.type = {
+ _joins ++= List(own(elem))
+ this
+ }
+
+ def update(n: Int, newelem: T2): Unit = {
+ unown(childAt(n)) match {
+ case Some(join) =>
+ val n2 = joins.indexOf(join)
+ val (before, after) = (joins.take(n2), joins.drop(n2+1))
+ _joins = before ++ List(own(newelem)) ++ after
+ case None =>
+ }
+ }
+
+ def remove(n: Int): T2 = {
+ val child = childAt(n)
+ unown(child).foreach(join => _joins = joins filterNot join.eq)
+ child
+ }
+
+ override def remove(idx: Int, count: Int): Unit = {
+ if (count > 0) {
+ @tailrec
+ def loop(c: Int, a: List[T2]): List[T2] =
+ if (c == 0) childAt(idx) :: a
+ else loop(c - 1, childAt(idx + c) :: a)
+
+ val joins0 = loop(count - 1, Nil) flatMap unown
+ _joins = joins filterNot joins0.contains
+ }
+ }
+
+ def clear(): Unit = {
+ children foreach unown
+ _joins = Nil
+ }
+
+ /**
+ * Discard the cached state of this MappedManyToMany's children and reinitialize it from the database
+ */
+ def refresh: List[T2] = {
+ val by = new Cmp[O, TheKeyType](thisField, OprEnum.Eql, Full(primaryKeyField.get.asInstanceOf[K]), Empty, Empty)
+
+ _joins = joinMeta.findAll( (by :: qp.toList): _*)
+ all
+ }
+
+ /**
+ * Save the state of this MappedManyToMany to the database.
+ * This will do the following:
+ * 1) Prune join table instances whose "child" foreign key's value is its defaultValue, i.e., -1
+ * 2) Set all join table instances' "parent" foreign key
+ * 3) Delete all join table instances whose child instance was removed
+ * 4) Save all child instances
+ * 5) If step 3 succeeds save all join instances
+ * 6) Return true if steps 2-4 all returned true; otherwise false
+ */
+ def save: Boolean = {
+ _joins = joins.filter { join =>
+ otherFK(join)(f => f.get != f.defaultValue)
+ }
+ _joins foreach {
+ thisField.actualField(_).asInstanceOf[MappedForeignKey[K,O,X] forSome {type X <: KeyedMapper[K,X]}] set ManyToMany.this.primaryKeyField.get.asInstanceOf[K]
+ }
+
+ removedJoins.forall {_.delete_!} & ( // continue saving even if deleting fails
+ children.forall(_.save) &&
+ joins.forall(_.save)
+ )
+ }
+
+ /**
+ * Deletes all join rows, including those
+ * marked for removal.
+ * Returns true if both succeed, otherwise false
+ */
+ def delete_! : Boolean = {
+ removedJoins.forall(_.delete_!) &
+ joins.forall(_.delete_!)
+ }
+ }
+}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/OneToMany.scala b/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/OneToMany.scala
similarity index 85%
rename from persistence/mapper/src/main/scala/net/liftweb/mapper/OneToMany.scala
rename to persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/OneToMany.scala
index bde7eedb49..d31e6a93f0 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/OneToMany.scala
+++ b/persistence/mapper/src/main/scala-2.12/net/liftweb/mapper/OneToMany.scala
@@ -22,7 +22,7 @@ private[mapper] object RecursiveType {
val rec: { type R0 <: Mapper[R0] } = null
type Rec = rec.R0
}
-import RecursiveType._
+import net.liftweb.mapper.RecursiveType._
/**
* Add this trait to a Mapper for managed one-to-many support
@@ -46,7 +46,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* Returns false as soon as the parent or a one-to-many field returns false.
* If they are all successful returns true.
*/
- override def save = {
+ override def save: Boolean = {
val ret = super.save &&
oneToManyFields.forall(_.save)
ret
@@ -58,7 +58,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* Returns false as soon as the parent or a one-to-many field returns false.
* If they are all successful returns true.
*/
- override def delete_! = DB.use(connectionIdentifier){_ =>
+ override def delete_! : Boolean = DB.use(connectionIdentifier){ _ =>
if(oneToManyFields.forall{(_: MappedOneToManyBase[_ <: Mapper[_]]) match {
case f: Cascade[_] => f.delete_!
case _ => true
@@ -104,8 +104,8 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* @param reloadFunc A function that returns a sequence of children from storage.
* @param foreign A function that gets the MappedForeignKey on the child that refers to this parent
*/
- class MappedOneToManyBase[O <: Mapper[_]](val reloadFunc: ()=>Seq[O],
- val foreign: O => MappedForeignKey[K,_,T] /*forSome { type X <: Mapper[X] }*/) extends scala.collection.mutable.Buffer[O] {
+ class MappedOneToManyBase[O <: Mapper[_]](val reloadFunc: () => Seq[O],
+ val foreign: O => MappedForeignKey[K,_,T]) extends scala.collection.mutable.Buffer[O] {
private var inited = false
private var _delegate: List[O] = _
/**
@@ -114,17 +114,17 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
private var unlinked: List[O] = Nil
protected def delegate: List[O] = {
if(!inited) {
- refresh
+ refresh()
inited = true
}
_delegate
}
- protected def delegate_=(d: List[O]) = _delegate = d
+ protected def delegate_=(d: List[O]): Unit = _delegate = d
/**
* Takes ownership of e. Sets e's foreign key to our primary key
*/
- protected def own(e: O) = {
+ protected def own(e: O): O = {
val f0 = foreign(e).asInstanceOf[Any]
f0 match {
case f: MappedLongForeignKey[O,T] with MappedForeignKey[K,_,T] =>
@@ -139,7 +139,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
/**
* Relinquishes ownership of e. Resets e's foreign key to its default value.
*/
- protected def unown(e: O) = {
+ protected def unown(e: O): O = {
val f = foreign(e)
f.set(f.defaultValue)
unlinked = unlinked filter {e.ne}
@@ -148,21 +148,22 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
/**
* Returns the backing List
*/
- def all = delegate
+ def all: List[O] = delegate
// 2.8: return this
- def +=(elem: O) = {
+ def +=(elem: O): MappedOneToManyBase.this.type = {
delegate = delegate ++ List(own(elem))
this
}
// 2.7
//def readOnly = all
- def length = delegate.length
+ def length: Int = delegate.length
// 2.7
//def elements = delegate.elements
// 2.8
- def iterator = delegate.iterator
- def apply(n: Int) = delegate(n)
+ def iterator: Iterator[O] = delegate.iterator
+
+ def apply(n: Int): O = delegate(n)
// 2.7
/* def +:(elem: O) = {
@@ -170,13 +171,12 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
this
} */
// 2.8
- def +=:(elem: O) = {
+ def +=:(elem: O): MappedOneToManyBase.this.type = {
delegate ::= own(elem)
this
}
- override def indexOf[B >: O](e: B): Int =
- delegate.indexWhere(e.asInstanceOf[AnyRef].eq)
+ override def indexOf[B >: O](e: B): Int = delegate.indexWhere(e.asInstanceOf[AnyRef].eq)
// 2.7
// def insertAll(n: Int, iter: Iterable[O]) {
@@ -187,21 +187,19 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
delegate = before ++ iter ++ after
}
- def update(n: Int, newelem: O) {
+ def update(n: Int, newelem: O): Unit = {
unown(delegate(n))
- val (before, after) = (delegate.take(n), delegate.drop(n+1))
- delegate = before ++ List(own(newelem)) ++ after
+ delegate = delegate.take(n) ++ List(own(newelem)) ++ delegate.drop(n+1)
}
- def remove(n: Int) = {
+ def remove(n: Int): O = {
val e = unown(delegate(n))
delegate = delegate.filterNot(e.eq)
e
}
-
- def clear() {
- while(delegate.length>0)
+ def clear(): Unit = {
+ while(delegate.nonEmpty)
remove(0)
}
@@ -210,7 +208,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* NOTE: This may leave children in an inconsistent state.
* It is recommended to call save or clear() before calling refresh.
*/
- def refresh {
+ def refresh(): Unit = {
delegate = reloadFunc().toList
if(saved_?)
unlinked = Nil
@@ -223,7 +221,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* Returns false as soon as save on a child returns false.
* Returns true if all children were saved successfully.
*/
- def save = {
+ def save: Boolean = {
unlinked foreach {u =>
val f = foreign(u)
if(f.obj.map(_ eq OneToMany.this) openOr true) // obj is Empty or this
@@ -237,7 +235,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
delegate.forall(_.save)
}
- override def toString = {
+ override def toString: String = {
val c = getClass.getSimpleName
val l = c.lastIndexOf("$")
c.substring(c.lastIndexOf("$",l-1)+1, l) + delegate.mkString("[",", ","]")
@@ -257,7 +255,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
removed = removed filter {e.ne}
super.own(e)
}
- override def save = {
+ override def save: Boolean = {
val unowned = removed.filter{ e =>
val f = foreign(e)
f.get == f.defaultValue
@@ -272,7 +270,7 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* by this field should be deleted when the parent is deleted.
*/
trait Cascade[O<:Mapper[_]] extends MappedOneToManyBase[O] {
- def delete_! = {
+ def delete_! : Boolean = {
delegate.forall { e =>
if(foreign(e).get ==
OneToMany.this.primaryKeyField.get) {
@@ -284,4 +282,3 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
}
}
}
-
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/FieldFinder.scala b/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/FieldFinder.scala
similarity index 81%
rename from persistence/mapper/src/main/scala/net/liftweb/mapper/FieldFinder.scala
rename to persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/FieldFinder.scala
index c1f70bd2eb..ee258ab82c 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/FieldFinder.scala
+++ b/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/FieldFinder.scala
@@ -17,14 +17,14 @@
package net.liftweb
package mapper
-import scala.reflect.{ClassTag,classTag}
+import scala.reflect.{ClassTag, classTag}
-class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: net.liftweb.common.Logger) {
+class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: common.Logger) {
import java.lang.reflect._
logger.debug("Created FieldFinder for " + classTag[T].runtimeClass)
- def isMagicObject(m: Method) = m.getReturnType.getName.endsWith("$"+m.getName+"$") && m.getParameterTypes.length == 0
+ def isMagicObject(m: Method): Boolean = m.getReturnType.getName.endsWith("$"+m.getName+"$") && m.getParameterTypes.length == 0
def typeFilter: Class[_]=>Boolean = classTag[T].runtimeClass.isAssignableFrom
@@ -43,13 +43,13 @@ class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: net.liftweb.common.Lo
case c =>
// get the names of fields that represent the type we want
- val fields = Map(c.getDeclaredFields.
- filter{f =>
- val ret = typeFilter(f.getType)
- logger.trace("typeFilter(" + f.getType + "); T=" + classTag[T].runtimeClass)
- ret
- }.
- map(f => (deMod(f.getName), f)) :_*)
+ val fields = Map.from(c.getDeclaredFields
+ .filter{f =>
+ val ret = typeFilter(f.getType)
+ logger.trace("typeFilter(" + f.getType + "); T=" + classTag[T].runtimeClass)
+ ret
+ }
+ .map(f => (deMod(f.getName), f)))
logger.trace("fields: " + fields)
@@ -77,9 +77,7 @@ class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: net.liftweb.common.Lo
// find out if the class name of the actual thing starts
// with the name of this class or some superclass...
// basically, is an inner class of this class
- getAllSupers(clz).find{
- c =>
- inst.getClass.getName.startsWith(c.getName)}.isDefined
+ getAllSupers(clz).exists(c => inst.getClass.getName.startsWith(c.getName))
}
}
@@ -106,4 +104,3 @@ class FieldFinder[T: ClassTag](metaMapper: AnyRef, logger: net.liftweb.common.Lo
lazy val accessorMethods = findMagicFields(metaMapper, metaMapper.getClass.getSuperclass)
}
-
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/ManyToMany.scala b/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/ManyToMany.scala
similarity index 67%
rename from persistence/mapper/src/main/scala/net/liftweb/mapper/ManyToMany.scala
rename to persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/ManyToMany.scala
index feff467a1d..636dd633db 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/ManyToMany.scala
+++ b/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/ManyToMany.scala
@@ -17,10 +17,10 @@
package net.liftweb
package mapper
-import scala.language.existentials
+import common._
-import net.liftweb.util._
-import net.liftweb.common._
+import scala.annotation.tailrec
+import scala.language.existentials
/**
* Add this trait to a Mapper to add support for many-to-many relationships
@@ -40,7 +40,7 @@ trait ManyToMany extends BaseKeyedMapper {
* Returns false as soon as the parent or a one-to-many field returns false.
* If they are all successful returns true.
*/
- abstract override def save = {
+ abstract override def save: Boolean = {
super.save && manyToManyFields.forall(_.save)
}
@@ -50,7 +50,7 @@ trait ManyToMany extends BaseKeyedMapper {
* Returns false as soon as the parent or a one-to-many field returns false.
* If they are all successful returns true.
*/
- abstract override def delete_! = {
+ abstract override def delete_! : Boolean = {
super.delete_! &&
manyToManyFields.forall( _.delete_!)
}
@@ -83,67 +83,61 @@ trait ManyToMany extends BaseKeyedMapper {
/**
* Get the list of instances of joinMeta
*/
- def joins = _joins // read only to the public
+ def joins: List[O] = _joins // read only to the public
protected var removedJoins: List[O] = Nil
-
refresh
manyToManyFields ::= this
- protected def isJoinForChild(e: T2)(join: O) = otherField.actualField(join).get == e.primaryKeyField.get
- protected def joinForChild(e: T2): Option[O] =
- joins.find(isJoinForChild(e))
+ protected def isJoinForChild(e: T2)(join: O): Boolean = otherField.actualField(join).get == e.primaryKeyField.get
+
+ protected def joinForChild(e: T2): Option[O] = joins.find(isJoinForChild(e))
protected def own(e: T2): O = {
- joinForChild(e) match {
- case None =>
- removedJoins.find { // first check if we can recycle a removed join
- otherField.actualField(_).get == e.primaryKeyField
- } match {
- case Some(removedJoin) =>
- removedJoins = removedJoins filter removedJoin.ne
- removedJoin // well, noLongerRemovedJoin...
- case None =>
- val newJoin = joinMeta.create
- thisField.actualField(newJoin) match {
- case mfk: MappedForeignKey[K,O,T] => mfk.set(primaryKeyField.get.asInstanceOf[K])
- }
- otherFK(newJoin)(_.apply(e))
- newJoin
+ joinForChild(e).fold {
+ removedJoins
+ // first check if we can recycle a removed join
+ .find(otherField.actualField(_).get == e.primaryKeyField)
+ .fold{
+ val newJoin = joinMeta.create
+ thisField.actualField(newJoin) match {
+ case mfk: MappedForeignKey[K, O, T] => mfk.set(primaryKeyField.get.asInstanceOf[K])
+ }
+ otherFK(newJoin)(_.apply(e))
+ newJoin
+ }{ removedJoin =>
+ removedJoins = removedJoins filter removedJoin.ne
+ removedJoin // well, noLongerRemovedJoin...
}
- case Some(join) =>
- join
- }
+ }(join => join)
}
- protected def unown(e: T2) = {
- joinForChild(e) match {
- case Some(join) =>
- removedJoins = join :: removedJoins
- val o = otherField.actualField(join)
- o.set(o.defaultValue)
- thisField.actualField(join) match { case mfk => mfk set mfk.defaultValue }
- Some(join)
- case None =>
- None
+
+ protected def unown(e: T2): Option[O] =
+ joinForChild(e).map{ join =>
+ removedJoins = join :: removedJoins
+ val o = otherField.actualField(join)
+ o.set(o.defaultValue)
+ thisField.actualField(join) match { case mfk => mfk set mfk.defaultValue }
+ join
}
- }
/**
* Get the List backing this Buffer.
*/
- def all = children
+ def all: List[T2] = children
- def length = children.length
+ def length: Int = children.length
- def iterator = children.iterator
+ def iterator: Iterator[T2] = children.iterator
- protected def childAt(n: Int) = children(n)
- def apply(n: Int) = childAt(n)
- def indexOf(e: T2) =
- children.indexWhere(e.eq)
+ protected def childAt(n: Int): T2 = children(n)
+ def apply(n: Int): T2 = childAt(n)
+ def indexOf(e: T2): Int = children.indexWhere(e.eq)
- def insertAll(n: Int, traversable: Traversable[T2]) {
- val ownedJoins = traversable map own
+ def insert(idx: Int, elem: T2): Unit = insertAll(idx, Seq(elem))
+
+ def insertAll(n: Int, traversable: IterableOnce[T2]): Unit = {
+ val ownedJoins = traversable.iterator.map(own)
val n2 = joins.indexWhere(isJoinForChild(children(n)))
val before = joins.take(n2)
val after = joins.drop(n2)
@@ -151,17 +145,17 @@ trait ManyToMany extends BaseKeyedMapper {
_joins = before ++ ownedJoins ++ after
}
- def +=:(elem: T2) = {
+ def prepend(elem: T2): MappedManyToMany.this.type = {
_joins ::= own(elem)
this
}
- def +=(elem: T2) = {
+ def addOne(elem: T2): MappedManyToMany.this.type = {
_joins ++= List(own(elem))
this
}
- def update(n: Int, newelem: T2) {
+ def update(n: Int, newelem: T2): Unit = {
unown(childAt(n)) match {
case Some(join) =>
val n2 = joins.indexOf(join)
@@ -171,18 +165,31 @@ trait ManyToMany extends BaseKeyedMapper {
}
}
- def remove(n: Int) = {
+ def remove(n: Int): T2 = {
val child = childAt(n)
- unown(child) match {
- case Some(join) =>
- _joins = joins filterNot join.eq
- case None =>
- }
+ unown(child).foreach(join => _joins = joins filterNot join.eq)
child
}
+ override def remove(idx: Int, count: Int): Unit = {
+ if (count > 0) {
+ @tailrec
+ def loop(c: Int, a: List[T2]): List[T2] =
+ if (c == 0) childAt(idx) :: a
+ else loop(c - 1, childAt(idx + c) :: a)
- def clear() {
+ val joins0 = loop(count - 1, Nil) flatMap unown
+ _joins = joins filterNot joins0.contains
+ }
+ }
+
+ override def patchInPlace(from: Int, patch: IterableOnce[T2], replaced: Int): MappedManyToMany.this.type = {
+ remove(from, replaced)
+ insertAll(from, patch)
+ this
+ }
+
+ def clear(): Unit = {
children foreach unown
_joins = Nil
}
@@ -190,7 +197,7 @@ trait ManyToMany extends BaseKeyedMapper {
/**
* Discard the cached state of this MappedManyToMany's children and reinitialize it from the database
*/
- def refresh = {
+ def refresh: List[T2] = {
val by = new Cmp[O, TheKeyType](thisField, OprEnum.Eql, Full(primaryKeyField.get.asInstanceOf[K]), Empty, Empty)
_joins = joinMeta.findAll( (by :: qp.toList): _*)
@@ -207,7 +214,7 @@ trait ManyToMany extends BaseKeyedMapper {
* 5) If step 3 succeeds save all join instances
* 6) Return true if steps 2-4 all returned true; otherwise false
*/
- def save = {
+ def save: Boolean = {
_joins = joins.filter { join =>
otherFK(join)(f => f.get != f.defaultValue)
}
@@ -226,10 +233,9 @@ trait ManyToMany extends BaseKeyedMapper {
* marked for removal.
* Returns true if both succeed, otherwise false
*/
- def delete_! = {
+ def delete_! : Boolean = {
removedJoins.forall(_.delete_!) &
joins.forall(_.delete_!)
}
}
}
-
diff --git a/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/OneToMany.scala b/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/OneToMany.scala
new file mode 100644
index 0000000000..b868894f6c
--- /dev/null
+++ b/persistence/mapper/src/main/scala-2.13/net/liftweb/mapper/OneToMany.scala
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2006-2011 WorldWide Conferencing, LLC
+ *
+ * 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 net.liftweb.mapper
+
+private[mapper] object RecursiveType {
+ val rec: { type R0 <: Mapper[R0] } = null
+ type Rec = rec.R0
+}
+import RecursiveType._
+
+/**
+ * Add this trait to a Mapper for managed one-to-many support
+ * For example: class Contact extends LongKeyedMapper[Contact] with OneToMany[Long, Contact] { ... }
+ * @tparam K the type of the primary key
+ * @tparam T the mapper type
+ * @author nafg
+ */
+trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
+
+ private[mapper] lazy val oneToManyFields: List[MappedOneToManyBase[Rec]] = {
+ new FieldFinder[MappedOneToManyBase[Rec]](
+ getSingleton,
+ net.liftweb.common.Logger(classOf[OneToMany[K,T]])
+ ).accessorMethods map (_.invoke(this).asInstanceOf[MappedOneToManyBase[Rec]])
+ }
+
+ /**
+ * An override for save to propagate the save to all children
+ * of this parent.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ override def save: Boolean = {
+ val ret = super.save &&
+ oneToManyFields.forall(_.save)
+ ret
+ }
+
+ /**
+ * An override for delete_! to propagate the deletion
+ * to all children of one-to-many fields implementing Cascade.
+ * Returns false as soon as the parent or a one-to-many field returns false.
+ * If they are all successful returns true.
+ */
+ override def delete_! : Boolean = DB.use(connectionIdentifier){ _ =>
+ if(oneToManyFields.forall{(_: MappedOneToManyBase[_ <: Mapper[_]]) match {
+ case f: Cascade[_] => f.delete_!
+ case _ => true
+ }
+ })
+ super.delete_!
+ else {
+ DB.rollback(connectionIdentifier)
+ false
+ }
+ }
+
+
+ /**
+ * This implicit allows a MappedForeignKey to be used as foreignKey function.
+ * Returns a function that takes a Mapper and looks up the actualField of field on the Mapper.
+ */
+ implicit def foreignKey[K, O<:Mapper[O], T<:KeyedMapper[K,T]](field: MappedForeignKey[K,O,T]): O=>MappedForeignKey[K,O,T] =
+ field.actualField(_).asInstanceOf[MappedForeignKey[K,O,T]]
+
+ /**
+ * Simple OneToMany support for children from the same table
+ */
+ class MappedOneToMany[O <: Mapper[O]](meta: MetaMapper[O], foreign: MappedForeignKey[K,O,T], qp: QueryParam[O]*)
+ extends MappedOneToManyBase[O](
+ ()=>{
+ val ret = meta.findAll(By(foreign, primaryKeyField.get) :: qp.toList : _*)
+ for(child <- ret) {
+ foreign.actualField(child).asInstanceOf[MappedForeignKey[K,O,T]].primeObj(net.liftweb.common.Full(OneToMany.this : T))
+ }
+ ret
+ },
+ foreign
+ )
+
+ /**
+ * This is the base class to use for fields that represent one-to-many or parent-child relationships.
+ * Maintains a list of children, tracking pending additions and deletions, and
+ * keeping their foreign key pointed to this mapper.
+ * Implements Buffer, so the children can be managed as one.
+ * Most users will use MappedOneToMany, however to support children from multiple tables
+ * it is necessary to use MappedOneToManyBase.
+ * @param reloadFunc A function that returns a sequence of children from storage.
+ * @param foreign A function that gets the MappedForeignKey on the child that refers to this parent
+ */
+ class MappedOneToManyBase[O <: Mapper[_]](val reloadFunc: () => Seq[O],
+ val foreign: O => MappedForeignKey[K,_,T]) extends scala.collection.mutable.Buffer[O] {
+ private var inited = false
+ private var _delegate: List[O] = _
+ /**
+ * children that were added before the parent was ever saved
+ */
+ private var unlinked: List[O] = Nil
+ protected def delegate: List[O] = {
+ if(!inited) {
+ refresh()
+ inited = true
+ }
+ _delegate
+ }
+ protected def delegate_=(d: List[O]): Unit = _delegate = d
+
+ /**
+ * Takes ownership of e. Sets e's foreign key to our primary key
+ */
+ protected def own(e: O): O = {
+ val f0 = foreign(e).asInstanceOf[Any]
+ f0 match {
+ case f: MappedLongForeignKey[O,T] with MappedForeignKey[K,_,T] =>
+ f.apply(OneToMany.this)
+ case f: MappedForeignKey[K,_,T] =>
+ f.set(OneToMany.this.primaryKeyField.get)
+ }
+ if(!OneToMany.this.saved_?)
+ unlinked ::= e
+ e
+ }
+ /**
+ * Relinquishes ownership of e. Resets e's foreign key to its default value.
+ */
+ protected def unown(e: O): O = {
+ val f = foreign(e)
+ f.set(f.defaultValue)
+ unlinked = unlinked filter {e.ne}
+ e
+ }
+ /**
+ * Returns the backing List
+ */
+ def all: List[O] = delegate
+
+ // 2.8: return this
+ def addOne(elem: O): MappedOneToManyBase.this.type = {
+ delegate = delegate ++ List(own(elem))
+ this
+ }
+ // 2.7
+ //def readOnly = all
+ def length: Int = delegate.length
+ // 2.7
+ //def elements = delegate.elements
+ // 2.8
+ def iterator: Iterator[O] = delegate.iterator
+
+ def apply(n: Int): O = delegate(n)
+
+ // 2.7
+ /* def +:(elem: O) = {
+ delegate ::= own(elem)
+ this
+ } */
+ // 2.8
+ def prepend(elem: O): MappedOneToManyBase.this.type = {
+ delegate ::= own(elem)
+ this
+ }
+
+ override def indexOf[B >: O](e: B): Int = delegate.indexWhere(e.asInstanceOf[AnyRef].eq)
+
+ override def insert(idx: Int, elem: O): Unit = insertAll(idx, List(elem))
+
+ // 2.7
+ // def insertAll(n: Int, iter: Iterable[O]) {
+ // 2.8
+ def insertAll(n: Int, iter: IterableOnce[O]): Unit = {
+ val (before, after) = delegate.splitAt(n)
+ delegate = before ++ iter.iterator.map(own) ++ after
+ }
+
+ def patchInPlace(from: Int, patch: IterableOnce[O], replaced: Int): MappedOneToManyBase.this.type = {
+ val endIds = from + replaced
+ delegate.slice(from, endIds).foreach(unown)
+ delegate = delegate.take(from) ++ patch.iterator.map(own) ++ delegate.drop(endIds)
+ this
+ }
+
+ def update(n: Int, newelem: O): Unit = {
+ unown(delegate(n))
+ delegate = delegate.take(n) ++ List(own(newelem)) ++ delegate.drop(n+1)
+ }
+
+ def remove(n: Int): O = {
+ val e = unown(delegate(n))
+ delegate = delegate.filterNot(e.eq)
+ e
+ }
+
+ def remove(idx: Int, count: Int): Unit = {
+ val endIds = idx + count
+ delegate.slice(idx, endIds).foreach(unown)
+ delegate = delegate.take(idx) ++ delegate.drop(endIds)
+ }
+
+ def clear(): Unit = {
+ while(delegate.nonEmpty)
+ remove(0)
+ }
+
+ /**
+ * Reloads the children from storage.
+ * NOTE: This may leave children in an inconsistent state.
+ * It is recommended to call save or clear() before calling refresh.
+ */
+ def refresh(): Unit = {
+ delegate = reloadFunc().toList
+ if(saved_?)
+ unlinked = Nil
+ else
+ unlinked = _delegate
+ }
+
+ /**
+ * Saves this "field," i.e., all the children it represents.
+ * Returns false as soon as save on a child returns false.
+ * Returns true if all children were saved successfully.
+ */
+ def save: Boolean = {
+ unlinked foreach {u =>
+ val f = foreign(u)
+ if(f.obj.map(_ eq OneToMany.this) openOr true) // obj is Empty or this
+ f.apply(OneToMany.this)
+ }
+ unlinked = Nil
+ delegate = delegate.filter {e =>
+ foreign(e).get == OneToMany.this.primaryKeyField.get ||
+ foreign(e).obj.map(_ eq OneToMany.this).openOr(false) // obj is this but not Empty
+ }
+ delegate.forall(_.save)
+ }
+
+ override def toString: String = {
+ val c = getClass.getSimpleName
+ val l = c.lastIndexOf("$")
+ c.substring(c.lastIndexOf("$",l-1)+1, l) + delegate.mkString("[",", ","]")
+ }
+ }
+
+ /**
+ * Adds behavior to delete orphaned fields before save.
+ */
+ trait Owned[O<:Mapper[_]] extends MappedOneToManyBase[O] {
+ var removed: List[O] = Nil
+ override def unown(e: O) = {
+ removed = e :: removed
+ super.unown(e)
+ }
+ override def own(e: O) = {
+ removed = removed filter {e.ne}
+ super.own(e)
+ }
+ override def save: Boolean = {
+ val unowned = removed.filter{ e =>
+ val f = foreign(e)
+ f.get == f.defaultValue
+ }
+ unowned foreach {_.delete_!}
+ super.save
+ }
+ }
+
+ /**
+ * Trait that indicates that the children represented
+ * by this field should be deleted when the parent is deleted.
+ */
+ trait Cascade[O<:Mapper[_]] extends MappedOneToManyBase[O] {
+ def delete_! : Boolean = {
+ delegate.forall { e =>
+ if(foreign(e).get ==
+ OneToMany.this.primaryKeyField.get) {
+ e.delete_!
+ }
+ else
+ true // doesn't constitute a failure
+ }
+ }
+ }
+}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/AjaxMapper.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/AjaxMapper.scala
index c9243a5b3b..565794bced 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/AjaxMapper.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/AjaxMapper.scala
@@ -29,7 +29,7 @@ trait AjaxEditableField[FieldType,OwnerType <: Mapper[OwnerType]] extends Mapped
if (editableField) {
* field() = new_value
@@ -372,11 +363,11 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
* field.set(new_value)
* are all the same
*/
- def update[Q <% FieldType](v: Q) {
+ def update[Q](v: Q)(implicit implFn: Q => FieldType): Unit = {
this.set(v)
}
- def apply[Q <% FieldType](v: Q): OwnerType = {
+ def apply[Q](v: Q)(implicit implFn: Q => FieldType): OwnerType = {
this.set(v)
fieldOwner
}
@@ -386,7 +377,6 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
fieldOwner
}
-
/**
* The unique field id is the field name and the mapper name
*/
@@ -401,28 +391,27 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
else throw new Exception("Do not have permissions to set this field")
}
- def :=[Q <% FieldType](v: Q): FieldType = {
+ def :=[Q](v: Q)(implicit implFn: Q => FieldType): FieldType = {
set(v)
}
- def :=(v: FieldType): FieldType = {
+ def :=(v: FieldType): FieldType = {
set(v)
}
-
- private var _name : String = null
+ private var _name : String = _
/**
* The internal name of this field. Use name
*/
- private[mapper] final def i_name_! = _name
+ private[mapper] final def i_name_! : String = _name
/**
* The name of this field
*/
- final def name = synchronized {
+ final def name: String = synchronized {
if (_name eq null) {
- fieldOwner.checkNames
+ fieldOwner.checkNames()
}
_name
}
@@ -440,11 +429,10 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
*/
override def displayName: String = MapperRules.displayNameCalculator.vend(fieldOwner, S.locale, name)
- def resetDirty {
+ def resetDirty(): Unit = {
if (safe_?) dirty_?(false)
}
-
/**
* Attempt to figure out what the incoming value is and set the field to that value. Return true if
* the value could be assigned
@@ -490,14 +478,12 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
* If the field has a defined fieldId, append it
*/
protected def appendFieldId(in: Elem): Elem = fieldId match {
- case Some(i) => {
+ case Some(i) =>
import util.Helpers._
in % ("id" -> i)
- }
case _ => in
}
-
/**
* Set the field to the Box value if the Box is Full
*/
@@ -534,7 +520,7 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
def buildSetDateValue(accessor: Method, columnName: String): (OwnerType, Date) => Unit
def buildSetBooleanValue(accessor: Method, columnName: String) : (OwnerType, Boolean, Boolean) => Unit
protected def getField(inst: OwnerType, meth: Method) = meth.invoke(inst).asInstanceOf[MappedField[FieldType,OwnerType]];
- protected def doField(inst: OwnerType, meth: Method, func: PartialFunction[MappedField[FieldType, OwnerType], Unit]) {
+ protected def doField(inst: OwnerType, meth: Method, func: PartialFunction[MappedField[FieldType, OwnerType], Unit]): Unit = {
val f = getField(inst, meth)
if (func.isDefinedAt(f)) func(f)
}
@@ -577,13 +563,13 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
/**
* Return the field name and field value, delimited by an '='
*/
- def asString = name + "=" + toString
+ def asString: String = name + "=" + toString
def dbColumnCount = 1
- def dbColumnNames(in : String) = if (dbColumnCount == 1) List(_dbColumnNameLC) else List(in.toLowerCase)
+ def dbColumnNames(in : String): List[String] = if (dbColumnCount == 1) List(_dbColumnNameLC) else List(in.toLowerCase)
- def dbColumnName = {
+ def dbColumnName: String = {
val columnName = MapperRules.columnName(fieldOwner.connectionIdentifier, name)
if(DB.reservedWords.contains(columnName.toLowerCase))
columnName+"_c"
@@ -591,7 +577,7 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
columnName
}
- def dbSelectString = fieldOwner.getSingleton._dbTableNameLC + "." + _dbColumnNameLC
+ def dbSelectString: String = fieldOwner.getSingleton._dbTableNameLC + "." + _dbColumnNameLC
def dbIndexed_? : Boolean = false
@@ -642,7 +628,8 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
}
*/
- def runValidations(validators: List[FieldType => List[FieldError]]) {
+ @tailrec
+ def runValidations(validators: List[FieldType => List[FieldError]]): Unit = {
validators match {
case Nil => ()
case x :: rest =>
@@ -692,7 +679,7 @@ trait MappedField[FieldType <: Any,OwnerType <: Mapper[OwnerType]] extends Typed
)
}
- def canEqual(that: Any) = that match {
+ def canEqual(that: Any): Boolean = that match {
case ar: AnyRef => ar.getClass==this.getClass
case _ => false
}
@@ -715,22 +702,22 @@ trait BaseIndexedField extends BaseMappedField {
trait LifecycleCallbacks {
- def beforeValidation {}
- def beforeValidationOnCreate {}
- def beforeValidationOnUpdate {}
- def afterValidation {}
- def afterValidationOnCreate {}
- def afterValidationOnUpdate {}
-
- def beforeSave {}
- def beforeCreate {}
- def beforeUpdate {}
-
- def afterSave {}
- def afterCreate {}
- def afterUpdate {}
-
- def beforeDelete {}
- def afterDelete {}
+ def beforeValidation: Unit = {}
+ def beforeValidationOnCreate: Unit = {}
+ def beforeValidationOnUpdate: Unit = {}
+ def afterValidation: Unit = {}
+ def afterValidationOnCreate: Unit = {}
+ def afterValidationOnUpdate: Unit = {}
+
+ def beforeSave: Unit = {}
+ def beforeCreate: Unit = {}
+ def beforeUpdate: Unit = {}
+
+ def afterSave: Unit = {}
+ def afterCreate: Unit = {}
+ def afterUpdate: Unit = {}
+
+ def beforeDelete: Unit = {}
+ def afterDelete: Unit = {}
}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedForeignKey.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedForeignKey.scala
index 4d1810cd7b..d6ba790b06 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedForeignKey.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedForeignKey.scala
@@ -95,7 +95,7 @@ with LifecycleCallbacks {
private def checkTypes(km: KeyedMapper[KeyType, _]): Boolean =
km.getSingleton eq foreignMeta
- override def equals(other: Any) = other match {
+ override def equals(other: Any): Boolean = other match {
case km: KeyedMapper[KeyType, Other] if checkTypes(km) => this.get == km.primaryKeyField.get
case _ => super.equals(other)
}
@@ -124,7 +124,7 @@ with LifecycleCallbacks {
*/
def cached_? : Boolean = synchronized{ _calcedObj}
- override protected def dirty_?(b: Boolean) = synchronized { // issue 165
+ override protected def dirty_?(b: Boolean): Unit = synchronized { // issue 165
// invalidate if the primary key has changed Issue 370
if (_obj.isEmpty || (_calcedObj && _obj.isDefined &&
_obj.openOrThrowException("_obj was just checked as full.").primaryKeyField.get != this.i_is_!)) {
@@ -151,13 +151,13 @@ with LifecycleCallbacks {
_obj
}
- private[mapper] def _primeObj(obj: Box[Any]) =
+ private[mapper] def _primeObj(obj: Box[Any]): Unit =
primeObj(obj.asInstanceOf[Box[Other]])
/**
* Prime the reference of this FK reference
*/
- def primeObj(obj: Box[Other]) = synchronized {
+ def primeObj(obj: Box[Other]): Unit = synchronized {
_obj = obj
_calcedObj = true
}
@@ -194,7 +194,7 @@ with LifecycleCallbacks {
* sets the field's value from obj if it's set to the default (!defined_?).
* Overrides LifecycleCallbacks.beforeSave
*/
- override def beforeSave {
+ override def beforeSave: Unit = {
if(!defined_?)
for(o <- obj)
set(o.primaryKeyField.get)
@@ -212,7 +212,7 @@ with LifecycleCallbacks {
abstract class MappedLongForeignKey[T<:Mapper[T],O<:KeyedMapper[Long, O]](theOwner: T, _foreignMeta: => KeyedMetaMapper[Long, O])
extends MappedLong[T](theOwner) with MappedForeignKey[Long,T,O] with BaseForeignKey {
- def defined_? = i_is_! > 0L
+ def defined_? : Boolean = i_is_! > 0L
def foreignMeta = _foreignMeta
@@ -255,7 +255,7 @@ extends MappedLong[T](theOwner) with MappedForeignKey[Long,T,O] with BaseForeign
*/
def dbAddedForeignKey: Box[() => Unit] = Empty
- override def toString = if (defined_?) super.toString else "NULL"
+ override def toString: String = if (defined_?) super.toString else "NULL"
def findFor(key: KeyType): List[OwnerType] = theOwner.getSingleton.findAll(By(this, key))
@@ -272,7 +272,7 @@ extends MappedLong[T](theOwner) with MappedForeignKey[Long,T,O] with BaseForeign
abstract class MappedStringForeignKey[T<:Mapper[T],O<:KeyedMapper[String, O]](override val fieldOwner: T, foreign: => KeyedMetaMapper[String, O],override val maxLen: Int)
extends MappedString[T](fieldOwner, maxLen) with MappedForeignKey[String,T,O] with BaseForeignKey {
- def defined_? = i_is_! ne null
+ def defined_? : Boolean = i_is_! ne null
type KeyType = String
type KeyedForeignType = O
@@ -297,7 +297,7 @@ extends MappedString[T](fieldOwner, maxLen) with MappedForeignKey[String,T,O] wi
*/
def dbAddedForeignKey: Box[() => Unit] = Empty
- override def toString = if (defined_?) super.toString else "NULL"
+ override def toString: String = if (defined_?) super.toString else "NULL"
def set(v: Box[O]): T = {
val toSet: String = v match {
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedInt.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedInt.scala
index eec22ce66f..71c80a066e 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedInt.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedInt.scala
@@ -17,7 +17,7 @@
package net.liftweb
package mapper
-import java.sql.{ResultSet, Types}
+import java.sql.Types
import java.lang.reflect.Method
import net.liftweb.common._
import net.liftweb.util._
@@ -30,7 +30,6 @@ import scala.xml.{Text, NodeSeq}
import js._
-
/**
* Warning: Do not use unnamed Enumerations with 2.8.1 as this will cause too many items to be displayed in the dropdown.
*
@@ -40,19 +39,19 @@ abstract class MappedEnum[T<:Mapper[T], ENUM <: Enumeration](val fieldOwner: T,
private var data: ENUM#Value = defaultValue
private var orgData: ENUM#Value = defaultValue
def defaultValue: ENUM#Value = enum.values.iterator.next
- def dbFieldClass = classOf[ENUM#Value]
+ def dbFieldClass: Class[ENUM#Value] = classOf[ENUM#Value]
/**
* Get the JDBC SQL Type for this field
*/
- def targetSQLType = Types.BIGINT
+ def targetSQLType: Int = Types.BIGINT
- protected def i_is_! = data
- protected def i_was_! = orgData
+ protected def i_is_! : ENUM#Value = data
+ protected def i_was_! : ENUM#Value = orgData
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
+ override protected[mapper] def doneWithSave(): Unit = {
orgData = data
}
@@ -141,7 +140,7 @@ abstract class MappedEnum[T<:Mapper[T], ENUM <: Enumeration](val fieldOwner: T,
protected def i_obscure_!(in : ENUM#Value) = defaultValue
- private def st(in: ENUM#Value) {
+ private def st(in: ENUM#Value): Unit = {
data = in
orgData = in
}
@@ -251,12 +250,12 @@ abstract class MappedInt[T<:Mapper[T]](val fieldOwner: T) extends MappedField[In
private var orgData: Int = defaultValue
def defaultValue = 0
- def dbFieldClass = classOf[Int]
+ def dbFieldClass: Class[Int] = classOf[Int]
/**
* Get the JDBC SQL Type for this field
*/
- def targetSQLType = Types.INTEGER
+ def targetSQLType: Int = Types.INTEGER
import scala.reflect.runtime.universe._
def manifest: TypeTag[Int] = typeTag[Int]
@@ -302,12 +301,12 @@ abstract class MappedInt[T<:Mapper[T]](val fieldOwner: T) extends MappedField[In
def asSeq(v: T): Box[Seq[SourceFieldInfo]] = Empty
})
- protected def i_is_! = data
- protected def i_was_! = orgData
+ protected def i_is_! : Int = data
+ protected def i_was_! : Int = orgData
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
+ override protected[mapper] def doneWithSave(): Unit = {
orgData = data
}
@@ -349,7 +348,7 @@ abstract class MappedInt[T<:Mapper[T]](val fieldOwner: T) extends MappedField[In
protected def i_obscure_!(in : Int) = 0
- private def st(in: Int) {
+ private def st(in: Int): Unit = {
data = in
orgData = in
}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala
index dae152e042..d06bd9af5e 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedLong.scala
@@ -19,14 +19,16 @@ package mapper
import java.sql.Types
import java.lang.reflect.Method
-import net.liftweb.util.Helpers._
-import net.liftweb.util._
-import net.liftweb.common._
import java.util.Date
+
+import common._
+import util.Helpers._
+import util._
+import http.SHtml
+import http.js._
+import json._
+
import scala.xml.{Text, NodeSeq}
-import net.liftweb.http.{S, SHtml}
-import net.liftweb.http.js._
-import net.liftweb.json._
abstract class MappedLongIndex[T<:Mapper[T]](theOwner: T) extends MappedLong[T](theOwner) with IndexedField[Long] {
@@ -80,21 +82,19 @@ abstract class MappedEnumList[T<:Mapper[T], ENUM <: Enumeration](val fieldOwner:
private var orgData: Seq[ENUM#Value] = defaultValue
def defaultValue: Seq[ENUM#Value] = Nil
- def dbFieldClass = classOf[Seq[ENUM#Value]]
+ def dbFieldClass: Class[Seq[ENUM#Value]] = classOf[Seq[ENUM#Value]]
/**
* Get the JDBC SQL Type for this field
*/
- def targetSQLType = Types.BIGINT
+ def targetSQLType: Int = Types.BIGINT
- protected def i_is_! = data
- protected def i_was_! = orgData
+ protected def i_is_! : Seq[ENUM#Value] = data
+ protected def i_was_! : Seq[ENUM#Value] = orgData
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
- orgData = data
- }
+ override protected[mapper] def doneWithSave(): Unit = orgData = data
/**
* Get the source field metadata for the field
@@ -183,7 +183,7 @@ abstract class MappedEnumList[T<:Mapper[T], ENUM <: Enumeration](val fieldOwner:
protected def i_obscure_!(in : Seq[ENUM#Value]) = Nil
- private def st(in: Seq[ENUM#Value]) {
+ private def st(in: Seq[ENUM#Value]): Unit = {
data = in
orgData = in
}
@@ -219,7 +219,7 @@ abstract class MappedEnumList[T<:Mapper[T], ENUM <: Enumeration](val fieldOwner:
* Mix with MappedLong to give a default time of millis
*/
trait DefaultMillis extends TypedField[Long] {
- override def defaultValue = millis
+ override def defaultValue: Long = millis
}
@@ -228,12 +228,12 @@ abstract class MappedNullableLong[T<:Mapper[T]](val fieldOwner: T) extends Mappe
private var orgData: Box[Long] = defaultValue
def defaultValue: Box[Long] = Empty
- def dbFieldClass = classOf[Box[Long]]
+ def dbFieldClass: Class[Box[Long]] = classOf[Box[Long]]
/**
* Get the JDBC SQL Type for this field
*/
- def targetSQLType = Types.BIGINT
+ def targetSQLType: Int = Types.BIGINT
import scala.reflect.runtime.universe._
def manifest: TypeTag[Box[Long]] = typeTag[Box[Long]]
@@ -280,12 +280,12 @@ abstract class MappedNullableLong[T<:Mapper[T]](val fieldOwner: T) extends Mappe
})
- protected def i_is_! = data
- protected def i_was_! = orgData
+ protected def i_is_! : Box[Long] = data
+ protected def i_was_! : Box[Long] = orgData
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
+ override protected[mapper] def doneWithSave(): Unit = {
orgData = data
}
@@ -336,7 +336,7 @@ abstract class MappedNullableLong[T<:Mapper[T]](val fieldOwner: T) extends Mappe
protected def i_obscure_!(in: Box[Long]) = defaultValue
- private def st(in: Box[Long]) {
+ private def st(in: Box[Long]): Unit = {
data = in
orgData = in
}
@@ -410,19 +410,19 @@ abstract class MappedLong[T<:Mapper[T]](val fieldOwner: T) extends MappedField[L
})
def defaultValue: Long = 0L
- def dbFieldClass = classOf[Long]
+ def dbFieldClass: Class[Long] = classOf[Long]
/**
* Get the JDBC SQL Type for this field
*/
- def targetSQLType = Types.BIGINT
+ def targetSQLType: Int = Types.BIGINT
- protected def i_is_! = data
- protected def i_was_! = orgData
+ protected def i_is_! : Long = data
+ protected def i_was_! : Long = orgData
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
+ override protected[mapper] def doneWithSave(): Unit = {
orgData = data
}
@@ -468,7 +468,7 @@ abstract class MappedLong[T<:Mapper[T]](val fieldOwner: T) extends MappedField[L
protected def i_obscure_!(in : Long) = defaultValue
- private def st(in: Long) {
+ private def st(in: Long): Unit = {
data = in
orgData = in
}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala
index 18cf9642e5..588997e752 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPassword.scala
@@ -183,7 +183,7 @@ extends MappedField[String, T] {
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
+ override protected[mapper] def doneWithSave(): Unit = {
}
protected def i_obscure_!(in : String) : String = in
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPostalCode.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPostalCode.scala
index f8754654c9..307b3c0e28 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPostalCode.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedPostalCode.scala
@@ -68,17 +68,16 @@ object Countries extends Enumeration(1) {
def I18NCountry = new I18NCountry
class I18NCountry extends Val {
- override def toString() =
- S.?("country_" + id)
+ override def toString(): String = S.?("country_" + id)
}
}
abstract class MappedLocale[T <: Mapper[T]](owner: T) extends MappedString[T](owner, 16) {
- override def defaultValue = Locale.getDefault.toString
+ override def defaultValue: String = Locale.getDefault.toString
def isAsLocale: Locale = Locale.getAvailableLocales.filter(_.toString == get).toList match {
case Nil => Locale.getDefault
- case x :: xs => x
+ case x :: _ => x
}
override def _toForm: Box[Elem] =
@@ -89,7 +88,7 @@ abstract class MappedLocale[T <: Mapper[T]](owner: T) extends MappedString[T](ow
}
abstract class MappedTimeZone[T <: Mapper[T]](owner: T) extends MappedString[T](owner, 32) {
- override def defaultValue = TimeZone.getDefault.getID
+ override def defaultValue: String = TimeZone.getDefault.getID
def isAsTimeZone: TimeZone = TimeZone.getTimeZone(get) match {
case null => TimeZone.getDefault
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedString.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedString.scala
index cb4e4c64b5..45e47acd1d 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedString.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedString.scala
@@ -17,22 +17,18 @@
package net.liftweb
package mapper
-import java.sql.{ResultSet, Types}
+import java.sql.Types
import java.lang.reflect.Method
-import util._
-import net.liftweb.common.{Box, Full, Empty, Failure}
import java.util.Date
-import java.util.regex._
-import scala.xml.{NodeSeq, Text, Elem}
-import net.liftweb.http.{S}
-import net.liftweb.http.js._
-import net.liftweb.json._
+
+import util._
+import common.{Box, Full, Empty, Failure}
+import http.S
+import http.js._
+import json._
import S._
-import common.Full
-import scala.Some
-import common.Full
-import scala.Some
-import util.SourceFieldMetadataRep
+
+import scala.xml.{NodeSeq, Text, Elem}
/**
* Just like MappedString, except it's defaultValue is "" and the length is auto-cropped to
@@ -62,7 +58,7 @@ abstract class MappedString[T<:Mapper[T]](val fieldOwner: T,val maxLen: Int) ext
private val data: FatLazy[String] = FatLazy(defaultValue) // defaultValue
private val orgData: FatLazy[String] = FatLazy(defaultValue) // defaultValue
- def dbFieldClass = classOf[String]
+ def dbFieldClass: Class[String] = classOf[String]
import scala.reflect.runtime.universe._
def manifest: TypeTag[String] = typeTag[String]
@@ -123,15 +119,15 @@ abstract class MappedString[T<:Mapper[T]](val fieldOwner: T,val maxLen: Int) ext
/**
* Get the JDBC SQL Type for this field
*/
- def targetSQLType = Types.VARCHAR
+ def targetSQLType: Int = Types.VARCHAR
def defaultValue = ""
override def writePermission_? = true
override def readPermission_? = true
- protected def i_is_! = data.get
- protected def i_was_! = orgData.get
+ protected def i_is_! : String = data.get
+ protected def i_was_! : String = orgData.get
def asJsonValue: Box[JsonAST.JValue] = Full(get match {
case null => JsonAST.JNull
@@ -141,7 +137,7 @@ abstract class MappedString[T<:Mapper[T]](val fieldOwner: T,val maxLen: Int) ext
/**
* Called after the field is saved to the database
*/
- override protected[mapper] def doneWithSave() {
+ override protected[mapper] def doneWithSave(): Unit = {
orgData.setFrom(data)
}
@@ -167,7 +163,7 @@ abstract class MappedString[T<:Mapper[T]](val fieldOwner: T,val maxLen: Int) ext
override def setFromAny(in: Any): String = {
in match {
case JsonAST.JNull => this.set(null)
- case seq: Seq[_] if !seq.isEmpty => seq.map(setFromAny).apply(0)
+ case seq: Seq[_] if seq.nonEmpty => seq.map(setFromAny).head
case (s: String) :: _ => this.set(s)
case s :: _ => this.setFromAny(s)
case JsonAST.JString(v) => this.set(v)
@@ -188,7 +184,7 @@ abstract class MappedString[T<:Mapper[T]](val fieldOwner: T,val maxLen: Int) ext
def real_convertToJDBCFriendly(value: String): Object = value
- private def wholeSet(in: String) {
+ private def wholeSet(in: String): Unit = {
this.data() = in
this.orgData() = in
}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala
index 6dca64430a..c4a1b161f0 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTextarea.scala
@@ -17,11 +17,10 @@
package net.liftweb
package mapper
-import scala.xml.{NodeSeq, Elem}
-import net.liftweb.http.S
-import net.liftweb.http.S._
-import net.liftweb.util._
-import net.liftweb.common._
+import http.S
+import common._
+
+import scala.xml.Elem
abstract class MappedTextarea[T<:Mapper[T]](owner : T, maxLen: Int) extends MappedString[T](owner, maxLen) {
/**
@@ -37,7 +36,7 @@ abstract class MappedTextarea[T<:Mapper[T]](owner : T, maxLen: Int) extends Mapp
case s => s}}))}
}
- override def toString = {
+ override def toString: String = {
val v = get
if (v == null || v.length < 100) super.toString
else v.substring(0,40)+" ... "+v.substring(v.length - 40)
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala
index bfde33d444..66ebb6ccb8 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedTime.scala
@@ -17,16 +17,14 @@
package net.liftweb
package mapper
-import java.sql.{ResultSet, Types}
+import java.sql.Types
import java.util.Date
import java.lang.reflect.Method
-import net.liftweb._
import util._
import common._
import Helpers._
import http._
-import S._
import js._
import json._
@@ -136,7 +134,7 @@ abstract class MappedTime[T<:Mapper[T]](val fieldOwner: T) extends MappedField[D
protected def i_is_! = data.get
protected def i_was_! = orgData.get
- protected[mapper] def doneWithSave() {orgData.setFrom(data)}
+ protected[mapper] def doneWithSave(): Unit = {orgData.setFrom(data)}
protected def i_obscure_!(in : Date) : Date = {
new Date(0L)
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedUniqueId.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedUniqueId.scala
index 372da1fb52..c61c313d49 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedUniqueId.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MappedUniqueId.scala
@@ -17,12 +17,12 @@
package net.liftweb
package mapper
-import net.liftweb.common._
-import net.liftweb.util._
+import common._
+import util._
import Helpers._
-import net.liftweb.http.{S, SHtml}
+import http.{S, SHtml}
+
import scala.xml.NodeSeq
-import net.liftweb.http.js._
abstract class MappedUniqueId[T<:Mapper[T]](override val fieldOwner: T, override val maxLen: Int) extends MappedString[T](fieldOwner, maxLen) {
override def writePermission_? = false
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/Mapper.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/Mapper.scala
index ebb9dbd176..c3d65d03db 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/Mapper.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/Mapper.scala
@@ -17,15 +17,15 @@
package net.liftweb
package mapper
+import java.util.Date
+
import scala.xml.{Elem, NodeSeq}
-import net.liftweb.http.S
-import net.liftweb.http.js._
+import http.S
+import http.js._
import util._
-import net.liftweb.common.{Box, Empty, Full, ParamFailure}
+import common.{Box, Empty, Full, ParamFailure}
+
import collection.mutable.StringBuilder
-import net.liftweb.util
-import common.Full
-import common.Full
trait BaseMapper extends FieldContainer {
type MapperType <: Mapper[MapperType]
@@ -85,7 +85,7 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
this
}
- def save(): Boolean = {
+ def save: Boolean = {
runSafe {
getSingleton.save(this)
}
@@ -161,7 +161,7 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
def formFields: List[MappedField[_, A]] =
getSingleton.formFields(this)
- def allFields: scala.collection.Seq[BaseField] = formFields
+ def allFields: Seq[BaseField] = formFields
/**
* map the fields titles and forms to generate a list
@@ -176,7 +176,7 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
* @param func called with displayHtml, fieldId, form
*/
def flatMapFieldTitleForm[T]
- (func: (NodeSeq, Box[NodeSeq], NodeSeq) => scala.collection.Seq[T]): List[T] =
+ (func: (NodeSeq, Box[NodeSeq], NodeSeq) => Seq[T]): List[T] =
getSingleton.flatMapFieldTitleForm(this, func)
/**
@@ -184,7 +184,7 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
* @param func called with displayHtml, fieldId, form
*/
def flatMapFieldTitleForm2[T]
- (func: (NodeSeq, MappedField[_, A], NodeSeq) => scala.collection.Seq[T]): List[T] =
+ (func: (NodeSeq, MappedField[_, A], NodeSeq) => Seq[T]): List[T] =
getSingleton.flatMapFieldTitleForm2(this, func)
/**
@@ -225,7 +225,7 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
def toForm(button: Box[String], redoSnippet: NodeSeq => NodeSeq, onSuccess: A => Unit): NodeSeq = {
val snipName = S.currentSnippet
- def doSubmit() {
+ def doSubmit(): Unit = {
this.validate match {
case Nil => onSuccess(this)
case xs => S.error(xs)
@@ -247,25 +247,18 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
def dirty_? : Boolean = getSingleton.dirty_?(this)
- override def toString = {
- val ret = new StringBuilder
-
- ret.append(this.getClass.getName)
-
- ret.append("={")
-
- ret.append(getSingleton.appendFieldToStrings(this))
-
- ret.append("}")
-
- ret.toString
- }
+ override def toString: String =
+ new StringBuilder(this.getClass.getName)
+ .append("={")
+ .append(getSingleton.appendFieldToStrings(this))
+ .append("}")
+ .toString
def toXml: Elem = {
getSingleton.toXml(this)
}
- def checkNames {
+ def checkNames(): Unit = {
runSafe {
getSingleton match {
case null =>
@@ -304,11 +297,11 @@ trait Mapper[A<:Mapper[A]] extends BaseMapper with Serializable with SourceInfo
*/
def fieldTransforms = fieldTransforms_i
- def appendFieldTransform(transform: CssSel) {
+ def appendFieldTransform(transform: CssSel): Unit = {
fieldTransforms_i = fieldTransforms_i :+ transform
}
- def prependFieldTransform(transform: CssSel) {
+ def prependFieldTransform(transform: CssSel): Unit = {
fieldTransforms_i = transform +: fieldTransforms_i
}
@@ -405,9 +398,9 @@ trait UpdatedTrait {
lazy val updatedAt: MyUpdatedAt = new MyUpdatedAt(this)
protected class MyUpdatedAt(obj: self.type) extends MappedDateTime(obj.asInstanceOf[MapperType]) with LifecycleCallbacks {
- override def beforeSave() {super.beforeSave; this.set(Helpers.now)}
- override def defaultValue = Helpers.now
- override def dbIndexed_? = updatedAtIndexed_?
+ override def beforeSave: Unit = {super.beforeSave; this.set(Helpers.now)}
+ override def defaultValue: Date = Helpers.now
+ override def dbIndexed_? : Boolean = updatedAtIndexed_?
}
}
@@ -429,7 +422,7 @@ trait KeyedMapper[KeyType, OwnerType<:KeyedMapper[KeyType, OwnerType]] extends M
def primaryKeyField: MappedField[KeyType, OwnerType] with IndexedField[KeyType]
def getSingleton: KeyedMetaMapper[KeyType, OwnerType];
- override def comparePrimaryKeys(other: OwnerType) = primaryKeyField.get == other.primaryKeyField.get
+ override def comparePrimaryKeys(other: OwnerType): Boolean = primaryKeyField.get == other.primaryKeyField.get
def reload: OwnerType = getSingleton.find(By(primaryKeyField, primaryKeyField.get)) openOr this
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala
index d7ec3db8f2..a5c7cd89af 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/MetaMapper.scala
@@ -42,7 +42,7 @@ trait BaseMetaMapper {
def dbTableName: String
def _dbTableNameLC: String
- def mappedFields: scala.collection.Seq[BaseMappedField];
+ def mappedFields: Seq[BaseMappedField];
def dbAddTable: Box[() => Unit]
def dbIndexes: List[BaseIndex[RealType]]
@@ -91,13 +91,13 @@ object MapperRules extends Factory {
* What are the rules and mechanisms for putting quotes around table names?
*/
val quoteTableName: FactoryMaker[String => String] =
- new FactoryMaker[String => String]((s: String) => if (s.indexOf(' ') >= 0) '"'+s+'"' else s) {}
+ new FactoryMaker[String => String]((s: String) => if (s.indexOf(' ') >= 0) "\""+s+"\"" else s) {}
/**
* What are the rules and mechanisms for putting quotes around column names?
*/
val quoteColumnName: FactoryMaker[String => String] =
- new FactoryMaker[String => String]((s: String) => if (s.indexOf(' ') >= 0) '"'+s+'"' else s) {}
+ new FactoryMaker[String => String]((s: String) => if (s.indexOf(' ') >= 0) "\""+s+"\"" else s) {}
/**
* Function that determines if foreign key constraints are
@@ -173,7 +173,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
*/
def validation: List[A => List[FieldError]] = Nil
- private def clearPostCommit(in: A) {
+ private def clearPostCommit(in: A): Unit = {
in.addedPostCommit = false
}
@@ -271,7 +271,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
//type OtherMapper = KeyedMapper[_, (T forSome {type T})]
//type OtherMetaMapper = KeyedMetaMapper[_, OtherMapper]
- def findAllFields(fields: scala.collection.Seq[SelectableField],
+ def findAllFields(fields: Seq[SelectableField],
by: QueryParam[A]*): List[A] =
findMapFieldDb(dbDefaultConnectionIdentifier,
fields, by :_*)(v => Full(v))
@@ -759,7 +759,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
index: Int,
field: MappedField[_, A],
columnName : String,
- setObj : (PreparedStatement, Int, AnyRef, Int) => Unit) {
+ setObj : (PreparedStatement, Int, AnyRef, Int) => Unit): Unit = {
setPreparedStatementValue(conn, st, index, field,
field.targetSQLType(columnName),
field.jdbcFriendly(columnName),
@@ -784,7 +784,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
field: BaseMappedField,
columnType : Int,
value : Object,
- setObj : (PreparedStatement, Int, AnyRef, Int) => Unit) {
+ setObj : (PreparedStatement, Int, AnyRef, Int) => Unit): Unit = {
// Remap the type if the driver wants
val mappedColumnType = conn.driverType.columnTypeMap(columnType)
@@ -905,7 +905,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
val query = "INSERT INTO "+MapperRules.quoteTableName.vend(_dbTableNameLC)+" ("+columnNamesForInsert+") VALUES ("+columnQueriesForInsert+")"
- def prepStat(st : PreparedStatement) {
+ def prepStat(st : PreparedStatement): Unit = {
var colNum = 1
for (col <- mappedColumns) {
@@ -1394,7 +1394,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
private[mapper] lazy val internal_dbTableName = fixTableName(internalTableName_$_$)
- private def setupInstanceForPostCommit(inst: A) {
+ private def setupInstanceForPostCommit(inst: A): Unit = {
afterCommit match {
case Nil =>
// If there's no post-commit functions, then don't
@@ -1408,7 +1408,7 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
}
}
- private def eachField(what: A, toRun: List[(A) => Any])(f: (LifecycleCallbacks) => Any) {
+ private def eachField(what: A, toRun: List[(A) => Any])(f: (LifecycleCallbacks) => Any): Unit = {
mappedCallbacks.foreach (e =>
e._2.invoke(what) match {
case lccb: LifecycleCallbacks => f(lccb)
@@ -1416,26 +1416,26 @@ trait MetaMapper[A<:Mapper[A]] extends BaseMetaMapper with Mapper[A] {
})
toRun.foreach{tf => tf(what)}
}
- private def _beforeValidation(what: A) {setupInstanceForPostCommit(what); eachField(what, beforeValidation) {field => field.beforeValidation} }
- private def _beforeValidationOnCreate(what: A) {eachField(what, beforeValidationOnCreate) {field => field.beforeValidationOnCreate} }
- private def _beforeValidationOnUpdate(what: A) {eachField(what, beforeValidationOnUpdate) {field => field.beforeValidationOnUpdate} }
- private def _afterValidation(what: A) { eachField(what, afterValidation) {field => field.afterValidation} }
- private def _afterValidationOnCreate(what: A) {eachField(what, afterValidationOnCreate) {field => field.afterValidationOnCreate} }
- private def _afterValidationOnUpdate(what: A) {eachField(what, afterValidationOnUpdate) {field => field.afterValidationOnUpdate} }
+ private def _beforeValidation(what: A): Unit = {setupInstanceForPostCommit(what); eachField(what, beforeValidation) { field => field.beforeValidation} }
+ private def _beforeValidationOnCreate(what: A): Unit = {eachField(what, beforeValidationOnCreate) { field => field.beforeValidationOnCreate} }
+ private def _beforeValidationOnUpdate(what: A): Unit = {eachField(what, beforeValidationOnUpdate) { field => field.beforeValidationOnUpdate} }
+ private def _afterValidation(what: A): Unit = { eachField(what, afterValidation) { field => field.afterValidation} }
+ private def _afterValidationOnCreate(what: A): Unit = {eachField(what, afterValidationOnCreate) { field => field.afterValidationOnCreate} }
+ private def _afterValidationOnUpdate(what: A): Unit = {eachField(what, afterValidationOnUpdate) { field => field.afterValidationOnUpdate} }
- private def _beforeSave(what: A) {setupInstanceForPostCommit(what); eachField(what, beforeSave) {field => field.beforeSave} }
- private def _beforeCreate(what: A) { eachField(what, beforeCreate) {field => field.beforeCreate} }
- private def _beforeUpdate(what: A) { eachField(what, beforeUpdate) {field => field.beforeUpdate} }
+ private def _beforeSave(what: A): Unit = {setupInstanceForPostCommit(what); eachField(what, beforeSave) { field => field.beforeSave} }
+ private def _beforeCreate(what: A): Unit = { eachField(what, beforeCreate) { field => field.beforeCreate} }
+ private def _beforeUpdate(what: A): Unit = { eachField(what, beforeUpdate) { field => field.beforeUpdate} }
- private def _afterSave(what: A) {eachField(what, afterSave) {field => field.afterSave} }
- private def _afterCreate(what: A) {eachField(what, afterCreate) {field => field.afterCreate} }
- private def _afterUpdate(what: A) {eachField(what, afterUpdate) {field => field.afterUpdate} }
+ private def _afterSave(what: A): Unit = {eachField(what, afterSave) { field => field.afterSave} }
+ private def _afterCreate(what: A): Unit = {eachField(what, afterCreate) { field => field.afterCreate} }
+ private def _afterUpdate(what: A): Unit = {eachField(what, afterUpdate) { field => field.afterUpdate} }
- private def _beforeDelete(what: A) {setupInstanceForPostCommit(what); eachField(what, beforeDelete) {field => field.beforeDelete} }
- private def _afterDelete(what: A) {eachField(what, afterDelete) {field => field.afterDelete} }
+ private def _beforeDelete(what: A): Unit = {setupInstanceForPostCommit(what); eachField(what, beforeDelete) { field => field.beforeDelete} }
+ private def _afterDelete(what: A): Unit = {eachField(what, afterDelete) { field => field.afterDelete} }
- def beforeSchemifier {}
- def afterSchemifier {}
+ def beforeSchemifier: Unit = {}
+ def afterSchemifier: Unit = {}
def dbIndexes: List[BaseIndex[A]] = Nil
@@ -1605,12 +1605,10 @@ final case class InRaw[TheType <:
extends QueryParam[TheType]
object NotIn {
- def fk[InnerMapper <: Mapper[InnerMapper], JoinTypeA,
- Zoom <% QueryParam[InnerMapper],
- OuterMapper <:KeyedMapper[JoinTypeA, OuterMapper]]
- (fielda: MappedForeignKey[JoinTypeA, InnerMapper, OuterMapper],
- qp: Zoom*): InThing[OuterMapper]
- = {
+ def fk[InnerMapper <: Mapper[InnerMapper], JoinTypeA, Zoom, OuterMapper <: KeyedMapper[JoinTypeA, OuterMapper]](
+ fielda: MappedForeignKey[JoinTypeA, InnerMapper, OuterMapper],
+ qp: Zoom*
+ )(implicit ev: Zoom => QueryParam[InnerMapper]): InThing[OuterMapper] = {
new InThing[OuterMapper] {
type JoinType = JoinTypeA
type InnerType = InnerMapper
@@ -1626,13 +1624,11 @@ object NotIn {
}
}
- def apply[InnerMapper <: Mapper[InnerMapper], JoinTypeA,
- Zoom <% QueryParam[InnerMapper],
- OuterMapper <: Mapper[OuterMapper]]
- (_outerField: MappedField[JoinTypeA, OuterMapper],
- _innerField: MappedField[JoinTypeA, InnerMapper],
- qp: Zoom*): InThing[OuterMapper]
- = {
+ def apply[InnerMapper <: Mapper[InnerMapper], JoinTypeA, Zoom, OuterMapper <: Mapper[OuterMapper]](
+ _outerField: MappedField[JoinTypeA, OuterMapper],
+ _innerField: MappedField[JoinTypeA, InnerMapper],
+ qp: Zoom*
+ )(implicit ev: Zoom => QueryParam[InnerMapper]): InThing[OuterMapper] = {
new InThing[OuterMapper] {
type JoinType = JoinTypeA
type InnerType = InnerMapper
@@ -1651,12 +1647,10 @@ object NotIn {
}
object In {
- def fk[InnerMapper <: Mapper[InnerMapper], JoinTypeA,
- Zoom <% QueryParam[InnerMapper],
- OuterMapper <:KeyedMapper[JoinTypeA, OuterMapper]]
- (fielda: MappedForeignKey[JoinTypeA, InnerMapper, OuterMapper],
- qp: Zoom*): InThing[OuterMapper]
- = {
+ def fk[InnerMapper <: Mapper[InnerMapper], JoinTypeA, Zoom, OuterMapper <: KeyedMapper[JoinTypeA, OuterMapper]](
+ fielda: MappedForeignKey[JoinTypeA, InnerMapper, OuterMapper],
+ qp: Zoom*
+ )(implicit ev: Zoom => QueryParam[InnerMapper]): InThing[OuterMapper] = {
new InThing[OuterMapper] {
type JoinType = JoinTypeA
type InnerType = InnerMapper
@@ -1672,13 +1666,11 @@ object In {
}
}
- def apply[InnerMapper <: Mapper[InnerMapper], JoinTypeA,
- Zoom <% QueryParam[InnerMapper],
- OuterMapper <: Mapper[OuterMapper]]
- (_outerField: MappedField[JoinTypeA, OuterMapper],
- _innerField: MappedField[JoinTypeA, InnerMapper],
- qp: Zoom*): InThing[OuterMapper]
- = {
+ def apply[InnerMapper <: Mapper[InnerMapper], JoinTypeA, Zoom, OuterMapper <: Mapper[OuterMapper]](
+ _outerField: MappedField[JoinTypeA, OuterMapper],
+ _innerField: MappedField[JoinTypeA, InnerMapper],
+ qp: Zoom*
+ )(implicit ev: Zoom => QueryParam[InnerMapper]): InThing[OuterMapper] = {
new InThing[OuterMapper] {
type JoinType = JoinTypeA
type InnerType = InnerMapper
@@ -1709,7 +1701,7 @@ object NotLike {
object By {
import OprEnum._
- def apply[O <: Mapper[O], T, U <% T](field: MappedField[T, O], value: U) = Cmp[O,T](field, Eql, Full(value), Empty, Empty)
+ def apply[O <: Mapper[O], T, U](field: MappedField[T, O], value: U)(implicit ev: U => T) = Cmp[O,T](field, Eql, Full(value), Empty, Empty)
def apply[O <: Mapper[O], T](field: MappedNullableField[T, O], value: Box[T]) = value match {
case Full(x) => Cmp[O,Box[T]](field, Eql, Full(value), Empty, Empty)
case _ => NullRef(field)
@@ -1728,8 +1720,8 @@ object By_>= {
import OprEnum._
- def apply[O <: Mapper[O], T, U <% T](field: MappedField[T, O],
- value: U) = Cmp[O, T](field, >=, Full(value), Empty, Empty)
+ def apply[O <: Mapper[O], T, U](field: MappedField[T, O],
+ value: U)(implicit ev: U => T) = Cmp[O, T](field, >=, Full(value), Empty, Empty)
def apply[O <: Mapper[O], T](field: MappedField[T, O], otherField:
MappedField[T, O]) = Cmp[O, T](field, >=, Empty, Full(otherField),
@@ -1740,8 +1732,8 @@ object By_<= {
import OprEnum._
- def apply[O <: Mapper[O], T, U <% T](field: MappedField[T, O],
- value: U) = Cmp[O, T](field, <=, Full(value), Empty, Empty)
+ def apply[O <: Mapper[O], T, U](field: MappedField[T, O],
+ value: U)(implicit ev: U => T) = Cmp[O, T](field, <=, Full(value), Empty, Empty)
def apply[O <: Mapper[O], T](field: MappedField[T, O], otherField:
MappedField[T, O]) = Cmp[O, T](field, <=, Empty, Full(otherField),
@@ -1751,7 +1743,7 @@ object By_<= {
object NotBy {
import OprEnum._
- def apply[O <: Mapper[O], T, U <% T](field: MappedField[T, O], value: U) = Cmp[O,T](field, <>, Full(value), Empty, Empty)
+ def apply[O <: Mapper[O], T, U](field: MappedField[T, O], value: U)(implicit ev: U => T) = Cmp[O,T](field, <>, Full(value), Empty, Empty)
def apply[O <: Mapper[O], T](field: MappedNullableField[T, O], value: Box[T]) = value match {
case Full(x) => Cmp[O,Box[T]](field, <>, Full(value), Empty, Empty)
@@ -1782,14 +1774,14 @@ object NotByRef {
object By_> {
import OprEnum._
- def apply[O <: Mapper[O], T, U <% T](field: MappedField[T, O], value: U) = Cmp[O,T](field, >, Full(value), Empty, Empty)
+ def apply[O <: Mapper[O], T, U](field: MappedField[T, O], value: U)(implicit ev: U => T) = Cmp[O,T](field, >, Full(value), Empty, Empty)
def apply[O <: Mapper[O], T](field: MappedField[T, O], otherField: MappedField[T,O]) = Cmp[O,T](field, >, Empty, Full(otherField), Empty)
}
object By_< {
import OprEnum._
- def apply[O <: Mapper[O], T, U <% T](field: MappedField[T, O], value: U) = Cmp[O,T](field, <, Full(value), Empty, Empty)
+ def apply[O <: Mapper[O], T, U](field: MappedField[T, O], value: U)(implicit ev: U => T) = Cmp[O,T](field, <, Full(value), Empty, Empty)
def apply[O <: Mapper[O], T](field: MappedField[T, O], otherField: MappedField[T,O]) = Cmp[O,T](field, <, Empty, Full(otherField), Empty)
}
@@ -1874,15 +1866,15 @@ trait KeyedMetaMapper[Type, A<:KeyedMapper[Type, A]] extends MetaMapper[A] with
def find(key: Any): Box[A] =
key match {
- case qp: QueryParam[A] => find(List(qp.asInstanceOf[QueryParam[A]]) :_*)
- case prod: Product if (testProdArity(prod)) => find(convertToQPList(prod) :_*)
+ case qp: QueryParam[A] => find(qp)
+ case prod: Product if (testProdArity(prod)) => find(convertToQPList(prod).toIndexedSeq :_*)
case key => anyToFindString(key) flatMap (find(_))
}
def findDb(dbId: ConnectionIdentifier, key: Any): Box[A] =
key match {
case qp: QueryParam[A] => findDb(dbId, List(qp.asInstanceOf[QueryParam[A]]) :_*)
- case prod: Product if (testProdArity(prod)) => findDb(dbId, convertToQPList(prod) :_*)
+ case prod: Product if (testProdArity(prod)) => findDb(dbId, convertToQPList(prod).toIndexedSeq :_*)
case key => anyToFindString(key) flatMap (find(dbId, _))
}
@@ -1947,6 +1939,8 @@ trait KeyedMetaMapper[Type, A<:KeyedMapper[Type, A]] extends MetaMapper[A] with
}
}
+ def find(by: QueryParam[A]): Box[A] = find(Seq(by): _*)
+
def find(by: QueryParam[A]*): Box[A] =
findDb(dbDefaultConnectionIdentifier, by :_*)
@@ -1973,7 +1967,7 @@ trait KeyedMetaMapper[Type, A<:KeyedMapper[Type, A]] extends MetaMapper[A] with
}
}
- override def afterSchemifier {
+ override def afterSchemifier: Unit = {
if (crudSnippets_?) {
LiftRules.snippets.append(crudSnippets)
}
@@ -2014,7 +2008,7 @@ trait KeyedMetaMapper[Type, A<:KeyedMapper[Type, A]] extends MetaMapper[A] with
def formSnippet(html: NodeSeq, obj: A, cleanup: (A => Unit)): NodeSeq = {
val name = internal_dbTableName
- def callback() {
+ def callback(): Unit = {
cleanup(obj)
}
@@ -2115,14 +2109,14 @@ trait KeyedMetaMapper[Type, A<:KeyedMapper[Type, A]] extends MetaMapper[A] with
*
* @param obj mapped object of this metamapper's type
*/
- def editSnippetCallback(obj: A) { obj.save }
+ def editSnippetCallback(obj: A): Unit = { obj.save }
/**
* Default callback behavior of the add snippet. Called when the user
* presses submit. Saves the passed in object.
*
* @param obj mapped object of this metamapper's type
*/
- def addSnippetCallback(obj: A) { obj.save }
+ def addSnippetCallback(obj: A): Unit = { obj.save }
}
@@ -2153,8 +2147,8 @@ class KeyObfuscator {
obscure(what.getSingleton, what.primaryKeyField.get)
}
- def apply[KeyType, MetaType <: KeyedMapper[KeyType, MetaType], Q <% KeyType](theType:
- KeyedMetaMapper[KeyType, MetaType], key: Q): String = {
+ def apply[KeyType, MetaType <: KeyedMapper[KeyType, MetaType], Q](theType:
+ KeyedMetaMapper[KeyType, MetaType], key: Q)(implicit ev: Q => KeyType): String = {
val k: KeyType = key
obscure(theType, k)
}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoExtendedSession.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoExtendedSession.scala
index 75b4d74b9a..a28bfc7ba1 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoExtendedSession.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoExtendedSession.scala
@@ -17,16 +17,14 @@
package net.liftweb
package mapper
-import net.liftweb._
-import net.liftweb.http.provider._
+import http.provider._
import common._
import util._
import http._
import Helpers._
-trait ProtoExtendedSession[T <: ProtoExtendedSession[T]] extends
-KeyedMapper[Long, T] {
+trait ProtoExtendedSession[T <: ProtoExtendedSession[T]] extends KeyedMapper[Long, T] {
self: T =>
override def primaryKeyField: MappedLongIndex[T] = id
@@ -95,16 +93,16 @@ KeyedMetaMapper[Long, T] with ProtoSessionCookiePath {
def recoverUserId: Box[String]
- def userDidLogin(uid: UserType) {
+ def userDidLogin(uid: UserType): Unit = {
userDidLogout(Full(uid))
- val inst = create.userId(uid.userIdAsString).saveMe
+ val inst = create.userId(uid.userIdAsString).saveMe()
val cookie = HTTPCookie(CookieName, inst.cookieId.get).
setMaxAge(((inst.expiration.get - millis) / 1000L).toInt).
setPath(sessionCookiePath)
S.addCookie(cookie)
}
- def userDidLogout(uid: Box[UserType]) {
+ def userDidLogout(uid: Box[UserType]): Unit = {
for (cook <- S.findCookie(CookieName)) {
S.deleteCookie(cook)
find(By(cookieId, cook.value openOr "")).foreach(_.delete_!)
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoTag.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoTag.scala
index 81775ad079..e36e8eaebf 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoTag.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoTag.scala
@@ -35,7 +35,7 @@ trait MetaProtoTag[ModelType <: ProtoTag[ModelType]] extends KeyedMetaMapper[Lon
else {
find(By(name, tag)) match {
case Full(t) => tagCache(tag) = t; t
- case _ => val ret: ModelType = (createInstance).name(tag).saveMe
+ case _ => val ret: ModelType = createInstance.name(tag).saveMe
tagCache(tag) = ret
ret
}
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoUser.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoUser.scala
index 9dd169dfce..d181721212 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoUser.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/ProtoUser.scala
@@ -17,19 +17,12 @@
package net.liftweb
package mapper
-import net.liftweb.http._
-import js._
-import JsCmds._
-import scala.xml.{NodeSeq, Node, Text, Elem}
-import scala.xml.transform._
-import net.liftweb.sitemap._
-import net.liftweb.sitemap.Loc._
-import net.liftweb.util.Helpers._
-import net.liftweb.util._
-import net.liftweb.common._
-import net.liftweb.util.Mailer._
-import S._
-import net.liftweb.proto.{ProtoUser => GenProtoUser}
+import http._
+import util._
+import common._
+import proto.{ProtoUser => GenProtoUser}
+
+import scala.xml.{NodeSeq, Text}
/**
* ProtoUser is a base class that gives you a "User" that has a first name,
diff --git a/persistence/mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala b/persistence/mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala
index e4b4928be1..330f537232 100644
--- a/persistence/mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala
+++ b/persistence/mapper/src/main/scala/net/liftweb/mapper/Schemifier.scala
@@ -17,14 +17,15 @@
package net.liftweb
package mapper
-import java.sql.{Connection, ResultSet, DatabaseMetaData}
+import java.sql.{Connection, DatabaseMetaData, ResultSet}
import scala.collection.mutable.{HashMap, ListBuffer}
-
-import common.{Full, Box, Loggable}
+import common.{Box, Full, Loggable}
import util.Helpers
import Helpers._
+import scala.annotation.tailrec
+
/**
* Given a list of MetaMappers, make sure the database has the right schema
*