how to do polymorphic relations in lift? - scala

I am new to Lift and scala and trying to do some stuff.
in the moment i want to create polymorphic associations with the lift
mapper.
here one example:
i want to create a class Entry what can be an entry in any of the n
ListX objects. How can i accomplish to let parent and entries be
polymorphic?
Is there a generic Way to to these polymorphic associations with
OneToMany & ManyToMany in both directions?
class Entry extends BaseModel[Entry] {
def getSingleton = Entry
object parent extends MappedBase(this, AnyList)
}
object Entry extends Entry with LongKeyedMetaMapper[Entry] {
}
class ListA extends BaseModel[ListA] with OneToMany[Long, ListA] {
def getSingleton = ListA
object entries extends MappedOneToMany(Entry, Entry.parent)
}
object ListA extends ListA with LongKeyedMetaMapper[ListA] {
}
class ListB extends BaseModel[ListB] with OneToMany[Long, ListB] {
def getSingleton = ListB
object entries extends MappedOneToMany(Entry, Entry.parent)
}
object ListB extends ListB with LongKeyedMetaMapper[ListB] {
}
class ListC extends BaseModel[ListC] with OneToMany[Long, ListC] {
def getSingleton = ListC
object entries extends MappedOneToMany(Entry, Entry.parent)
}
object ListC extends ListC with LongKeyedMetaMapper[ListC] {
}

Related

scala create dynamic factory based on trait inheritance

I have several classes which extends a trait.
I created a factory method that uses pattern matching in order to instantiate the relevant class.
The problem is that whenever I create a new class that extend this trait I need to add it to the factory method manually.
is there an option to create the list of classes dynamically from all the classes available?
Thanks
some code examples:
current implementation :
object Test {
trait Parent
object Parent{
def apply(classType:String): Parent = classType match {
case "A" => new A
case "B" => new B
case "C" => new C
}
}
class A extends Parent
class B extends Parent
class C extends Parent
}
wanted behaviour:
object Test {
trait Parent
object Parent{
def apply(classType:String): Parent = SomeFunction(ClassType)
}
}
class A extends Parent
class B extends Parent
class C extends Parent
}
Using reflection get all the classes that extend this trait
get relevant classes and add them to list.
Alternatively you can create a Map which can help locate classes by some key
Code
package demo
trait Animal {
}
class Dog extends Animal
class Cat extends Animal
library used org.clapper" %% "classutil" % "1.0.11"
import org.clapper.classutil.{ClassFinder, ClassInfo}
object Main {
def main(args: Array[String]): Unit = {
val finder = ClassFinder()
val classes = ClassFinder.classInfoMap(finder.getClasses().iterator)
val impl = find("demo.Animal", classes)
impl.foreach(println)
}
def find(ancestor: String, classes: Map[String, ClassInfo]): List[ClassInfo] =
classes.get(ancestor).fold(List.empty[ClassInfo]) { ancestorInfo =>
val ancestorName = ancestorInfo.name
def compare(info: ClassInfo): Boolean =
info.name == ancestorName ||
(info.superClassName :: info.interfaces).exists {
n => classes.get(n).exists(compare)
}
val it = classes.valuesIterator
it.filter { info => info.isConcrete && compare(info) } .toList
}
}
output
demo.Dog
demo.Cat
note that most of the code is taken from this post and changed to suite current purpose Get all the classes that implments a trait in Scala using reflection

Scala: Getting the clean class name

Upon digging it seems this is a sensitive issue.
class TestNames {
private[this] lazy val _name: String = this.getClass.getName.split("\\.").last
def name: String = _name
}
class Parent extends TestNames
class Parent2 extends Parent
class ClassNameExtraction extends FlatSpec {
it should "correctly extract the table name" in {
object TestNames extends TestNames
assert(TestNames.name === "TestNames")
}
it should "correctly extract the parent name" in {
object Parent extends Parent
assert(Parent.name === "Parent")
}
it should "correctly extract the column names" in {
object Parent2 extends Parent2
assert((Parent2.name === "Parent2"))
}
}
I can see there is a simple pattern: $$annonfun$number$ + ACTUAL_CLASS_NAME + $number$.
Is there a simpler way of doing this?
Update:
Got something working without inheritance:
import scala.reflect.ClassTag
class SomeClass {
private[this] lazy val _name: String = implicitly[ClassTag[this.type]].runtimeClass.getSimpleName
def name: String = _name
}
However this returns the same name in sub classes:
class SomeOtherClass extends SomeClass {}
object SomeOtherClass extends SomeOtherClass
SomeOtherClass.name// is still SomeClass
There is an issue:
https://issues.scala-lang.org/browse/SI-2034
Do you need a class per se or a type name? Because that's what reflection is for.
The policy is not to discuss religion, politics or name mangling.

