Create nested map from key in groovy - dictionary

I'm relatively new to groovy and am using it in the context of a gradle build. So please don't be harsh if there is an easy out-of-the-box solution for this.
Basically I'm trying to accomplish the reverse of Return Nested Key in Groovy. That is, I have some keys read from the System.properties map for example user.home and corresponding values like C:\User\dpr. Now I want to create a map that reflects this structure to use it in a groovy.text.SimpleTemplateEngine as bindings:
[user : [home : 'C:\Users\dpr']]
The keys may define an arbitrary deep hierarchy. For example java.vm.specification.vendor=Oracle Corporation should become:
[java : [vm : [spec : [vendor : 'Oracle Corporation']]]]
Additionally there are properties with the same parents such as user.name=dpr and user.country=US:
[
user: [
name: 'dpr',
country: 'US'
]
]
Edit: While ConfigSlurper is really nice, it is somewhat too defensive with creating the nested maps as it stops nesting at the minimum depth of a certain key.
I currently ended up using this
def bindings = [:]
System.properties.sort().each {
def map = bindings
def split = it.key.split("\\.")
for (int i = 0; i < split.length; i++) {
def part = split[i];
// There is already a property value with the same parent
if (!(map instanceof Map)) {
println "Skipping property ${it.key}"
break;
}
if (!map.containsKey(part)) {
map[part] = [:]
}
if (i == split.length - 1) {
map[part] = it.value
} else {
map = map[part]
}
}
map = it.value
}
With this solution the properties file.encoding.pkg, java.vendor.url and java.vendor.url.bug are discarded, which is not nice but something I can cope with.
However the above code is not very groovyish.

You can use a ConfigSlurper :
def conf = new ConfigSlurper().parse(System.properties)
println conf.java.specification.version

Related

Akka Multi Node Testing available in Java?

I have read the Akka Java documentation about Multi Node Testing, however all codes are in Scala. Is there any reason for that? Google search was unsuccessful as well.
EDIT:
To reduce the tumbleweedness of this question, I did try :). A simple translation to Java of the existing Scala codes migth look like this:
public class ClusterTest {
protected RoleName first;
#Test
public void SimpleClusterListenerClusterJoinTest() throws Exception {
new MultiNodeSpec(new MultiNodeConfig() {{
first = this.role("first");
second = this.role("second");
third = this.role("third");
this.commonConfig(ConfigFactory.parseString(
"akka.crdt.convergent.leveldb.destroy-on-shutdown = on\n" +
"akka.actor.provider = akka.cluster.ClusterActorRefProvider\n" +
"akka.cluster.auto-join = off\n" +
"akka.cluster.auto-down = on\n" +
"akka.loggers = [\"akka.testkit.TestEventListener\"]\n" +
"akka.loglevel = INFO\n" +
"akka.remote.log-remote-lifecycle-events = off")); }}) {
{
Address firstAddress = node(first).address();
#SuppressWarnings("serial")
ArrayList<RoleName> firstnode = new ArrayList<RoleName>() {{
add(first);
}};
Seq<RoleName> fisrtnodeseq = (Seq<RoleName>)JavaConversions.asScalaBuffer(firstnode).toList();
runOn(fisrtnodeseq, null);
Cluster cluster = new Cluster((ExtendedActorSystem) system());
cluster.join(firstAddress);
// verify that single node becomes member
cluster.subscribe(testActor(), MemberEvent.class);
expectMsg(MemberUp.class);
}
#Override
public int initialParticipants() {
return roles().size();
}};
}
}
HOWEVER During the run with the arguments:
-Dmultinode.max-nodes=4 -Dmultinode.host=127.0.0.1 etc. according to Multi Node Testing (if I list here all of the arguments the editor heavily complains :[ ) I will get the following error:
java.lang.IllegalArgumentException: invalid ActorSystem name [ClusterTest_2], must contain only word characters (i.e. [a-zA-Z0-9] plus non-leading '-')
at akka.actor.ActorSystemImpl.<init>(ActorSystem.scala:497)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:141)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:118)
at akka.remote.testkit.MultiNodeSpec.<init>(MultiNodeSpec.scala:252)
at com.akkamint.demo.ClusterTest$2.<init>(ClusterTest.java:51)
is the internally generated ActorSystem name wrong?
Besides this I have two questions:
How can access the gossips from Java as in the Scala code,
awaitCond(Cluster(system).latestGossip.members.exists(m ⇒ m.address == firstAddress && m.status == Up))
and I have not found any way to implement the same in Java. My workaround is to subscribe to member events (see above), otherwise I do not know, is this effectively the same or not?
Thunk function (the second argument of runOn method)? What is that? How can use it?

