Skip to content

Commit

Permalink
Merge pull request #103 from frees-io/ff-issue-101-case-class-from-row
Browse files Browse the repository at this point in the history
Adds the code for creating case classes from rows
  • Loading branch information
Francisco Pérez Paradas committed Oct 24, 2017
2 parents 4bd7631 + c4ed44a commit 3f86761
Show file tree
Hide file tree
Showing 8 changed files with 322 additions and 116 deletions.
82 changes: 0 additions & 82 deletions core/src/main/scala/mapper/package.scala

This file was deleted.

57 changes: 57 additions & 0 deletions core/src/main/scala/query/FieldLister.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
*
* 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 freestyle.cassandra
package query

import shapeless._
import shapeless.labelled.FieldType

trait FieldLister[A] {
val list: List[String]
}

trait FieldListerPrimitive {
implicit def primitiveFieldLister[K <: Symbol, H, T <: HList](
implicit witness: Witness.Aux[K],
tLister: FieldLister[T]): FieldLister[FieldType[K, H] :: T] =
FieldLister[FieldType[K, H] :: T](witness.value.name :: tLister.list)
}

trait FieldListerGeneric extends FieldListerPrimitive {

implicit def genericLister[A, R](
implicit gen: LabelledGeneric.Aux[A, R],
lister: Lazy[FieldLister[R]]): FieldLister[A] = FieldLister[A](lister.value.list)

implicit val hnilLister: FieldLister[HNil] = FieldLister[HNil](Nil)

}

object FieldLister extends FieldListerGeneric {
def apply[A](l: List[String]): FieldLister[A] = new FieldLister[A] {
override val list: List[String] = l
}
}

object FieldListerExpanded extends FieldListerGeneric {

implicit def hconsLister[K, H, T <: HList](
implicit hLister: Lazy[FieldLister[H]],
tLister: FieldLister[T]): FieldLister[FieldType[K, H] :: T] =
FieldLister[FieldType[K, H] :: T](hLister.value.list ++ tLister.list)

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

package freestyle.cassandra
package mapper
package query.mapper

trait ByteBufferMapper[A] {
def map(a: A): List[FieldMapper]
Expand Down
66 changes: 66 additions & 0 deletions core/src/main/scala/query/mapper/ByteBufferToField.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
*
* 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 freestyle.cassandra
package query.mapper

import cats.MonadError
import freestyle.cassandra.codecs.ByteBufferCodec
import freestyle.cassandra.query._
import shapeless._
import shapeless.labelled.{FieldBuilder, FieldType}
import shapeless.{::, HList, Witness}

trait FromReader[A] {
def apply[M[_]](reader: ByteBufferReader)(implicit ME: MonadError[M, Throwable]): M[A]
}

trait GenericFromReader {

implicit val hnilFromReader: FromReader[HNil] = new FromReader[HNil] {
override def apply[M[_]](reader: ByteBufferReader)(
implicit ME: MonadError[M, Throwable]): M[HNil] = ME.pure(HNil)
}

implicit def hconsFromReader[K <: Symbol, V, L <: HList](
implicit
witness: Witness.Aux[K],
codec: ByteBufferCodec[V],
grT: FromReader[L],
printer: Printer): FromReader[FieldType[K, V] :: L] =
new FromReader[FieldType[K, V] :: L] {
override def apply[M[_]](reader: ByteBufferReader)(
implicit ME: MonadError[M, Throwable]): M[FieldType[K, V] :: L] = {
val newName = printer.print(witness.value.name)
ME.flatMap(reader.read(newName)) { byteBuffer =>
ME.map2(codec.deserialize(byteBuffer), grT(reader)) {
case (result, l) => new FieldBuilder[K].apply(result) :: l
}
}
}
}

implicit def productFromReader[A, L <: HList](
implicit
gen: LabelledGeneric.Aux[A, L],
grL: FromReader[L]): FromReader[A] =
new FromReader[A] {
override def apply[M[_]](reader: ByteBufferReader)(
implicit ME: MonadError[M, Throwable]): M[A] = ME.map(grL(reader))(gen.from)
}
}

object GenericFromReader extends GenericFromReader
75 changes: 75 additions & 0 deletions core/src/main/scala/query/mapper/FieldToByteBuffer.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright 2017 47 Degrees, LLC. <http://www.47deg.com>
*
* 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 freestyle.cassandra
package query.mapper

import java.nio.ByteBuffer

import cats.MonadError
import freestyle.cassandra.codecs.ByteBufferCodec
import shapeless._
import shapeless.labelled.FieldType

abstract class FieldMapper(val name: String) {
def serialize[M[_]](implicit E: MonadError[M, Throwable]): M[ByteBuffer]
}

trait FieldListMapper[A] {
def map(a: A): List[FieldMapper]
}

trait FieldMapperPrimitive {

implicit def primitiveFieldMapper[K <: Symbol, H, T <: HList](
implicit witness: Witness.Aux[K],
codec: Lazy[ByteBufferCodec[H]],
tMapper: FieldListMapper[T]): FieldListMapper[FieldType[K, H] :: T] = {
val fieldName = witness.value.name
FieldListMapper { hlist =>
val fieldMapper = new FieldMapper(fieldName) {
override def serialize[M[_]](implicit E: MonadError[M, Throwable]): M[ByteBuffer] =
codec.value.serialize(hlist.head)
}
fieldMapper :: tMapper.map(hlist.tail)
}
}
}

trait FieldMapperGeneric extends FieldMapperPrimitive {

implicit def genericMapper[A, R](
implicit gen: LabelledGeneric.Aux[A, R],
mapper: Lazy[FieldListMapper[R]]): FieldListMapper[A] =
FieldListMapper(value => mapper.value.map(gen.to(value)))

implicit val hnilMapper: FieldListMapper[HNil] = FieldListMapper[HNil](_ => Nil)

}

object FieldListMapper extends FieldMapperGeneric {
def apply[A](f: (A) => List[FieldMapper]): FieldListMapper[A] = new FieldListMapper[A] {
override def map(a: A): List[FieldMapper] = f(a)
}
}

object FieldMapperExpanded extends FieldMapperGeneric {

implicit def hconsMapper[K, H, T <: HList](
implicit hMapper: Lazy[FieldListMapper[H]],
tMapper: FieldListMapper[T]): FieldListMapper[FieldType[K, H] :: T] =
FieldListMapper(hlist => hMapper.value.map(hlist.head) ++ tMapper.map(hlist.tail))
}
45 changes: 13 additions & 32 deletions core/src/main/scala/query/query.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,30 @@

package freestyle.cassandra

import shapeless._
import shapeless.labelled.FieldType
import java.nio.ByteBuffer

import cats.MonadError

package object query {

trait FieldLister[A] {
val list: List[String]
trait ByteBufferReader {
def read[M[_]](name: String)(implicit ME: MonadError[M, Throwable]): M[ByteBuffer]
}

trait FieldListerPrimitive {
implicit def primitiveFieldLister[K <: Symbol, H, T <: HList](
implicit witness: Witness.Aux[K],
tLister: FieldLister[T]): FieldLister[FieldType[K, H] :: T] =
new FieldLister[FieldType[K, H] :: T] {
override val list: List[String] = witness.value.name :: tLister.list
}
trait Printer {
def print(name: String): String
}

trait FieldListerGeneric extends FieldListerPrimitive {

implicit def genericLister[A, R](
implicit gen: LabelledGeneric.Aux[A, R],
lister: Lazy[FieldLister[R]]): FieldLister[A] = new FieldLister[A] {
override val list: List[String] = lister.value.list
}

implicit val hnilLister: FieldLister[HNil] = new FieldLister[HNil] {
override val list: List[String] = Nil
object Printer {
def apply(f: String => String): Printer = new Printer {
override def print(name: String): String = f(name)
}

}

object FieldLister extends FieldListerGeneric

object FieldListerExpanded extends FieldListerGeneric {
val identityPrinter: Printer = Printer(identity)

implicit def hconsLister[K, H, T <: HList](
implicit hLister: Lazy[FieldLister[H]],
tLister: FieldLister[T]): FieldLister[FieldType[K, H] :: T] =
new FieldLister[FieldType[K, H] :: T] {
override val list: List[String] = hLister.value.list ++ tLister.list
}
val lowerCasePrinter: Printer = Printer(_.toLowerCase)

}
val upperCasePrinter: Printer = Printer(_.toUpperCase)

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

package freestyle.cassandra
package mapper
package query.mapper

import java.nio.ByteBuffer

Expand Down
Loading

0 comments on commit 3f86761

Please sign in to comment.