uk.co.real_logic.sbe.codec.java.MethodSelector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sbe-all Show documentation
Show all versions of sbe-all Show documentation
FIX/SBE - OSI layer 6 presentation for encoding and decoding application messages in binary format for low-latency applications.
/*
* Copyright 2013-2024 Real Logic Limited.
*
* 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 uk.co.real_logic.sbe.codec.java;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Selects sorted methods of a class that are annotated with {@link GroupOrder}.
*/
public class MethodSelector
{
private final Set ignoredMethods;
private final Map, Set> sortedMethods = new HashMap<>();
/**
* The method names for method belonging to Object and Iterator.
*
* @return the method names for method belonging to Object and Iterator.
*/
public static Set objectAndIteratorMethods()
{
return new HashSet<>(
Arrays.asList("hashCode", "clone", "toString", "getClass", "next", "hasNext", "remove", "iterator"));
}
/**
* Create a method selector with a set of methods to be ignored.
*
* @param ignoredMethods to be skipped over.
*/
public MethodSelector(final Set ignoredMethods)
{
this.ignoredMethods = ignoredMethods;
}
/**
* Select a list of methods from a given class.
*
* @param clazz to select the method for.
* @return the list of methods
*/
public List select(final Class> clazz)
{
final Method[] methods = clazz.getMethods();
final Set sortedMethodNames = getSortedMethods(clazz, methods);
final Map sortedMethods = new HashMap<>();
final List unsortedMethods = new ArrayList<>();
for (final Method method : methods)
{
selectMethod(sortedMethodNames, sortedMethods, unsortedMethods, method);
}
for (final String name : sortedMethodNames)
{
unsortedMethods.add(sortedMethods.get(name));
}
return unsortedMethods;
}
private Set getSortedMethods(final Class> clazz, final Method[] methods)
{
final Set sortedMethodNames = sortedMethods.get(clazz);
if (null == sortedMethodNames)
{
final GroupOrder order = clazz.getAnnotation(GroupOrder.class);
if (null == order)
{
sortedMethods.put(clazz, Collections.emptySet());
return Collections.emptySet();
}
else
{
final Set result = new LinkedHashSet<>();
for (final Class> groupClazz : order.value())
{
for (final Method method : methods)
{
if (method.getReturnType() == groupClazz && method.getParameterTypes().length == 0)
{
result.add(method.getName());
}
}
}
sortedMethods.put(clazz, result);
return result;
}
}
return sortedMethodNames;
}
private void selectMethod(
final Set sortedMethodNames,
final Map sortedMethods,
final List unsortedMethods,
final Method method)
{
final int mods = method.getModifiers();
if (!Modifier.isPublic(mods) ||
Modifier.isStatic(mods) ||
method.getParameterTypes().length != 0 ||
method.getReturnType().equals(Void.TYPE) ||
ignoredMethods.contains(method.getName()))
{
return;
}
if (null == sortedMethodNames)
{
unsortedMethods.add(method);
}
else
{
if (sortedMethodNames.contains(method.getName()))
{
sortedMethods.put(method.getName(), method);
}
else
{
unsortedMethods.add(method);
}
}
}
}