How do I add multiple Groovy map entries without overwriting the current entries?

My question with Groovy Maps. I've been searching for a way to programmatically add a new entry to a Groovy map without overwriting the current entry. For example
def editsMap = [:]
lineEdits.flag.each
{ lineEdits_Flag ->
editsMap.put('FlagId',lineEdits_Flag.id)
editsMap.put('FlagMnemonic',lineEdits_Flag.mnemonic)
editsMap.put('Action',lineEdits_Flag.action)
println "editsMap: ${editsMap}"
}
The first pass produces this map:
editsMap: [FlagId:10001, FlagMnemonic:TRA, Action:review]
But the second pass overwrites the first pass with:
editsMap: [FlagId:10002, FlagMnemonic:REB, Action:deny]
What I'm trying to do is create multiple entries within the one map. I need my map to populate something like this:
editsMap: [FlagId:10001, FlagMnemonic:TRA, Action:review]
editsMap: [FlagId:10002, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:10003, FlagMnemonic:UNB, Action:deny]
editsMap: [FlagId:20001, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:20002, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:30001, FlagMnemonic:REB, Action:deny]
editsMap: [FlagId:40001, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:40002, FlagMnemonic:MPR, Action:review]
editsMap: [FlagId:50001, FlagMnemonic:CPT, Action:deny]
editsMap: [FlagId:60001, FlagMnemonic:DTU, Action:deny]
editsMap: [FlagId:70001, FlagMnemonic:ICD, Action:review]
editsMap: [FlagId:70002, FlagMnemonic:MPR, Action:review]
Once I have populated my map then I need to be able to find certain values in order to process a message. I believe that I can use something like:
def thisValue = appliedEditsMap[FlagId, '10001'] ?: "default"
to do a quick lookup.
Can someone help me understand how to programmatically add values to a Groovy map without overwriting the values already in the map?
You want something like Guava's MultiMap:
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
// Getting values
Collection<string> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
This guy makes a pure Groovy emulation of Multimap:
class GroovyMultimap {
Map map = [:]
public boolean put(Object key, Object value) {
List list = map.get(key, [])
list.add(value)
map."$key" = list
}
}
You can use putAt and getAt for syntatic sugar in map operations. You can also try a mixin in a map object.
He also uses Groovy with Guava's multimap:
List properties = ['value1', 'value2', 'value3']
Multimap multimap = list.inject(LinkedListMultimap.create()) {
Multimap map, object ->
properties.each {
map.put(it, object."$it")
}
map
}
properties.each {
assertEquals (multimap.get(it), list."$it")
}
I came across this several years ago as an answer to a similar question on another site. I can't find where it originally came from so if anyone knows the source please post it here.
LinkedHashMap.metaClass.multiPut << { key, value ->
delegate[key] = delegate[key] ?: []; delegate[key] += value
}
def myMap = [:]
myMap.multiPut("a", "1")
myMap.multiPut("a", "2")
myMap.multiPut("a", "3")
myMap.each {key, list ->
println '${key} -> ${list}'
}
Gives:
a -> 1,2,3
The use of the injected multiPut() method does the magic.
You could also do something like this:
// Dummy map for testing
lineEdits = [ flag:[
[id:10001, mnemonic:'TRA', action:'review'],
[id:10002, mnemonic:'REB', action:'deny'],
[id:10003, mnemonic:'UNB', action:'deny'],
[id:20001, mnemonic:'REB', action:'deny'],
[id:20002, mnemonic:'ICD', action:'review'],
[id:30001, mnemonic:'REB', action:'deny'],
[id:40001, mnemonic:'ICD', action:'review'],
[id:40002, mnemonic:'MPR', action:'review'],
[id:50001, mnemonic:'CPT', action:'deny'],
[id:60001, mnemonic:'DTU', action:'deny'],
[id:70001, mnemonic:'ICD', action:'review'],
[id:70002, mnemonic:'MPR', action:'review'] ] ]
def editsMap = lineEdits.flag
.groupBy { it.id } // Group by id
.collectEntries { k, v ->
[ k, v[ 0 ] ] // Just grab the first one (flatten)
}
assert editsMap[ 60001 ] == [ id:60001, mnemonic:'DTU', action:'deny' ]
If you want to do the multimap thing without external classes, you can just store a map of lists instead, the syntax won't be cumbersome or anything.
def editsMap = [:].withDefault{[]}
lineEdits.flag.each
{
lineEdits_Flag ->
editsMap.FlagId << lineEdits_Flag.id
editsMap.FlagMnemonic << lineEdits_Flag.mnemonic
editsMap.Action << lineEdits_Flag.action
println "editsMap: ${editsMap}"
}
or if you really preferred your original syntax it would look like:
editsMap.get('FlagId').add(lineEdits_Flag.id)
or even this should work:
editsMap.get('FlagId') << lineEdits_Flag.id
The advantage of this solution is that it tends to be more obvious what you are doing... for instance it's not a magic map that converts single items to a list (which is not the standard map contract) but it's always a map of lists that you simply use as a map of lists.
The .get will always work the same way the multimap was described--it will always return the list for that item in the map.
A map is a set of key-value mappings, you plug in different values by key so that you can use the key to find them later. Your example is plugging in values for the same keys over and over. You need to pick unique keys.
Make some class to store your values for one entry in the map:
class Stuff {
String flagMnemonic
String action
}
Make a map where you will use flagId as the key (because that's how you identify the flag uniquely) and Stuff as the value (because it's the data you want to lookup).
def editsMap = [:]
If you used type declarations here, and if flagId is a String, the map's type would be Map<String, Stuff>.
Now you can put stuff in the map:
lineEdits.flag.each { lineEdits_Flag ->
editsMap[lineEdits_Flag.id] =
new Stuff(
flagMnemonic: lineEdits_Flag.mnemonic,
action: lineEdits_Flag.action)
}
and get it back out with
def myStuffFor10001 = editsMap['10001']
println myStuffFor10001.flagMnemonic // should equal 'TRA'
println myStuffFor10001.action // should equal 'review'
Also there's an easy alternative to using ?: "default" to set default values, you can use withDefault when creating your map:
def defaultStuff = new Stuff(
flagMnemonic: "defaultMnemonic", action:"defaultAction")
def editsMap = [:].withDefault { defaultStuff }
so that whenever you ask for something from the map that is not present there, you get the specified default object.
Why not use a list and closure like:
editsList = [
[FlagId:10001, FlagMnemonic:TRA, Action:review],
[FlagId:10002, FlagMnemonic:REB, Action:deny],
[FlagId:10003, FlagMnemonic:UNB, Action:deny],
[FlagId:20001, FlagMnemonic:REB, Action:deny],
[FlagId:20002, FlagMnemonic:ICD, Action:review],
[FlagId:30001, FlagMnemonic:REB, Action:deny],
[FlagId:40001, FlagMnemonic:ICD, Action:review],
[FlagId:40002, FlagMnemonic:MPR, Action:review],
[FlagId:50001, FlagMnemonic:CPT, Action:deny],
[FlagId:60001, FlagMnemonic:DTU, Action:deny],
[FlagId:70001, FlagMnemonic:ICD, Action:review],
[FlagId:70002, FlagMnemonic:MPR, Action:review]
]
def appliedEditsMap = {property,idValue->
return editsList.find{it[property] == idValue}
}
def thisValue = appliedEditsMap(FlagId, '10001') ?: "default"
You need to put this in to a class and then add that class in to the Map. From what I see your information is related so having a class to store makes sense unless I'm missing anything
What you can do is define your class as
class Flag {
String flagID
String flagMnemonic
String action
}
Now Put your Flag in to your map as
editsMap.put(10000,newFlag(flagID:'10000',flagMnemonic:'TES',action:'tes'))
I had a similar issue recently and I knew it was possible because some coworkers had done it. Reading the answers here and experimenting, I finally found a simple answer that worked for my use-case and isn't difficult to read. Writing a "generic code" answer makes this a little less readable than it is in our code with the proper column names, etc...
In my case, I was getting a List<Map> back from a repo query; I needed something like Map<String, List<Object>> and I need to add to the List if a result set's key matched a previous one. Of course, my Object wasn't a POJO, but you can use any Class. And to further complicate it, I needed to create a composite key from a few of the result values (don't ask, I didn't create it) and remove those keys from the original Map so I could use the remaining entries to create a business Object.
Here's what I did:
List<Map> listMap = repo.findWhateverItWas()
Map<String, List<Object>> resultMap = [:].withDefault {[]} //required to avoid NPE
listMap.each { Map<String, Object> it ->
String compKey = it['col1'] + it['col2'] + it['col3']
Map tempMap =[:]
it.keySet.each { k ->
if (!(k in ['col1','col2','col3'])) {
tempMap << [(k): it[k]] // this is the business Object result map
}
}
// createEntity is a static Entity Factory
// the simple += is the magic
resultMap[(compKey)] += createEntity(Entity.class, tempMap)
}
return resultMap
I realize this doesn't address your specific scenario, but I do believe it answers the question and provides an answer for a more complex situation.
I was able to prove the expected functionality of this with a simple test case. We use Spock...
def "Map of Lists test"() {
given:
Map<String, List<String>> map = [:].withDefault { [] }
when:
map['key1'] += 'item1'
map['key1'] += 'item2'
map['key2'] += 'item3'
map['key1'] += 'item4'
map['key2'] += 'item5'
then:
map['key1'] == ['item1', 'item2', 'item4']
map['key2'] == ['item3', 'item5']
}

