Skip to content

Commit

Permalink
Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim Butov committed Jul 10, 2020
1 parent 139e92d commit 967ab8a
Show file tree
Hide file tree
Showing 20 changed files with 84 additions and 92 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import java.util.function.Function;

/**
* A pool for objects of any type. Can be used to reduce memory usage when working with large amount repeatable objects,
* e.g. words in the long text.
*
* @author Maxim Butov
*/
public class SharedObjectsPool {
Expand All @@ -14,12 +17,23 @@ static class InstanceHolder {

}

/**
* Calls {@link #pooled(Object)} of global pool.
* @see #pooled(Object)
*/
public static <T> T global(T object) {
return InstanceHolder.INSTANCE.pooled(object);
}

private final Map<Object, Object> pool = WeakKeysCaches.weakValues();

/**
* Returns same object from pool if such exists. If not, puts the object into pool and returns it.
*
* @param object reusable object
*
* @return the same object from pool (if found) or the same object
*/
public <T> T pooled(T object) {
return object == null ? null : (T) pool.computeIfAbsent(object, Function.identity());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public Error fail(String message, Object... args) throws E {
}

public void check(boolean condition, Supplier<String> message) throws E {
if (condition) {
fail(message.get());
if (!condition) {
throw fail(message.get());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
* @author Maxim Butov
*/
public interface XAnnotated<T extends AnnotatedElement> extends XReflectionObject<T> {
public interface XAnnotated<AE extends AnnotatedElement> extends XReflectionObject<AE> {

default Stream<? extends Annotation> getDeclaredAnnotations() {
return Arrays.stream(getReflectionObject().getDeclaredAnnotations());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,11 @@ public Stream<XMethod<?>> getMethods() {
return computeIfAbsent(this::getMethodsInternal).stream();
}

public Optional<XConstructor<C>> findConstructor(Class... types) {
public Optional<XConstructor<C>> findConstructor(Class<?>... types) {
return getConstructors().filter(withParameterTypes(types)).collect(toOptional());
}

public XConstructor<C> getConstructor(Class... types) {
public XConstructor<C> getConstructor(Class<?>... types) {
return findConstructor(types)
.orElseThrow(withMessage(() -> String.format("Constructor %s(%s) not found", getName(), getParameterNames(types))));
}
Expand All @@ -148,40 +148,40 @@ public <X> XField<X> getField(String name) {
));
}

public <X> Optional<XMethod<X>> findDeclaredMethod(String name, Class... types) {
public <X> Optional<XMethod<X>> findDeclaredMethod(String name, Class<?>... types) {
return getDeclaredMethods()
.map(XMethod::<X>cast)
.filter(withNameAndParameterTypes(name, types))
.collect(toOptional());
}

public <X> XMethod<X> getDeclaredMethod(String name, Class... types) {
public <X> XMethod<X> getDeclaredMethod(String name, Class<?>... types) {
return this.<X>findDeclaredMethod(name, types)
.orElseThrow(withMessage(() ->
String.format("Method %s.%s(%s) not found", getName(), name, getParameterNames(types))));
}

public <X> Optional<XMethod<X>> findMethod(String name, Class... types) {
public <X> Optional<XMethod<X>> findMethod(String name, Class<?>... types) {
return getMethods()
.map(XMethod::<X>cast)
.filter(withNameAndParameterTypes(name, types))
.findFirst();
}

public <X> XMethod<X> getMethod(String name, Class... types) {
public <X> XMethod<X> getMethod(String name, Class<?>... types) {
return this.<X>findMethod(name, types)
.orElseThrow(withMessage(() -> String.format("Method %s.%s(%s) not found in class hierarchy", getName(), name, getParameterNames(types))));
}

private static String getParameterNames(Class[] types) {
private static String getParameterNames(Class<?>[] types) {
return stream(types).map(Class::getName).collect(Collectors.joining(","));
}

private transient Map cache;

private <X> Map<Supplier<X>, X> getCache() {
if (this.cache == null) {
this.cache = new WeakHashMap();
this.cache = new WeakHashMap<>();
}
return this.cache;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,17 @@
*
* @author Maxim Butov
*/
public class XConstructor<T> extends XReloadableReflectionObject<Constructor<T>>
implements XAnnotated<Constructor<T>>, XExecutable<T>, XMember<Constructor<T>>, XModifiers {

private final Class<T> declaringClass;
private final Class<?>[] parameterTypes;
public class XConstructor<T> extends XExecutable<T, Constructor<T>> {

XConstructor(Constructor<T> reflectionObject) {
super(reflectionObject);
this.declaringClass = reflectionObject.getDeclaringClass();
this.parameterTypes = reflectionObject.getParameterTypes();
super(reflectionObject, reflectionObject.getParameterTypes());
}

@Override
protected Constructor<T> loadReflectionObject() throws ReflectiveOperationException {
return declaringClass.getDeclaredConstructor(parameterTypes);
}

@Override
public Class<?>[] getParameterTypes() {
return parameterTypes;
}

public T newInstance(Object... args) {
return execute(() -> getReflectionObject().newInstance(args));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
package org.sugarcubes.reflection;

import java.lang.reflect.Executable;
import java.util.Arrays;

/**
* Common part of constructor and method.
* Common part of {@link XConstructor} and {@link XMethod}.
*
* @author Maxim Butov
*/
public interface XExecutable<T> {
public abstract class XExecutable<T, E extends Executable> extends XReloadableReflectionObject<E>
implements XAnnotated<E>, XMember<E>, XModifiers {

Class<?>[] getParameterTypes();
protected final Class<T> declaringClass;
protected final Class<?>[] parameterTypes;

default boolean hasParameterTypes(Class... types) {
return Arrays.equals(types, getParameterTypes());
protected XExecutable(E reflectionObject, Class<?>[] parameterTypes) {
super(reflectionObject);
this.declaringClass = (Class<T>) reflectionObject.getDeclaringClass();
this.parameterTypes = parameterTypes;
}

default boolean argumentsMatch(Object... args) {
Class[] parameterTypes = getParameterTypes();
public Class<?>[] getParameterTypes() {
return parameterTypes.clone();
}

public boolean hasParameterTypes(Class<?>... types) {
return Arrays.equals(types, parameterTypes);
}

public boolean argumentsMatch(Object... args) {
if (args.length != parameterTypes.length) {
return false;
}
for (int k = 0; k < args.length; k++) {
Object arg = args[k];
Class parameterType = parameterTypes[k];
Class<?> parameterType = parameterTypes[k];
if (arg == null) {
if (parameterType.isPrimitive()) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class XField<T> extends XReloadableReflectionObject<Field>
/**
* {@link Field#getDeclaringClass()}
*/
private final Class declaringClass;
private final Class<?> declaringClass;

/**
* {@link Field#getName()}
Expand Down Expand Up @@ -45,26 +45,24 @@ protected Field loadReflectionObject() throws ReflectiveOperationException {
return fieldWithModifiers(loadField(), modifiers);
}

private void checkStatic() {
Checks.state().check(this, XModifiers::isStatic, "Field is not static");
public XField<T> checkStatic() {
return Checks.state().check(this, XModifiers::isStatic, "Field is not static");
}

public T get(Object obj) {
return execute(() -> getReflectionObject().get(obj));
}

public T staticGet() {
checkStatic();
return get(null);
return checkStatic().get(null);
}

public void set(Object obj, T value) {
execute(() -> getReflectionObject().set(obj, value));
}

public void staticSet(T value) {
checkStatic();
set(null, value);
checkStatic().set(null, value);
}

public T getAndSet(Object obj, T value) {
Expand All @@ -74,8 +72,7 @@ public T getAndSet(Object obj, T value) {
}

public T staticGetAndSet(T value) {
checkStatic();
return getAndSet(null, value);
return checkStatic().getAndSet(null, value);
}

public XObjectFieldAccessor<T> getAccessor(Object obj) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
* @author Maxim Butov
*/
public interface XMember<T extends Member> extends XModifiers, XReflectionObject<T> {
public interface XMember<M extends Member> extends XModifiers, XReflectionObject<M> {

@Override
default String getName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,29 @@
package org.sugarcubes.reflection;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.sugarcubes.stream.ZeroOneCollectors;
import static org.sugarcubes.reflection.XPredicates.withName;
import static org.sugarcubes.reflection.XPredicates.withReflectionObject;
import static org.sugarcubes.reflection.XReflectionUtils.execute;

/**
* Wrapper for {@link Method}.
*
* @author Maxim Butov
*/
public class XMethod<R> extends XReloadableReflectionObject<Method>
implements XAnnotated<Method>, XExecutable<R>, XMember<Method>, XModifiers {
public class XMethod<R> extends XExecutable<R, Method> {

private final Class<?> declaringClass;
private final String name;
private final Class<?>[] parameterTypes;

XMethod(Method reflectionObject) {
super(reflectionObject);
this.declaringClass = reflectionObject.getDeclaringClass();
super(reflectionObject, reflectionObject.getParameterTypes());
this.name = reflectionObject.getName();
this.parameterTypes = reflectionObject.getParameterTypes();
}

@Override
protected Method loadReflectionObject() throws ReflectiveOperationException {
return declaringClass.getDeclaredMethod(name, parameterTypes);
}

@Override
public Class<?>[] getParameterTypes() {
return parameterTypes.clone();
}

public boolean hasNameAndParameterTypes(String name, Class... types) {
public boolean hasNameAndParameterTypes(String name, Class<?>... types) {
return hasName(name) && hasParameterTypes(types);
}

Expand All @@ -50,19 +36,8 @@ public <X> XMethod<X> cast() {
}

public <X> XMethod<X> getSuper() {
Method method = getReflectionObject();
if (method.isBridge()) {
// todo: this is not working
return getDeclaringClass().getSuperclass().getMethods()
.filter(withName(name))
.filter(withReflectionObject(candidate -> candidate.getReturnType().isAssignableFrom(method.getReturnType()) &&
Arrays.equals(method.getGenericParameterTypes(), candidate.getGenericParameterTypes())))
.collect(ZeroOneCollectors.onlyElement())
.cast();
}
else {
return getDeclaringClass().getSuperclass().<R>findMethod(name, parameterTypes).orElse(this).cast();
}
// todo: check this
return getDeclaringClass().getSuperclass().<R>findMethod(name, parameterTypes).orElse(this).cast();
}

public <X> XMethod<X> getRoot() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ static boolean isValidModifier(int modifier) {
*/
int getModifiers();

default boolean isModifier(int modifier) {
default boolean isAnyModifier(int modifier) {
return (getModifiers() & modifier) != 0;
}

Expand Down Expand Up @@ -59,7 +59,7 @@ default boolean isProtected() {
return isModifier(Modifier::isProtected);
}

default boolean isPackage() {
default boolean isPackageLocal() {
return !isPublic() && !isPrivate() && !isProtected();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sugarcubes.reflection;

import java.io.ObjectStreamException;
import java.util.stream.Stream;

/**
Expand Down Expand Up @@ -97,4 +98,8 @@ public String toString() {
return "XNullClass";
}

private Object readResolve() throws ObjectStreamException {
return INSTANCE;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sugarcubes.reflection;

import java.lang.reflect.Executable;
import java.util.function.Predicate;

import org.sugarcubes.check.Checks;
Expand All @@ -17,13 +18,13 @@ public static <X, R extends XReflectionObject<X>> Predicate<R> withName(String n
return obj -> obj.hasName(name);
}

public static <T, R extends XExecutable<T>> Predicate<R> withParameterTypes(Class... types) {
public static <T, E extends Executable, R extends XExecutable<T, E>> Predicate<R> withParameterTypes(Class<?>... types) {
Checks.arg().notNull(types, "types must not be null");
return obj -> obj.hasParameterTypes(types);
}

public static <T, R extends XMethod<T>> Predicate<R> withNameAndParameterTypes(String name, Class... types) {
return and(withName(name), withParameterTypes(types));
public static <T, R extends XMethod<T>> Predicate<R> withNameAndParameterTypes(String name, Class<?>... types) {
return and(XPredicates.withName(name), XPredicates.withParameterTypes(types));
}

public static <X, R extends XReflectionObject<X>> Predicate<R> withReflectionObject(Predicate<X> predicate) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static <X> XField<X> of(Field field) {
/**
* Cache for xreflection objects.
*/
private static final Map<Object, XReflectionObject> CACHE = WeakKeysCaches.softValues();
private static final Map<Object, XReflectionObject<?>> CACHE = WeakKeysCaches.softValues();

private static <K, V> V computeIfAbsent(K key, Function<K, V> mappingFunction) {
return ((Map<K, V>) CACHE).computeIfAbsent(key, mappingFunction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public boolean equals(Object obj) {
if (!(obj instanceof XReflectionObject)) {
return false;
}
XReflectionObject that = (XReflectionObject) obj;
XReflectionObject<?> that = (XReflectionObject) obj;
return getReflectionObject().equals(that.getReflectionObject());
}

Expand Down
Loading

0 comments on commit 967ab8a

Please sign in to comment.