An open API service indexing awesome lists of open source software.

https://github.com/harmonysoft-tech/jenome

Provides convenient access and utility methods for working with statically available information about java generics
https://github.com/harmonysoft-tech/jenome

Last synced: 11 months ago
JSON representation

Provides convenient access and utility methods for working with statically available information about java generics

Awesome Lists containing this project

README

          

## Table of Contents

* [1. License](#1-license)
* [2. Overview](#2-overview)
* [3. API](#3-overview)
* [4. Releases](#4-releases)

## 1. License

See the [LICENSE](LICENSE.md) file for license rights and limitations (MIT).

## 2. Overview

Although *Java* generics are rather limited comparing to 'true' generics, it's still possible to extract and use their data in some circumstances:

Here we are unable to extract type argument's value (*String*) given, say, a reference to the `data` field:
```java
class MyClass {
List data = new ArrayList();
}
```

In contrast, here we can find out that target type argument's value is *Number*:
```java
class MyClass implements Comparable {
}
```

Current library helps with type argument values extraction and processing.

## 3. API

**Extract type argument value**

That functionality is covered by the [TypeArgumentResolver](src/main/java/tech/harmonysoft/oss/jenome/resolve/TypeArgumentResolver.java) interface.

*Example*

Given the declarations below:
```java
class MyInterface {}
class StringParent implements MyInterface {}
class Child extends StringParent {}
```

We can find out the following:
```java
typeArgumentResolver.resolve(MyInterface.class, Child.class, 0) -> String
typeArgumentResolver.resolve(MyInterface.class, Child.class, 1) -> Long
```

Real-world usage example:

```java
interface Handler {
void handle(T input);
}

class StringHandler implements Handler {
public void handle(String input) {}
}

class LongHandler implements Handler {
public void handle(Long input) {}
}

@Component
class Router {

private final Map> handlers;

@Autowired
public Router(Collection> handlers) {
this.handlers = JenomeResolveUtil.byTypeValue(handlers);
}

public void process(Object data) {
Handler handler = handlers.get(data.getClass());
if (handler == null) {
throw new IllegalArgumentException(String.format(
"No handler is registered for payload of type %s. Known payload mappings: %s",
data.getClass().getSimpleName(), handlers
));
}
handler.handle(data);
}
}
```

**Check if one type IS-A another type**

This functionality is covered by the [TypeComplianceMatcher](src/main/java/tech/harmonysoft/oss/jenome/match/TypeComplianceMatcher.java).

*Example*

```java
interface TestInterface
{}
class TestInterfaceImpl
implements TestInterface {}
class SimpleBaseClass implements TestInterface {}
class SimpleMatchedClass extends TestInterfaceImpl {}
class SimpleUnmatchedClass extends TestInterfaceImpl {}

typeComplianceMatcher.match(SimpleBaseClass.class.getGenericInterfaces()[0], SimpleMatchedClass.class.getGenericSuperclass()) -> true
typeComplianceMatcher.match(SimpleBaseClass.class.getGenericInterfaces()[0], SimpleUnmatchedClass.class.getGenericSuperclass()) -> false
```

This is a must-have functionality when we want to, say, enhance autowiring rules by type argument values. E.g. consider a spring context with beans of the following types:
```java
MyClass
MyClass
MyClass
MyClass
```

We'd like to be able to autowire arguments like `Collection` (`MyClass` and `MyClass` go here) and `Collection` (`MyClass` and `MyClass` should be provided).

*Note: right now Spring checks only the base type (`MyClass`) and provides all such beans regarding the type argument's value.*

## 4. Releases

[Release Notes](RELEASE.md)