I have the following class diagram and would like some help with refactoring.
The code:
trait id {
val id: String
def uuid = java.util.UUID.randomUUID.toString
}
abstract class node extends id {
def deepCopy: node
def hasSameId(n: node): Boolean = n.id == id
}
trait manifest {
val properties = new mutable.HashMap[String, Any]
val manifest: immutable.HashMap[String, (String, String)]
def isComplete: Boolean
def setProperty(k: String, v: Any): this.type
def getProperty(k: String) = properties(k)
def getAllProperties = properties
def hasEqualProperties(p: mutable.HashMap[String, Any]): Boolean = {
if (properties.size != p.size) false
else {
properties.map(prop => p(prop._1) == prop._2).foldLeft(true)((r, c) => r && c) // this will give trouble if off manifest property table have the same size but different optionals from an open manifest
}
}
}
trait sealedManifest extends manifest {
def setProperty(k: String, v: Any) = {
if (manifest.contains(k)) {
val keyType = manifest(k)._1
val valueType = v.getClass.getCanonicalName
if (keyType == valueType) properties(k) = v
else throw new IllegalArgumentException(""" Expecting type "%s" received type "%s" for "%s" """.format(keyType,valueType,k))
} // test for type as well
else throw new IllegalArgumentException(""" "%s" is not on manifest""".format(k))
this
}
}
trait openManifest extends manifest {
def setProperty(k: String, v: Any) = {
if (manifest.contains(k)) {
val keyType = manifest(k)._1
val valueType = v.getClass.getCanonicalName
if (keyType == valueType) properties(k) = v
else throw new IllegalArgumentException(""" Expecting type "%s" received type "%s" for "%s" """.format(keyType,valueType,k))
} // test for type as well
else properties(k) = v
this
}
}
case class system(val uid: String = null) extends node with openManifest {
val id = if (uid != null) uid else uuid
override val manifest = immutable.HashMap(
"name" -> ("java.lang.String","req"),
"description" -> ("java.lang.String","opt")
)
override def isComplete: Boolean = true
def CONNECTS(s: system, id: String = null) = {
new systemCONNECTSsystem(this, s, id)
}
def PRODUCES(d: dataset, id: String = null) = {
new systemPRODUCESdataset(this, d, id)
}
def <= (kv: (String, Any)): system = {
setProperty(kv._1,kv._2)
this
}
def deepCopy = {
val s = new system(id)
getAllProperties.foreach(p => s.setProperty(p._1,p._2))
s
}
def isIdenticalTo(s: system) = {
hasSameId(s) && hasEqualProperties(s.getAllProperties)
}
}
case class dataset(val uid: String = null) extends node with sealedManifest{
val id = if (uid != null) uid else uuid
override val manifest = immutable.HashMap(
"name" -> ("java.lang.String","req"),
"description" -> ("java.lang.String","opt")
)
override def isComplete = true
def <= (kv: (String, Any)): dataset = {
setProperty(kv._1,kv._2)
this
}
def deepCopy = {
val d = new dataset(id)
getAllProperties.foreach(p => d.setProperty(p._1,p._2))
d
}
def isIdenticalTo(d: dataset) = {
hasSameId(d) && hasEqualProperties(d.getAllProperties)
}
}
The use case is ultimately that many additional classes like 'system' and 'dataset' will be generated. I am seeing a lot of build up of boiler plate at this level notably in 'deepCopy' and 'isIdenticalTo'. That smells wrong and I think that these blocks of code can be moved to higher levels in the class diagram, but I am struggling to achieve this.
When I try to move the code to higher levels I run into problems because these methods are identical in everything except type. So I was hoping the type classes might help, or simply (multiple-)inheritance.
Can anyone help?
Related
class Person {
val studentName = "Arpana"
def changeName(id:String, name:String) ={
val studentName = name
useName(id)
}
def useName(id:String) = {
println(s"use name is $id, by $studentName")
}
}
object Person {
def main(args: Array[String]): Unit = {
(new Person).changeName("2", "Shubham")
}
}
I don't want to use var in code, can we do it by keywords, I tried with keywords like super, protected, private, final but didn't work.
In actual I want to apply this in the below code.
abstract class BaseRepository[T <: BaseModel : ClassTag : StriveSerializer] {
self: BaseConnection =>
val tableName: String = implicitly[ClassTag[T]].runtimeClass.getSimpleName
private val serializer = implicitly[StriveSerializer[T]]
private def executeInserts(query: String): Future[Boolean] = Future {
val preparedStatement = self.connection.prepareStatement(query)
preparedStatement.execute()
}
def exist(id: String, name: String): Future[Boolean] = {
val tableName = name
val promise = Promise[Boolean]
queryById(id).onComplete {
case Success(_) => promise.success(true)
case Failure(ex) => promise.failure(ex)
}
promise.future
}
def queryById(id: String): Future[T] = {
val getSql = s"SELECT * FROM $tableName WHERE id == $id;"
executeReads(getSql).map(serializer.fromResultSet)
}
}
I want when i call exist function then table name given in exist function override in queryById method table name .
It seems like a bit of mix of Java and Scala style. I tried to refactor a bit assuming the intention behind the code. Try and see if this achieves what you want to do:
class Person(_id: String, _studentName: String) {
private val id: String = _id
private val studentName: String = _studentName
def useName() = {
println(s"use name is $id, by $studentName")
}
}
object Person extends App {
new Person("2", "Shubham").useName()
}
I think you should use case class For Model
case class Student(id:String,name:String)
def changeId(student:Student, newId:String): Student ={
student.copy(id=newId)
}
val s1 = Student("1","A")
val newS1 = changeId(s1,"2")
I think it okay to use mutable in a class
e.g.
class MySuperService{
var lastHeartbeat: Option[Timestamp] = None
def setLastHeartbeat(ts:Timestamp): Unit ={
lastHeartbeat = Some(ts)
}
}
val mss1 = new MySuperService()
mss1.setLastHeartbeat(???)
Say I have this situation
class Pipe {
var vel = 3.4
var V = 300
var a = 10.2
var in = ???
var TotV = V+in
var out = TotV*a/vel
}
val pipe1 = new Pipe
val pipe2 = new Pipe
The in variable is were my problem is, what i'd like to do is get the out variable from pipe1 and feed that in as the in variable for pipe 2 effectively to join the two pipes but I cant figure out if this is even possible in the same class. So I can do it manually but need to know if its possible to do in the class.
pipe2.in = pipe1.out
my attempted fix was to add an ID field then try and use that to reference an instance with a higher id field but that doesnt seem doable. ie
class Pipe(id:Int) {
var vel = 3.4
var V = 300
var a = 10.2
var in = Pipe(id+1).out //this is the sticking point, I want to reference instances of this class and use their out value as in value for instances with a lower ID
var TotV = V+in
var out = TotV*a/vel
}
any help would be appreciated
You can do this by defining a companion object for the class and passing in the upstream pipe as an optional parameter to the factory method, then extracting its in value and passing it to the class constructor, as follows:
object Pipe {
def apply(upstreamPipe: Option[Pipe]): Pipe = {
val inValue = upstreamPipe match {
case Some(pipe) => pipe.out
case None => 0 // or whatever your default value is
new Pipe(inValue)
}
You would then call
val pipe1 = Pipe(None)
val pipe2 = Pipe(Some(pipe1))
Unfortunately your question is not clear now. Under certain assumptions what you describe looks like what is now called "FRP" aka "Functional Reactive Programming". If you want to do it in a serious way, you probably should take a look at some mature library such as RxScala or Monix that handle many important in the real world details such as error handling or scheduling/threading and many others.
For a simple task you might roll out a simple custom implementation like this:
trait Observable {
def subscribe(subscriber: Subscriber): RxConnection
}
trait RxConnection {
def disconnect(): Unit
}
trait Subscriber {
def onChanged(): Unit
}
trait RxOut[T] extends Observable {
def currentValue: Option[T]
}
class MulticastObservable extends Observable with Subscriber {
private val subscribers: mutable.Set[Subscriber] = mutable.HashSet()
override def onChanged(): Unit = subscribers.foreach(s => s.onChanged())
override def subscribe(subscriber: Subscriber): RxConnection = {
subscribers.add(subscriber)
new RxConnection {
override def disconnect(): Unit = subscribers.remove(subscriber)
}
}
}
abstract class BaseRxOut[T](private var _lastValue: Option[T]) extends RxOut[T] {
private val multicast = new MulticastObservable()
protected def lastValue: Option[T] = _lastValue
protected def lastValue_=(value: Option[T]): Unit = {
_lastValue = value
multicast.onChanged()
}
override def currentValue: Option[T] = lastValue
override def subscribe(subscriber: Subscriber): RxConnection = multicast.subscribe(subscriber)
}
class RxValue[T](initValue: T) extends BaseRxOut[T](Some(initValue)) {
def value: T = this.lastValue.get
def value_=(value: T): Unit = {
this.lastValue = Some(value)
}
}
trait InputConnector[T] {
def connectInput(input: RxOut[T]): RxConnection
}
class InputConnectorImpl[T] extends BaseRxOut[T](None) with InputConnector[T] {
val inputHolder = new RxValue[Option[(RxOut[T], RxConnection)]](None)
private def updateValue(): Unit = {
lastValue = for {inputWithDisconnect <- inputHolder.value
value <- inputWithDisconnect._1.currentValue}
yield value
}
override def connectInput(input: RxOut[T]): RxConnection = {
val current = inputHolder.value
if (current.exists(iwd => iwd._1 == input))
current.get._2
else {
current.foreach(iwd => iwd._2.disconnect())
inputHolder.value = Some(input, input.subscribe(() => this.updateValue()))
updateValue()
new RxConnection {
override def disconnect(): Unit = {
if (inputHolder.value.exists(iwd => iwd._1 == input)) {
inputHolder.value.foreach(iwd => iwd._2.disconnect())
inputHolder.value = None
updateValue()
}
}
}
}
}
}
abstract class BaseRxCalculation[Out] extends BaseRxOut[Out](None) {
protected def registerConnectors(connectors: InputConnectorImpl[_]*): Unit = {
connectors.foreach(c => c.subscribe(() => this.recalculate()))
}
private def recalculate(): Unit = {
var newValue = calculateOutput()
if (newValue != lastValue) {
lastValue = newValue
}
}
protected def calculateOutput(): Option[Out]
}
case class RxCalculation1[In1, Out](func: Function1[In1, Out]) extends BaseRxCalculation[Out] {
private val conn1Impl = new InputConnectorImpl[In1]
def conn1: InputConnector[In1] = conn1Impl // show to the outer world only InputConnector
registerConnectors(conn1Impl)
override protected def calculateOutput(): Option[Out] = {
for {v1 <- conn1Impl.currentValue}
yield func(v1)
}
}
case class RxCalculation2[In1, In2, Out](func: Function2[In1, In2, Out]) extends BaseRxCalculation[Out] {
private val conn1Impl = new InputConnectorImpl[In1]
def conn1: InputConnector[In1] = conn1Impl // show to the outer world only InputConnector
private val conn2Impl = new InputConnectorImpl[In2]
def conn2: InputConnector[In2] = conn2Impl // show to the outer world only InputConnector
registerConnectors(conn1Impl, conn2Impl)
override protected def calculateOutput(): Option[Out] = {
for {v1 <- conn1Impl.currentValue
v2 <- conn2Impl.currentValue}
yield func(v1, v2)
}
}
// add more RxCalculationN if needed
And you can use it like this:
def test(): Unit = {
val pipe2 = new RxCalculation1((in: Double) => {
println(s"in = $in")
val vel = 3.4
val V = 300
val a = 10.2
val TotV = V + in
TotV * a / vel
})
val in1 = new RxValue(2.0)
println(pipe2.currentValue)
val conn1 = pipe2.conn1.connectInput(in1)
println(pipe2.currentValue)
in1.value = 3.0
println(pipe2.currentValue)
conn1.disconnect()
println(pipe2.currentValue)
}
which prints
None
in = 2.0
Some(905.9999999999999)
in = 3.0
Some(909.0)
None
Here your "pipe" is RxCalculation1 (or other RxCalculationN) which wraps a function and you can "connect" and "disconnect" other "pipes" or just "values" to various inputs and start a chain of updates.
I am trying to compare two Lists containing case classes. Can't figure out which method to override to get this working. Please refer to the code below.
trait Filter {
def toQueryString: String
}
trait SimpleFilter extends Filter {
val key: String
val value: Any
override def toQueryString = value match {
case v: String => s"$key='$v'"
case _ => s"$key=$value"
}
override def toString = "$key:$value"
override def equals(that: Any) = {
that match {
case s: SimpleFilter => {
key == key && value == value
}
case _ => false
}
}
override def hashCode() = key.hashCode + value.hashCode
}
class DestinationFilter(override val value: String) extends SimpleFilter {
override val key = "destination"
}
object DestinationFilter {
def apply(value: String) = new DestinationFilter(value)
}
object Tester {
def main(args: Array[String]): Unit = {
val d1 = DestinationFilter("Google")
val d2 = DestinationFilter("Google")
val l1 = List(d1)
val l2 = List(d2)
println(11 == 12)
println(d1 == d2)
}
}
which returns
false
true
Can't understand why the list comparison returns false. Ultimately what I want is this to be equal
List(DestinationFilter("Amazon"), LocationFilter("Yahoo"), DestinationFilter("Google") == List(DestinationFilter("Yahoo"), LocationFilter("Amazon"), DestinationFilter("Google")
*they should be equal irrespective of order.
You have a typo in your comparison, 11 and 12 should be l1 and l2:
println(l1 == l2) // true
So 11 == 12 is always false, you're just comparing Ints.
You also need to change your equals override, your just comparing key and value to themselves, which is always true:
override def equals(that: Any) = {
that match {
case s: SimpleFilter =>
key == s.key && value == s.value //edited
case _ => false
}
}
I want something like this:
private val cachedResponse = mutable.Option.empty[A]
def get: A = cachedResponse getOrElseUpdate db.findModel()
def update: Unit = {
db.updateModel
cachedResponse.empty() // set it to None/Option.empty
}
I am not looking for a generic HashMap based memoization like this. I tried implementing it using a var Option[A] but it did not look very idiomatic to me:
private var cachedResponse: Option[A] = None
def get: A = cachedResponse getOrElse {
cachedResponse = Option(db.findModel())
cachedResponse.get
}
def update: Unit = {
db.updateModel
cachedResponse = None
}
There isn't one built into the standard library.
Using a var containing an immutable Option is the idiomatic way to do it (assuming you can't rewrite this to not use state at all).
Otherwise, you should build your own. Here's the core of an implementation:
class MutableOpt[A] {
private[this] var myValue: A = _
private[this] var loaded = false
private def valueEquals(o: Any) = myValue == o
def get = if (loaded) myValue else throw new NoSuchElementException("MutableOpt")
def set(a: A): this.type = { loaded = true; myValue = a; this }
def getOrSet(a: => A): A = {
if (!loaded) {
myValue = a
loaded = true
}
myValue
}
def isEmpty = !loaded
def nonEmpty = loaded
def foreach[U](f: A => U): Unit = if (loaded) f(myValue)
def transform(f: A => A): this.type = { if (loaded) myValue = f(myValue); this }
def clear(): this.type = { loaded = false; this }
def toOption = if (loaded) Some(myValue) else None
override def toString = if (loaded) "MutableOpt("+myValue.toString+")" else "MutableOpt()"
override def hashCode = if (loaded) myValue.hashCode else 1751
override def equals(o: Any) = o match {
case m: MutableOpt[_] =>
(isEmpty && m.isEmpty) || (nonEmpty && m.nonEmpty && m.valueEquals(myValue))
case _ => false
}
}
object MutableOpt {
def from[A](o: Option[A]) = {
val m = new MutableOpt[A]
o match {
case Some(a) => m set a
case _ =>
}
m
}
}
Define together with :paste if using the REPL.
I want to be able to do something like this:
prepare form:
val formDescription = formBuilder(_.textField[User](_.firstName)
.textField[User](_.lastName)
).build
showForm(formDescription)
extract data from user filled form, using User:
//contains data of a form submitted by a user:
val formData: Map[String, String] = getFormData
val newUser = User(id = randomUuid, firstName = formData.extract[User](_.firstName))
One solution I see is to use a dynamic proxy that extends provided class and remembers what was invoked on him:
def getFieldName[T:Manifest](foo: T => Any) = {
val clazz = implicitly[Manifest[T]].erasure
val proxy = createDynamicProxy(clazz)
foo(proxy)
proxy.lastInvokedMethodName
}
Is there a better way to do it? Is there any lib that implements it already?
This reflective approach takes a case class and invokes its companion apply, calling getField and fetching default args if the field is not in the data.
import scala.reflect.runtime.{currentMirror => cm, universe => uni}
import uni._
def fromXML(xml: Node): Option[PluginDescription] = {
def extract[A]()(implicit tt: TypeTag[A]): Option[A] = {
// extract one field
def getField(field: String): Option[String] = {
val text = (xml \\ field).text.trim
if (text == "") None else Some(text)
}
val apply = uni.newTermName("apply")
val module = uni.typeOf[A].typeSymbol.companionSymbol.asModule
val ts = module.moduleClass.typeSignature
val m = (ts member apply).asMethod
val im = cm reflect (cm reflectModule module).instance
val mm = im reflectMethod m
def getDefault(i: Int): Option[Any] = {
val n = uni.newTermName("apply$default$" + (i+1))
val m = ts member n
if (m == NoSymbol) None
else Some((im reflectMethod m.asMethod)())
}
def extractArgs(pss: List[List[Symbol]]): List[Option[Any]] =
pss.flatten.zipWithIndex map (p => getField(p._1.name.encoded) orElse getDefault(p._2))
val args = extractArgs(m.paramss)
if (args exists (!_.isDefined)) None
else Some(mm(args.flatten: _*).asInstanceOf[A])
}
// check the top-level tag
xml match {
case <plugin>{_*}</plugin> => extract[PluginDescription]()
case _ => None
}
}
The idea was to do something like:
case class User(id: Int = randomUuid, firstName: String, lastName: String)
val user = extract[User]()
That's my own solution:
package utils
import javassist.util.proxy.{MethodHandler, MethodFilter, ProxyFactory}
import org.specs2.mutable._
import javassist.util.proxy.Proxy
import java.lang.reflect.{Constructor, Method}
class DynamicProxyTest extends Specification with MemberNameGetter {
"Dynamic proxy" should {
"extract field name" in {
memberName[TestClass](_.a) must ===("a")
memberName[TestClass](_.i) must ===("i")
memberName[TestClass](_.b) must ===("b")
memberName[TestClass](_.variable) must ===("variable")
memberName[TestClass](_.value) must ===("value")
memberName[TestClass](_.method) must ===("method")
}
}
}
trait MemberNameGetter {
def memberName[T: Manifest](foo: T => Any) = {
val mf = manifest[T]
val clazz = mf.erasure
val proxyFactory = new ProxyFactory
proxyFactory.setSuperclass(clazz)
proxyFactory.setFilter(new MethodFilter {
def isHandled(p1: Method) = true
})
val newClass = proxyFactory.createClass()
var lastInvokedMethod: String = null
val mh = new MethodHandler {
def invoke(p1: Any, p2: Method, p3: Method, p4: Array[AnyRef]) = {
lastInvokedMethod = p2.getName
p3.invoke(p1, p4: _*)
}
}
val constructor = defaultConstructor(newClass)
val parameters = defaultConstructorParameters(constructor)
// val proxy = constructor.newInstance("dsf", new Integer(0))
val proxy2 = constructor.newInstance(parameters: _*)
proxy2.asInstanceOf[Proxy].setHandler(mh)
foo(proxy2.asInstanceOf[T])
lastInvokedMethod
}
private def defaultConstructor(c: Class[_]) = c.getConstructors.head
private def defaultConstructorParameters(constructor: Constructor[_]) = {
val parameterTypes = constructor.getParameterTypes
parameterTypes.map{
case Integer.TYPE => Integer.valueOf(0)
case _ => null
}
}
}
case class TestClass(a: String, i: Int, b: Boolean) {
var variable = "asdf"
val value = "asdfasdfasd"
def method = "method"
}
val mh = new MethodHandler {
def invoke(p1: Any, p2: Method, p3: Method, p4: Array[AnyRef]) = {
lastInvokedMethod = p2.getName
p3.invoke(p1, p4: _*)
}
}
val constructor = defaultConstructor(newClass)
val parameters = defaultConstructorParameters(constructor)
// val proxy = constructor.newInstance("dsf", new Integer(0))
val proxy2 = constructor.newInstance(parameters: _*)
proxy2.asInstanceOf[Proxy].setHandler(mh)
foo(proxy2.asInstanceOf[T])
lastInvokedMethod
}
private def defaultConstructor(c: Class[_]) = c.getConstructors.head
private def defaultConstructorParameters(constructor: Constructor[_]) = {
val parameterTypes = constructor.getParameterTypes
parameterTypes.map{
case Integer.TYPE => Integer.valueOf(0)
case java.lang.Double.TYPE => java.lang.Double.valueOf(0)
case java.lang.Long.TYPE => java.lang.Long.valueOf(0)
case java.lang.Boolean.TYPE => java.lang.Boolean.FALSE
case _ => null
}
}
}
case class TestClass(a: String, i: Int, b: Boolean) {
var variable = "asdf"
val value = "asdfasdfasd"
def method = "method"
}