Scala - a type-parametrized trait method returning a type-parametrized object - how to implement?

I have the following class hierarchy:
trait Entity {
type E <: Entity
type S <: Something[E]
def in: S
}
trait Something[E <: Entity] {
def doSomething {
// something
}
}
class A extends Entity {
def in = InA
object InA extends Something[A]
}
class B extends Entity {
def in = InB
object InB extends Something[B]
}
class C extends Entity {
def in = InC
object InC extends Something[C]
}
and somewhere else I want to:
val entities = Seq[Entity]
entities.map(_.in.doSomething)
however, the type system does not let me get away with that in method definition - I just can't figure out what types should I specify there for the piece of code to work?
It works if you override the type members like this. Scala does not infer them automatically.
class A extends Entity {
type E = A
type S = Something[A]
def in = InA
object InA extends Something[A]
}
class B extends Entity {
type E = B
type S = Something[B]
def in = InB
object InB extends Something[B]
}
class C extends Entity {
type E = C
type S = Something[C]
def in = InC
object InC extends Something[C]
}
Another option would be to do away with type members and only use type parameters.
trait Entity[E <: Entity[E]] {
def in: Something[E]
}
trait Something[E <: Entity[E]] {
def doSomething {
// something
}
}
class A extends Entity[A] {
def in = InA
object InA extends Something[A]
}
class B extends Entity[B] {
def in = InB
object InB extends Something[B]
}
class C extends Entity[C] {
def in = InC
object InC extends Something[C]
}
val entities = Seq[Entity[_]]()
entities.map(_.in.doSomething)
This uses a technique called F-bounded polymorphism.

How to determine if `this` is an instance of a class or an object?

Suppose I have two descendants of an abstract class:
object Child1 extends MyAbstrClass {
...
}
class Child2 extends MyAbstrClass {
}
Now I'd like to determine (preferably in the constructor of MyAbstrClass) if the instance being created is an object or something created by new:
abstract class MyAbstrClass {
{
if (/* is this an object? */) {
// do something
} else {
// no, a class instance, do something else
}
}
}
Is anything like that possible in Scala? My idea is to collect all objects that descend from a class into a collection, but only object, not instances created by new.
Something like:
package objonly
/** There's nothing like a downvote to make you not want to help out on SO. */
abstract class AbsFoo {
println(s"I'm a ${getClass}")
if (isObj) {
println("Object")
} else {
println("Mere Instance")
}
def isObj: Boolean = isObjReflectively
def isObjDirty = getClass.getName.endsWith("$")
import scala.reflect.runtime.{ currentMirror => cm }
def isObjReflectively = cm.reflect(this).symbol.isModuleClass
}
object Foo1 extends AbsFoo
class Foo2 extends AbsFoo
object Test extends App {
val foob = new Foo2
val fooz = new AbsFoo { }
val f = Foo1
}
Here's a rather cheesy idea:
trait X {
println("A singleton? " + getClass.getName.endsWith("$"))
}
object Y extends X
Y // objects are lazily initialised! this enforces it
class Z extends X
new Z

How to create Composite-key for a Model in lift's mapper?

Does mapper allows creation of composite key in Models ? If yes, kindly give an example.
This is one example:
class FooBar extends LongKeyedMapper[FooBar] {
def getSingleton = FooBar
def primaryKeyField = id
object id extends MappedLongIndex(this)
object foo extends MappedLongForeignKey(this, Foo)
object bar extends MappedLongForeignKey(this, Bar)
}
object FooBar extends FooBar with LogKeyedMetaMapper[FooBar] {
override def dbIndexes = Index(foo, bar) :: super.dbIndexes
}
Example taken from the Lift mailing list