How to make a class wrapping an immutable collection immutable in Scala? - multithreading

In a previous SO post I asked about an idiomatic way to make a container class wrapping an immutable collection thread-safe. Answers that I received all involved using various flavors of read/write locks or synchronization which is not what I wanted.
Let me ask a different question. How do I make the following class that wraps an immutable container immutable? The methods add/remove need to return a new MyContainer class instance suitably altered, but I can't quite see how to do it...
class MyContainer[A] {
// method that returns a new MyContainer that includes the additional thing...
def add(thing: A): MyContainer[A] = {
???
}
def filter(p: A => Boolean): Option[Iterable[A]] = {
val filteredThings = backingStore.values.filter(p)
if (filteredThings.isEmpty) None else Some(filteredThings)
}
// method that returns a new MyContainer that does not include the thing with given uuid
def remove(uuid: UUID): MyContainer[A] = {
???
}
# volatile private[this] var backingStore = immutable.HashMap.empty[UUID, A]
}
Thoughts?
EDIT: In response to comment, one possible solution would be something similar to the following...
class MyContainer[A](val backingStore: immutable.HashMap[UUID, A]) {
def add(thing: A): MyContainer[A] = {
new MyContainer(backingStore + (thing.uuid -> thing))
}
def filter(p: A => Boolean): Option[Iterable[A]] = {
val filteredThings = backingStore.values.filter(p)
if (filteredThings.isEmpty) None else Some(filteredThings)
}
def remove(uuid: UUID): MyContainer[A] = {
new MyContainer(backingStore - uuid)
}
}
...backingStore is no longer private (but could put private in constructor). More thoughts?

You need a way to construct a new MyContainer that already contains some elements and preferably maintain the same UUIDs. That means you will essentially need a constructor that initalizes backingStore. However, if you don't want to expose it in any way, you can make the constructor private, and provide an overloaded constructor that only allows external code to create an empty collection to begin with (let's say). backingStore can simply be moved into a private constructor for this.
class MyContainer[A] private (backingStore: HashMap[UUID, A]) {
def this() = this(HashMap.empty[UUID, A])
def add(thing: A): MyContainer[A] = {
val uuid: UUID = UUID.randomUUID() // or however the UUID is generated
new MyContainer(backingStore + ((uuid, thing)))
}
def remove(uuid: UUID): MyContainer[A] =
new MyContainer(backingStore - uuid)
}
scala> val container = new MyContainer[String]()
scala> container.add("a").add("b").add("c")
res2: MyContainer[String] = MyContainer#4a183d02
It's really up to you want you want to expose in the API, though. I wasn't sure what you were going for with filter so I removed it from my example.

Related

Kotlin how to combine different receivers via with clause without repeating it

