Skip to content

Commit

Permalink
Deprecate InterfaceCandidateConcretePropertyResolver
Browse files Browse the repository at this point in the history
  • Loading branch information
seongahjo committed Jan 10, 2025
1 parent dcd98dd commit 40ce311
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/content/v1.0.x-kor/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ sectionStart
### v.1.0.21
Deprecate the ObjectPropertyGenerator that modify child properties listed below.
For example, `InterfaceObjectPropertyGenerator`, `SealedTypeObjectPropertyGenerator`, `SingleValueObjectPropertyGenerator`
Use `InterfaceCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.
Use `ConcreteTypeCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.

Fix set `ZoneId` in Kotlin JDK21.

Expand Down
2 changes: 1 addition & 1 deletion docs/content/v1.0.x/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ sectionStart
### v.1.0.21
Deprecate the ObjectPropertyGenerator that modify child properties listed below.
For example, `InterfaceObjectPropertyGenerator`, `SealedTypeObjectPropertyGenerator`, `SingleValueObjectPropertyGenerator`
Use `InterfaceCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.
Use `ConcreteTypeCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.

Fix set `ZoneId` in Kotlin JDK21.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,5 +271,50 @@ FixtureMonkey fixture = FixtureMonkey.builder()
SealedDefaultStringSupplier stringSupplier = (SealedDefaultStringSupplier)fixture.giveMeOne(SealedStringSupplier.class);
```

### For advanced users
만약 인터페이스의 구현체가 너무 많다면 프로그래밍 방식으로 (progammatic) 인터페이스 구현체를 추가할 수 있습니다.
`CandidateConcretePropertyResolver` 인터페이스를 구현한 클래스를 만들어서 `InterfacePlugin`에 추가하면 됩니다.

```java
class YourCustomCandidateConcretePropertyResolver implements CandidateConcretePropertyResolver {
@Override
public List<Property> resolveCandidateConcreteProperties(Property property) {
// 구현체를 추가하는 로직을 작성하세요.
return List.of(...);
}
}
```

만약 `List<Property>` 를 만들기 어렵다면 `Property` 생성 로직을 `ConcreteTypeCandidateConcretePropertyResolver` 에게 위임할 수 있습니다.
`ConcreteTypeCandidateConcretePropertyResolver``CandidateConcretePropertyResolver`를 구현한 클래스로 생성자로 제공된 타입들과 Property 정보를 사용해 `List<Property>`로 변환해줍니다.
Property 정보는 타입 파라미터를 추론할 때 사용됩니다.

아래와 같이 선언한 FixtureMonkey 인스턴스를 사용해서 `Collection<String>`을 생성하면 `List<String>`, `Set<String>` 중 하나로 타입이 결정됩니다.
추가 옵션을 사용해서 구현체를 직접 결정할 수도 있고, 픽스쳐 몽키에게 위임할 수도 있습니다.
픽스쳐 몽키의 기본 설정은 `List<String>`을 구현체 `ArrayList<String>`로 결정하고 `Set<String>``HashSet<String>`으로 결정합니다.

{{< alert icon="💡" title="notice">}}

첫 번째 파라미터로 옵션을 적용할 타입 조건은 주의해서 설정해야 합니다.
예를 들어, 아래 예시에서 `AssignableTypeMatcher`를 사용하면 구현체들도 조건을 만족하므로 무한 루프에 걸립니다.

{{</ alert>}}

```java
FixtureMonkey sut = FixtureMonkey.builder()
.plugin(new InterfacePlugin()
.interfaceImplements(
new ExactTypeMatcher(Collection.class),
new ConcreteTypeCandidateConcretePropertyResolver<>(List.of(List.class, Set.class))
)
)
.build();

Collection<String> actual = sut.giveMeOne(new TypeReference<>() {
});

then(actual).isInstanceOfAny(List.class, Set.class);
```

이번 장에서는 인터페이스 타입을 생성하는 방법을 간단한 예제를 보며 배웠습니다. 인터페이스를 생성하는 데 문제가 있다면 `InterfacePlugin` 옵션들을 살펴보세요.
그래도 문제가 해결되지 않는다면 GitHub에 재현 가능한 예제를 포함한 이슈를 올려주세요.
2 changes: 1 addition & 1 deletion docs/content/v1.1.x-kor/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ sectionStart
### v.1.0.21
Deprecate the ObjectPropertyGenerator that modify child properties listed below.
For example, `InterfaceObjectPropertyGenerator`, `SealedTypeObjectPropertyGenerator`, `SingleValueObjectPropertyGenerator`
Use `InterfaceCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.
Use `ConcreteTypeCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.

Fix set `ZoneId` in Kotlin JDK21.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,5 +273,53 @@ FixtureMonkey fixture = FixtureMonkey.builder()
SealedDefaultStringSupplier stringSupplier = (SealedDefaultStringSupplier)fixture.giveMeOne(SealedStringSupplier.class);
```

