How to pass values instead of Vector in foreach loop? - scala

My Reponse is:
[
{"id":106455,"assetId":482282,"masterKeyframeId":157060,"closed":false},
{"id":106661,"assetId":502174,"masterKeyframeId":169193,"closed":false}
{.....and so many...}
]
I have fetched "assetId" and "masterKeyframeId" correctly using below request, but the problem is how do I set both values in foreach loop? (I have used "aid" and it fetches single value but don't know about passing single value for "mkeyframeId" as it takes Vector)
.exec(http("request_7")
.get(uri3 + "/sortBy=SEGGREGATED_SESSION_SORT;reviewState=IN_PROGRESS")
.check(jsonPath("$..assetId").findAll.saveAs("astId"))
.check(jsonPath("$..masterKeyframeId").findAll.saveAs("mkeyframeId"))
.headers(headers_7)
)
.foreach("${astId}", "aid") {
doIf(session => session("aid").as[String] != "-1")
{
exec(http("Set_IDs")
.get("/a/" + accountname + "/assets/${aid}/keyframe/${mkeyframeId}")
)
}
}
Here the problem is ${mkeyframeId} it takes vector and pass in url like this,
Sending request=Set_IDs uri=https://qa1.net/a/hbmin1ac/assets/482282/keyframe/Vector(157060,%20169193):
Instead of
https://qa1.net/a/hbmin1ac/assets/482282/keyframe/157060
https://qa1.net/a/hbmin1ac/assets/502174/keyframe/169193
Thanks.

You should try something like this:
.foreach("${astId}", "aid", "counter") {
doIf { session =>
for {
aid <- session("aid").validate[String]
} yield aid != "-1"
} {
exec(http("Set_IDs")
.get { session =>
for {
aid <- session("aid").validate[String]
mkeyframeId <- session("mkeyframeId").validate[Seq[String]]
c <- session("counter").validate[Int]
} yield s"/a/$accountname/assets/$aid/keyframe/${mkeyframeId(c)}"
}
)
}
}
You can write the doIf block like this too:
doIf( _("aid").validate[String].map(_ != "-1"))

Related

How to provide the output result of a function as a PUT request in scala?

i have a scala code that converts a layer to a Geotiff file. Now i want this Geotiff file to be passed in a PUT request as a REST service. How can i do that?
Here is a section of code:
val labeled_layerstack =
{
//Labeled Layerstack
//val layers_input = Array(layer_dop) ++ layers_sat
val layers_labeled_input = Array(layer_label) ++ Array(output_layerstack) //++ layers_input
ManyLayersToMultibandLayer(layers_labeled_input, output_labeled_layerstack)
output_labeled_layerstack
}
if (useCleanup) {
DeleteLayer(layer_label)
if(useDOP)
DeleteLayer(layer_dop)
for( layer_x <- layers_sat)
DeleteLayer(layer_x)
}
labeled_layerstack
}
else output_labeled_layerstack //if reusing existing layerstack ( processing steps w/o "layerstack")
if(processingSteps.isEmpty || processingSteps.get.steps.exists(step => step == "classification")) {
if (useRandomForest) {
ClusterTestRandomForest(labeled_layerstack, fileNameClassifier, layerResult, Some(output_layerstack))
if (useExportResult) {
LayerToGeotiff(layerResult, fileNameResult, useStitching = useExportStitching)
}
}
else if (useSVM) {
ClusterTestSVM(labeled_layerstack, fileNameClassifier, layerResult, Some(output_layerstack))
if (useExportResult) {
LayerToGeotiff(layerResult, fileNameResult, useStitching = useExportStitching)
}
}
}
The original code is quite long and is not shareable so i am sharing this which is relevant to the problem. The output of LayertoGeotiff should be passed as an PUT request. How can i create such a request?
I suggest to you the Play framework to send a PUT request

How can I reduce the redundancies of the fields handling of feed handler