I have Parent-Search-Child system as below:
class Room
class Building {
fun find(by: By) = Room()
}
sealed class By {
abstract fun search(): Room
class ById(id: String) : By() {
override fun search(): Room = Room() // epic search method
}
class ByName(name: String) : By() {
override fun search(): Room = Room() // epic search method
}
class Byurpose(purpose: String) : By() {
override fun search(): Room = Room() // epic search method
}
companion object {
fun id(id: String) = ById(id)
fun name(name: String) = ByName(name)
fun purpose(purpose: String) = Byurpose(purpose)
}
}
Which can be used as follows:
val building = Building()
val room = building.find(By.name("Toilet"))
However, I am not very satisfied with the current syntax, which could be much less verbose in Kotlin. In addition, building.find can appear thousands times in the code. I could implement it differently, but actually I don't own Room, Building or By classes, so I can't. Thus this was my approach:
I implemented context class that stores Building reference, and use it internally as source for search methods:
class BuildingContext(private val building: Building) {
fun String.findById() = building.find(By.id(this))
fun String.findByName() = building.find(By.name(this))
fun String.findByPurpose() = building.find(By.purpose(this))
}
It can be used as below:
with(BuildingContext(building)) {
val room2 = "Toilet".findByName()
}
After that I noticed that I only use one search method in 99% cases, so (for sake of even shorter syntax!) I implemented following classes:
object AlwaysSearchById {
fun String.find(building: Building) = building.find(By.id(this))
}
object AlwaysSearchByName {
fun String.find(building: Building) = building.find(By.name(this))
}
object AlwaysSearchByPurpose {
fun String.find(building: Building) = building.find(By.purpose(this))
}
Which can be used this way:
with(AlwaysSearchByName) {
val room3 = "Toilet".find(building)
}
Unfortunately, building reference appears again. The ideal syntax would be "Toilet".find(). I could fix it re-implementing Always~ classes as follows:
class AlwaysSearchByNameV2(private val building: Building) {
fun String.find() = building.find(By.name(this))
}
And it would be used as below:
with(AlwaysSearchByNameV2(building)) {
val room = "Toilet".find()
}
But it some cases, I would like to access BuildingContext methods as well, so So I have to write:
with(BuildingContext(building)) {
with(AlwaysSearchByNameV2(building)) {
val toilet = "Toilet".find()
val randomRoom = "123".findById()
}
}
The question is - How I reduce multiple with clauses in this case?
In the example above there are only 2 with clauses, but it's only basic example. In real world there could be dozens of them, and writing with(with(with(with(with... would surely be a pain.
On the side note this doesn't work:
with(BuildingContext(building), AlwaysSearchByNameV2(building)) {
val toilet = "Toilet".find()
val randomRoom = "123".findById()
}
nor this
with(*arrayOf(BuildingContext(building), BuildingContext(building))) {
val toilet = "Toilet".find()
val randomRoom = "123".findById()
}
You can write custom scoping functions instead of relying on with all the time. For example you can add an extension function that will run a block of code in scope of AlwaysSearchByNameV2 object:
inline fun BuildingContext.byName(f : AlwaysSearchByNameV2.() -> Unit) = AlwaysSearchByNameV2(building).apply(f)
And use it:
with(BuildingContext(building)) { // this: BuildingContext
byName { // this: AlwaysSearchByNameV2
val toilet = "Toilet".find()
val randomRoom = "123".findById() // can still refer to BuildingContext
}
// back to this: BuildingContext
}

Saving argument method with MOP

I am doing some integration tests with Spock with 3rd party apps. Now I am struggling with a problem that I am not sure wether I am approaching the issue properly or not.
In one of the tests I am connecting to a 3rd party service to get some information in an array. Then each of these items are passed to another method to process them individually.
def get3rdPartyItems = {
[item1, item2, item3]
}
def processItem = { item ->
//do something with item
}
get3rdPartyItems.each {
processItem(it)
}
Then I have a test that connects to real 3rd party service using the method get3rdPartyItems() in which I am testing that processItem is called as many times as items has returned the method get3rdPartyItems().
What I am trying to do is to save one of the items as #Shared variable to write another test to know that the item is processed properly as I don't want to mock the content retrieved from the 3rd party service as I want real data.
Basically, this is what I am doing:
#Shared def globalItem
MyClass.metaClass.processItem = { i ->
if (!globalItem)
globalItem = i
//And now I would need to call the original method processItem
}
Any clue how to achieve this? I am probably overheading too much so I am open to change the solution.
Not sure if this is what you want, as it's hard to see your existing structure from the code and the code isn't runnable as-is, but given this class:
class MyClass {
def get3rdPartyItems = {
['item1', 'item2', 'item3']
}
def processItem( item ) {
println item
//do something with item
}
def run() {
get3rdPartyItems().each {
processItem( it )
}
}
}
You can do this:
def globalItem
def oldProcessItem = MyClass.metaClass.getMetaMethod("processItem", Object)
MyClass.metaClass.processItem = { item ->
if (!globalItem) {
println "Setting global item to $item"
globalItem = item
}
oldProcessItem.invoke( delegate, item )
}
def mc = new MyClass()
new MyClass().run()
Just as a matter of concision, that should be the way of passing the parameters to the metamethod in case you pass multiple parameters:
def globalItem
def oldProcessItem = MyClass.metaClass.getMetaMethod("processItem", ["",[:]] as Object[])
MyClass.metaClass.processItem = { String p1, Map p2 ->
if (!globalItem) {
println "Setting global item to $item"
globalItem = p2
}
oldProcessItem.invoke( delegate, [p1,p2] as Object[] )
}
def mc = new MyClass()
new MyClass().run()

Map with default value created in a closure

