This commit is contained in:
heavyrain.lee
2019-05-22 08:38:55 +08:00
parent 721abfe3a5
commit 79bd0c3304
98 changed files with 1017 additions and 132 deletions
+110
View File
@@ -0,0 +1,110 @@
/*
* Copyright 2016 ikidou
*
* 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 ikidou.reflect;
import ikidou.reflect.exception.TypeException;
import ikidou.reflect.typeimpl.ParameterizedTypeImpl;
import ikidou.reflect.typeimpl.WildcardTypeImpl;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
public class TypeBuilder {
private final TypeBuilder parent;
private final Class raw;
private final List<Type> args = new ArrayList<>();
private TypeBuilder(Class raw, TypeBuilder parent) {
assert raw != null;
this.raw = raw;
this.parent = parent;
}
public static TypeBuilder newInstance(Class raw) {
return new TypeBuilder(raw, null);
}
private static TypeBuilder newInstance(Class raw, TypeBuilder parent) {
return new TypeBuilder(raw, parent);
}
public TypeBuilder beginSubType(Class raw) {
return newInstance(raw, this);
}
public TypeBuilder endSubType() {
if (parent == null) {
throw new TypeException("expect beginSubType() before endSubType()");
}
parent.addTypeParam(getType());
return parent;
}
public TypeBuilder addTypeParam(Class clazz) {
return addTypeParam((Type) clazz);
}
public TypeBuilder addTypeParamExtends(Class... classes) {
if (classes == null) {
throw new NullPointerException("addTypeParamExtends() expect not null Class");
}
WildcardTypeImpl wildcardType = new WildcardTypeImpl(null, classes);
return addTypeParam(wildcardType);
}
public TypeBuilder addTypeParamSuper(Class... classes) {
if (classes == null) {
throw new NullPointerException("addTypeParamSuper() expect not null Class");
}
WildcardTypeImpl wildcardType = new WildcardTypeImpl(classes, null);
return addTypeParam(wildcardType);
}
public TypeBuilder addTypeParam(Type type) {
if (type == null) {
throw new NullPointerException("addTypeParam expect not null Type");
}
args.add(type);
return this;
}
public Type build() {
if (parent != null) {
throw new TypeException("expect endSubType() before build()");
}
return getType();
}
private Type getType() {
if (args.isEmpty()) {
return raw;
}
return new ParameterizedTypeImpl(raw, args.toArray(new Type[args.size()]), null);
}
}
+39
View File
@@ -0,0 +1,39 @@
/*
* Copyright 2016 ikidou
*
* 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 ikidou.reflect;
import ikidou.reflect.exception.TypeException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public abstract class TypeToken<T> {
private final Type type;
public TypeToken() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof Class) {
throw new TypeException("No generics found!");
}
ParameterizedType type = (ParameterizedType) superclass;
this.type = type.getActualTypeArguments()[0];
}
public Type getType() {
return type;
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2016 ikidou
*
* 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 ikidou.reflect.exception;
public class TypeException extends RuntimeException {
public TypeException() {
}
public TypeException(String message) {
super(message);
}
public TypeException(String message, Throwable cause) {
super(message, cause);
}
public TypeException(Throwable cause) {
super(cause);
}
public TypeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
@@ -0,0 +1,123 @@
/*
* Copyright 2016 ikidou
*
* 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 ikidou.reflect.typeimpl;
import ikidou.reflect.exception.TypeException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
@SuppressWarnings("SpellCheckingInspection")
public class ParameterizedTypeImpl implements ParameterizedType {
private final Class raw;
private final Type[] args;
private final Type owner;
public ParameterizedTypeImpl(Class raw, Type[] args, Type owner) {
this.raw = raw;
this.args = args != null ? args : new Type[0];
this.owner = owner;
checkArgs();
}
private void checkArgs() {
if (raw == null) {
throw new TypeException("raw class can't be null");
}
TypeVariable[] typeParameters = raw.getTypeParameters();
if (args.length != 0 && typeParameters.length != args.length) {
throw new TypeException(raw.getName() + " expect " + typeParameters.length + " arg(s), got " + args.length);
}
}
@Override
public Type[] getActualTypeArguments() {
return args;
}
@Override
public Type getRawType() {
return raw;
}
@Override
public Type getOwnerType() {
return owner;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(raw.getName());
if (args.length != 0) {
sb.append('<');
for (int i = 0; i < args.length; i++) {
if (i != 0) {
sb.append(", ");
}
Type type = args[i];
if (type instanceof Class) {
Class clazz = (Class) type;
if (clazz.isArray()) {
int count = 0;
do {
count++;
clazz = clazz.getComponentType();
} while (clazz.isArray());
sb.append(clazz.getName());
for (int j = count; j > 0; j--) {
sb.append("[]");
}
} else {
sb.append(clazz.getName());
}
} else {
sb.append(args[i].toString());
}
}
sb.append('>');
}
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ParameterizedTypeImpl that = (ParameterizedTypeImpl) o;
if (!raw.equals(that.raw)) return false;
// Probably incorrect - comparing Object[] arrays with Arrays.equals
if (!Arrays.equals(args, that.args)) return false;
return owner != null ? owner.equals(that.owner) : that.owner == null;
}
@Override
public int hashCode() {
int result = raw.hashCode();
result = 31 * result + Arrays.hashCode(args);
result = 31 * result + (owner != null ? owner.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2016 ikidou
*
* 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 ikidou.reflect.typeimpl;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
public class WildcardTypeImpl implements WildcardType {
private final Class[] upper;
private final Class[] lower;
public WildcardTypeImpl(Class[] lower, Class[] upper) {
this.lower = lower != null ? lower : new Class[0];
this.upper = upper != null ? upper : new Class[0];
checkArgs();
}
private void checkArgs() {
if (lower.length == 0 && upper.length == 0) {
throw new IllegalArgumentException("lower or upper can't be null");
}
checkArgs(lower);
checkArgs(upper);
}
private void checkArgs(Class[] args) {
for (int i = 1; i < args.length; i++) {
Class clazz = args[i];
if (!clazz.isInterface()) {
throw new IllegalArgumentException(clazz.getName() + " not a interface!");
}
}
}
@Override
public Type[] getUpperBounds() {
return upper;
}
@Override
public Type[] getLowerBounds() {
return lower;
}
@Override
public String toString() {
if (upper.length > 0) {
if (upper[0] == Object.class) {
return "?";
}
return getTypeString("? extends ", upper);
} else {
return getTypeString("? super ", lower);
}
}
private String getTypeString(String prefix, Class[] type) {
StringBuilder sb = new StringBuilder();
sb.append(prefix);
for (int i = 0; i < type.length; i++) {
if (i != 0) {
sb.append(" & ");
}
sb.append(type[i].getName());
}
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
WildcardTypeImpl that = (WildcardTypeImpl) o;
return Arrays.equals(upper, that.upper) && Arrays.equals(lower, that.lower);
}
@Override
public int hashCode() {
int result = Arrays.hashCode(upper);
result = 31 * result + Arrays.hashCode(lower);
return result;
}
}