简体   繁体   中英

micronaut petstore a code segment from java to groovy

The actual code is here

private Function<String, Mono<? extends Offer>> keyToOffer(RedisReactiveCommands<String, String> commands) {
        return key -> {
            Flux<KeyValue<String, String>> values = commands.hmget(key, "price", "description");
            Map<String, String> map = new HashMap<>(3);
            return values.reduce(map, (all, keyValue) -> {
                all.put(keyValue.getKey(), keyValue.getValue());
                return all;
            })
                    .map(ConvertibleValues::of)
                    .flatMap(entries -> {
                        String description = entries.get("description", String.class).orElseThrow(() -> new IllegalStateException("No description"));
                        BigDecimal price = entries.get("price", BigDecimal.class).orElseThrow(() -> new IllegalStateException("No price"));
                        Flowable<Pet> findPetFlowable = petClient.find(key).toFlowable();
                        return Mono.from(findPetFlowable).map(pet -> new Offer(pet, description, price));
                    });
        };
    }

I have tried in a variety of different ways to convert above into groovy and all attempts so far not worked out too well. I wondered if anyone better with groovy could help

My attempt wasn't posted since the code itself firstly returns Ambiguous code block in Intelij and secondly looks totally wrong.

 private Function<String, Mono<? extends Orders>> keyToOrder(RedisReactiveCommands<String, String> commands) {
    return { key -> {
        Flux<KeyValue<String, String>> values = commands.hmget(key, "price", "description");
        Map map = [:]
        return values.reduce(map, (all, keyValue)= {all.put(keyValue.getKey(), keyValue.getValue());
            return all
        }).map({entries -> ConvertibleValues.of(entries)})
                .flatMap({entries -> {
            String description = entries.get("description", String.class).orElseThrow({ new IllegalStateException("No description")});
            BigDecimal price = entries.get("price", BigDecimal.class).orElseThrow({new IllegalStateException("No price")});
            Flowable<Item> findItemFlowable = itemClient.find(key).toFlowable();
            return Mono.from(findItemFlowable).map({item -> new Orders(item, description, price)});
        }});
    }}
}

When attempting to convert to groovy the biggest struggle appeared to be around:

return values.reduce(map, (all, keyValue)= {all.put(keyValue.getKey(), keyValue.getValue());
                    return all

This is nothing like what the original java code looked like and really unsure if it would even behave as it should. The issue I had was to find anything aorund RXJAVA Flux .reduce written in groovy out there.

The Ambiguous code block is around this entire flatMap segment at the very bottom

 .flatMap({entries -> {

I haven't checked in this change nor did I post it since frankly it was embarrassing.

I have also come across: http://reactivex.io/documentation/operators/reduce.html#collapseRxGroovy

numbers.reduce({ a, b -> a+b }).

and ended up with:

Map<String, String> map = new HashMap<>(3);
            return values.reduce({all, keyValue->
                all.put(keyValue.getKey(), keyValue.getValue());
                return all
        }).map({entries -> ConvertibleValues.of(entries)})

But this again looks wrong and doesn't really match what the java code was doing.

Final edit to suggest I have got Intelij to accept the code as groovy but not quite sure if it is what the java code was actually doing, since declared map is not even used:

private Function<String, Mono<? extends Orders>> keyToOrder(RedisReactiveCommands<String, String> commands) {
    Flux<KeyValue<String, String>> values = commands.hmget(key, "price", "description");
        Map<String, String> map = new HashMap<>(3);
        values.reduce({all, keyValue->
            all.put(keyValue.getKey(), keyValue.getValue());
            return all
    }).map({entries -> ConvertibleValues.of(entries)})
                .flatMap({entries ->  bindEntry(entries)});
    return values.key
}

private Mono<Orders> bindEntry(entries) {
    String description = entries.get("description", String.class).orElseThrow({ new IllegalStateException("No description")});
    BigDecimal price = entries.get("price", BigDecimal.class).orElseThrow({new IllegalStateException("No price")});
    Flowable<Item> findItemFlowable = itemClient.find(key).toFlowable();
    return Mono.from(findItemFlowable).map({item -> new Orders(item, description, price)});

}

The likely issue you're facing is because Groovy doesn't support Java method references or lambdas.

The first line is returning a lambda

Java: return key -> {

Groovy: return { key - >

That is using a groovy closure that takes the key as the argument.

Other places that use method references need to be converted

Java: .map(ConvertibleValues::of)

Groovy: .map({ values -> ConvertibleValues.of(values) })

It seems like you have most of that worked out, however you specifically asked about the map not being used. That is because you simply aren't passing it to the method.

values.reduce({all, keyValue-> vs values.reduce(map, {all, keyValue ->

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM