Annotation processor in Kotlin: nullable types - annotations

I'm writting my first annotation processor in Kotlin. I need to check the type of a annotated property in order to know if is optional or not.
The client code looks like:
#MyAnnotation var property: String?
In my annotation processor, I have an instance of Element class from javax.lang.model.element packpage which represents my annotated property. I can do element.asType() to get the type the property, but I don't know how to check if this property is optional or not.

Related

How does EF Core instantiate and initialize entities?

How does EF Core instantiate and initialize objects that are retrieved from a database? In the following example, the Person class has a default constructor and a parameterized constructor. Neither of these constructors is called when my program retrieves the Person object from the database.
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Person()
{
Console.WriteLine("Default ctor accessed");
}
public Person(string firstName, string lastName)
{
Console.WriteLine("Parameterized ctor accessed");
FirstName = firstName;
LastName = lastName;
}
}
// Program.cs
// Other code omitted for brevity
var personRead = context.Persons.First(p => p.FirstName.Equals("MyName"));
Console.WriteLine($"Firstname: {personRead.FirstName}");
This conflicts with the microsoft documentation:
When EF Core creates instances of these types, such as for the results of a query, it will first call the default parameterless constructor and then set each property to the value from the database. However, if EF Core finds a parameterized constructor with parameter names and types that match those of mapped properties, then it will instead call the parameterized constructor with values for those properties and will not set each property explicitly
The article was written on 14/10/2020 so it might be out of date. However my question still remains. How does EF core instantiate and initialize these objects? I'm using Microsoft.EntityFrameworkCore version 6.0.8
Neither of these constructors is called when my program retrieves the Person object from the database
This can't be true except you have another constructor(s) not shown here.
EF Core definitely uses class constructor for instantiating entities, so the documentation is correct, however it's unclear which one in case there are multiple. All it says is:
Note
Currently, all constructor binding is by convention. Configuration of specific constructors to use is planned for a future release.
The answer is hidden inside the implementation of the ConstructorBindingFactory class which is responsible for selecting the constructor to be used, and more specifically the following comment inside GetBindings method:
Trying to find the constructor with the most service properties
followed by the least scalar property parameters
Service properties are explained in Injecting services section, and scalar property parameters refer to primitive type constructor arguments explained in Binding to mapped properties.
In your example, there is no constructor with service type arguments, so the one with the least scalar property parameters will be chosen, which in this case is the parameterless constructor (parameters count is 0)
public Person()
{
Console.WriteLine("Default ctor accessed");
}
Again, if you have other constructors, check if some of them is "better". But as it looks, if you have parameterless constructor (doesn't matter if public, protected, internal, private etc.) and no constructors with service type arguments, then EF Core will always use the parameterless one.
If you want, you can check the entity instantiation info using the metadata API, e.g.
var entityType = dbContext.Model.FindEntityType(typeof(Person));
var info = entityType.ConstructorBinding;
ConstructorBinding property returns instance of abstract type InstantiationBinding class. ParameterBindings property returns information about parameters and corresponding properties, and CreateConstructorExpression method which
Creates an expression tree that represents creating an entity instance from the given binding information. For example, this might be a NewExpression to call a constructor, or a MethodCallExpression to call a factory method.
Currently there are two implementations of aforementioned abstract type - ConstructorBinding class for instantiation using constructor, and FactoryMethodBinding class for instantiation via factory method.
So, currently by convention EF Core uses constructor instantiation, but factory method instantiation might be added in the future (it might even be used currently by proxies extension, but it uses/requires parameterless constructor in the class they are inheriting).

replacing drools getter lookup for non-pojo

Drools supports the usage of properties of Pojos using a simple name. For example Person(age==10) to match a Person instance that has a getAge() method returning 10.
My problem now is that I have to handle something that is not a pure Pojo and instead has a generic getter. So for the Person example above I need a transformation to Person(myGenericPropertyLookupMethod("age")==10). And I need this for all such property usages, which includes for example the usage of from and chaining like $street : String() from $person.address.street. where at least street must be looked up using myGenericPropertyLookupMethod.

What is the default target for an annotation when annotating property in Kotlin?

Annotations in Kotlin can have different use-site targets as explained here: https://kotlinlang.org/docs/reference/annotations.html#annotation-use-site-targets
My question is: When use-site is not explicitly defined, what is the default target when annotating property in a class like in the example below?
class Test {
#SomeAnnotation
var someProperty: String? = null
}
Background
I'm trying Jongo as MongoDB client in Kotlin and have problems annotating id field. Jongo does not map id property correctly when it's annotated like this:
#MongoId #MongoObjectId var id: String? = null
The annotations in question are just meta-annotations for Jackson. However it seems to work when I annotate the property like this, indicating use-site problem:
#field:[MongoId MongoObjectId]
var id: String? = null
I would expect that #field is default use-site, but it seems that it isn't.
The reference says:
If you don’t specify a use-site target, the target is chosen according
to the #Target annotation of the annotation being used. If there are
multiple applicable targets, the first applicable target from the
following list is used:
param (constructor parameter)
property (annotations with this target are not visible to Java)
field
So if your annotation has #Target({ElementType.FIELD}), the annotation in Kotlin will target #field:.
If it has no #Target specified, it may be used on any program element: the #property: target is also applicable and is chosen by default.

Swift: How to assign a value whose type is 'AnyObject!'?

I'm trying to use the Google Maps pod, but I'm having an issue setting a variable that's of type AnyObject!.
Here's my code:
mapPin.userData = venue as Venue
It complains Cannot assign value of type 'Venue' to type 'AnyObject!'. How do I fix this error? P.S. Venue is just a custom type that I wrote.
AnyObject is the protocol to which all classes conform.
Therefore Venue must be defined as class Venue (and not struct Venue), otherwise instances of that type are not assignable to
a property of type AnyObject.

How does Swift implement ARC in property attributes?

How does Swift implement ARC in property attributes? For example, how do I make my String variable use copy instead of strong in Swift?
You can use the #NSCopying attribute when you want the copy behaviour from Objective-C.
From the Swift Book:
Apply this attribute to a stored variable property of a class. This
attribute causes the property’s setter to be synthesized with a copy
of the property’s value—returned by the copyWithZone method—instead of
the value of the property itself. The type of the property must
conform to the NSCopying protocol.
The NSCopying attribute behaves in a way similar to the Objective-C
copy property attribute.
However, in the specific case of String properties, it's not necessary to do so.
Strings are a value type in Swift. As such, when an existing String is assigned to a new variable, the variable actually stores a copy of the String, rather than a reference to the existing one.
Swift’s String type is a value type. If you create a new String value,
that String value is copied when it is passed to a function or method,
or when it is assigned to a constant or variable. In each case, a new
copy of the existing String value is created, and the new copy is
passed or assigned, not the original version.
So, the #NSCopying attribute is to be used when you have properties of a reference type that you want to set using the copy behaviour.