remove duplicates from collection

I want to get a list of all Locales that have a different language, where the ISO3 code is used to identify the language of a Locale. I thought the following should work
class ISO3LangComparator implements Comparator<Locale> {
int compare(Locale locale1, Locale locale2) {
locale1.ISO3Language <=> locale2.ISO3Language
}
}
def allLocales = Locale.getAvailableLocales().toList()
def uniqueLocales = allLocales.unique {new ISO3LangComparator()}
// Test how many locales there are with iso3 code 'ara'
def arabicLocaleCount = uniqueLocales.findAll {it.ISO3Language == 'ara'}.size()
// This assertion fails
assert arabicLocaleCount <= 1
You are using the wrong syntax: you are using Collection.unique(Closure closure):
allLocales.unique {new ISO3LangComparator()}
You should use Collection.unique(Comparator comparator)
allLocales.unique (new ISO3LangComparator())
So simply use () instead of {}, and your problem is solved.
what Adam said.
or...
allLocales.unique{it.ISO3Language}
and you forget about the comparator

Dynamic properties in Scala

Does Scala support something like dynamic properties? Example:
val dog = new Dynamic // Dynamic does not define 'name' nor 'speak'.
dog.name = "Rex" // New property.
dog.speak = { "woof" } // New method.
val cat = new Dynamic
cat.name = "Fluffy"
cat.speak = { "meow" }
val rock = new Dynamic
rock.name = "Topaz"
// rock doesn't speak.
def test(val animal: Any) = {
animal.name + " is telling " + animal.speak()
}
test(dog) // "Rex is telling woof"
test(cat) // "Fluffy is telling meow"
test(rock) // "Topaz is telling null"
What is the closest thing from it we can get in Scala? If there's something like "addProperty" which allows using the added property like an ordinary field, it would be sufficient.
I'm not interested in structural type declarations ("type safe duck typing"). What I really need is to add new properties and methods at runtime, so that the object can be used by a method/code that expects the added elements to exist.
Scala 2.9 will have a specially handled Dynamic trait that may be what you are looking for.
This blog has a big about it: http://squirrelsewer.blogspot.com/2011/02/scalas-upcoming-dynamic-capabilities.html
I would guess that in the invokeDynamic method you will need to check for "name_=", "speak_=", "name" and "speak", and you could store values in a private map.
I can not think of a reason to really need to add/create methods/properties dynamically at run-time unless dynamic identifiers are also allowed -and/or- a magical binding to an external dynamic source (JRuby or JSON are two good examples).
Otherwise the example posted can be implemented entirely using the existing static typing in Scala via "anonymous" types and structural typing. Anyway, not saying that "dynamic" wouldn't be convenient (and as 0__ pointed out, is coming -- feel free to "go edge" ;-).
Consider:
val dog = new {
val name = "Rex"
def speak = { "woof" }
}
val cat = new {
val name = "Fluffy"
def speak = { "meow" }
}
// Rock not shown here -- because it doesn't speak it won't compile
// with the following unless it stubs in. In both cases it's an error:
// the issue is when/where the error occurs.
def test(animal: { val name: String; def speak: String }) = {
animal.name + " is telling " + animal.speak
}
// However, we can take in the more general type { val name: String } and try to
// invoke the possibly non-existent property, albeit in a hackish sort of way.
// Unfortunately pattern matching does not work with structural types AFAIK :(
val rock = new {
val name = "Topaz"
}
def test2(animal: { val name: String }) = {
animal.name + " is telling " + (try {
animal.asInstanceOf[{ def speak: String }).speak
} catch { case _ => "{very silently}" })
}
test(dog)
test(cat)
// test(rock) -- no! will not compile (a good thing)
test2(dog)
test2(cat)
test2(rock)
However, this method can quickly get cumbersome (to "add" a new attribute one would need to create a new type and copy over the current data into it) and is partially exploiting the simplicity of the example code. That is, it's not practically possible to create true "open" objects this way; in the case for "open" data a Map of sorts is likely a better/feasible approach in the current Scala (2.8) implementation.
Happy coding.
First off, as #pst pointed out, your example can be entirely implemented using static typing, it doesn't require dynamic typing.
Secondly, if you want to program in a dynamically typed language, program in a dynamically typed language.
That being said, you can actually do something like that in Scala. Here is a simplistic example:
class Dict[V](args: (String, V)*) extends Dynamic {
import scala.collection.mutable.Map
private val backingStore = Map[String, V](args:_*)
def typed[T] = throw new UnsupportedOperationException()
def applyDynamic(name: String)(args: Any*) = {
val k = if (name.endsWith("_=")) name.dropRight(2) else name
if (name.endsWith("_=")) backingStore(k) = args.first.asInstanceOf[V]
backingStore.get(k)
}
override def toString() = "Dict(" + backingStore.mkString(", ") + ")"
}
object Dict {
def apply[V](args: (String, V)*) = new Dict(args:_*)
}
val t1 = Dict[Any]()
t1.bar_=("quux")
val t2 = new Dict("foo" -> "bar", "baz" -> "quux")
val t3 = Dict("foo" -> "bar", "baz" -> "quux")
t1.bar // => Some(quux)
t2.baz // => Some(quux)
t3.baz // => Some(quux)
As you can see, you were pretty close, actually. Your main mistake was that Dynamic is a trait, not a class, so you can't instantiate it, you have to mix it in. And you obviously have to actually define what you want it to do, i.e. implement typed and applyDynamic.
If you want your example to work, there are a couple of complications. In particular, you need something like a type-safe heterogenous map as a backing store. Also, there are some syntactic considerations. For example, foo.bar = baz is only translated into foo.bar_=(baz) if foo.bar_= exists, which it doesn't, because foo is a Dynamic object.

