Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* 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
*
* https://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 org.springframework.core.hint;

import java.util.Objects;

/**
* Base {@link TypeReference} implementation that ensures consistent behaviour
* for {@code equals()}, {@code hashCode()}, and {@code toString()} based on
* the {@linkplain #getCanonicalName() canonical name}.
*
* @author Stephane Nicoll
* @since 6.0
*/
public abstract class AbstractTypeReference implements TypeReference {

@Override
public int hashCode() {
return Objects.hash(getCanonicalName());
}

@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof TypeReference otherReference)) {
return false;
}
return getCanonicalName().equals(otherReference.getCanonicalName());
}

@Override
public String toString() {
return getCanonicalName();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* 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
*
* https://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 org.springframework.core.hint;

import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* A hint that describes the need for a proxy against a concrete class.
*
* @author Stephane Nicoll
* @since 6.0
*/
public final class ClassProxyHint {

private final TypeReference targetClass;

private final List<TypeReference> proxiedInterfaces;


private ClassProxyHint(Builder builder) {
this.targetClass = builder.targetClass;
this.proxiedInterfaces = builder.proxiedInterfaces.stream().distinct().toList();
}

/**
* Initialize a builder with the target class to use.
* @param targetClass the target class of the proxy
* @return a builder for the hint
*/
public static Builder of(TypeReference targetClass) {
return new Builder(targetClass);
}

/**
* Initialize a builder with the target class to use.
* @param targetClass the target class of the proxy
* @return a builder for the hint
*/
public static Builder of(Class<?> targetClass) {
return of(TypeReference.of(targetClass));
}

/**
* Return the target class of the proxy.
* @return the target class
*/
public TypeReference getTargetClass() {
return this.targetClass;
}

/**
* Return the interfaces to be proxied.
* @return the interfaces that the proxy should implement
*/
public List<TypeReference> getProxiedInterfaces() {
return this.proxiedInterfaces;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ClassProxyHint that = (ClassProxyHint) o;
return this.targetClass.equals(that.targetClass)
&& this.proxiedInterfaces.equals(that.proxiedInterfaces);
}

@Override
public int hashCode() {
return Objects.hash(this.targetClass, this.proxiedInterfaces);
}


/**
* Builder for {@link ClassProxyHint}.
*/
public static class Builder {

private final TypeReference targetClass;

private final LinkedList<TypeReference> proxiedInterfaces = new LinkedList<>();


public Builder(TypeReference targetClass) {
this.targetClass = targetClass;
}

/**
* Add the specified interfaces that the proxy should implement.
* @param proxiedInterfaces the interfaces the proxy should implement
* @return {@code this}, to facilitate method chaining
*/
public Builder proxiedInterfaces(TypeReference... proxiedInterfaces) {
this.proxiedInterfaces.addAll(Arrays.asList(proxiedInterfaces));
return this;
}

/**
* Add the specified interfaces that the proxy should implement.
* @param proxiedInterfaces the interfaces the proxy should implement
* @return {@code this}, to facilitate method chaining
*/
public Builder proxiedInterfaces(Class<?>... proxiedInterfaces) {
this.proxiedInterfaces.addAll(Arrays.stream(proxiedInterfaces)
.map(TypeReference::of).collect(Collectors.toList()));
return this;
}

/**
* Create a {@link ClassProxyHint} based on the state of this builder.
* @return a class proxy hint
*/
public ClassProxyHint build() {
return new ClassProxyHint(this);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* 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
*
* https://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 org.springframework.core.hint;

import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.springframework.util.ObjectUtils;

/**
* A hint that describes the need for reflection on a {@link Method} or
* {@link Constructor}.
*
* @author Stephane Nicoll
* @since 6.0
*/
public final class ExecutableHint extends MemberHint {

private final List<TypeReference> parameterTypes;

private final List<ExecutableMode> modes;


private ExecutableHint(Builder builder) {
super(builder.name);
this.parameterTypes = List.copyOf(builder.parameterTypes);
this.modes = List.copyOf(builder.modes);
}

/**
* Initialize a builder with the parameter types of a constructor.
* @param parameterTypes the parameter types of the constructor
* @return a builder
*/
public static Builder ofConstructor(List<TypeReference> parameterTypes) {
return new Builder("<init>", parameterTypes);
}

/**
* Initialize a builder with the name and parameters types of a method.
* @param name the name of the method
* @param parameterTypes the parameter types of the method
* @return a builder
*/
public static Builder ofMethod(String name, List<TypeReference> parameterTypes) {
return new Builder(name, parameterTypes);
}

/**
* Return the parameter types of the executable.
* @return the parameter types
* @see Executable#getParameterTypes()
*/
public List<TypeReference> getParameterTypes() {
return this.parameterTypes;
}

/**
* Return the {@linkplain ExecutableMode modes} that apply to this hint.
* @return the modes
*/
public List<ExecutableMode> getModes() {
return this.modes;
}


/**
* Builder for {@link ExecutableHint}.
*/
public static final class Builder {

private final String name;

private final List<TypeReference> parameterTypes;

private final Set<ExecutableMode> modes = new LinkedHashSet<>();


private Builder(String name, List<TypeReference> parameterTypes) {
this.name = name;
this.parameterTypes = parameterTypes;
}

/**
* Add the specified {@linkplain ExecutableMode mode} if necessary.
* @param mode the mode to add
* @return {@code this}, to facilitate method chaining
*/
public Builder withMode(ExecutableMode mode) {
this.modes.add(mode);
return this;
}

/**
* Set the {@linkplain ExecutableMode modes} to use.
* @param modes the mode to use
* @return {@code this}, to facilitate method chaining
*/
public Builder setModes(ExecutableMode... modes) {
this.modes.clear();
if (!ObjectUtils.isEmpty(modes)) {
this.modes.addAll(Arrays.asList(modes));
}
return this;
}

/**
* Create an {@link ExecutableHint} based on the state of this builder.
* @return an executable hint
*/
public ExecutableHint build() {
return new ExecutableHint(this);
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* 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
*
* https://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 org.springframework.core.hint;

import java.lang.reflect.Executable;

/**
* Represent the need of reflection for a given {@link Executable}.
*
* @author Stephane Nicoll
* @since 6.0
*/
public enum ExecutableMode {

/**
* Only retrieving the {@link Executable} and its metadata is required.
*/
INTROSPECT,

/**
* Full reflection support is required, including the ability to invoke
* the {@link Executable}.
*/
INVOKE;

}
Loading