-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): refine AsyncGenericOperationBinding
- Loading branch information
Showing
14 changed files
with
343 additions
and
61 deletions.
There are no files selected for viewing
33 changes: 33 additions & 0 deletions
33
...shamir/springwolf/asyncapi/scanners/bindings/annotation/AsyncGenericOperationBinding.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation; | ||
|
||
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.annotation.AsyncOperationBinding; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
// TODO: move classes to new bindings package | ||
|
||
/** | ||
* Springwolf cannot support all available protocol bindings that exist. | ||
* To allow users to manually define them, {@link AsyncGenericOperationBinding} can be used. | ||
* <p> | ||
* Use the {@link AsyncGenericOperationBinding#fields()} to define the attributes | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(value = {ElementType.METHOD}) | ||
@Repeatable(AsyncGenericOperationBindings.class) | ||
@AsyncOperationBinding | ||
public @interface AsyncGenericOperationBinding { | ||
/** | ||
* The name of the binding | ||
*/ | ||
String type(); | ||
|
||
/** | ||
* All binding fields | ||
*/ | ||
String[] fields() default {}; | ||
} |
15 changes: 15 additions & 0 deletions
15
...hamir/springwolf/asyncapi/scanners/bindings/annotation/AsyncGenericOperationBindings.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation; | ||
|
||
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.annotation.AsyncOperationBinding; | ||
|
||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(value = {ElementType.METHOD}) | ||
@AsyncOperationBinding | ||
public @interface AsyncGenericOperationBindings { | ||
AsyncGenericOperationBinding[] value(); | ||
} |
33 changes: 33 additions & 0 deletions
33
...syncapi/scanners/bindings/annotation/processor/AsyncGenericOperationBindingProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation.processor; | ||
|
||
import com.asyncapi.v2.binding.operation.OperationBinding; | ||
import io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation.AsyncGenericOperationBinding; | ||
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.AbstractOperationBindingProcessor; | ||
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.ProcessedOperationBinding; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.stereotype.Component; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
@Component | ||
@Slf4j | ||
// TODO: Add bindingPriority | ||
public class AsyncGenericOperationBindingProcessor | ||
extends AbstractOperationBindingProcessor<AsyncGenericOperationBinding> { | ||
|
||
@Override | ||
protected ProcessedOperationBinding mapToOperationBinding(AsyncGenericOperationBinding bindingAnnotation) { | ||
Map<String, Object> bindingData = PropertiesUtil.stringsToMap(bindingAnnotation.fields()); | ||
|
||
return new ProcessedOperationBinding( | ||
bindingAnnotation.type(), new DefaultAsyncGenerialOperationBinding(bindingData)); | ||
} | ||
|
||
public static class DefaultAsyncGenerialOperationBinding extends OperationBinding { | ||
|
||
public DefaultAsyncGenerialOperationBinding(Map<String, Object> properties) { | ||
this.extensionFields = new HashMap<>(properties); | ||
} | ||
} | ||
} |
48 changes: 48 additions & 0 deletions
48
...stavshamir/springwolf/asyncapi/scanners/bindings/annotation/processor/PropertiesUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation.processor; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import java.io.IOException; | ||
import java.io.StringReader; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.LinkedList; | ||
import java.util.Map; | ||
import java.util.Properties; | ||
|
||
@Slf4j | ||
public class PropertiesUtil { | ||
|
||
public static Map<String, Object> stringsToMap(String[] propertyStrings) { | ||
return convertPropertiesToNestedMap(buildProperties((propertyStrings))); | ||
} | ||
|
||
private static Properties buildProperties(String[] propertyStrings) { | ||
Properties properties = new Properties(); | ||
for (String bindingProperty : propertyStrings) { | ||
try { | ||
properties.load(new StringReader(bindingProperty)); | ||
} catch (IOException e) { | ||
log.warn("Unable to parse property %s".formatted(bindingProperty), e); | ||
} | ||
} | ||
return properties; | ||
} | ||
|
||
private static Map<String, Object> convertPropertiesToNestedMap(Properties properties) { | ||
Map<String, Object> bindingData = new HashMap<>(); | ||
for (String propertyName : properties.stringPropertyNames()) { | ||
LinkedList<String> path = new LinkedList<>(Arrays.asList(propertyName.split("\\."))); | ||
Map<String, Object> mapIterator = bindingData; | ||
while (path.size() > 1) { | ||
if (!mapIterator.containsKey(path.get(0))) { | ||
mapIterator.put(path.get(0), new HashMap<>()); | ||
} | ||
mapIterator = (Map<String, Object>) mapIterator.get(path.get(0)); | ||
path.pop(); | ||
} | ||
mapIterator.put(path.get(0), properties.get(propertyName)); | ||
} | ||
return bindingData; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 0 additions & 26 deletions
26
...r/springwolf/asyncapi/scanners/channels/operationdata/annotation/AsyncGenericBinding.java
This file was deleted.
Oops, something went wrong.
26 changes: 0 additions & 26 deletions
26
...ingwolf/asyncapi/scanners/channels/operationdata/annotation/AsyncGenericBindingField.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,4 @@ | |
* Mapped to {@link OperationData} | ||
*/ | ||
AsyncOperation operation(); | ||
|
||
AsyncGenericBinding[] bindings() default {}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,4 @@ | |
* Mapped to {@link OperationData} | ||
*/ | ||
AsyncOperation operation(); | ||
|
||
AsyncGenericBinding[] bindings() default {}; | ||
} |
101 changes: 101 additions & 0 deletions
101
...api/scanners/bindings/annotation/processor/AsyncGenericOperationBindingProcessorTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation.processor; | ||
|
||
import io.github.stavshamir.springwolf.asyncapi.scanners.bindings.annotation.AsyncGenericOperationBinding; | ||
import io.github.stavshamir.springwolf.asyncapi.scanners.channels.operationdata.ProcessedOperationBinding; | ||
import org.junit.jupiter.api.Nested; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
class AsyncGenericOperationBindingProcessorTest { | ||
|
||
private final AsyncGenericOperationBindingProcessor processor = new AsyncGenericOperationBindingProcessor(); | ||
|
||
@Nested | ||
class MapToOperationBinding { | ||
|
||
@Test | ||
void testClassWithoutAnnotation() { | ||
// when | ||
List<ProcessedOperationBinding> result = getProcessedOperationBindings(ClassWithoutAnnotation.class); | ||
|
||
// then | ||
assertThat(result).hasSize(0); | ||
} | ||
|
||
@Test | ||
void testClassWithAnnotationHasABinding() { | ||
// when | ||
List<ProcessedOperationBinding> result = getProcessedOperationBindings(ClassWithAnnotation.class); | ||
|
||
// then | ||
assertThat(result).hasSize(1); | ||
ProcessedOperationBinding processedOperationBinding = result.get(0); | ||
assertThat(processedOperationBinding.getType()).isEqualTo("test-binding"); | ||
AsyncGenericOperationBindingProcessor.DefaultAsyncGenerialOperationBinding binding = | ||
(AsyncGenericOperationBindingProcessor.DefaultAsyncGenerialOperationBinding) | ||
processedOperationBinding.getBinding(); | ||
assertThat(binding.getExtensionFields()) | ||
.isEqualTo(Map.of("binding", Map.of("field", "1"), "field", "true")); | ||
} | ||
|
||
@Test | ||
void testClassWithMultipleAnnotationHasABinding() { | ||
// when | ||
List<ProcessedOperationBinding> result = getProcessedOperationBindings(ClassWithMultipleAnnotation.class); | ||
|
||
// then | ||
assertThat(result).hasSize(2); | ||
|
||
ProcessedOperationBinding processedOperationBinding = result.get(0); | ||
assertThat(processedOperationBinding.getType()).isEqualTo("test-binding"); | ||
AsyncGenericOperationBindingProcessor.DefaultAsyncGenerialOperationBinding binding = | ||
(AsyncGenericOperationBindingProcessor.DefaultAsyncGenerialOperationBinding) | ||
processedOperationBinding.getBinding(); | ||
assertThat(binding.getExtensionFields()) | ||
.isEqualTo(Map.of("binding", Map.of("field", "1"), "field", "true")); | ||
|
||
ProcessedOperationBinding processedOperationBinding2 = result.get(1); | ||
assertThat(processedOperationBinding2.getType()).isEqualTo("another-binding"); | ||
assertThat(processedOperationBinding2.getBinding()) | ||
.isEqualTo( | ||
new AsyncGenericOperationBindingProcessor.DefaultAsyncGenerialOperationBinding(Map.of())); | ||
} | ||
|
||
private List<ProcessedOperationBinding> getProcessedOperationBindings(Class<?> testClass) { | ||
List<ProcessedOperationBinding> result = Arrays.stream(testClass.getDeclaredMethods()) | ||
.map((m) -> m.getAnnotationsByType(AsyncGenericOperationBinding.class)) | ||
.flatMap(Arrays::stream) | ||
.map(processor::mapToOperationBinding) | ||
.toList(); | ||
return result; | ||
} | ||
|
||
private static class ClassWithoutAnnotation { | ||
private void methodWithoutAnnotation() {} | ||
} | ||
|
||
private static class ClassWithAnnotation { | ||
@AsyncGenericOperationBinding( | ||
type = "test-binding", | ||
fields = {"binding.field=1", "field=true"}) | ||
private void methodWithAnnotation() {} | ||
|
||
private void methodWithoutAnnotation() {} | ||
} | ||
|
||
private static class ClassWithMultipleAnnotation { | ||
@AsyncGenericOperationBinding( | ||
type = "test-binding", | ||
fields = {"binding.field=1", "field=true"}) | ||
@AsyncGenericOperationBinding(type = "another-binding") | ||
private void methodWithAnnotation() {} | ||
|
||
private void methodWithoutAnnotation() {} | ||
} | ||
} | ||
} |
Oops, something went wrong.