Compare commits

...

2 Commits

Author SHA1 Message Date
Robinson d3a767806b
Version 1.44 2023-08-05 10:16:25 -06:00
Robinson 27921e22ff
Moved classutils to their own project 2023-08-05 10:15:55 -06:00
11 changed files with 5 additions and 766 deletions

92
LICENSE
View File

@ -75,12 +75,6 @@
The Netty Project
Contributors. See source NOTICE
- TypeTools - A simple, zero-dependency library for working with types. Supports Java 1.6+ and Android.
[The Apache Software License, Version 2.0]
https://github.com/jhalterman/typetools
Copyright 2023
Jonathan Halterman and friends
- Kotlin -
[The Apache Software License, Version 2.0]
https://github.com/JetBrains/kotlin
@ -95,92 +89,6 @@
Copyright 2023
JetBrains s.r.o.
- Collections - Niche collections to augment what is already available.
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Collections
Copyright 2023
Dorkbox LLC
Extra license information
- Bias, BinarySearch -
[MIT License]
https://git.dorkbox.com/dorkbox/Collections
https://github.com/timboudreau/util
Copyright 2013
Tim Boudreau
- ConcurrentEntry -
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Collections
Copyright 2016
bennidi
dorkbox
- Collection Utilities (Array, ArrayMap, BooleanArray, ByteArray, CharArray, FloatArray, IdentityMap, IntArray, IntFloatMap, IntIntMap, IntMap, IntSet, LongArray, LongMap, ObjectFloatMap, ObjectIntMap, ObjectMap, ObjectSet, OrderedMap, OrderedSet) -
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Collections
https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils
Copyright 2011
LibGDX
Mario Zechner (badlogicgames@gmail.com)
Nathan Sweet (nathan.sweet@gmail.com)
- Predicate -
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Collections
https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils
Copyright 2011
LibGDX
Mario Zechner (badlogicgames@gmail.com)
Nathan Sweet (nathan.sweet@gmail.com)
xoppa
- Select, QuickSelect -
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Collections
https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils
Copyright 2011
LibGDX
Mario Zechner (badlogicgames@gmail.com)
Nathan Sweet (nathan.sweet@gmail.com)
Jon Renner
- TimSort, ComparableTimSort -
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Collections
https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/utils
Copyright 2008
The Android Open Source Project
- ConcurrentWeakIdentityHashMap - Concurrent WeakIdentity HashMap
[The Apache Software License, Version 2.0]
https://github.com/spring-projects/spring-loaded/blob/master/springloaded/src/main/java/org/springsource/loaded/support/ConcurrentWeakIdentityHashMap.java
Copyright 2016
zhanhb
- Kotlin -
[The Apache Software License, Version 2.0]
https://github.com/JetBrains/kotlin
Copyright 2020
JetBrains s.r.o. and Kotlin Programming Language contributors
Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply
See: https://github.com/JetBrains/kotlin/blob/master/license/README.md
- Updates - Software Update Management
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Updates
Copyright 2021
Dorkbox LLC
Extra license information
- Kotlin -
[The Apache Software License, Version 2.0]
https://github.com/JetBrains/kotlin
Copyright 2020
JetBrains s.r.o. and Kotlin Programming Language contributors
Kotlin Compiler, Test Data+Libraries, and Tools repository contain third-party code, to which different licenses may apply
See: https://github.com/JetBrains/kotlin/blob/master/license/README.md
- Executor - Shell, JVM, and SSH command execution on Linux, MacOS, or Windows for Java 8+
[The Apache Software License, Version 2.0]
https://git.dorkbox.com/dorkbox/Executor

View File