### For advanced users
If there are too many implementations of an interface, you can add interface implementations programmatically.
All you have to do is create a class that implements the `CandidateConcretePropertyResolver` interface and add it to the `InterfacePlugin`.

```java
class YourCustomCandidateConcretePropertyResolver implements CandidateConcretePropertyResolver {
@Override
public List<Property> resolveCandidateConcreteProperties(Property property) {
// resolve your implementations
return List.of(...);
}
}
```

If you have a trouble creating `List<Property>`, you can delegate the creation logic to `ConcreteTypeCandidateConcretePropertyResolver`.

`ConcreteTypeCandidateConcretePropertyResolver` is a class that implements the `CandidateConcretePropertyResolver` interface.
It converts the types and property information provided in the constructor to `List<Property>`.
The property information is used when inferring type parameters.

In the case below, the `ConcreteTypeCandidateConcretePropertyResolver` is used to resolve the implementations of `List` and `Set`.
`Collection<String>` is resolved as either `List<String>` or `Set<String>`.
You can resolve the actual implementations programmatically or delegate the creation logic to Fixture Monkey.
By default, Fixture Monkey resolves `List<String>` as `ArrayList<String>` and `Set<String>` as `HashSet<String>`.

{{< alert icon="💡" title="notice">}}

You should be careful when setting the type condition to apply the options as the first parameter.
For example, using `AssignableTypeMatcher` in the example below will cause an infinite loop because the implementations also satisfy the condition.

{{</ alert>}}

```java
FixtureMonkey sut = FixtureMonkey.builder()
.plugin(new InterfacePlugin()
.interfaceImplements(
new ExactTypeMatcher(Collection.class),
new ConcreteTypeCandidateConcretePropertyResolver<>(List.of(List.class, Set.class))
)
)
.build();

Collection<String> actual = sut.giveMeOne(new TypeReference<>() {
});

then(actual).isInstanceOfAny(List.class, Set.class);
```

This chapter illustrates how to create an interface type. If you get stuck, all you need to remember is the `InterfacePlugin' plugin.
If the plugin doesn't solve your problem, please post a bug with a reproducible example.
2 changes: 1 addition & 1 deletion docs/content/v1.1.x/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ sectionStart
### v.1.0.21
Deprecate the ObjectPropertyGenerator that modify child properties listed below.
For example, `InterfaceObjectPropertyGenerator`, `SealedTypeObjectPropertyGenerator`, `SingleValueObjectPropertyGenerator`
Use `InterfaceCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.
Use `ConcreteTypeCandidateConcretePropertyResolver`, `SealedTypeCandidateConcretePropertyResolver` instead.

Fix set `ZoneId` in Kotlin JDK21.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
import com.navercorp.fixturemonkey.api.type.GenericType;
import com.navercorp.fixturemonkey.api.type.Types;

/**
* This class is used to resolve more concrete types for a given interface.
* The concrete types could be an interface or a class that implements the interface.
*
* @param <T> the type parameter of the interface
*/
@API(since = "1.0.16", status = Status.EXPERIMENTAL)
public final class ConcreteTypeCandidateConcretePropertyResolver<T> implements CandidateConcretePropertyResolver {
private final List<Class<? extends T>> concreteTypes;
Expand All @@ -38,6 +44,16 @@ public ConcreteTypeCandidateConcretePropertyResolver(List<Class<? extends T>> co
this.concreteTypes = concreteTypes;
}

/**
* Resolves more concrete types for a given interface.
* The concrete types could be an interface or a class that implements the interface.
* The provided property could be a property of concrete type or an abstract class or interface.
* The type parameter of the interface is used to generate properties of concrete types.
* It returns a list of properties of concrete types that implement the interface.
*
* @param property it could be a property of concrete type or an abstract class or interface.
* @return a list of properties of concrete types that implement the interface
*/
@Override
public List<Property> resolve(Property property) {
List<AnnotatedType> genericsTypes = Types.getGenericsTypes(property.getAnnotatedType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
import org.apiguardian.api.API;
import org.apiguardian.api.API.Status;

@API(since = "1.0.21", status = Status.EXPERIMENTAL)
/**
* It is deprecated.
* Use {@link ConcreteTypeCandidateConcretePropertyResolver} instead.
*/
@API(since = "1.0.21", status = Status.DEPRECATED)
@Deprecated
public final class InterfaceCandidateConcretePropertyResolver<T> implements CandidateConcretePropertyResolver {
private final List<Class<? extends T>> implementations;

Expand Down

0 comments on commit 40ce311

Please sign in to comment.