I am subscript to a message feed for a number of fields, I need to set the values from the feed to the domain object and have code like below:
if (map.contains(quoteBidPriceAcronym)) {
quote.bid.price = Some(map.get(quoteBidPriceAcronym).get.asInstanceOf[Number].doubleValue());
quote.changed = true;
}
if (map.contains(quoteBidSizeAcronym)) {
quote.bid.size = Some(sizeMultipler() * map.get(quoteBidSizeAcronym).get.asInstanceOf[Number].intValue());
quote.changed = true;
}
if (map.contains(quoteBidNumAcronym)) {
quote.bid.num = Some(map.get(quoteBidNumAcronym).get.asInstanceOf[Number].shortValue());
quote.changed = true;
}
if (map.contains(quoteAskPriceAcronym)) {
quote.ask.price = Some(map.get(quoteAskPriceAcronym).get.asInstanceOf[Number].doubleValue());
quote.changed = true;
}
if (map.contains(quoteAskSizeAcronym)) {
quote.ask.size = Some(sizeMultipler() * map.get(quoteAskSizeAcronym).get.asInstanceOf[Number].intValue());
quote.changed = true;
}
if (map.contains(quoteAskNumAcronym)) {
quote.ask.num = Some(map.get(quoteAskNumAcronym).get.asInstanceOf[Number].shortValue());
quote.changed = true;
}
if (map.contains(quoteExchTimeAcronym)) {
quote.exchtime = getExchTime(String.valueOf(map.get(quoteExchTimeAcronym).get));
}
It look pretty redundant, any suggestion to improve it?
You can do something like:
map.get(quoteBidPriceAcronym).map { item =>
quote.bid.price = item.map(_.asInstanceOf[Number].doubleValue())
quote.changed = true
}
Other issues might be better to fix outside. E.g. why map[quoteBidPriceAcronym] is storing an Option, if your code assumes it's not going to be None?
Something like this perhaps?
val handlers = Map[String, Number => Unit] (
quoteBidPriceAcronym -> { n => quote.bid.price = Some(n.doubleValue) },
quoteBidSizeAcronym -> { n => quote.bid.size = Some(sizeMultipler() * n.intValue },
etc. ...
)
for {
(k,handler) <- handlers
values <- map.get(k).toSeq
quote.chanded = true
_ = handler(n.asInstanceof[Number])
}
Personally, I don't like code changing an object state (quote) but this is a question on Scala, not functional programming.
That said I would reverse the way you are using you map map keys. Instead of checking whether a value exists to perform some action, I'd have a map from your keys to actions and I'd iterate over your map elements.
e.g (assuming map is of the type Map[String, Any]):
val actions: Map[String, PartialFunction[Any, Unit]] = Map(
(quoteBidPriceAcronym, {case n: Number => quote.bid.price = Some(n.doubleValue())}),
(quoteBidSizeAcronym, {case n: Number => quote.bid.size = Some(sizeMultipler() * n.doubleValue())}),
...
...
)
for((k,v) <- map; action <- actions.get(k); _ <- action.lift(v))
quote.changed = true;
The for construct here iterates over map key-values, then (next level of iteration, over the possible action available for the key. If an action is found, which is a partial function, it gets lifted to make it a function from Any to Option[Unit]. That way, you can iterate in an additional inner level so quote.changed = true is only run when the action is defined for v.

removing elements from a sequence using for/yield

Given a Future[Seq[Widget]], where Widget contains a amount : Int property, I'd like to return a Seq[Widget] but for only those Widgets whose amount value is greater than 100. I believe the for { if … } yield { } construct will give me what I want but am unsure how to filter through the Sequence. I have:
val myWidgetFuture : Future[Seq[Widget]] = ...
for {
widgetSeq <- myWidgetFuture
if (??? amount > 100) <— what to put here?
} yield {
widgetSeq
}
If there's a clean non-yield way of doing this that will also work for me.
You don't even need yield. Use map.
val myWidgetFuture: Future[Seq[Widget]] = ???
myWidgetFuture map { ws => ws filter (_.amount > 100) }
If you want to use for … yield with an if filter, you'll need to use two fors:
for {
widgetSeq <- myWidgetFuture
} yield for {
widget <- widgetSeq
if widget.amount > 100
} yield widget

how to setup a for loop inside if statement with correct syntax Play framework Scala Template

I am trying to setup a variable in the scala template. Loop through the roles that user have , if found out the user is customer , then do something with the input. If not then do something else.
But scala isnt that simple , it won't compile on following code.
#var = #{ if(user != null){
#for(role <- user.roles.filter(_.getName()=="customer")) {
var=#customer(input)
}
}
}
#if( var == null){
var=#others(input)
}
It gives me two errors
t.scala.html:275:: identifier expected but 'for' found.
[error] #for(role <- user.roles.filter(_.getName()=="customer"))
t.scala.html:278: expected start of definition
Also , is there a better way to do this in scala ? Thanks
My reference : Scala template set variable
Update:
My goal was trying to do something like below , but in scala template:
result=null
for role in User.roles:
if(role == "customer"):
result=customer(xyz)
break
if(result==null):
result = others(xyz)
To set up a for loop inside of an if statement in a Scala template, you don't need to assign a variable. You can simply use an if block in the template where you want to display stuff. For example
#if(user != null) {
#for(role <- user.roles.filter(_.getName()=="customer")) {
#customer(input)
#* Do other stuff related to 'role' and 'input' here *#
}
} else {
#* Do something else *#
}
For further reference I encourage you to look at the documentation for Play templates. If you really want to define a variable you could do it using the defining helper:
#defining(user.getFirstName() + " " + user.getLastName()) { fullName =>
<div>Hello #fullName</div>
}
Instead of defining a variable you could also define a resusable block, which might be useful in your case. For example,
#customer_loop(input: String) = {
#if(user != null) {
#for(role <- user.roles.filter(_.getName()=="customer")) {
#customer(input)
#* Do other stuff related to 'role' and 'input' here *#
}
} else {
#* Do something else *#
}
}
To declare a variable do
#import scala.Any; var result:Any=null //where Any is the datatype accoding to your requirement
To reassign its value do
#{result = "somevalue"}
So the solution accoding to the pseudo you provided
#import java.lang.String; var result:String=null
#import scala.util.control._;val loop = new Breaks;
#loop.breakable {
#for(role <- roleList) {
#if(role.equals("customer")) {
#{
result = "somevalue"
}
#{loop.break};
}
}
}
#if(result==null){
#{result="notfound"}
}
Also check Similar1,Similar2