Reflection on a Scala case class

I'm trying to write a trait (in Scala 2.8) that can be mixed in to a case class, allowing its fields to be inspected at runtime, for a particular debugging purpose. I want to get them back in the order that they were declared in the source file, and I'd like to omit any other fields inside the case class. For example:
trait CaseClassReflector extends Product {
def getFields: List[(String, Any)] = {
var fieldValueToName: Map[Any, String] = Map()
for (field <- getClass.getDeclaredFields) {
field.setAccessible(true)
fieldValueToName += (field.get(this) -> field.getName)
}
productIterator.toList map { value => fieldValueToName(value) -> value }
}
}
case class Colour(red: Int, green: Int, blue: Int) extends CaseClassReflector {
val other: Int = 42
}
scala> val c = Colour(234, 123, 23)
c: Colour = Colour(234,123,23)
scala> val fields = c.getFields
fields: List[(String, Any)] = List((red,234), (green,123), (blue,23))
The above implementation is clearly flawed because it guesses the relationship between a field's position in the Product and its name by equality of the value on those field, so that the following, say, will not work:
Colour(0, 0, 0).getFields
Is there any way this can be implemented?
Look in trunk and you'll find this. Listen to the comment, this is not supported: but since I also needed those names...
/** private[scala] so nobody gets the idea this is a supported interface.
*/
private[scala] def caseParamNames(path: String): Option[List[String]] = {
val (outer, inner) = (path indexOf '$') match {
case -1 => (path, "")
case x => (path take x, path drop (x + 1))
}
for {
clazz <- getSystemLoader.tryToLoadClass[AnyRef](outer)
ssig <- ScalaSigParser.parse(clazz)
}
yield {
val f: PartialFunction[Symbol, List[String]] =
if (inner.isEmpty) {
case x: MethodSymbol if x.isCaseAccessor && (x.name endsWith " ") => List(x.name dropRight 1)
}
else {
case x: ClassSymbol if x.name == inner =>
val xs = x.children filter (child => child.isCaseAccessor && (child.name endsWith " "))
xs.toList map (_.name dropRight 1)
}
(ssig.symbols partialMap f).flatten toList
}
}
Here's a short and working version, based on the example above
trait CaseClassReflector extends Product {
def getFields = getClass.getDeclaredFields.map(field => {
field setAccessible true
field.getName -> field.get(this)
})
}
In every example I've seen the fields are in reverse order: the last item in the getFields array is the first one listed in the case class. If you use case classes "nicely", then you should just be able to map productElement(n) onto getDeclaredFields()( getDeclaredFields.length-n-1).
But this is rather dangerous, as I don't know of anything in the spec that insists that it must be that way, and if you override a val in the case class, it won't even appear in getDeclaredFields (it'll appear in the fields of that superclass).
You might change your code to assume things are this way, but check that the getter method with that name and the productIterator return the same value and throw an exception if they don't (which means that you don't actually know what corresponds to what).
You can also use the ProductCompletion from the interpreter package to get to attribute names and values of case classes:
import tools.nsc.interpreter.ProductCompletion
// get attribute names
new ProductCompletion(Colour(1, 2, 3)).caseNames
// returns: List(red, green, blue)
// get attribute values
new ProductCompletion(Colour(1, 2, 3)).caseFields
Edit: hints by roland and virtualeyes
It is necessary to include the scalap library which is part of the scala-lang collection.
Thanks for your hints, roland and virtualeyes.

Resources