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

net.liftweb.mapper.HasManyThrough.scala Maven / Gradle / Ivy

The newest version!
/*
 * 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 util.FatLazy
import common._

import scala.collection.mutable

class HasManyThrough[From <: KeyedMapper[ThroughType, From],
                     To <: Mapper[To],
                     Through <: Mapper[Through],
                     ThroughType <: Any](
                      owner: From,
                      otherSingleton: MetaMapper[To],
                      through: MetaMapper[Through],
                      throughFromField: MappedField[ThroughType, Through],
                      throughToField: MappedField[ThroughType, Through])
  extends LifecycleCallbacks {
  private var theSetList: Seq[ThroughType] = Nil

  private val others = FatLazy[List[To]] {
    DB.use(owner.connectionIdentifier) { conn =>
      val query = "SELECT DISTINCT "+otherSingleton._dbTableNameLC+".* FROM "+otherSingleton._dbTableNameLC+","+
      through._dbTableNameLC+" WHERE "+
      otherSingleton._dbTableNameLC+"."+otherSingleton.indexedField(otherSingleton.asInstanceOf[To]).openOrThrowException("legacy code")._dbColumnNameLC+" = "+
      through._dbTableNameLC+"."+throughToField._dbColumnNameLC+" AND "+
      through._dbTableNameLC+"."+throughFromField._dbColumnNameLC+" = ?"
      DB.prepareStatement(query, conn) { st =>
        owner.getSingleton.indexedField(owner).map { indVal =>
          if (indVal.dbIgnoreSQLType_?)
            st.setObject(1, indVal.jdbcFriendly)
          else
            st.setObject(1, indVal.jdbcFriendly, indVal.targetSQLType)

          DB.exec(st) { rs =>
            otherSingleton.createInstances(owner.connectionIdentifier, rs, Empty, Empty)
          }
        } openOr Nil
      }
    }
  }

  def apply(): List[To] = others.get

  def get: List[To] = this()

  def reset(): Unit = others.reset

  def set(what: Seq[ThroughType]): Seq[ThroughType] = {
    theSetList = what
    theSetList
  }

  override def beforeDelete: Unit = {
    through.findAll(By(throughFromField, owner.primaryKeyField.get)).foreach {
      toDelete => toDelete.delete_!
    }
  }

  override def afterUpdate: Unit = {
    val current = through.findAll(By(throughFromField, owner.primaryKeyField.get))

    val newKeys = new mutable.HashSet[ThroughType]

    theSetList.foreach(i => newKeys += i)
    val toDelete = current.filter(c => !newKeys.contains(throughToField.actualField(c).get))
    toDelete.foreach(_.delete_!)

    val oldKeys = new mutable.HashSet[ThroughType]
    current.foreach(i => oldKeys += throughToField.actualField(i).get)

    theSetList.toList.distinct.filter(i => !oldKeys.contains(i)).foreach { i =>
      val toCreate = through.createInstance
      throughFromField.actualField(toCreate).set(owner.primaryKeyField.get)
      throughToField.actualField(toCreate).set(i)
      toCreate.save
    }

    theSetList = Nil
    others.reset
    super.afterUpdate
  }

  override def afterCreate: Unit = {
    theSetList.toList.distinct.foreach { i =>
      val toCreate = through.createInstance
      throughFromField.actualField(toCreate)(owner.primaryKeyField.get)
      throughToField.actualField(toCreate)(i)
      toCreate.save
    }
    theSetList = Nil
    others.reset
    super.afterCreate
  }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy