#48 : worked on Manifests

This commit is contained in:
Timo Westkämper 2011-11-30 00:36:19 +02:00
parent 4bfad1096c
commit fece4c141b
13 changed files with 130 additions and 47 deletions

Binary file not shown.

View File

@ -129,17 +129,15 @@ class ScalaEntitySerializer @Inject()(val typeMappings: TypeMappings) extends Se
case LIST | SET | COLLECTION => {
val componentType = writer.getGenericName(true, property.getParameter(0))
val queryType = typeMappings.getPathType(getRaw(property.getParameter(0)), model, false)
methodName + "(\"" + property.getName + "\", classOf[" + componentType + "], classOf[" +
writer.getGenericName(true, queryType) + "])"
methodName + "["+componentType+","+writer.getGenericName(true, queryType)+"](\"" + property.getName + "\")"
}
case MAP => {
val keyType = writer.getGenericName(true, property.getParameter(0))
val valueType = writer.getGenericName(true, property.getParameter(1))
val queryType = typeMappings.getPathType(getRaw(property.getParameter(1)), model, false)
methodName + "(\"" + property.getName + "\", classOf[" + keyType + "], classOf[" + valueType + "], classOf[" +
writer.getGenericName(true, queryType) + "])"
methodName + "["+keyType+","+valueType+","+writer.getGenericName(true, queryType)+"](\"" + property.getName + "\")"
}
case _ => methodName + "(\"" + property.getName + "\", classOf[" + writer.getRawName(property.getType) + "])"
case _ => methodName + "[" + writer.getRawName(property.getType) + "](\"" + property.getName + "\")"
}
(property.getEscapedName, value)
}

View File

@ -6,6 +6,7 @@ import com.mysema.query.codegen._;
import com.mysema.codegen.model.TypeCategory
import com.mysema.scala.ManifestUtils._
import TypeDefs._
/**
@ -17,7 +18,7 @@ import TypeDefs._
object Paths {
type Metadata[X] = PathMetadata[X]
def array[T <: Array[_]](t: Class[T], md: Metadata[_]) = new ArrayPath[T](t, md)
def simple[T](t: Class[_ <: T], md: Metadata[_]) = new SimplePath[T](t, md)
@ -76,40 +77,42 @@ class ArrayPath[T <: Array[_]](t: Class[T], md: PathMetadata[_])
class BeanPath[T](t: Class[_ <: T], md: PathMetadata[_])
extends PathImpl[T](t, md) with SimpleExpression[T] {
import Paths._
type Mf[X] = Manifest[X]
def add[P <: Path[_]](path: P): P = path
def createArray[T <: Array[_]](property: String, t: Class[T]) = add(array(t, forProperty(property)))
def createArray[T <: Array[_]](property: String)(implicit mf: Mf[T]) = add(array(mf, forProperty(property)))
def createSimple[T](property: String, t: Class[T]) = add(simple(t, forProperty(property)))
def createSimple[T](property: String)(implicit mf: Mf[T]) = add(simple(mf, forProperty(property)))
def createEntity[T](property: String, t: Class[T]) = add(entity(t, forProperty(property)))
def createEntity[T](property: String)(implicit mf: Mf[T]) = add(entity(t, forProperty(property)))
def createCollection[T, Q <: Ex[_ >: T]](property: String, t: Class[T], q: Class[Q]) = add(collection(t, q, forProperty(property)))
def createCollection[T, Q <: Ex[_ >: T]](property: String)(implicit t: Mf[T], q: Mf[Q]) = add(collection(t, q, forProperty(property)))
def createSet[T, Q <: Ex[_ >: T]](property: String, t: Class[T], q: Class[Q]) = add(set(t, q, forProperty(property)))
def createSet[T, Q <: Ex[_ >: T]](property: String)(implicit t: Mf[T], q: Mf[Q]) = add(set(t, q, forProperty(property)))
def createList[T, Q <: Ex[_ >: T]](property: String, t: Class[T], q: Class[Q]) = add(list(t, q, forProperty(property)))
def createList[T, Q <: Ex[_ >: T]](property: String)(implicit t: Mf[T], q: Mf[Q]) = add(list(t, q, forProperty(property)))
def createMap[K, V, Q <: Ex[_ >: V]](property: String, k: Class[K], v: Class[V], q: Class[Q]) = add(map(k, v, q, forProperty(property)))
def createMap[K, V, Q <: Ex[_ >: V]](property: String)(implicit k: Mf[K], v: Mf[V], q: Mf[Q]) = add(map(k, v, q, forProperty(property)))
def createComparable[T <: Comparable[_]](property: String, t: Class[T]) = add(comparable(t, forProperty(property)))
def createComparable[T <: Comparable[_]](property: String)(implicit mf: Mf[T]) = add(comparable(mf, forProperty(property)))
def createDate[T <: Comparable[_]](property: String, t: Class[T]) = add(date(t, forProperty(property)))
def createDate[T <: Comparable[_]](property: String)(implicit mf: Mf[T]) = add(date(mf, forProperty(property)))
def createDateTime[T <: Comparable[_]](property: String, t: Class[T]) = add(dateTime(t, forProperty(property)))
def createDateTime[T <: Comparable[_]](property: String)(implicit mf: Mf[T]) = add(dateTime(mf, forProperty(property)))
def createTime[T <: Comparable[_]](property: String, t: Class[T]) = add(time(t, forProperty(property)))
def createTime[T <: Comparable[_]](property: String)(implicit mf: Mf[T]) = add(time(mf, forProperty(property)))
def createNumber[T <: Number with Comparable[T]](property: String, t: Class[T]) = add(number(t, forProperty(property)))
def createNumber[T <: Number with Comparable[T]](property: String)(implicit mf: Mf[T]) = add(number(mf, forProperty(property)))
def createBoolean(property: String) = add(boolean(forProperty(property)))
def createString(property: String) = add(string(forProperty(property)))
def createEnum[T <: Enum[T]](property: String, t: Class[T]) = add(enum(t, forProperty(property)))
def createEnum[T <: Enum[T]](property: String)(implicit mf: Mf[T]) = add(enum(mf, forProperty(property)))
private def forProperty(property: String) = PathMetadataFactory.forProperty(this, property)

View File

@ -1,4 +1,6 @@
package com.mysema.query.scala.sql;
import com.mysema.scala.ReflectionUtils._
import com.mysema.query.scala.BeanPath
import com.mysema.query.sql._
import com.mysema.query.types._
@ -7,6 +9,7 @@ import java.util.ArrayList;
import java.lang.reflect._
import scala.reflect.BeanProperty
import com.mysema.query.scala.TypeDefs._
import scala.collection.JavaConversions.mapAsJavaMap
/**
* Implementation of RelationsPathImpl for Scala
@ -30,19 +33,18 @@ class RelationalPathImpl[T](md: PathMetadata[_], schema: String, table: String)(
@BeanProperty
val inverseForeignKeys: JList[ForeignKey[_]] = new ArrayList[ForeignKey[_]]
// TODO : implementation into Utility class
@BeanProperty
lazy val projection: FactoryExpression[T] = {
lazy val projection: FactoryExpression[T] = {
val rp = RelationalPathImpl.this
val bindings = new java.util.HashMap[String, Ex[_]]
def supers(cl: Class[_]): List[Class[_]] = cl :: Option(cl.getSuperclass).map(supers).getOrElse(Nil)
supers(getClass).flatMap(_.getDeclaredFields)
val bindings = getFields(getClass())
// only non static Path typed fields
.filter(f => classOf[Path[_]].isAssignableFrom(f.getType) && !Modifier.isStatic(f.getModifiers))
.foreach(f => {
f.setAccessible(true)
val col = f.get(rp).asInstanceOf[Path[_]]
if (rp == col.getMetadata.getParent) bindings.put(f.getName, col)
})
// map to property,value tuples
.map(f => getNameAndValue[Path[_]](rp,f))
// filter non related tuples out
.filter(rp == _._2.getMetadata.getParent)
.toMap
new QBean[T](getType.asInstanceOf[Class[T]], true, bindings)
}

View File

@ -11,6 +11,16 @@ import com.mysema.query.scala.TypeDefs._
import com.mysema.query.scala.RichProjectable
import com.mysema.query.scala.Projections._
/**
* RichSimpleQuery provides a simplied query DSL for Querydsl SQL + Scala
*
* @author tiwe
*
* @param <PT>
* @param <P>
* @param <T>
* @param <E>
*/
class RichSimpleQuery[PT, P <: RelationalPath[PT], T, E <: Ex[T]](path: P, expr: E, qry: SQLQuery)
extends RichProjectable(qry) {
@ -88,7 +98,7 @@ object ExprToTarget {
implicit def pathToTuple2[T,E <: RP[T],T2,E2 <: RP[T2]] = {
new ExprToTarget[T,E,T2,E2,(T,T2),Tu2Ex[T,T2]]() {
def toTarget(e: E, rp: E2) = new Tu2Ex[T,T2](e,rp)
def toTarget(e: E, rp: E2) = new Tu2Ex[T,T2](e, rp)
}}
implicit def tuple2ToTuple3[T1,E1 <: Ex[T1],T2,E2 <: Ex[T2],T3,E3 <: RP[T3]] = {
@ -96,6 +106,16 @@ object ExprToTarget {
def toTarget(e: Tu2Ex[T1,T2], rp: E3) = new Tu3Ex[T1,T2,T3](e(0), e(1), rp)
}}
implicit def tuple3ToTuple4[T1,E1 <: Ex[T1],T2,E2 <: Ex[T2],T3,E3 <: Ex[T3],T4,E4 <: RP[T4]] = {
new ExprToTarget[(T1,T2,T3),Tu3Ex[T1,T2,T3],T4,E4,(T1,T2,T3,T4),Tu4Ex[T1,T2,T3,T4]]() {
def toTarget(e: Tu3Ex[T1,T2,T3], rp: E4) = new Tu4Ex[T1,T2,T3,T4](e(0), e(1), e(2), rp)
}}
implicit def tuple4ToTuple5[T1,E1 <: Ex[T1],T2,E2 <: Ex[T2],T3,E3 <: Ex[T3],T4,E4 <: Ex[T4],T5,E5 <: RP[T5]] = {
new ExprToTarget[(T1,T2,T3,T4),Tu4Ex[T1,T2,T3,T4],T5,E5,(T1,T2,T3,T4,T5),Tu5Ex[T1,T2,T3,T4,T5]]() {
def toTarget(e: Tu4Ex[T1,T2,T3,T4], rp: E5) = new Tu5Ex[T1,T2,T3,T4,T5](e(0), e(1), e(2), e(3), rp)
}}
}
// combine E1 and E2 into E3

View File

@ -0,0 +1,11 @@
package com.mysema.scala
/**
* @author tiwe
*
*/
object ManifestUtils {
implicit def toClass[X](mf: Manifest[X]) = mf.erasure.asInstanceOf[Class[X]]
}

View File

@ -0,0 +1,31 @@
package com.mysema.scala;
import java.lang.reflect._
import javax.annotation.Nullable;
import scala.collection.mutable.ListBuffer
/**
* @author tiwe
*
*/
object ReflectionUtils {
def getSuperClasses(cl: Class[_]): List[Class[_]] = {
if (cl != null) Nil else cl :: getSuperClasses(cl.getSuperclass)
}
def getFields(cl: Class[_]): List[Field] = {
getSuperClasses(cl).flatMap(_.getDeclaredFields)
}
def getImplementedInterfaces(cl: Class[_]): Set[Class[_]] = {
getSuperClasses(cl).flatMap(_.getInterfaces).toSet
}
def getNameAndValue[T](o: AnyRef, field: Field): (String,T) = {
field.setAccessible(true)
val v = field.get(o).asInstanceOf[T]
(field.getName, v)
}
}

View File

@ -19,30 +19,30 @@ class QPerson(cl: Class[_ <: Person], md: PathMetadata[_]) extends EntityPathImp
lazy val other = new QPerson(this, "other")
val array = createArray("array", classOf[Array[String]])
val array = createArray[Array[String]]("array")
val firstName = createString("firstName")
val javaCollection = createCollection("javaCollection", classOf[String], classOf[StringPath])
val javaCollection = createCollection[String,StringPath]("javaCollection")
val javaDouble = createNumber("javaDouble", classOf[java.lang.Double])
val javaDouble = createNumber[java.lang.Double]("javaDouble")
val javaInt = createNumber("javaInt", classOf[Integer])
val javaInt = createNumber[Integer]("javaInt")
val javaList = createList("javaList", classOf[String], classOf[StringPath])
val javaList = createList[String,StringPath]("javaList")
val javaMap = createMap("javaMap", classOf[String], classOf[String], classOf[StringPath])
val javaMap = createMap[String,String,StringPath]("javaMap")
val javaSet = createSet("javaSet", classOf[String], classOf[StringPath])
val javaSet = createSet[String,StringPath]("javaSet")
val lastName = createString("lastName")
val listOfPersons = createList("listOfPersons", classOf[Person], classOf[QPerson])
val listOfPersons = createList[Person,QPerson]("listOfPersons")
val scalaInt = createNumber("scalaInt", classOf[Integer])
val scalaInt = createNumber[Integer]("scalaInt")
val scalaList = createList("scalaList", classOf[String], classOf[StringPath])
val scalaList = createList[String,StringPath]("scalaList")
val scalaMap = createMap("scalaMap", classOf[String], classOf[String], classOf[StringPath])
val scalaMap = createMap[String,String,StringPath]("scalaMap")
}

View File

@ -9,7 +9,7 @@ import Matchers._
class QPersonTest {
val person = QPerson as "person"
@Test
def EntityPath {
assertEquals("person.other.firstName", person.other.firstName)

View File

@ -0,0 +1,17 @@
package com.mysema.query.scala.sql
import org.junit._
import org.junit.Assert._
import com.mysema.query.sql._
import com.mysema.query.types._
import test._
class PathsTest {
@Test
def Projection {
val projection = Employee.getProjection.asInstanceOf[FactoryExpression[_]]
assertEquals(4, projection.getArgs.size)
}
}

View File

@ -3,6 +3,7 @@ package com.mysema.query.scala.sql
import org.junit._
import org.junit.Assert._
import com.mysema.query.sql._
import com.mysema.query.types._
import java.sql.Connection
import test._
@ -12,7 +13,7 @@ class QueriesTest extends SQLHelpers {
val templates = new H2Templates()
def connection: Connection = null
@Test
def From {
assertEquals("from EMPLOYEE employee", Employee.query.toString)

View File

@ -21,11 +21,11 @@ class QEmployee(md: PathMetadata[_]) extends RelationalPathImpl[Employee](md, "P
val firstname = createString("FIRSTNAME")
val id = createNumber("ID", classOf[Integer])
val id = createNumber[Integer]("ID")
val lastname = createString("LASTNAME")
val superiorId = createNumber("SUPERIOR_ID", classOf[Integer])
val superiorId = createNumber[Integer]("SUPERIOR_ID")
val sysIdx55: PrimaryKey[Employee] = createPrimaryKey(id);

View File

@ -18,7 +18,7 @@ class QSurvey(md: PathMetadata[_]) extends RelationalPathImpl[Survey](md, "PUBLI
def this(parent: Path[_], variable: String) = this(forProperty(parent, variable))
val id = createNumber("ID", classOf[Integer])
val id = createNumber[Integer]("ID")
val name = createString("NAME")