-
-
Notifications
You must be signed in to change notification settings - Fork 803
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add record component registry and pool.
- Loading branch information
Showing
9 changed files
with
696 additions
and
17 deletions.
There are no files selected for viewing
38 changes: 37 additions & 1 deletion
38
byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/DynamicType.java
Large diffs are not rendered by default.
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
297 changes: 297 additions & 0 deletions
297
byte-buddy-dep/src/main/java/net/bytebuddy/dynamic/scaffold/RecordComponentRegistry.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,297 @@ | ||
/* | ||
* Copyright 2014 - 2020 Rafael Winterhalter | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package net.bytebuddy.dynamic.scaffold; | ||
|
||
import net.bytebuddy.build.HashCodeAndEqualsPlugin; | ||
import net.bytebuddy.description.type.RecordComponentDescription; | ||
import net.bytebuddy.description.type.TypeDescription; | ||
import net.bytebuddy.dynamic.Transformer; | ||
import net.bytebuddy.implementation.attribute.RecordComponentAttributeAppender; | ||
import net.bytebuddy.matcher.ElementMatcher; | ||
import net.bytebuddy.matcher.LatentMatcher; | ||
|
||
import java.util.*; | ||
|
||
/** | ||
* A record component registry represents an extendable collection of record components which are identified by their names that are mapped | ||
* to a given {@link RecordComponentAttributeAppender}. Record components | ||
* can be uniquely identified by their name for a given type since record components are never inherited. | ||
* <p> </p> | ||
* This registry is the counterpart of a {@link MethodRegistry}. | ||
* However, a record component registry is implemented simpler since it does not have to deal with complex signatures or | ||
* inheritance. For the sake of consistency, the record component registry follows however a similar pattern without introducing | ||
* unnecessary complexity. | ||
*/ | ||
public interface RecordComponentRegistry { | ||
|
||
/** | ||
* Prepends the given record component definition to this record component registry, i.e. this configuration is applied first. | ||
* | ||
* @param matcher The matcher to identify any record component that this definition concerns. | ||
* @param recordComponentAttributeAppenderFactory The record component attribute appender factory to apply on any matched record component. | ||
* @param transformer The record component transformer to apply to any matched record component. | ||
* @return An adapted version of this method registry. | ||
*/ | ||
RecordComponentRegistry prepend(LatentMatcher<? super RecordComponentDescription> matcher, | ||
RecordComponentAttributeAppender.Factory recordComponentAttributeAppenderFactory, | ||
Transformer<RecordComponentDescription> transformer); | ||
|
||
/** | ||
* Prepares the record component registry for a given instrumented type. | ||
* | ||
* @param instrumentedType The instrumented type. | ||
* @return A prepared record component registry. | ||
*/ | ||
Compiled compile(TypeDescription instrumentedType); | ||
|
||
/** | ||
* Represents a compiled record component registry. | ||
*/ | ||
interface Compiled extends TypeWriter.RecordComponentPool { | ||
|
||
/** | ||
* A no-op record component registry that does not register annotations for any record component. | ||
*/ | ||
enum NoOp implements Compiled { | ||
|
||
/** | ||
* The singleton instance. | ||
*/ | ||
INSTANCE; | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public Record target(RecordComponentDescription recordComponentDescription) { | ||
return new Record.ForImplicitRecordComponent(recordComponentDescription); | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* An immutable default implementation of a record component registry. | ||
*/ | ||
@HashCodeAndEqualsPlugin.Enhance | ||
class Default implements RecordComponentRegistry { | ||
|
||
/** | ||
* This registries entries. | ||
*/ | ||
private final List<Entry> entries; | ||
|
||
/** | ||
* Creates a new empty default record component registry. | ||
*/ | ||
public Default() { | ||
this(Collections.<Entry>emptyList()); | ||
} | ||
|
||
/** | ||
* Creates a new default record component registry. | ||
* | ||
* @param entries The entries of the record component registry. | ||
*/ | ||
private Default(List<Entry> entries) { | ||
this.entries = entries; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public RecordComponentRegistry prepend(LatentMatcher<? super RecordComponentDescription> matcher, | ||
RecordComponentAttributeAppender.Factory recordComponentAttributeAppenderFactory, | ||
Transformer<RecordComponentDescription> transformer) { | ||
List<Entry> entries = new ArrayList<Entry>(this.entries.size() + 1); | ||
entries.add(new Entry(matcher, recordComponentAttributeAppenderFactory, transformer)); | ||
entries.addAll(this.entries); | ||
return new Default(entries); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public RecordComponentRegistry.Compiled compile(TypeDescription instrumentedType) { | ||
List<Compiled.Entry> entries = new ArrayList<Compiled.Entry>(this.entries.size()); | ||
Map<RecordComponentAttributeAppender.Factory, RecordComponentAttributeAppender> recordComponentAttributeAppenders = new HashMap<RecordComponentAttributeAppender.Factory, RecordComponentAttributeAppender>(); | ||
for (Entry entry : this.entries) { | ||
RecordComponentAttributeAppender recordComponentAttributeAppender = recordComponentAttributeAppenders.get(entry.getRecordComponentAttributeAppender()); | ||
if (recordComponentAttributeAppender == null) { | ||
recordComponentAttributeAppender = entry.getRecordComponentAttributeAppender().make(instrumentedType); | ||
recordComponentAttributeAppenders.put(entry.getRecordComponentAttributeAppender(), recordComponentAttributeAppender); | ||
} | ||
entries.add(new Compiled.Entry(entry.resolve(instrumentedType), recordComponentAttributeAppender, entry.getTransformer())); | ||
} | ||
return new Compiled(instrumentedType, entries); | ||
} | ||
|
||
/** | ||
* An entry of the default record component registry. | ||
*/ | ||
@HashCodeAndEqualsPlugin.Enhance | ||
protected static class Entry implements LatentMatcher<RecordComponentDescription> { | ||
|
||
/** | ||
* The matcher to identify any record component that this definition concerns. | ||
*/ | ||
private final LatentMatcher<? super RecordComponentDescription> matcher; | ||
|
||
/** | ||
* The record component attribute appender factory to apply on any matched record component. | ||
*/ | ||
private final RecordComponentAttributeAppender.Factory recordComponentAttributeAppender; | ||
|
||
/** | ||
* The record component transformer to apply to any matched record component. | ||
*/ | ||
private final Transformer<RecordComponentDescription> transformer; | ||
|
||
/** | ||
* Creates a new entry. | ||
* | ||
* @param matcher The matcher to identify any record component that this definition concerns. | ||
* @param recordComponentAttributeAppender The record component attribute appender factory to apply on any matched record component. | ||
* @param transformer The record component transformer to apply to any matched record component. | ||
*/ | ||
protected Entry(LatentMatcher<? super RecordComponentDescription> matcher, | ||
RecordComponentAttributeAppender.Factory recordComponentAttributeAppender, | ||
Transformer<RecordComponentDescription> transformer) { | ||
this.matcher = matcher; | ||
this.recordComponentAttributeAppender = recordComponentAttributeAppender; | ||
this.transformer = transformer; | ||
} | ||
|
||
/** | ||
* Returns the record component attribute appender factory to apply on any matched record component. | ||
* | ||
* @return The record component attribute appender factory to apply on any matched record component. | ||
*/ | ||
protected RecordComponentAttributeAppender.Factory getRecordComponentAttributeAppender() { | ||
return recordComponentAttributeAppender; | ||
} | ||
|
||
/** | ||
* Returns the record component transformer to apply to any matched record component. | ||
* | ||
* @return The record component transformer to apply to any matched record component. | ||
*/ | ||
protected Transformer<RecordComponentDescription> getTransformer() { | ||
return transformer; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public ElementMatcher<? super RecordComponentDescription> resolve(TypeDescription typeDescription) { | ||
return matcher.resolve(typeDescription); | ||
} | ||
} | ||
|
||
/** | ||
* A compiled default record component registry. | ||
*/ | ||
@HashCodeAndEqualsPlugin.Enhance | ||
protected static class Compiled implements RecordComponentRegistry.Compiled { | ||
|
||
/** | ||
* The instrumented type for which this registry was compiled for. | ||
*/ | ||
private final TypeDescription instrumentedType; | ||
|
||
/** | ||
* The entries of this compiled record component registry. | ||
*/ | ||
private final List<Entry> entries; | ||
|
||
/** | ||
* Creates a new compiled record component registry. | ||
* | ||
* @param instrumentedType The instrumented type for which this registry was compiled for. | ||
* @param entries The entries of this compiled record component registry. | ||
*/ | ||
protected Compiled(TypeDescription instrumentedType, List<Entry> entries) { | ||
this.instrumentedType = instrumentedType; | ||
this.entries = entries; | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public Record target(RecordComponentDescription recordComponentDescription) { | ||
for (Entry entry : entries) { | ||
if (entry.matches(recordComponentDescription)) { | ||
return entry.bind(instrumentedType, recordComponentDescription); | ||
} | ||
} | ||
return new Record.ForImplicitRecordComponent(recordComponentDescription); | ||
} | ||
|
||
/** | ||
* An entry of a compiled record component registry. | ||
*/ | ||
@HashCodeAndEqualsPlugin.Enhance | ||
protected static class Entry implements ElementMatcher<RecordComponentDescription> { | ||
|
||
/** | ||
* The matcher to identify any record component that this definition concerns. | ||
*/ | ||
private final ElementMatcher<? super RecordComponentDescription> matcher; | ||
|
||
/** | ||
* The record component attribute appender to apply on any matched record component. | ||
*/ | ||
private final RecordComponentAttributeAppender recordComponentAttributeAppender; | ||
|
||
/** | ||
* The record component transformer to apply to any matched record component. | ||
*/ | ||
private final Transformer<RecordComponentDescription> transformer; | ||
|
||
/** | ||
* Creates a new entry. | ||
* | ||
* @param matcher The matcher to identify any record component that this definition concerns. | ||
* @param recordComponentAttributeAppender The record component attribute appender to apply on any matched record component. | ||
* @param transformer The record component transformer to apply to any matched record component. | ||
*/ | ||
protected Entry(ElementMatcher<? super RecordComponentDescription> matcher, | ||
RecordComponentAttributeAppender recordComponentAttributeAppender, | ||
Transformer<RecordComponentDescription> transformer) { | ||
this.matcher = matcher; | ||
this.recordComponentAttributeAppender = recordComponentAttributeAppender; | ||
this.transformer = transformer; | ||
} | ||
|
||
/** | ||
* Binds this entry to the provided record component description. | ||
* | ||
* @param instrumentedType The instrumented type for which this entry applies. | ||
* @param recordComponentDescription The record component description to be bound to this entry. | ||
* @return A record representing the binding of this entry to the provided record component. | ||
*/ | ||
protected Record bind(TypeDescription instrumentedType, RecordComponentDescription recordComponentDescription) { | ||
return new Record.ForExplicitRecordComponent(recordComponentAttributeAppender, transformer.transform(instrumentedType, recordComponentDescription)); | ||
} | ||
|
||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public boolean matches(RecordComponentDescription target) { | ||
return matcher.matches(target); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.