@ -35,7 +35,7 @@ object Extras {
// set for the project
const val description = "Utilities for use within Java projects"
const val group = "com.dorkbox"
const val version = "1.43"
const val version = "1.44"
// set as project.ext
const val name = "Utilities"
@ -129,7 +129,6 @@ tasks.jar.get().apply {
dependencies {
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4")
api("com.dorkbox:Collections:1.6")
api("com.dorkbox:Executor:3.13")
api("com.dorkbox:OS:1.6")
api("com.dorkbox:Updates:1.1")
@ -150,13 +149,11 @@ dependencies {
// runtime "com.koloboke:koloboke-impl-jdk8:1.0.0"
compileOnly("io.netty:netty-buffer:4.1.94.Final")
compileOnly("net.jodah:typetools:0.6.3")
// compileOnly("net.jodah:typetools:0.6.3")
testImplementation("junit:junit:4.13.2")
// testImplementation("ch.qos.logback:logback-classic:1.4.5")
}
repositories {
mavenCentral()
// implementation(kotlin("stdlib-jdk8"))
}
publishToSonatype {

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 dorkbox, llc
* Copyright 2023 dorkbox, llc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

View File

@ -27,7 +27,7 @@ object Sys {
/**
* Gets the version number.
*/
val version = "1.43"
val version = "1.44"
init {
// Add this project to the updates system, which verifies this class + UUID + version information

View File

@ -1,199 +0,0 @@
/*
* Copyright 2018 dorkbox, llc.
*
* 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 dorkbox.util.classes;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Objects;
import net.jodah.typetools.TypeResolver;
public final
class ClassHelper {
/**
* Retrieves the generic type parameter for the PARENT (super) class of the specified class or lambda expression.
*
* Because of how type erasure works in java, this will work on lambda expressions and ONLY parent/super classes.
*
* @param genericTypeClass this class is what you are looking for
* @param classToCheck class to actually get the parameter from
* @param genericParameterToGet 0-based index of parameter as class to get
*
* @return null if the generic type could not be found.
*/
@SuppressWarnings({"StatementWithEmptyBody", "UnnecessaryLocalVariable"})
public static
Class<?> getGenericParameterAsClassForSuperClass(Class<?> genericTypeClass, Class<?> classToCheck, int genericParameterToGet) {
Class<?> loopClassCheck = classToCheck;
// this will ALWAYS return something, if it is unknown, it will return TypeResolver.Unknown.class
Class<?>[] classes = TypeResolver.resolveRawArguments(genericTypeClass, loopClassCheck);
if (classes.length > genericParameterToGet && classes[genericParameterToGet] != TypeResolver.Unknown.class) {
return classes[genericParameterToGet];
}
// case of multiple inheritance, we are trying to get the first available generic info
// don't check for Object.class (this is where superclass is null)
while (loopClassCheck != Object.class) {
// check to see if we have what we are looking for on our CURRENT class
Type superClassGeneric = loopClassCheck.getGenericSuperclass();
classes = TypeResolver.resolveRawArguments(superClassGeneric, loopClassCheck);
if (classes.length > genericParameterToGet) {
Class<?> aClass = classes[genericParameterToGet];
if (aClass != TypeResolver.Unknown.class) {
return classes[genericParameterToGet];
}
}
// NO MATCH, so walk up.
loopClassCheck = loopClassCheck.getSuperclass();
}
// NOTHING! now check interfaces!
loopClassCheck = classToCheck;
while (loopClassCheck != Object.class) {
// check to see if we have what we are looking for on our CURRENT class interfaces
Type[] genericInterfaces = loopClassCheck.getGenericInterfaces();
for (Type genericInterface : genericInterfaces) {
classes = TypeResolver.resolveRawArguments(genericInterface, loopClassCheck);
if (classes.length > genericParameterToGet) {
Class<?> aClass = classes[genericParameterToGet];
if (aClass != TypeResolver.Unknown.class) {
return aClass;
}
}
}
// NO MATCH, so walk up.
loopClassCheck = loopClassCheck.getSuperclass();
}
// couldn't find it.
return null;
}
// from: https://github.com/square/retrofit/blob/108fe23964b986107aed352ba467cd2007d15208/retrofit/src/main/java/retrofit2/Utils.java
public static Class<?> getRawType(Type type) {
Objects.requireNonNull(type, "type == null");
if (type instanceof Class<?>) {
// Type is a normal class.
return (Class<?>) type;
}
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
// suspects some pathological case related to nested classes exists.
Type rawType = parameterizedType.getRawType();
if (!(rawType instanceof Class)) throw new IllegalArgumentException();
return (Class<?>) rawType;
}
if (type instanceof GenericArrayType) {
Type componentType = ((GenericArrayType) type).getGenericComponentType();
return Array.newInstance(getRawType(componentType), 0).getClass();
}
if (type instanceof TypeVariable) {
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
// type that's more general than necessary is okay.
return Object.class;
}
if (type instanceof WildcardType) {
return getRawType(((WildcardType) type).getUpperBounds()[0]);
}
throw new IllegalArgumentException(
"Expected a Class, ParameterizedType, or "
+ "GenericArrayType, but <"
+ type
+ "> is of type "
+ type.getClass().getName());
}
/**
* Check to see if clazz or interface directly has one of the interfaces defined by requiredClass
* <p/>
* If the class DOES NOT directly have the interface it will fail.
*/
public static
boolean hasInterface(Class<?> requiredClass, Class<?> clazz) {
if (requiredClass == clazz) {
return true;
}
Class<?>[] interfaces = clazz.getInterfaces();
for (Class<?> iface : interfaces) {
if (iface == requiredClass) {
return true;
}
}
// now walk up to see if we can find it.
for (Class<?> iface : interfaces) {
boolean b = hasInterface(requiredClass, iface);
if (b) {
return b;
}
}
// nothing, so now we check the PARENT of this class
Class<?> superClass = clazz.getSuperclass();
// case of multiple inheritance, we are trying to get the first available generic info
// don't check for Object.class (this is where superclass is null)
while (superClass != null && superClass != Object.class) {
// check to see if we have what we are looking for on our CURRENT class
if (hasInterface(requiredClass, superClass)) {
return true;
}
// NO MATCH, so walk up.
superClass = superClass.getSuperclass();
}
// if we don't find it.
return false;
}
/**
* Checks to see if the clazz is a subclass of a parent class.
*/
@SuppressWarnings("SimplifiableIfStatement")
public static
boolean hasParentClass(Class<?> parentClazz, Class<?> clazz) {
Class<?> superClass = clazz.getSuperclass();
if (parentClazz == superClass) {
return true;
}
if (superClass != null && superClass != Object.class) {
return hasParentClass(parentClazz, superClass);
}
return false;
}
private
ClassHelper() {
}
}

View File

@ -1,187 +0,0 @@
/*
* Copyright 2015 dorkbox, llc
*
* 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 dorkbox.util.classes;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import dorkbox.collections.IdentityMap;
/**
* @author dorkbox
* Date: 4/1/15
*/
public final
class ClassHierarchy {
private volatile IdentityMap<Class<?>, Class<?>> arrayCache;
private volatile IdentityMap<Class<?>, Class<?>[]> superClassesCache;
// Recommended for best performance while adhering to the "single writer principle". Must be static-final
private static final AtomicReferenceFieldUpdater<ClassHierarchy, IdentityMap> arrayREF =
AtomicReferenceFieldUpdater.newUpdater(ClassHierarchy.class,
IdentityMap.class,
"arrayCache");
private static final AtomicReferenceFieldUpdater<ClassHierarchy, IdentityMap> superClassesREF =
AtomicReferenceFieldUpdater.newUpdater(ClassHierarchy.class,
IdentityMap.class,
"superClassesCache");
/**
* These data structures are never reset because the class hierarchy doesn't change at runtime. This class uses the "single writer
* principle" for storing data, EVEN THOUGH it's not accessed by a single writer. This DOES NOT MATTER because duplicates DO NOT matter
*/
public
ClassHierarchy(float loadFactor) {
this.arrayCache = new IdentityMap<Class<?>, Class<?>>(32, loadFactor);
this.superClassesCache = new IdentityMap<Class<?>, Class<?>[]>(32, loadFactor);
}
/**
* will return the class + parent classes as an array.
* if parameter clazz is of type array, then the super classes are of array type as well
* <p>
* race conditions will result in DUPLICATE answers, which we don't care if happens
* never returns null
* never reset (class hierarchy never changes during runtime)
*/
public
Class<?>[] getClassAndSuperClasses(final Class<?> clazz) {
// access a snapshot of the subscriptions (single-writer-principle)
final IdentityMap<Class<?>, Class<?>[]> cache = cast(superClassesREF.get(this));
Class<?>[] classes = cache.get(clazz);
// duplicates DO NOT MATTER
if (classes == null) {
// publish all super types of class
final Iterator<Class<?>> superTypesIterator = getSuperTypes(clazz);
final ArrayList<Class<?>> newList = new ArrayList<Class<?>>(16);
Class<?> c;
final boolean isArray = clazz.isArray();
// have to add the original class to the front of the list
newList.add(clazz);
if (isArray) {
// super-types for an array ALSO must be an array.
while (superTypesIterator.hasNext()) {
c = superTypesIterator.next();
c = getArrayClass(c);
if (c != clazz) {
newList.add(c);
}
}
}
else {
while (superTypesIterator.hasNext()) {
c = superTypesIterator.next();
if (c != clazz) {
newList.add(c);
}
}
}
classes = new Class<?>[newList.size()];
newList.toArray(classes);
cache.put(clazz, classes);
// save this snapshot back to the original (single writer principle)
superClassesREF.lazySet(this, cache);
}
return classes;
}
/**
* race conditions will result in DUPLICATE answers, which we don't care if happens
* never returns null
* never resets (class hierarchy never changes during runtime)
*
* https://bugs.openjdk.java.net/browse/JDK-6525802 (fixed this in 2007, so Array.newInstance is just as fast (via intrinsics) new [])
* Cache is in place to keep GC down.
*/
public
Class<?> getArrayClass(final Class<?> c) {
// access a snapshot of the subscriptions (single-writer-principle)
final IdentityMap<Class<?>, Class<?>> cache = cast(arrayREF.get(this));
Class<?> clazz = cache.get(c);
if (clazz == null) {
// messy, but the ONLY way to do it. Array super types are also arrays
final Object[] newInstance = (Object[]) Array.newInstance(c, 0);
clazz = newInstance.getClass();
cache.put(c, clazz);
// save this snapshot back to the original (single writer principle)
arrayREF.lazySet(this, cache);
}
return clazz;
}
/**
* Collect all directly and indirectly related super types (classes and interfaces) of a given class.
*
* @param from The root class to start with
* @return An array of classes, each representing a super type of the root class
*/
public static
Iterator<Class<?>> getSuperTypes(Class<?> from) {
// This must be a 'set' because there can be duplicates, depending on the object hierarchy
final IdentityMap<Class<?>, Boolean> superclasses = new IdentityMap<Class<?>, Boolean>();
collectInterfaces(from, superclasses);
while (!from.equals(Object.class) && !from.isInterface()) {
superclasses.put(from.getSuperclass(), Boolean.TRUE);
from = from.getSuperclass();
collectInterfaces(from, superclasses);
}
return superclasses.keys();
}
private static
void collectInterfaces(Class<?> from, IdentityMap<Class<?>, Boolean> accumulator) {
for (Class<?> intface : from.getInterfaces()) {
accumulator.put(intface, Boolean.TRUE);
collectInterfaces(intface, accumulator);
}
}
/**
* Clears the caches, should only be called on shutdown
*/
public
void shutdown() {
this.arrayCache.clear();
this.superClassesCache.clear();
}
@SuppressWarnings("unchecked")
private static
<T> T cast(Object obj) {
return (T) obj;
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2015 dorkbox, llc
*
* 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 dorkbox.util.classes;
public abstract class ClassResolver {
/**
* A helper class to get the call context. It subclasses SecurityManager to make getClassContext() accessible. An instance of
* CallerResolver only needs to be created, not installed as an actual security manager.
*/
private static final class CallerResolver extends SecurityManager {
@Override
protected Class<?>[] getClassContext() {
return super.getClassContext();
}
}
private static final int CALL_CONTEXT_OFFSET = 3; // may need to change if this class is redesigned
private static final CallerResolver CALLER_RESOLVER;
static {
try {
// This can fail if the current SecurityManager does not allow
// RuntimePermission ("createSecurityManager"):
CALLER_RESOLVER = new CallerResolver();
} catch (SecurityException se) {
throw new RuntimeException("ClassLoaderResolver: could not create CallerResolver: " + se);
}
}
/**
* Indexes into the current method call context with a given offset.
*/
public static Class<?> getCallerClass(final int callerOffset) {
return CALLER_RESOLVER.getClassContext()[CALL_CONTEXT_OFFSET + callerOffset];
}
}

View File

@ -1,188 +0,0 @@
/*
* Copyright 2012 Benjamin Diedrichsen
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
* Copyright 2015 dorkbox, llc
*
* 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 dorkbox.util.classes;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.ArrayList;
import dorkbox.collections.IdentityMap;
/**
* @author bennidi
* Date: 2/16/12
* Time: 12:14 PM
* @author dorkbox
* Date: 2/2/15
*/
public final
class ReflectionUtils {
private static final Method[] EMPTY_METHODS = new Method[0];
private
ReflectionUtils() {
}
/**
* Get methods annotated with the specified annotation.
*
* @param target the class that you are looking for the methods on
* @param annotationClass the annotations that define the method you are looking for
* @param <A> the annotation type
*
* @return the array of methods that match the target + annotation
*/
public static
<A extends Annotation> Method[] getMethods(Class<?> target, Class<A> annotationClass) {
ArrayList<Method> methods = new ArrayList<Method>();
getMethods(target, annotationClass, methods);
return methods.toArray(EMPTY_METHODS);
}
private static
<A extends Annotation> void getMethods(Class<?> target, Class<A> annotationClass, ArrayList<Method> methods) {
try {
for (Method method : target.getDeclaredMethods()) {
if (getAnnotation(method, annotationClass) != null) {
methods.add(method);
}
}
} catch (Exception ignored) {
}
// recursively go until root
if (!target.equals(Object.class)) {
getMethods(target.getSuperclass(), annotationClass, methods);
}
}
/**
* Traverses the class hierarchy upwards, starting at the given subclass, looking
* for an override of the given methods -> finds the bottom most override of the given
* method if any exists
*/
public static
Method getOverridingMethod(final Method overridingMethod, final Class<?> subclass) {
Class<?> current = subclass;
while (!current.equals(overridingMethod.getDeclaringClass())) {
try {
return current.getDeclaredMethod(overridingMethod.getName(), overridingMethod.getParameterTypes());
} catch (NoSuchMethodException e) {
current = current.getSuperclass();
}
}
return null;
}
public static
boolean containsOverridingMethod(final Method[] allMethods, final Method methodToCheck) {
final int length = allMethods.length;
Method method;
for (int i = 0; i < length; i++) {
method = allMethods[i];
if (isOverriddenBy(methodToCheck, method)) {
return true;
}
}
return false;
}
/**
* Searches for an Annotation of the given type on the class. Supports meta annotations.
*
* @param from AnnotatedElement (class, method...)
* @param annotationType Annotation class to look for.
* @param <A> Class of annotation type
* @return Annotation instance or null
*/
private static
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType, IdentityMap<AnnotatedElement, Boolean> visited) {
if (visited.containsKey(from)) {
return null;
}
visited.put(from, Boolean.TRUE);
A ann = from.getAnnotation(annotationType);
if (ann != null) {
return ann;
}
for (Annotation metaAnn : from.getAnnotations()) {
ann = getAnnotation(metaAnn.annotationType(), annotationType, visited);
if (ann != null) {
return ann;
}
}
return null;
}
public static
<A extends Annotation> A getAnnotation(AnnotatedElement from, Class<A> annotationType) {
return getAnnotation(from, annotationType, new IdentityMap<AnnotatedElement, Boolean>());
}
private static
boolean isOverriddenBy(final Method superclassMethod, final Method subclassMethod) {
// if the declaring classes are the same or the subclass method is not defined in the subclass
// hierarchy of the given superclass method or the method names are not the same then
// subclassMethod does not override superclassMethod
if (superclassMethod.getDeclaringClass().equals(subclassMethod.getDeclaringClass()) ||
!superclassMethod.getDeclaringClass().isAssignableFrom(subclassMethod.getDeclaringClass()) ||
!superclassMethod.getName().equals(subclassMethod.getName())) {
return false;
}
final Class<?>[] superClassMethodParameters = superclassMethod.getParameterTypes();
final Class<?>[] subClassMethodParameters = subclassMethod.getParameterTypes();
// method must specify the same number of parameters
//the parameters must occur in the exact same order
for (int i = 0; i < subClassMethodParameters.length; i++) {
if (!superClassMethodParameters[i].equals(subClassMethodParameters[i])) {
return false;
}
}
return true;
}
}

View File

@ -1,17 +0,0 @@
/*
* Copyright 2021 dorkbox, llc
*
* 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 dorkbox.util.classes;

View File

@ -1,24 +0,0 @@
/*
* Copyright 2021 dorkbox, llc
*
* 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 dorkbox.util.classes;
/**
* Required for intellij to not complain regarding `module-info` for a multi-release jar.
* This file is completely ignored by the gradle build process
*/
public
class EmptyClass {}

View File

@ -2,7 +2,6 @@ module dorkbox.utilities {
exports dorkbox.exit;
exports dorkbox.urlHandler;
exports dorkbox.util;
exports dorkbox.util.classes;
exports dorkbox.util.entropy;
exports dorkbox.util.exceptions;
exports dorkbox.util.gwt;