I want to store objects in a map (called result). The objects are created or updated from SQL rows.
For each row I read I access the map as follows:
def result = [:]
sql.eachRow('SELECT something') { row->
{
// check if the Entry is already existing
def theEntry = result[row.KEY]
if (theEntry == null) {
// create the entry
theEntry = new Entry(row.VALUE1, row.VALUE2)
// put the entry in the result map
result[row.KEY] = theEntry
}
// use the Entry (create or update the next hierarchie elements)
}
I want to minimize the code for checking and updating the map. How can this be done?
I know the function map.get(key, defaultValue), but I will not use it, because it is to expensive to create an instance on each iteration even if I don't need it.
What I would like to have is a get function with a closure for providing the default value. In this case I would have lazy evaluation.
Update
The solution dmahapatro provided is exactly what I want. Following an example of the usage.
// simulate the result from the select
def select = [[a:1, b:2, c:3], [a:1, b:5, c:6], [a:2, b:2, c:4], [a:2, b:3, c:5]]
// a sample class for building an object hierarchie
class Master {
int a
List<Detail> subs = []
String toString() { "Master(a:$a, subs:$subs)" }
}
// a sample class for building an object hierarchie
class Detail {
int b
int c
String toString() { "Detail(b:$b, c:$c)" }
}
// the goal is to build a tree from the SQL result with Master and Detail entries
// and store it in this map
def result = [:]
// iterate over the select, row is visible inside the closure
select.each { row ->
// provide a wrapper with a default value in a closure and get the key
// if it is not available then the closure is executed to create the object
// and put it in the result map -> much compacter than in my question
def theResult = result.withDefault {
new Master(a: row.a)
}.get(row.a)
// process the further columns
theResult.subs.add new Detail(b: row.b, c: row.c )
}
// result should be [
// 1:Master(a:1, subs:[Detail(b:2, c:3), Detail(b:5, c:6)]),
// 2:Master(a:2, subs:[Detail(b:2, c:4), Detail(b:3, c:5)])]
println result
What I learned from this sample:
withDefault returns a wrapper, so for manipulating the map use the wrapper and not the original map
row variable is visible in the closure!
create the wrapper for the map in each iteration again, since row var changed
You asked for it, Groovy has it for you. :)
def map = [:]
def decoratedMap = map.withDefault{
new Entry()
}
It works the same way you would expect it to work lazily. Have a look at withDefault API for a detailed explanation.

Spock unit testing and Inner closures

