Why is my dataweave map code not working? - mule-studio

I'm trying to convert some code from mule 3 to mule 4 so I'm using dataweave 2. I keep getting errors from this code
keySets: if(payload.autoQuote !=null) payload.autoQuote map (autoQuote) -> {
(if(payload.autoQuote.personalAuto.vehicles != null) autoQuote.personalAuto.vehicles map ((vehicles,indexOfvehicle) ->{
keySet: {
key: if(vehicles.usage != null) vehicles.usage else 'DNF' ,
keySequence: "TAUTO_USE_TYPE" ++ '_' ++ indexOfvehicle
}
} else {}))
} else {}
On the first line I'm getting
mismatched input '->' expecting 'else'
on the second line I'm getting
- missing EOF at 'payload'
and
- no viable alternative at input '('
on the first two '('

I believe keySets is a list and not a object, you should be using [] and not {} in your else statements. I edited some of the braces, and it is compiling fine for me, though not sure if it will work as expected for you.
keySets: if(payload.autoQuote !=null) (payload.autoQuote map (autoQuote) -> {
(if(payload.autoQuote.personalAuto.vehicles != null)
autoQuote.personalAuto.vehicles map ((vehicles,indexOfvehicle) -> {
keySet: {
key: if(vehicles.usage != null) vehicles.usage else 'DNF',
keySequence: "TAUTO_USE_TYPE" ++ '_' ++ indexOfvehicle
}
}) else [])
}) else []
Give it a try and let me know if it worked.

This doesn't give me errors, though I'm not sure if it makes sense:
%dw 2.0
output application/json
---
{
keySets: if(payload.autoQuote !=null) (payload.autoQuote) map(autoQuote, i) -> {
( if(payload.autoQuote.personalAuto.vehicles != null) (autoQuote.personalAuto.vehicles) map (vehicles,indexOfvehicle) ->{
keySet: {
key: if(vehicles.usage != null) vehicles.usage else 'DNF' ,
keySequence: "TAUTO_USE_TYPE" ++ '_' ++ indexOfvehicle
}
} else {})
} else {}
}
You should give an example of the input and the expected output.
Also I'm not sure why you don't use the autoQuoteparameter of the map inside of the map instead of payload.autoQuote...

Turns out I had the parentheses wrong. The first else was in the parentheeses after the map. It should look like this. Don't know if it works but it at least compiles.
keySets: if(payload.autoQuote !=null) payload.autoQuote map (autoQuote) -> {
(if(payload.autoQuote.personalAuto.vehicles != null) autoQuote.personalAuto.vehicles map ((vehicles,indexOfvehicle) ->{
keySet: {
key: if(vehicles.usage != null) vehicles.usage else 'DNF' ,
keySequence: "TAUTO_USE_TYPE" ++ '_' ++ indexOfvehicle
}
}) else {})
} else {}

Related

Put a filter into a future

I want to execute sql statements when the type isn't fruits. This is meant by (type != "fruits" && !isFruits)
I tried the following code, but it drops an error because an else is missing. I don't need an else.
if (type != "fruits" && !isFruits) {
con.executeFuture(query).flatMap(_ => {
conn.initQuery(query, isVegetables)
if (isVegetables) {
conn.VegetableCon.get.queryFuture(RunArgs)
} else {
conn.VegetableQueryCon.get.queryFuture(RunArgs)
}
})
}
I did some research and found ".filter", so I tried the following code:
con.executeFuture(query).filter(_ => type != ("ddl") && !isFruits).flatMap(_ => {
conn.initQuery(query, isVegetables)
if (isVegetables) {
conn.VegetableCon.get.queryFuture(RunArgs)
} else {
conn.VegetableQueryCon.get.queryFuture(RunArgs)
}
})
}
It drops me the error : "Future.filter predicate is not satisfied."
Now I don't know how to solve my problem. Do you have any idea about my mistakes?

Exceptions with if else statement in Scala

if ( option != "AB" || option != "BC"|| option != "CD") {
try {
var option = dbutils.widgets.get("option")
}
catch {
case e: Exception => println("The option shoud be following AB, BC or CD " + option)
}
}
I am trying to use exception in scala
However, the widget value is not throwing an exception when I use the value such as
"XY" or any other value than AB, BC or CD.
Please can someone let me know what I am doing wrong here. Thank you
If AB,BC & CD are the valid values, then your predicate should look like this:
if(option == "AB" || option == "BC" || option == "CD")
Also, you can use the require function to enforce the predicate and throw an exception if the input doesn't match:
def getWidget(option: String) = try {
require(option == "AB" || option == "BC"|| option == "CD", s"The option shoud be following AB, BC or CD instead got $option")
dbutils.widgets.get("option")
} catch { case e: Exception => println(e) }

