How do I access / manipulate an element within a Flux / Mono - spring-webflux

I need to access a method inside a class, which is inside the Mono. How do I do this?
I have:
public Mono<LegalPerson> find(Long id) {
return Optional.of(repository.findById(id)).orElseThrow(() -> new UserNotFoundException("Error"));
}
And here is my problem:
public void update(Mono<LegalPerson> legalPersonJson) {
var legalPersonDB = find(legalPersonJson.map(legalPerson -> legalPerson.getId()));
I am getting the following error:
Incompatible types. Required Long but 'map' was inferred to Mono<R>: no instance(s) of type variable(s) R exist so that Mono<R> conforms to Long

This is what you need to do
Mono<Long> legalPersonDB = legalPersonJson.map(legalPerson -> find(legalPerson.getId()))
You will still need to subscribe to the Mono in order for it to execute.

Related

Kotlin script - "extension method" is a member and an extension at the same time

I have Kotlin some code that works as a class but when I try and run it as a Kotlin script I am getting " error: 'getNameAndVersion' is a member and an extension at the same time. References to such elements are not allowed"
enum class Env { Test, Sit }
data class ImageVersions(val apiName: String, val versions: Map<Env, String?>)
fun String.getNameAndVersion() = substringBefore(':') to substringAfter(':')
val testList = listOf("api-car-v1:0.0.118", "api-dog-v1:0.0.11", "api-plane-v1:0.0.36")
val sitList = listOf("api-car-v1:0.0.119", "api-plane-v1:0.0.37", "api-dog-v1:0.0.12")
getVersions(
mapOf(
Env.Test to testList,
Env.Sit to sitList
)
).forEach(::println)
fun getVersions(envMap: Map<Env, List<String>>): List<ImageVersions> {
val envApiNameMap = envMap.mapValues { it.value.associate(String::getNameAndVersion) }
val allApiNames = envApiNameMap.flatMap { it.value.keys }.distinct()
return allApiNames.map { apiName ->
ImageVersions(apiName, envApiNameMap.mapValues { it.value[apiName] })
}
}
I don't think I'm doing anything wrong with the way I'm using the method reference but according to my compiler I'm wrong. Appreciate some help with this. thanks
kotlinc -script .\myscript.kts
error: 'getNameAndVersion' is a member and an extension at the same time. References to such elements are not allowed
I don't have any experience with scripts but this error occurs when you try to reference a function inside a class that is also an extension function. (Here it is pointing to String::getNameAndVersion). Maybe when you run a script, the entire code is wrapped inside a class and then executed.
To fix this you can do one of the following:
Convert the function to a normal function which accepts a String parameter.
fun getNameAndVersion(s: String) = s.substringBefore(':') to s.substringAfter(':')
And replace String::getNameAndVersion with just ::getNameAndVersion in associate function
Other option is to directly call the function in the associate's lambda instead of passing a reference of this function.
.associate { it.getNameAndVersion() }

How to figure out which methods IDynamicMemberReferenceOperation refers to?

I have the following function in my OperationWalker:
public override void VisitDynamicInvocation(IDynamicInvocationOperation operation)
{
var memberReferenceOp = (IDynamicMemberReferenceOperation)operation.Operation;
switch (memberReferenceOp.Instance.Type)
{
case INamedTypeSymbol type:
{
var memberName = memberReferenceOp.MemberName;
var members = type.GetMembers(memberName);
if (members.Length > 1)
{
// WHAT DO I DO HERE ???
}
else
{
Result.Add((IMethodSymbol)members[0]);
}
break;
}
case IDynamicTypeSymbol dynamicType:
Unresolved.Add((operation.Syntax, memberReferenceOp.MemberName));
break;
}
}
I am clueless when a method on a normal type (non dynamic) is called with a dynamic parameter and there is a choice of target methods with the same name. E.g.:
class A
{
public void Get(int i){}
public void Get(string s){}
public void Get(object o){}
public void Get(double s, int precision){}
}
...
dynamic x = ...;
A a;
a.Get(x)
In this case any of the first 3 A.Get methods may be called, depending on the actual type of x. But not the fourth method.
Is there a way in Roslyn to get this information? Specifically in this example, I would like to get the symbols for first 3 Get methods.
The logic is non trivial, because one needs to take into account:
Default parameters, so just counting the arguments may not be enough
Type conversions
Visibility Scope
Number of arguments
Parameters may be passed using the named syntax in arbitrary order
Combining it all together we get non trivial logic. Is there anything in the SemanticModel or anywhere else to help get the answer?
I figured it out and it is straightforward - SemanticModel.GetSymbolInfo. When there is exact match its Symbol property returns it. When there are multiple candidates, as may be the case when one of the passed arguments is dynamic, then the property CandidateSymbols holds all the options.
I have not tested it with extension methods, so it is possible there is a gap there.

Kotlin: Using method reference to a getter of another class

I have a class -
class ES {
var issue: SomeClass? = null
}
I need to access its getter in another class -
class CSS {
private val ref: Supplier<SomeClass?> = ES::issue
}
However this is not working. Its throws this error -
Type mismatch.
Required: Supplier<SomeClass?>
Found : KMutableProperty1<ES, SomeClass?>
Can someone tell me what am I doing wrong? I am actually in the process of converting java code to kotlin.
UPDATE
I need a static reference to the getter of the ES class, similar to JAVA, where we can do ->
Function<ES, SomeClass> ref = ES::getIssue;
In Kotlin, instead of using Supplier, you use functional syntax for the type. In this case, the equivalent of your Supplier<SomeClass?> would be () -> SomeClass? (assuming ES is an object since that's how you used it in your example code):
class CSS(/*...*/) {
private val ref: () -> SomeClass? = ES::issue
}
But if you have to use Supplier specifically so it can be easily used with Java code, you can wrap your getter reference in a Supplier implementation:
class CSS(/*...*/) {
private val ref: Supplier<SomeClass?> = Supplier(ES::issue)
}
Update
If you want the getter without a specific instance of the class, similar to Function<ES, SomeClass> in Java, then you need to make ES a parameter of the function.
Either
private val ref: (ES) -> SomeClass? = ES::issue
or
private val ref: ES.() -> SomeClass? = ES::issue
I don't believe there's a way to do this with Supplier, but I don't think you could do it in Java with Supplier either.

Kotlin lambda / Java SAM interop - type mismatch

I have an existing Java interface defined as follows
public interface MyRetriever extends Function<String, Optional<String>> {}
and want to define a variable holding a Kotlin lambda which conforms to the SAM conversion as per my understanding
var a : MyRetriever = { s : String -> Optional.ofNullable(s.toLowerCase()) }
But instead I get a type mismatch error.
Type missmatch.
Required: MyRetriever
Found: (String) -> Optional<String>
The lambda actually matches the Java function definition, what am I missing here?
When doing a SAM conversion, you need to explicitly provide a type:
var a = MyRetriever { s : String -> Optional.ofNullable(s.toLowerCase()) }
Note that you may omit declaration of type for a the way you did it before.

To create an object (of some class) in a listener

I'm creating a script and have troubles.
Is it possible to create an object (of some class) from within a listener?
I tried it but I get an error: ``class not found''.
I want to do something like:
class ONE {
class_ONE_code
}
class TWO {
object o = alloc(ONE)
}
I need this to create a new listener when I execute another listener.
What you wish to do is certainly possible. Most likely you have a syntax error in your code. For example, your implementation of class TWO is invalid since a member variable like "o" cannot be initialized in the member declaration section of the class code. This can only be done within a class method, as illustrated in the example code below.
class One
{
void DoClassOneAction(Object self)
{
OKDialog("Class One action executed.");
}
}
class Two
{
Object oneInstance;
void DoClassTwoAction(Object self)
{
if (!oneInstance.ScriptObjectIsValid())
oneInstance = Alloc(One);
oneInstance.DoClassOneAction();
}
}
void main()
{
Object twoInstance = Alloc(Two);
twoInstance.DoClassTwoAction();
}
main();
Note that the coding requirements for DM script classes differ somewhat from those of other languages that support objects. You may want to review details in the Scripting > Objects section of the DM on-line help (accessed via Help > Search… menu item).