I ran into a rather odd closure issue related to spock unit testing and wondered if anyone could explain this.
If we imagine a dao, model, and service as follows:
interface CustomDao {
List<Integer> getIds();
Model getModelById(int id);
}
class CustomModel {
int id;
}
class CustomService {
CustomDao customDao
public List<Object> createOutputSet() {
List<Model> models = new ArrayList<Model>();
List<Integer> ids = customDao.getIds();
for (Integer id in ids) {
models.add(customDao.getModelById(id));
}
return models;
}
}
I would like to unit test the CustomService.createOutputSet. I have created the following specification:
class TestSpec extends Specification {
def 'crazy closures'() {
def mockDao = Mock(CustomDao)
def idSet = [9,10]
given: 'An initialized object'
def customService = new CustomService
customService.customDao = mockDao
when: 'createOutput is called'
def outputSet = customService.createOutputSet()
then: 'the following methods should be called'
1*mockDao.getIds() >> {
return idSet
}
for (int i=0; i<idSet.size(); i++) {
int id = idSet.get(i)
1*mockDao.getModelById(idSet.get(i)) >> {
def tmp = new Model()
int tmpId = id // idSet.get(i)
return tmp
}
}
and: 'each compute package is accurate'
2 == outputSet.size()
9 == outputSet.get(0).getId()
10 == outputSet.get(1).getId()
}
}
Notice that in here I test two things. First, I initialize the dao with my mock, verify that the daos are correctly called and return the proper data, and then I verify that I get the proper output (i.e. "and:").
The tricky part is the for loop, in which I wanted to return models from the mock dao that are related to the method parameter. In the above example, if I use a simple for (__ in idSet), the models only return with id 10: outputSet.get(0).getId() == outputSet.get(1).getId() == 10. If I use the traditional for loop, and set the model with idSet.get(i), I get an IndexOutOfBoundsException . The only way to make this work is by retrieving the value in a local variable (id) and setting with variable, as above.
I know this is related to groovy closures and I suspect that spock captures the mock calls into a set of closures before executing them, which means that the model creation depends on the outer state of the closure. I understand why I would get the IndexOutOfBoundsException, but I don't understand why int id = idSet.get(i) is captured by the closure whereas i is not.
What is the difference?
Note: this is not the live code but rather simplified to demonstrate the crux of my challenge. I would not and do not make two subsequent dao calls on getIds() and getModelById().
While stubbing getModelById by a closure, the arguments to the closure has to match with that of the method. If you try something like below, you would not need the local variable id inside for anymore.
for (int i=0; i<idSet.size(); i++) {
//int id = idSet.get(i)
mockDao.getModelById(idSet.get(i)) >> {int id ->
def tmp = new Model()
tmp.id = id // id is closure param which represents idSet.get(i)
return tmp
}
}
Simplified version would be to use each
idSet.each {
mockDao.getModelById(it) >> {int id ->
def tmp = new Model()
tmp.id = id // id is closure param which represents idSet.get(i)
tmp
}
}
Do we need to worry about how many times method is called if it is being stubbed?
Accessing mutable local variables from a closure whose execution is deferred is a common source of errors not specific to Spock.
I don't understand why int id = idSet.get(i) is captured by the closure whereas i is not.
The former gives rise to a separate hoisted variable per iteration whose value is constant. The latter gives rise to a single hoisted variable whose value changes over time (and before the result generator executes).
Instead of solving the problem by introducing a temporary variable, a better solution (already given by #dmahapatro) is to declare an int id -> closure parameter. If it's deemed good enough to stub the calls without enforcing them, the loop can be omitted altogether. Yet another potential solution is to construct the return values eagerly:
idSet.each { id ->
def model = new Model()
model.id = id
1 * mockDao.getModelById(id) >> model
}

Deep copy Map in Groovy

How can I deep copy a map of maps in Groovy? The map keys are Strings or Ints. The values are Strings, Primitive Objects or other maps, in a recursive way.
An easy way is this:
// standard deep copy implementation
def deepcopy(orig) {
bos = new ByteArrayOutputStream()
oos = new ObjectOutputStream(bos)
oos.writeObject(orig); oos.flush()
bin = new ByteArrayInputStream(bos.toByteArray())
ois = new ObjectInputStream(bin)
return ois.readObject()
}
To go about deep copying each member in a class, the newInstance() exists for Class objects. For example,
foo = ["foo": 1, "bar": 2]
bar = foo.getClass().newInstance(foo)
foo["foo"] = 3
assert(bar["foo"] == 1)
assert(foo["foo"] == 3)
See http://groovy-lang.org/gdk.html and navigate to java.lang, Class, and finally the newInstance method overloads.
UPDATE:
The example I have above is ultimately an example of a shallow copy, but what I really meant was that in general, you almost always have to define your own reliable deep copy logic, with perhaps using the newInstance() method, if the clone() method is not enough. Here's several ways how to go about that:
import groovy.transform.Canonical
import groovy.transform.AutoClone
import static groovy.transform.AutoCloneStyle.*
// in #AutoClone, generally the semantics are
// 1. clone() is called if property implements Cloneable else,
// 2. initialize property with assignment, IOW copy by reference
//
// #AutoClone default is to call super.clone() then clone() on each property.
//
// #AutoClone(style=COPY_CONSTRUCTOR) which will call the copy ctor in a
// clone() method. Use if you have final members.
//
// #AutoClone(style=SIMPLE) will call no arg ctor then set the properties
//
// #AutoClone(style=SERIALIZATION) class must implement Serializable or
// Externalizable. Fields cannot be final. Immutable classes are cloned.
// Generally slower.
//
// if you need reliable deep copying, define your own clone() method
def assert_diffs(a, b) {
assert a == b // equal objects
assert ! a.is(b) // not the same reference/identity
assert ! a.s.is(b.s) // String deep copy
assert ! a.i.is(b.i) // Integer deep copy
assert ! a.l.is(b.l) // non-identical list member
assert ! a.l[0].is(b.l[0]) // list element deep copy
assert ! a.m.is(b.m) // non-identical map member
assert ! a.m['mu'].is(b.m['mu']) // map element deep copy
}
// deep copy using serialization with #AutoClone
#Canonical
#AutoClone(style=SERIALIZATION)
class Bar implements Serializable {
String s
Integer i
def l = []
def m = [:]
// if you need special serialization/deserialization logic override
// writeObject() and/or readObject() in class implementing Serializable:
//
// private void writeObject(ObjectOutputStream oos) throws IOException {
// oos.writeObject(s)
// oos.writeObject(i)
// oos.writeObject(l)
// oos.writeObject(m)
// }
//
// private void readObject(ObjectInputStream ois)
// throws IOException, ClassNotFoundException {
// s = ois.readObject()
// i = ois.readObject()
// l = ois.readObject()
// m = ois.readObject()
// }
}
// deep copy by using default #AutoClone semantics and overriding
// clone() method
#Canonical
#AutoClone
class Baz {
String s
Integer i
def l = []
def m = [:]
def clone() {
def cp = super.clone()
cp.s = s.class.newInstance(s)
cp.i = i.class.newInstance(i)
cp.l = cp.l.collect { it.getClass().newInstance(it) }
cp.m = cp.m.collectEntries { k, v ->
[k.getClass().newInstance(k), v.getClass().newInstance(v)]
}
cp
}
}
// assert differences
def a = new Bar("foo", 10, ['bar', 'baz'], [mu: 1, qux: 2])
def b = a.clone()
assert_diffs(a, b)
a = new Baz("foo", 10, ['bar', 'baz'], [mu: 1, qux: 2])
b = a.clone()
assert_diffs(a, b)
I used #Canonical for the equals() method and tuple ctor. See groovy doc Chapter 3.4.2, Code Generation Transformations.
Another way to go about deep copying is using mixins. Let's say you wanted an existing class to have deep copy functionality:
class LinkedHashMapDeepCopy {
def deep_copy() {
collectEntries { k, v ->
[k.getClass().newInstance(k), v.getClass().newInstance(v)]
}
}
}
class ArrayListDeepCopy {
def deep_copy() {
collect { it.getClass().newInstance(it) }
}
}
LinkedHashMap.mixin(LinkedHashMapDeepCopy)
ArrayList.mixin(ArrayListDeepCopy)
def foo = [foo: 1, bar: 2]
def bar = foo.deep_copy()
assert foo == bar
assert ! foo.is(bar)
assert ! foo['foo'].is(bar['foo'])
foo = ['foo', 'bar']
bar = foo.deep_copy()
assert foo == bar
assert ! foo.is(bar)
assert ! foo[0].is(bar[0])
Or categories (again see the groovy doc) if you wanted deep copying semantics based on some sort of runtime context:
import groovy.lang.Category
#Category(ArrayList)
class ArrayListDeepCopy {
def clone() {
collect { it.getClass().newInstance(it) }
}
}
use(ArrayListDeepCopy) {
def foo = ['foo', 'bar']
def bar = foo.clone()
assert foo == bar
assert ! foo.is(bar)
assert ! foo[0].is(bar[0]) // deep copying semantics
}
def foo = ['foo', 'bar']
def bar = foo.clone()
assert foo == bar
assert ! foo.is(bar)
assert foo[0].is(bar[0]) // back to shallow clone
For Json (LazyMap) this wokred for me
copyOfMap = new HashMap<>()
originalMap.each { k, v -> copyOfMap.put(k, v) }
copyOfMap = new JsonSlurper().parseText(JsonOutput.toJson(copyOfMap))
EDIT: Simplification by: Ed Randall
copyOfMap = new JsonSlurper().parseText(JsonOutput.toJson(originalMap))
I've just hit this issue as well, and I just found:
deepCopy = evaluate(original.inspect())
Although I've been coding in Groovy for less than 12 hours, I wonder if there might be some trust issues with using evaluate. Also, the above doesn't handle backslashes. This:
deepCopy = evaluate(original.inspect().replace('\\','\\\\'))
does.
I am afraid you have to do it the clone way. You could give Apache Commons Lang SerializationUtils a try

Resources