Arguments in Auxiliary Constructor in Scala - scala

I am trying to create 2 auxiliary constructors .But not able to do so.
class learnMultipleAuxuliaryConstructor(firstname: String,
lastName: String,
middleName: String) {
println("This is primary constructor")
println("Complete Name is " + firstname + lastName + middleName)
def this(firstname: String) {
this(firstname, "", "")
println("This is Auxiliary constructor with firstname")
println("First Name is " + firstname)
}
def this(lastname: String) {
this("", lastname, "")
println("This is Auxiliary constructor with lastname")
println("lastname is " + lastname)
}
}
Can i do this?

You have to have distinct constructor signatures. So:
class learnMultipleAuxuliaryConstructor(firstname: String,
lastName: String,
middleName: String) {
def this(firstname: String) ...
def this(lastname: String) ...
}
is not possible. For such case it would be better to have either default parameters and named parameters:
class learnMultipleAuxuliaryConstructor(firstname: String = "",
lastName: String = "",
middleName: String = "")
new learnMultipleAuxuliaryConstructor(lastName = "Custom")
or separate methods in companion objects with distinct names:
object learnMultipleAuxuliaryConstructor {
def fromFirstName(firstName: String) = ...
def fromLastName(lastName: String) = ...
}

Related

class type required but T found in Encoders

I am trying to create a generic code to read using spark sql from a view. Where T can be any object passed at runtime, I should be able to get DataSet of T.
Method
def queryStream[T](sparkSession: SparkSession, query: String, filterParams: Array[String])(implicit tag: ClassTag[T]): Dataset[T] = sparkSession.sql(query)
.as(Encoders.bean[KafkaMessage](classOf[KafkaMessage]))
.map(f => {
init()
getObjectMapper.readValue(f.message, classTag[T].runtimeClass).asInstanceOf[T]
})(Encoders.bean[T](classOf[T]))
Invocation :
queryStream[Student](sparkSession,"select cast(value as string) as message,"
+ "cast(key as string) as messageKey, " +
"cast(partition as int) partition, " +
"cast(offset as long) offset from events",null)
KafkaMessage:
class KafkaMessage {
#BeanProperty
var messageKey: String = _
#BeanProperty
var message: String = _
#BeanProperty
var partition: Int = _
#BeanProperty
var offset: Long = _
override def toString(): String = s"Message Key: $messageKey, Message: $message, Partition:$partition, Offset:$offset"
}

Scala Implementation

I have a case class:
case class EvaluateAddress(addressFormat: String,
screeningAddressType: String,
value: Option[String])
This was working fine until I have a new use case where "value" parameter can be a class Object instead of String.
My initial implementation to handle this use case:
case class EvaluateAddress(addressFormat: String,
screeningAddressType: String,
addressId: Option[String],
addressValue: Option[MailingAddress]) {
def this(addressFormat: String, screeningAddressType: String, addressId: String) = {
this(addressFormat, screeningAddressType, Option(addressId), None)
}
def this(addressFormat: String, screeningAddressType: String, address: MailingAddress) = {
this(addressFormat, screeningAddressType, None, Option(address))
}
}
But because of some problem, I can not have four parameters in any constructor.
Is there a way I can create a class containing three parameters: ** addressFormat, screeningAddressType, value** and handle both the use cases?
Your code works fine, to use the other constructor's you just need to use the new keyword:
case class MailingAddress(i: Int)
case class EvaluateAddress(addressFormat: String, screeningAddressType: String, addressId: Option[String], addressValue: Option[MailingAddress]) {
def this(addressFormat: String, screeningAddressType: String, addressId: String) = {
this(addressFormat, screeningAddressType, Option(addressId), None)
}
def this(addressFormat: String, screeningAddressType: String, address: MailingAddress) = {
this(addressFormat, screeningAddressType, None, Option(address))
}
}
val e1 = EvaluateAddress("a", "b", None, None)
val e2 = new EvaluateAddress("a", "b", "c")
val e3 = new EvaluateAddress("a", "b", MailingAddress(0))
You can create an auxilliary ADT to wrap different types of values. Inside EvaluateAddress you can check the alternative that was provided with a match:
case class EvaluateAddress(addressFormat: String,
screeningAddressType: String,
value: Option[EvaluateAddress.Value]
) {
import EvaluateAddress._
def doEvaluation() = value match {
case Some(Value.AsId(id)) =>
case Some(Value.AsAddress(mailingAddress)) =>
case None =>
}
}
object EvaluateAddress {
sealed trait Value
object Value {
case class AsId(id: String) extends Value
case class AsAddress(address: MailingAddress) extends Value
}
}
It's then possible to also define some implicit conversions to automatically convert Strings and MailingAddresses into Values:
object EvaluateAddress {
sealed trait Value
object Value {
case class AsId(id: String) extends Value
case class AsAddress(address: MailingAddress) extends Value
implicit def idAsValue(id: String): Value = AsId(id)
implicit def addressAsValue(address: MailingAddress): Value = AsAddress(address)
}
def withRawValue[T](addressFormat: String,
screeningAddressType: String,
rawValue: Option[T])(implicit asValue: T => Value): EvaluateAddress =
{
EvaluateAddress(addressFormat, screeningAddressType, rawValue.map(asValue))
}
}
Some examples of using those implicit conversions:
scala> EvaluateAddress("a", "b", Some("c"))
res1: EvaluateAddress = EvaluateAddress(a,b,Some(AsId(c)))
scala> EvaluateAddress("a", "b", Some(MailingAddress("d")))
res2: EvaluateAddress = EvaluateAddress(a,b,Some(AsAddress(MailingAddress(d))))
scala> val id: Option[String] = Some("id")
id: Option[String] = Some(id)
scala> EvaluateAddress.withRawValue("a", "b", id)
res3: EvaluateAddress = EvaluateAddress(a,b,Some(AsId(id)))

Slick: how to get an object attribute in a result set?

Given the following Scala class enhanced with Slick:
class Users(tag: Tag) extends Table[(Int, String, String)](tag, "users") {
def id: Rep[Int] = column[Int]("sk", O.PrimaryKey)
def firstName: Rep[String] = column[String]("first_name")
def lastName: Rep[String] = column[String]("last_name")
def * : ProvenShape[(Int, String, String)] = (id, firstName, lastName)
}
I need to print the last names in a query loop:
val db = Database.forConfig("dbconfig")
try {
val users: TableQuery[Users] = TableQuery[Users]
val action = users.result
val future = db.run(action)
future onComplete {
case Success(u) => u.foreach { user => println("last name : " + **user.lastName**) }
case Failure(t) => println("An error has occured: " + t.getMessage)
}
} finally db.close
But Scala doesn't recognize user.lastName (I get an error saying that "Scala doesn't recognize the symbol"). How to print the last names ?
The problem is you're using Table[(Int, String, String)]. user in your case is therefore an instance of type (Int, String, String), so it doesn't have a lastName. Use user._3 to get at the tuple's third element (the last name). Even better might be to use a case class instead of a tuple:
case class DBUser(id: Int, firstName: String, lastName: String)
class Users(tag: Tag) extends Table[DBUser](tag, "users") {
def id: Rep[Int] = column[Int]("sk", O.PrimaryKey)
def firstName: Rep[String] = column[String]("first_name")
def lastName: Rep[String] = column[String]("last_name")
def * = (id, firstName, lastName) <> (DBUser.tupled, DBUser.unapply)
}

Using multiple projection in slick for the same table

I have a user table for which I will like to have multiple projections. For example, Can I have something like
class Users(tag: Tag) extends Table [User] (tag, "user") {
def * = (id.?, emailId, firstName, lastName, gender) <> (User.tupled, User.unapply)
def allDetails = (id.?, emailId, firstName, lastName, gender, createdTime, modifiedTime)
...
}
I searched on Google but could not find anything. Can somebody tell me how can I use allDetails?
I will like to do
object Users {
val users = TableQuery[Users]
def getAllDetails = ??? // How can I use allDetails here
}
Had the same need recently, and started to use something like that:
abstract class AnyUserTable[T](tag: Tag) extends Table[T](tag, "user") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def emailId = column[String]("email_id")
def firstName = column[String]("firstname")
def lastName = column[String]("lastname")
def gender = column[String]("gender")
}
class Users(tag: Tag) extends AnyUserTable[User](tag) {
def * = (emailId, firstName, lastName, gender, id.?) <> (User.tupled, User.unapply)
}
class UserDetails(tag: Tag) extends AnyUserTable[UserDetail](tag) {
def createdTime = column[Option[Timestamp]]("created_time")
def modifiedTime = column[Option[Timestamp]]("modified_time")
def * = (emailId, firstName, lastName, gender, createdTime, modifiedTime, id.?) <> (UserDetail.tupled, UserDetail.unapply)
}
object Users {
val users = TableQuery[Users]
val getAllDetails = TableQuery[UserDetails] // That is how I propose to get all the details
}
borrowing the case classes from Sky's answer.
case class User(
emailId: String, firstName: String, lastName: String,
gender: String, id: Option[Int] = None)
case class UserDetail(
emailId: String,
firstName: String, lastName: String, gender: String,
createdTime: Option[Timestamp],
modifiedTime: Option[Timestamp], id: Option[Int] = None)
I guess that is pretty close from what I would be tempted to do using updatable views in straight sql.
Do like this:
class UserTable(tag: Tag) extends Table[UserInfo](tag, "user") {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def emailId = column[String]("email_id", O.NotNull)
def firstName = column[String]("firstname")
def lastName = column[String]("lastname")
def gender = column[String]("gender")
def createdTime = column[Option[Timestamp]]("created_time")
def modifiedTime = column[Option[Timestamp]]("modified_time")
def userInfo = (emailId, firstName, lastName, gender, createdTime, modifiedTime, id.?) <> (User.tupled, User.unapply)
def * = (emailId, firstName, lastName, gender, id.?) <> (UserInfo.tupled, UserInfo.unapply)
}
case class User(emailId: String,
firstName: String, lastName: String, gender: String,
createdTime: Option[Timestamp],
modifiedTime: Option[Timestamp], id: Option[Int] = None)
case class UserInfo(emailId: String, firstName: String, lastName: String,
gender: String, id: Option[Int] = None)
for extra projection:
val userTable = TableQuery[UserTable]
def insert(userInfo: UserInfo) (implicit session: Session): Int = {
//return auto incremeted id
userTable returning (userTable.map(_.id)) += userInfo
}
def update(userInfo: UserInfo)(implicit session: Session) = {
userTable.filter(_.id === userInfo.id).update(userInfo)
}
def getUserInfo()(implicit session: Session): List[UserInfo] = {
userTable.list
}

Create model class in Scala with Play 2 Framework

I have a Play project, who contains a User model. Before, I used case class declaration with object declaration to access the model in my application. It works.
But now I want to declare a User class, to have multiple instances ; because I have understand that when you have a model with an object, it'as a singleton, so one instance.
And my project is a website which will have many users.
When I declare my class, as example :
class User(val username: String, var firstname: String, var lastname: String, var company: String, var password: String){}
The model isn't identified by my application (Application.scala)
How can I realise what I want ?
Old code :
case class User(username: String, password: String, firstname: String, lastname: String, company: String)
object User {
val simple = {
get[String]("username") ~
get[String]("password") ~
get[String]("firstname") ~
get[String]("lastname") ~
get[String]("company") map {
case username~password~firstname~lastname~company =>
User(username, password, firstname, lastname, company)
}
}
def findAll(): Seq[User] = {
DB.withConnection { implicit connection =>
SQL("SELECT * FROM user").as(User.simple *)
}
}
def create(user: User): Unit = {
DB.withConnection { implicit connection =>
SQL("INSERT INTO user(username, password, firstname, lastname, company) VALUES ({username}, {password}, {firstname}, {lastname}, {company})").on(
'username -> user.username,
'password -> user.password,
'firstname -> user.firstname,
'lastname -> user.lastname,
'company -> user.company
).executeUpdate()
}
}
def getOne(username: String): Option[User] = {
DB.withConnection { implicit connection =>
val selectUser = SQL("SELECT username, password, firstname, lastname, company FROM user where username={username}")
.on('username -> "azuken")()
.collectFirst {
case Row(username: String, password: String, firstname: String, lastname: String, company: String) =>
User(username, password, firstname, lastname, company)
case Row(username:String, password:String, firstname: String) =>
User(username, password, "bobby", "lqsdast", "sdf")
case _ =>
User("username", "password", "firstname", "lastname", "company")
}
selectUser
}
}
def authentication(username: String, password: String): Long = {
DB.withConnection { implicit connection =>
val firstRow = SQL("SELECT COUNT(*) AS NbRep FROM user WHERE username = {username} AND password = {password}").on(
'username -> username,
'password -> password
).apply().head
firstRow[Long]("NbRep")
}
}
}