Copy Groovy class properties

I want to copy object properties to another object in a generic way (if a property exists on target object, I copy it from the source object).
My code works fine using ExpandoMetaClass, but I don't like the solution. Are there any other ways to do this?
class User {
String name = 'Arturo'
String city = 'Madrid'
Integer age = 27
}
class AdminUser {
String name
String city
Integer age
}
def copyProperties(source, target) {
target.properties.each { key, value ->
if (source.metaClass.hasProperty(source, key) && key != 'class' && key != 'metaClass') {
target.setProperty(key, source.metaClass.getProperty(source, key))
}
}
}
def (user, adminUser) = [new User(), new AdminUser()]
assert adminUser.name == null
assert adminUser.city == null
assert adminUser.age == null
copyProperties(user, adminUser)
assert adminUser.name == 'Arturo'
assert adminUser.city == 'Madrid'
assert adminUser.age == 27
I think the best and clear way is to use InvokerHelper.setProperties method
Example:
import groovy.transform.ToString
import org.codehaus.groovy.runtime.InvokerHelper
#ToString
class User {
String name = 'Arturo'
String city = 'Madrid'
Integer age = 27
}
#ToString
class AdminUser {
String name
String city
Integer age
}
def user = new User()
def adminUser = new AdminUser()
println "before: $user $adminUser"
InvokerHelper.setProperties(adminUser, user.properties)
println "after : $user $adminUser"
Output:
before: User(Arturo, Madrid, 27) AdminUser(null, null, null)
after : User(Arturo, Madrid, 27) AdminUser(Arturo, Madrid, 27)
Note: If you want more readability you can use category
use(InvokerHelper) {
adminUser.setProperties(user.properties)
}
I think your solution is quite good and is in the right track. At least I find it quite understandable.
A more succint version of that solution could be...
def copyProperties(source, target) {
source.properties.each { key, value ->
if (target.hasProperty(key) && !(key in ['class', 'metaClass']))
target[key] = value
}
}
... but it's not fundamentally different. I'm iterating over the source properties so I can then use the values to assign to the target :). It may be less robust than your original solution though, as I think it would break if the target object defines a getAt(String) method.
If you want to get fancy, you might do something like this:
def copyProperties(source, target) {
def (sProps, tProps) = [source, target]*.properties*.keySet()
def commonProps = sProps.intersect(tProps) - ['class', 'metaClass']
commonProps.each { target[it] = source[it] }
}
Basically, it first computes the common properties between the two objects and then copies them. It also works, but I think the first one is more straightforward and easier to understand :)
Sometimes less is more.
Another way is to do:
def copyProperties( source, target ) {
[source,target]*.getClass().declaredFields*.grep { !it.synthetic }.name.with { a, b ->
a.intersect( b ).each {
target."$it" = source."$it"
}
}
}
Which gets the common properties (that are not synthetic fields), and then assigns them to the target
You could also (using this method) do something like:
def user = new User()
def propCopy( src, clazz ) {
[src.getClass(), clazz].declaredFields*.grep { !it.synthetic }.name.with { a, b ->
clazz.newInstance().with { tgt ->
a.intersect( b ).each {
tgt[ it ] = src[ it ]
}
tgt
}
}
}
def admin = propCopy( user, AdminUser )
assert admin.name == 'Arturo'
assert admin.city == 'Madrid'
assert admin.age == 27
So you pass the method an object to copy the properties from, and the class of the returned object. The method then creates a new instance of this class (assuming a no-args constructor), sets the properties and returns it.
Edit 2
Assuming these are Groovy classes, you can invoke the Map constructor and set all the common properties like so:
def propCopy( src, clazz ) {
[src.getClass(), clazz].declaredFields*.grep { !it.synthetic }.name.with { a, b ->
clazz.metaClass.invokeConstructor( a.intersect( b ).collectEntries { [ (it):src[ it ] ] } )
}
}
Spring BeanUtils.copyProperties will work even if source/target classes are different types. http://docs.spring.io/autorepo/docs/spring/3.2.3.RELEASE/javadoc-api/org/springframework/beans/BeanUtils.html