go insert composite type array unsupported type

sql
CREATE TABLE public.tiantang_page (
href varchar NOT NULL,
status int4 NOT NULL,
description varchar NOT NULL,
urls url[] NULL
);
CREATE TYPE url AS (
url varchar,
status int4);
insert composite type array
type url struct {
url string
status int
}
var urls [1]url
urls[0] = url{
url: "",
status: 0,
}
update := "UPDATE \"public\".\"tiantang_page\" SET \"urls\"=$1 where \"href\"=$2;"
r, err := db.Exec(update, pq.Array(urls),href)
if err != nil {
log.Fatal(err)
}
error
sql: converting argument $1 type: unsupported type parsetest.url, a struct
library
https://godoc.org/github.com/lib/pq
Note that custom composite types are not fully supported by lib/pq.
If all you want is to be able to store the urls then the simplest approach would be to implement the driver.Valuer interface on the url type and then use it as you do with pq.Array:
func (u url) Value() (driver.Value, error) {
return fmt.Sprintf("(%s,%d)", u.url, u.status), nil
}
// ...
r, err := db.Exec(update, pq.Array(urls), href)
more info on that can be found here: https://github.com/lib/pq/issues/544
Note that I haven't tried this with arrays, only with slices, so you may have to switch from using an array to using a slice, i.e. instead of var urls [1]url you would use var urls = make([]url, 1).
If you also want to be able to retrieve the array of urls back from the db, then you'll have to implement the sql.Scanner interface, however here the pq.Array is not very reliable and you'll have to implement the scanner on the slice type and do all the parsing yourself.
The general format of composite types is (val1, val2, ...) note that you have to put double quotes around values that contain commas or parentheses. For example to construct a value of the url type you would use the literal expression: (http://example.com,4). More info in the docs.
The format for an array of composite types is {"(val1, val2, ...)" [, ...]}, note that in this case if you need to put double quotes around the values you need to escape them. For example {"(http://example.com,4)","(\"http://example.com/?list=foo,bar,baz\",3)"}
So as you can see the more complex the data in the composite type the more complex will be the parsing as well.
Here's a crude example (does not handle quoted values):
type urlslice []url
func (s *urlslice) Scan(src interface{}) error {
var a []byte // the pq array as bytes
switch v := src.(type) {
case []byte:
a = v
case string:
a = []byte(v)
case nil:
*s = nil
return nil
default:
return fmt.Errorf("urlslice.Scan unexpected src type %T", src)
}
a = a[1 : len(a)-1] // drop curly braces
for i := 0; i < len(a); i++ {
if a[i] == '"' && (len(a) > (i+1) && a[i+1] == '(') { // element start?
i += 2 // move past `"(`
j := i // start of url.url
u := url{}
for ; i < len(a) && a[i] != ','; i++ {
}
u.url = string(a[j:i])
i += 1 // move past `,`
j = i // start of url.status
for ; i < len(a) && a[i] != ')'; i++ {
}
i64, err := strconv.ParseInt(string(a[j:i]), 10, 64)
if err != nil {
return err
}
u.status = int(i64)
*s = append(*s, u)
i += 2 // move past `)",`
}
}
return nil
}
for completeness, here's the Valuer interface implemented by the slice type, again not handling proper quoting of values that may require it:
func (s urlslice) Value() (driver.Value, error) {
data := []byte{'{'}
for _, url := range s {
data = append(data, '"', '(')
data = append(data, []byte(url.url)...)
data = append(data, ',')
data = strconv.AppendInt(data, int64(url.status), 10)
data = append(data, ')', '"', ',')
}
data[len(data)-1] = '}' // replace last ',' with '}' to close the array
return data, nil
}
With the urlslice implementing the two interfaces directly you can stop using pq.Array.
var urls = urlslice{{
url: "http://example.com",
status: 4,
}}
update := `UPDATE "public"."tiantang_page" SET "urls"=$1 where "href"=$2`
r, err := db.Exec(update, urls, href)
if err != nil {
log.Fatal(err)
}
var urls2 urlslice
selurls := `SELECT "urls" FROM "public"."tiantang_page" where "href" = $1`
if err := db.QueryRow(selurls, href).Scan(&urls2); err != nil {
log.Fatal(err)
}
Please keep in mind that both of the above examples should be considered only as hints of the direction to take in solving this problem. Not only are the two examples incomplete in that they don't handle quoted values, but they are also not very elegant implementations.
Reasonably complete composite literal parser:
type parseState int
const (
state_initial parseState = iota // start
state_value_start // no bytes read from value yet
state_value // unquoted value
state_quoted // inside quote
state_value_end // after a close quote
state_end // after close paren
)
func parseComposite(in []byte) ([]string, error) {
state := state_initial
ret := []string{}
val := []byte{}
for _, b := range in {
switch state {
case state_initial:
if b != '(' {
return nil, fmt.Errorf("initial character not ')': %v", in)
} else {
state = state_value_start
}
case state_value_start:
if b == '"' {
state = state_quoted
continue
}
fallthrough
case state_value:
if b == ',' {
ret = append(ret, string(val))
val = nil
state = state_value_start
} else if b == ')' {
ret = append(ret, string(val))
val = nil
state = state_end
} else {
val = append(val, b)
}
case state_quoted:
if b == '"' {
ret = append(ret, string(val))
val = nil
state = state_value_end
} else {
val = append(val, b)
}
case state_value_end:
if b == ',' {
state = state_value_start
} else if b == ')' {
state = state_end
} else {
return nil, fmt.Errorf("invalid delimiter after closing quote: %v", in)
}
case state_end:
return nil, fmt.Errorf("trailing bytes: %v", in)
}
}
if state != state_end {
return nil, fmt.Errorf("unterminated value: %v", in)
}
return ret, nil
}

How can I avoid return the input argument of lambda in RxJava?

How can I replace the following code?
return Observable.just(player1, player2)
.doOnNext(player -> player.status = // mutate status)
.flatMap(player -> {
playersDao
.savePlayerCompletable(player)
.andThen(Single.just(player));
}
)
;
I don't really like how I pass player into that lambda inside of flatMap and then I return it in Single.just. How can I get around? The idea is that I absolutely have to return that updated players (with different status) in Observable. And I don't really want to make saveReport to return Single.
EDIT: I do want to return Flowable<Player> as a result (so I don't want to lose them in RxChain).
Use a flatmap completable.
Throwable throwable = Flowable.fromIterable(players)
.doOnNext(request -> request.status == //mutate states)
.flatMapCompletable(savePlayerCompletable::save)
.blockingGet();
if (throwable != null) {
///something went wrong
}
or
return Flowable.fromIterable(players)
.doOnNext(request -> request.status == //mutate states)
.flatMapCompletable(savePlayerCompletable::save);

Cannot convert value of type 'String' to expected argument type 'Bool'

I am trying to write a function that will return true if the String str starts with a vowel. the following code will compile fine
func beginsWithVowel(str: String) -> Bool {
if(str.characters.count == 0){
return false
} else if(str.characters[str.startIndex] == "a"){
return true
}
return false
}
beginsWithVowel(str: "apple")
the problem is when I compare the first character to more than one character, for example
else if(str.characters[str.startIndex] == "a" || "e" || "i")
then I get the error 'Cannot convert the value of type 'String' to expected argument type 'Bool''
I've been fiddling with the code but no luck so far, any help would be appreciated. Thank you.
Swift cannot infer the logic you are trying to make. The logic to Swift becomes something like this:
if(str.characters[str.startIndex] == "a" || "e" || "i")
is equivalent to if(<Boolean expression> || "e" || "i")
is equivalent to if(<Boolean expression> || <String expression> || String expression)
An alternative solution can be:
if(["a", "b", "c"].contains(str.characters[str.startIndex])){
You should write it like this:
else if(str.characters[str.startIndex] == "a" || str.characters[str.startIndex] == "e" || str.characters[str.startIndex] == "i")
You get the error, because the compiler tries to convert both "e" and "i" to type Bool.
Instead of using if else switch will be more efficient:
func beginsWithVowel(str: String) -> Bool {
guard str.characters.count > 0 else {
return false
}
switch str.characters[str.startIndex]{
case "a","e","i","o","u":
return true
default:
return false
}
}
When you perform "a" || "e" || "i" you are comparing between the strings. Use this code:
if(str.characters[str.startIndex] == "a"
|| str.characters[str.startIndex] == "e"
|| str.characters[str.startIndex] == "i") {
// Your Code...
}
The boolean OR operator || expects boolean expressions.
So you would have to write EXPR == "a" || EXPR == "e" || EXPR == "i" where EXPR is the expression to get the first character.
However there is an easier solution (code is Swift 4)
func beginsWithVowel(str: String) -> Bool {
return "aeiou".contains(String(str.prefix(1)))
}
It considers also the empty string case.