-
Notifications
You must be signed in to change notification settings - Fork 298
refactor: change TypeTransformerRegistry to use a Map instead of Arraylist #5929
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,9 +20,7 @@ | |
| import org.eclipse.edc.transform.spi.TypeTransformerRegistry; | ||
| import org.jetbrains.annotations.NotNull; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.HashMap; | ||
| import java.util.List; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.Optional; | ||
|
|
@@ -31,7 +29,7 @@ | |
|
|
||
| public class TypeTransformerRegistryImpl implements TypeTransformerRegistry { | ||
| private final Map<String, Class<?>> aliases = new HashMap<>(); | ||
| private final List<TypeTransformer<?, ?>> transformers = new ArrayList<>(); | ||
| private final Map<Class<?>, Map<Class<?>, TypeTransformer<?, ?>>> transformers = new HashMap<>(); | ||
| private final Map<String, TypeTransformerRegistry> contextRegistries = new HashMap<>(); | ||
| private TypeTransformerRegistry parent; | ||
|
|
||
|
|
@@ -44,7 +42,8 @@ private TypeTransformerRegistryImpl(TypeTransformerRegistry parent) { | |
|
|
||
| @Override | ||
| public void register(TypeTransformer<?, ?> transformer) { | ||
| this.transformers.add(transformer); | ||
| transformers.computeIfAbsent(transformer.getInputType(), key -> new HashMap<>()) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it could worth to add a warning log in case of transformer override
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already did, thanks. |
||
| .put(transformer.getOutputType(), transformer); | ||
| } | ||
|
|
||
| @Override | ||
|
|
@@ -54,14 +53,33 @@ public void register(TypeTransformer<?, ?> transformer) { | |
|
|
||
| @Override | ||
| public @NotNull <INPUT, OUTPUT> TypeTransformer<INPUT, OUTPUT> transformerFor(@NotNull INPUT input, @NotNull Class<OUTPUT> outputType) { | ||
| return transformers.stream() | ||
| .filter(t -> t.getInputType().isInstance(input) && t.getOutputType().equals(outputType)) | ||
| .findAny() | ||
| return findTransformer(input, outputType) | ||
| .map(it -> (TypeTransformer<INPUT, OUTPUT>) it) | ||
| .or(() -> Optional.ofNullable(parent).map(p -> p.transformerFor(input, outputType))) | ||
| .orElseThrow(() -> new EdcException(format("No Transformer registered that can handle %s -> %s", input.getClass(), outputType))); | ||
| } | ||
|
|
||
| private Optional<TypeTransformer<?, ?>> findTransformer(Object input, Class<?> outputType) { | ||
| var inputTypes = transformers.entrySet().stream() | ||
| .filter(entry -> entry.getKey().isInstance(input)) | ||
| .filter(entry -> entry.getValue().containsKey(outputType)) | ||
| .map(Map.Entry::getKey) | ||
| .toList(); | ||
|
|
||
| var mostSpecificInputTypes = inputTypes.stream() | ||
| .filter(candidate -> inputTypes.stream() | ||
| .noneMatch(other -> !candidate.equals(other) && candidate.isAssignableFrom(other))) | ||
| .toList(); | ||
|
|
||
| if (mostSpecificInputTypes.size() > 1) { | ||
| throw new EdcException(format("Ambiguous transformers registered for %s -> %s", input.getClass(), outputType)); | ||
| } | ||
|
|
||
| return mostSpecificInputTypes.stream() | ||
| .findFirst() | ||
| .map(inputType -> transformers.get(inputType).get(outputType)); | ||
| } | ||
|
Comment on lines
+75
to
+101
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this logic is not wrong but I think it could be written in a more readable way - and slightly more performant, by avoiding multiple iterations over private Optional<TypeTransformer<?, ?>> findTransformer(Object input, Class<?> outputType) {
return transformers.entrySet().stream()
.filter(entry -> entry.getKey().isInstance(input))
.filter(entry -> entry.getValue().containsKey(outputType))
.map(Map.Entry::getKey)
.map(Optional::of)
.reduce(Optional.empty(), (current, candidate) -> {
if (current.isEmpty()) {
return candidate;
}
if (candidate.get().isAssignableFrom(current.get())) {
return current;
}
if (current.get().isAssignableFrom(candidate.get())) {
return candidate;
}
throw new EdcException(format("Ambiguous transformers registered for %s -> %s", input.getClass(), outputType));
})
.map(transformers::get)
.map(it -> it.get(outputType));
}so the "most specific" logic emerges in the reduce function itself:
the reduce function could also be extracted and called
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Your implementation is cleaner so I applied it. thanks |
||
|
|
||
| @Override | ||
| public <INPUT, OUTPUT> Result<OUTPUT> transform(@NotNull INPUT input, @NotNull Class<OUTPUT> outputType) { | ||
| Objects.requireNonNull(input); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* | ||
| * Copyright (c) 2022 - 2023 Bayerische Motoren Werke Aktiengesellschaft (BMW AG) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: copyright
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. changed it |
||
| * | ||
| * This program and the accompanying materials are made available under the | ||
| * terms of the Apache License, Version 2.0 which is available at | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| * | ||
| * Contributors: | ||
| * Bayerische Motoren Werke Aktiengesellschaft (BMW AG) - initial API and implementation | ||
| * | ||
| */ | ||
|
|
||
| package org.eclipse.edc.transform; | ||
|
|
||
| import org.eclipse.edc.transform.spi.TransformerContext; | ||
| import org.eclipse.edc.transform.spi.TypeTransformer; | ||
|
|
||
| public class TestTypeTransformer<INPUT, OUTPUT> implements TypeTransformer<INPUT, OUTPUT> { | ||
| private final Class<INPUT> inputType; | ||
| private final Class<OUTPUT> outputType; | ||
|
|
||
| public TestTypeTransformer(Class<INPUT> inputType, Class<OUTPUT> outputType) { | ||
| this.inputType = inputType; | ||
| this.outputType = outputType; | ||
| } | ||
|
|
||
| @Override | ||
| public Class<INPUT> getInputType() { | ||
| return inputType; | ||
| } | ||
|
|
||
| @Override | ||
| public Class<OUTPUT> getOutputType() { | ||
| return outputType; | ||
| } | ||
|
|
||
| @Override | ||
| public OUTPUT transform(INPUT input, TransformerContext context) { | ||
| return null; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's been a while that I see this aliases unused field, since you're here, could you please delete it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done