alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (MappedForeignKey.scala)

This example Lift Framework source code file (MappedForeignKey.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

box, box, empty, empty, keyedforeigntype, keyedmetamapper, keytype, list, mappedforeignkey, o, o, other, other, string

The Lift Framework MappedForeignKey.scala source code

/*
 * 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 common._


import scala.xml.{NodeSeq, Text, Elem}
import http.{js, S, SHtml}
import js._
import S.?
import json._
import util.FieldError


/**
 * A trait that defines foreign key references
 */
trait BaseForeignKey extends BaseMappedField {

  type KeyType
  type KeyedForeignType <: KeyedMapper[KeyType, KeyedForeignType]

  type OwnerType <: Mapper[OwnerType]

  /**
   * Is the key defined?
   */
  def defined_? : Boolean

  /**
   * get the object referred to by this foreign key
   */

  def dbKeyToTable: BaseMetaMapper

  def dbKeyToColumn: BaseMappedField

  def findFor(key: KeyType): List[OwnerType]

  def findFor(key: KeyedForeignType): List[OwnerType]

  /**
   * Called when Schemifier adds a foreign key.  Return a function that will be called when Schemifier
   * is done with the schemification.
   */
  def dbAddedForeignKey: Box[() => Unit]
}


object MappedForeignKey {
  implicit def getObj[KeyType,
          MyOwner <: Mapper[MyOwner],
          Other <: KeyedMapper[KeyType,
             Other]](in:
               MappedForeignKey[KeyType,
                    MyOwner,
                    Other]):
  Box[Other] = in.obj
}

/**
 * The Trait that defines a field that is mapped to a foreign key
 */
trait MappedForeignKey[KeyType, MyOwner <: Mapper[MyOwner], Other <: KeyedMapper[KeyType, Other]]
extends MappedField[KeyType, MyOwner]
with LifecycleCallbacks {
  type FieldType <: KeyType
  // type ForeignType <: KeyedMapper[KeyType, Other]

  /**
   * What's the MetaMapper for the foreign key
   */
  def foreignMeta: KeyedMetaMapper[KeyType, Other]

  /**
   * Make sure the MetaMapper for the KeyedMapper we're checking
   * is in fact the same one as we are associated with.  Issue #532.
   */
  private def checkTypes(km: KeyedMapper[KeyType, _]): Boolean =
    km.getSingleton eq foreignMeta

  override def equals(other: Any) = other match {
    case km: KeyedMapper[KeyType, Other] if checkTypes(km) => this.is == km.primaryKeyField.is
    case _ => super.equals(other)
  }

  def dbKeyToTable: KeyedMetaMapper[KeyType, Other]

  def validSelectValues: Box[List[(KeyType, String)]] = Empty


  def immutableMsg: NodeSeq = Text(?("Can't change"))

  override def _toForm: Box[Elem] = Full(validSelectValues.flatMap{
      case Nil => Empty

      case xs =>
        Full(SHtml.selectObj(xs, Full(this.is), this.set))
    }.openOr(<span>{immutableMsg}))

  /**
   * Is the key defined
   */
  def defined_? : Boolean

  /**
   * Is the obj field cached
   */
  def cached_? : Boolean = synchronized{ _calcedObj}

  override protected def dirty_?(b: Boolean) = synchronized { // issue 165
    // invalidate if the primary key has changed Issue 370
    if (_obj.isEmpty || (_calcedObj && _obj.isDefined &&
       _obj.open_!.primaryKeyField.is != this.i_is_!)) {
      _obj = Empty
      _calcedObj = false
    }
    super.dirty_?(b)
  }

  /**
   * Some people prefer the name foreign to materialize the
   * foreign reference.  This is a proxy to the obj method.
   */
  def foreign: Box[Other] = obj

  /**
   * Load and cache the record that this field references
   */
  def obj: Box[Other] = synchronized {
    if (!_calcedObj) {
      _calcedObj = true
      this._obj = if(defined_?) dbKeyToTable.find(i_is_!) else Empty
    }
    _obj
  }

  private[mapper] def _primeObj(obj: Box[Any]) =
    primeObj(obj.asInstanceOf[Box[Other]])

  /**
   * Prime the reference of this FK reference
   */
  def primeObj(obj: Box[Other]) = synchronized {
    _obj = obj
    _calcedObj = true
  }

  private var _obj: Box[Other] = Empty
  private var _calcedObj = false


  /**
   * Set the value from a possible instance of the foreign mapper class.
   * v will be cached in obj.
   * If v is Empty, set the value to defaultValue (-1)
   * @return the Mapper containing this field
   */
  def apply(v: Box[Other]): MyOwner = {
    apply(v.dmap(defaultValue)(_.primaryKeyField.is))
    primeObj(v)
    fieldOwner
  }

  /**
   * Set the value from an instance of the foreign mapper class.
   * obj will be set to Full(v)
   * @return the Mapper containing this field
   */
  def apply(v: Other): MyOwner = {
    apply(v.primaryKeyField.is)
    primeObj(Full(v))
    fieldOwner
  }

  /**
   * This method, which gets called when the mapper class is going to be saved,
   * sets the field's value from obj if it's set to the default (!defined_?).
   * Overrides LifecycleCallbacks.beforeSave
   */
  override def beforeSave {
    if(!defined_?)
      for(o <- obj)
        set(o.primaryKeyField.is)
    super.beforeSave
  }

  /**
   * A validation function that checks that obj is nonempty
   */
  val valHasObj = (value: Long) =>
    if (obj.isEmpty) List(FieldError(this, scala.xml.Text("Required field: " + name)))
    else Nil
}


@deprecated("Functionality folded into MappedForeignKey, so just use MappedLongForeignKey. Will be removed in 2.5")
class LongMappedMapper[T<:Mapper[T], O<:KeyedMapper[Long,O]](theOwner: T, foreign: => KeyedMetaMapper[Long, O])
  extends MappedLongForeignKey[T,O](theOwner, foreign) with LongMappedForeignMapper[T,O]


@deprecated("Functionality folded into MappedForeignKey, so just use MappedLongForeignKey. Will be removed in 2.5")
trait LongMappedForeignMapper[T<:Mapper[T],O<:KeyedMapper[Long,O]]
                              extends MappedLongForeignKey[T,O]


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 foreignMeta = _foreignMeta

  @deprecated("Use 'box' instead")
  def can: Box[Long] = if (defined_?) Full(is) else Empty

  def box: Box[Long] = if (defined_?) Full(is) else Empty

  type KeyType = Long
  type KeyedForeignType = O
  type OwnerType = T

  override def jdbcFriendly(field : String) = if (defined_?) new java.lang.Long(i_is_!) else null
  override def jdbcFriendly = if (defined_?) new java.lang.Long(i_is_!) else null

  lazy val dbKeyToTable: KeyedMetaMapper[Long, O] = foreignMeta

  def dbKeyToColumn = dbKeyToTable.primaryKeyField

  override def dbIndexed_? = true

  override def dbForeignKey_? = true


  def asSafeJs(obs: Box[KeyObfuscator]): JsExp =
  obs.map(o => JE.Str(o.obscure(dbKeyToTable, is))).openOr(JE.Num(is))

  override def asJsExp: JsExp = if (defined_?) super.asJsExp else JE.JsNull

  override def asJsonValue: Box[JsonAST.JValue] =
    if (defined_?) super.asJsonValue else Full(JsonAST.JNull)

  override def setFromAny(in: Any): Long =
  in match {
    case JsonAST.JNull => this.set(0L)
    case JsonAST.JInt(bigint) => this.set(bigint.longValue)
    case o => super.setFromAny(o)
  }

  /**
   * Called when Schemifier adds a foreign key.  Return a function that will be called when Schemifier
   * is done with the schemification.
   */
  def dbAddedForeignKey: Box[() => Unit] = Empty

  override def toString = if (defined_?) super.toString else "NULL"

  def findFor(key: KeyType): List[OwnerType] = theOwner.getSingleton.findAll(By(this, key))

  def findFor(key: KeyedForeignType): List[OwnerType] = theOwner.getSingleton.findAll(By(this, key))

  // def +(in: Long): Long = is + in

  /**
   * Given the driver type, return the string required to create the column in the database
   */
  override def fieldCreatorString(dbType: DriverType, colName: String): String = colName + " " + dbType.longForeignKeyColumnType  + notNullAppender()

}

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

  type KeyType = String
  type KeyedForeignType = O
  type OwnerType = T

  override def jdbcFriendly(field: String) = i_is_!
  override def jdbcFriendly = i_is_!

  def dbKeyToTable: KeyedMetaMapper[String, O] = foreign
  def dbKeyToColumn = dbKeyToTable.primaryKeyField

  override def dbIndexed_? = true

  override def dbForeignKey_? = true

  def asSafeJs(obs: Box[KeyObfuscator]): JsExp =
    obs.map(o => JE.Str(o.obscure(dbKeyToTable, is))).openOr(JE.Str(is))

  /**
   * Called when Schemifier adds a foreign key.  Return a function that will be called when Schemifier
   * is done with the schemification.
   */
  def dbAddedForeignKey: Box[() => Unit] = Empty

  override def toString = if (defined_?) super.toString else "NULL"

  def set(v: Box[O]): T = {
    val toSet: String = v match {
      case Full(i) => i.primaryKeyField.is
      case _ => null
    }

    this(toSet)
  }

  def findFor(key: KeyType): List[OwnerType] = fieldOwner.getSingleton.findAll(By(this, key))

  def findFor(key: KeyedForeignType): List[OwnerType] = fieldOwner.getSingleton.findAll(By(this, key))

  /**
   * Given the driver type, return the string required to create the column in the database
   */
  // defect 79 override def fieldCreatorString(dbType: DriverType, colName: String): String = colName + " " + dbType.longForeignKeyColumnType

}

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework MappedForeignKey.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.