--- a/src/main/scala/fis/base/model/BaseSchema.scala Fri Feb 10 09:53:04 2012 +0100
+++ b/src/main/scala/fis/base/model/BaseSchema.scala Fri Feb 10 09:53:05 2012 +0100
@@ -15,22 +15,70 @@
*/
package fis.base.model
-import org.squeryl.{Schema, Table}
import net.liftweb.squerylrecord.RecordTypeMode._
+import net.liftweb.util.Helpers.{snakify, tryo}
+import org.squeryl.{Schema, Session, Table}
+import org.squeryl.internals.StatementWriter
+import scala.collection.mutable.ListBuffer
trait BaseSchema extends Schema {
- val codeListItems = entityTable[CodeListItem]
+ val entityTableName = "entity"
+ val entities = new Table[EntityUnion](entityTableName) {
+ val tables = new ListBuffer[String]
+ }
+
+ val codeListItems = entityTable[CodeListItem]("code_list_item")
+
+ override def tableNameFromClass(c: Class[_]): String =
+ snakify(c.getSimpleName)
+
+ protected def entityTable[T <: Entity[_]](name: String)(implicit manifestT:
+ Manifest[T]): Table[T] = {
+
+ val tbl = table(name)(manifestT)
+ on(tbl) { t => declare(t.id.is(autoIncremented("entity_id_seq"))) }
+ entities.tables += name
+ tbl
+ }
- protected def entityTable[T <: Entity[_]]()(implicit manifestT: Manifest[T]):
- Table[T] = {
+ override def create = {
+ table[EntityUnion](entityTableName) // register entity table as the last one
+ super.create
+ }
- val tbl = table()
- on(tbl) { t => declare(t.id.is(autoIncremented("entity_id_seq"))) }
- tbl
+ override protected def drop = {
+ val dba = Session.currentSession.databaseAdapter
+ val sw = new StatementWriter(dba)
+ sw.write("drop view " + entityTableName + " cascade")
+ ex(sw)
+ super.drop
+ }
+
+ private def ex(sw: StatementWriter) = {
+ val sql = sw.statement
+ val cs = Session.currentSession
+ cs.log(sql)
+ val s = cs.connection.createStatement
+ tryo { s.execute(sql) }
+ tryo { s.close }
}
}
object BaseSchema extends BaseSchema
+class EntityViewH2Adapter extends SeqIdH2Adapter {
+ override def writeCreateTable[T](t: Table[T], sw: StatementWriter,
+ schema: Schema) = schema match {
+ case sch: BaseSchema if t.name == sch.entityTableName =>
+ sw.write("create view " + t.name + " as ")
+ val it = sch.entities.tables.iterator
+ while (it.hasNext) {
+ sw.write("select id, name, note from " + it.next)
+ if (it.hasNext)
+ sw.write(" union ")
+ }
+ case _ => super.writeCreateTable(t, sw, schema)
+ }
+}
// vim: set ts=2 sw=2 et:
--- a/src/main/scala/fis/base/model/Entity.scala Fri Feb 10 09:53:04 2012 +0100
+++ b/src/main/scala/fis/base/model/Entity.scala Fri Feb 10 09:53:05 2012 +0100
@@ -15,7 +15,7 @@
*/
package fis.base.model
-import net.liftweb.record.Record
+import net.liftweb.record.{MetaRecord, Record}
import net.liftweb.record.field._
import net.liftweb.squerylrecord.KeyedRecord
import org.squeryl.annotations.Column
@@ -54,6 +54,18 @@
def entity: T
}
+class EntityUnion private() extends Record[EntityUnion] with
+ Entity[EntityUnion] {
+ def meta = EntityUnion
+ //val entityType = new LongField(this)
+}
+
+object EntityUnion extends EntityUnion with MetaRecord[EntityUnion] with
+ MetaEntity[EntityUnion] {
+
+ def getTable = BaseSchema.entities
+}
+
/**
* Converter interface mixin.
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/fis/crm/model/Contact.scala Fri Feb 10 09:53:05 2012 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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 fis.crm.model
+
+import fis.base.model.{Entity, MetaEntity}
+import net.liftweb.record.{MetaRecord, Record}
+import net.liftweb.record.field._
+
+class Contact private() extends Record[Contact] with Entity[Contact] {
+
+ def meta = Contact
+
+ val firstName = new StringField(this, 80, "")
+ val lastName = new StringField(this, 80, "")
+ val position = new OptionalStringField(this, 40)
+ val workMail = new EmailField(this, 256)
+ val privateMail = new OptionalEmailField(this, 256)
+ val otherMail = new OptionalEmailField(this, 256)
+ val workMobile = new StringField(this, 40)
+ val privateMobile = new OptionalStringField(this, 40)
+ val otherMobile = new OptionalStringField(this, 40)
+ val workPhone = new OptionalStringField(this, 40)
+ val privatePhone = new OptionalStringField(this, 40)
+ val fax = new OptionalStringField(this, 40)
+
+ override def linkName = lastName.get + " " + firstName.get
+
+ lazy val entities = CrmSchema.entityContacts.right(this)
+}
+
+object Contact extends Contact with MetaRecord[Contact] with
+ MetaEntity[Contact] {
+
+ def getTable = CrmSchema.contacts
+}
+
+import org.squeryl.KeyedEntity
+import org.squeryl.dsl.CompositeKey3
+
+case class EntityContact(val entityId: Long, val contactId: Long,
+ val typeId: Long) extends KeyedEntity[CompositeKey3[Long, Long, Long]] {
+
+ def id = CompositeKey3(entityId, contactId, typeId)
+
+ lazy val contactType =
+ CrmSchema.contactTypeToEntityContacts.rightStateful(this)
+}
+
+// vim: set ts=2 sw=2 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/scala/fis/crm/model/CrmSchema.scala Fri Feb 10 09:53:05 2012 +0100
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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 fis.crm.model
+
+import fis.base.model.BaseSchema
+import net.liftweb.squerylrecord.RecordTypeMode._
+
+trait CrmSchema extends BaseSchema {
+
+ val contacts = entityTable[Contact]("contact")
+
+ val entityContacts = manyToManyRelation(entities, contacts).
+ via[EntityContact]((e, c, ec) => (
+ e.id === ec.entityId,
+ c.id === ec.contactId
+ ))
+
+ entityContacts.leftForeignKeyDeclaration.unConstrainReference
+
+ val contactTypeToEntityContacts = oneToManyRelation(codeListItems,
+ entityContacts).via((cli, ec) => cli.id === ec.typeId)
+}
+
+object CrmSchema extends CrmSchema
+
+// vim: set ts=2 sw=2 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/scala/fis/base/model/AbstractTest.scala Fri Feb 10 09:53:05 2012 +0100
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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 fis.base.model
+
+import net.liftweb.common._
+import net.liftweb.mapper.DB
+import net.liftweb.squerylrecord.SquerylRecord
+import org.scalatest._
+import org.scalatest.matchers.ShouldMatchers
+
+abstract class AbstractTest extends FlatSpec with ShouldMatchers with Logger
+ with BeforeAndAfterEach with BeforeAndAfterAll {
+
+ val db = this.getClass.getSimpleName
+ val h2vendor = H2Vendor(db)
+ val ci = TestConnectionIdentifier(db)
+
+ override def beforeAll() {
+ beforeEach()
+ }
+
+ override def beforeEach() {
+ super.beforeEach
+ DB.defineConnectionManager(ci, h2vendor)
+ SquerylRecord.init(() => new EntityViewH2Adapter)
+ }
+
+ override def afterEach() {
+ h2vendor.closeAllConnections_!
+ }
+
+ def doInDB(block: => Any) {
+ DB.use(ci) { _ => block }
+ }
+
+}
+
+import org.squeryl.Schema
+
+trait DropAndCreate { self: Schema =>
+ def dropAndCreate {
+ drop
+ create
+ }
+}
+
+
+// vim: set ts=2 sw=2 et:
--- a/src/test/scala/fis/base/model/CodeListSpec.scala Fri Feb 10 09:53:04 2012 +0100
+++ b/src/test/scala/fis/base/model/CodeListSpec.scala Fri Feb 10 09:53:05 2012 +0100
@@ -17,23 +17,16 @@
import net.liftweb.common._
import org.scalatest._
-import org.scalatest.matchers.ShouldMatchers
-class CodeListSpec extends FlatSpec with ShouldMatchers with Logger
- with BeforeAndAfterAllFunctions {
+class CodeListSpec extends AbstractTest {
- import net.liftweb.mapper.{DB, DefaultConnectionIdentifier, StandardDBVendor}
import net.liftweb.squerylrecord.RecordTypeMode._
import net.liftweb.squerylrecord.SquerylRecord
- import TestBaseSchema._
+ import BaseSchema._
- val dbVendor = new StandardDBVendor("org.h2.Driver",
- "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", Empty, Empty)
- DB.defineConnectionManager(DefaultConnectionIdentifier, dbVendor)
- SquerylRecord.init(() => new SeqIdH2Adapter)
-
- beforeAll {
- doInDB { dropAndCreate }
+ override def beforeAll {
+ super.beforeAll
+ doInDB { schema.dropAndCreate }
}
"CodeListItem" should "create/retrieve item" in {
@@ -50,16 +43,7 @@
}
}
- def doInDB(block: => Any) {
- DB.use(DefaultConnectionIdentifier) { _ => block }
- }
-}
-
-object TestBaseSchema extends BaseSchema {
- def dropAndCreate {
- drop
- create
- }
+ object schema extends BaseSchema with DropAndCreate
}
// vim: set ts=2 sw=2 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/scala/fis/base/model/H2Vendor.scala Fri Feb 10 09:53:05 2012 +0100
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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 fis.base.model
+
+import net.liftweb.common._
+import net.liftweb.mapper.ConnectionIdentifier
+import net.tz.lift.util.StandardDBVendor
+
+case class H2Vendor(val db: String) extends StandardDBVendor("org.h2.Driver",
+ "jdbc:h2:mem:"+ db + ";DB_CLOSE_DELAY=-1", Empty, Empty)
+
+case class TestConnectionIdentifier(val jndiName: String) extends
+ ConnectionIdentifier
+
+// vim: set ts=2 sw=2 et:
--- a/src/test/scala/fis/base/model/SeqIdPostgreSqlAdapterSpec.scala Fri Feb 10 09:53:04 2012 +0100
+++ b/src/test/scala/fis/base/model/SeqIdPostgreSqlAdapterSpec.scala Fri Feb 10 09:53:05 2012 +0100
@@ -23,7 +23,7 @@
with Logger with BeforeAndAfterAllFunctions {
import java.sql.Connection
- import net.liftweb.mapper.{DB, DefaultConnectionIdentifier}
+ import net.liftweb.mapper.DB
import net.liftweb.squerylrecord.SquerylRecord
import net.tz.lift.util.StandardDBVendor
import org.squeryl.PrimitiveTypeMode._
@@ -36,7 +36,7 @@
c.prepareStatement(testQuery).executeQuery
}
}
- DB.defineConnectionManager(DefaultConnectionIdentifier, dbVendor)
+ DB.defineConnectionManager(PgsqlConnectionIdentifier, dbVendor)
SquerylRecord.init(() => new SeqIdPostgreSqlAdapter)
beforeAll {
@@ -70,13 +70,19 @@
}
def doInDB(block: => Any) {
- DB.use(DefaultConnectionIdentifier) { c =>
+ DB.use(PgsqlConnectionIdentifier) { c =>
block
c.commit
}
}
}
+import net.liftweb.db.ConnectionIdentifier
+
+case object PgsqlConnectionIdentifier extends ConnectionIdentifier {
+ val jndiName = "pgsql"
+}
+
import org.squeryl.{KeyedEntity, Schema}
import org.squeryl.PrimitiveTypeMode._
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/scala/fis/crm/model/ContactSpec.scala Fri Feb 10 09:53:05 2012 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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 fis.crm.model
+
+import fis.base.model._
+import net.liftweb.common._
+import net.liftweb.util._
+import net.liftweb.util.Helpers._
+import org.scalatest._
+
+class ContactSpec extends AbstractTest {
+ import CrmSchema._
+
+ override def beforeAll() {
+ super.beforeAll
+ doInDB { schema.dropAndCreate }
+ }
+
+ "EntityContact" should "create" in { doInDB {
+ val c1 = Contact.createRecord.name("c1")
+ contacts.insert(c1)
+ val t1 = CodeListItem.createRecord.name("t1")
+ codeListItems.insert(t1)
+ val c2 = Contact.createRecord.name("c2") // acts here as entity
+ contacts.insert(c2)
+ entityContacts.insert(EntityContact(c2.id, c1.id, t1.id))
+
+ val el1 = c1.entities.toList
+ el1.size should equal (1)
+ el1.head.id should equal (c2.id)
+ el1.head.name.get should equal ("c2")
+ val al1 = c1.entities.associations.toList
+ al1.size should equal (1)
+ al1.head.contactType.one should equal (Some(t1))
+ }}
+
+ object schema extends CrmSchema with DropAndCreate
+
+}
+
+// vim: set ts=2 sw=2 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/scala/fis/crm/model/CrmSchemaSpec.scala Fri Feb 10 09:53:05 2012 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 Tomas Zeman <tzeman@volny.cz>
+ *
+ * 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 fis.crm.model
+
+import fis.base.model._
+import net.liftweb.common._
+import net.liftweb.util._
+import net.liftweb.util.Helpers._
+
+class CrmSchemaSpec extends AbstractTest {
+
+ "CrmSchema" should "create" in { doInDB {
+ schema.dropAndCreate
+ }}
+
+ object schema extends CrmSchema with DropAndCreate
+
+}
+
+
+
+// vim: set ts=2 sw=2 et: