Reputation: 2074
I have a few objects created with a function called .clean in each one:
HiveCleanerTbl
HiveCleanerDb
These Objects need to be called dynamically based on a record based on an API call being made that will let my Job know what object to call for instance I have it hard coded right now:
def matchSchema(schema:Int): Any = schema match {
case 1 => HiveCleanerTbl.clean(rawRecord)
case 32 => HiveCleanerDb.clean(rawRecord)
...
Earlier in the code instead of hardcoding the possible Objects is there a way to dynamically have the object populated like:
val systems = List[(String, String, Int)] = List((hiveTbl,HiveTblCleaner,6), (hiveDb,HiveDbCleaner,7))
And I have code that looks like this:
systems.foreach(x => if(x._1 == systemName) {
cleanObject = x._2
})
How will I make the cleanObject defined as the object I want to use that can call its .clean function?
Upvotes: 0
Views: 522
Reputation: 14825
Yes, you can do that.
val systems = List[(Cleanable, String, Int)] = List((hiveTbl,HiveTblCleaner,6), (hiveDb,HiveDbCleaner,7))
Lets say your hiveTbl
and hiveDb
are cleanable and lets say clean
method is available on them to invoke.
systems.foreach {
case (db: Cleanable, "cleanSchemeName", _) =>
db.clean
case _ => () //ignore
}
If db
does not have clean
method then check the type of db and try pattern matching to resolve the real type of the db
object.
Here is a general example how you can achieve this.
Cleanable
gives clean
method to A
and B
. List contains all cleanables so I can go ahead calling clean on each object without type casting the object.
Based on certain condition you can ignore clean some objects.
trait Cleanable {
def clean(): Unit
}
case class A(a: Int) extends Cleanable {
override def clean(): Unit = println("cleaned A")
}
case class B(a: Int) extends Cleanable {
override def clean(): Unit = println("cleaned B")
}
val cleanableStuff: List[(String, Cleanable)] = List(("clean", A(10)), ("donot_clean", B(10)))
def cleanAll(list: List[(String, Cleanable)]): Unit = {
list.foreach {
case ("donot_clean", v) => //Ignore 1st object
case (_, v) => v.clean() //clean other objects
}
}
Upvotes: 1
Reputation: 4161
All your objects seem to be "cleaners" - so create a trait called CanClean
that defines the method clean(rawRecord: SomeType)
and a property val schema: Int
. The schema
will be populated in each object with the appropriate value. Then put all these cleaners in a Map[Int, CanClean]
with key: schema
and value: object: CanClean. Then you can do cleanerMap(schema).clean(rawRecord)
. If you do not want to populate the cleanerMap
by hand, you can use reflection to make a list of "all objects that implement CanClean
".
Upvotes: 1