Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standardisation of collectional property setters and getters #2336

Open
homedirectory opened this issue Oct 17, 2024 · 0 comments
Open

Standardisation of collectional property setters and getters #2336

homedirectory opened this issue Oct 17, 2024 · 0 comments

Comments

@homedirectory
Copy link
Contributor

homedirectory commented Oct 17, 2024

Description

The goal of this issue is to define a standard form for collectional property setters, which will outline rules for setter declarations.

The motivation for this arose during the implementation of #2061, when a certain error in the entity copying procedure was encountered.

The error was due to the changes in dynamic property access (via methods AbstractEntity.{get,set})
which is used in the copying procedure to read values from the "source" entity and set them into the "destination" entity.
Please note that those changes were not committed to the #2061 branch, but were stashed locally as their scope exceeded that of the issue.

The said changes involved modification of the way property values are dynamically accessed.
Instead of reading values from property fields directly, as it is done now, calls to property getter methods were made.
The purpose of this change was to respect encapsulation of property values manifested in the form of their getter methods.

This change then led to a runtime error during copying of collectional property values.
Please note that the copying procedure also had to be modified, as it previously relied on dynamic getters reading values directly from property fields.

The error was due to a class cast exception, and occured only for those collectional properties whose setter had a parameter type equal to the property's runtime type, rather than its interface.

For example, the error would occur for the following property (1):

@IsProperty
private Set<Vehicle> vehicles = new HashSet<>();

@Observable
public Entity setVehicles(final HashSet<Vehicle> vehicles) {
  this.vehicles.clear();
  this.vehicles.addAll(vehicles);
}

public Set<Vehicle> getVehicles() {
  return unmodifiableSet(vehicles);
}

But it wouldn't occur if the setter accepted the more general type (2):

@Observable
public Entity setVehicles(final Set<Vehicle> vehicles) { ... }

So, when a property value is read directly from its field, the error doesn't occur because the value being set always has a type that is compatible with the setter's parameter type.
But, when an getter is used, the error occurs because the setter expects a specific type (assuming the getter returns a general type, [e.g., Set in the example above]).

In fact, with the setter in (1), the following statement doesn't compile because type-checking fails:

setVehicles(getVehicles());

Therefore, setter declarations as seen in (1) are incorrect, and declarations as seen in (2) should be standardised.

It is proposed to make the following rules a standard for collectional properties:

  1. A collectional property getters should have a return type that is between the actual property type and the most general collectional interface implemented by the actual type of the property.
  2. A collectional property setter should have a parameter type that is the most general collectional interface implemented by the actual type of the property.

Since TG supports a small set of collectional types, all of them can be outlined with the above rules applied:

  1. Property type - T extends List.
    • Getter return type - U, where T <= U <= List.
    • Setter parameter type - List.
  2. Property type - T extends Set.
    • Getter return type - U, where T <= U <= Set.
    • Setter parameter type - Set.
  3. Property type - T extends Map.
    • Getter return type - U, where T <= U <= Map.
    • Setter parameter type - Map.

Discussion: consider making the setter parameter type even more general (e.g., Collection, Iterable).

The property verifier should be enhanced to enforce these rules.

Also, method Reflector.obtainPropertySetter should be modified to support cases where the property type is not equal to the parameter type of its setter.
For example, when property type is ArrayList but the setter's parameter type is List.

Expected outcome

  • Standardised rules for collectional property setters and getters.
  • Existing TG applications are adjusted to follow the rules.
  • Property verifier is enhanced to enforce the rules.
@homedirectory homedirectory self-assigned this Oct 17, 2024
homedirectory added a commit that referenced this issue Oct 17, 2024
…yForCollectionModification

This entity is extended by TG application-level entities, making this
change a breaking one since the method signature has changed and
subclasses that override changed collectional setters will need to be
adjusted.
@01es 01es changed the title Standardisation of collectional property setters and accessors Standardisation of collectional property setters and getters Nov 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant