All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fluxtion.compiler.generation.util.ClassUtils Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2019, 2024 gregory higgins.
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the Server Side Public License, version 1,
 * as published by MongoDB, Inc.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Server Side Public License for more details.
 *
 * You should have received a copy of the Server Side Public License
 * along with this program.  If not, see
 * .
 */
package com.fluxtion.compiler.generation.util;

import com.fluxtion.compiler.generation.model.CbMethodHandle;
import com.fluxtion.compiler.generation.model.ExportFunctionData;
import com.fluxtion.compiler.generation.model.Field;
import com.fluxtion.compiler.generation.model.SimpleEventProcessorModel;
import com.fluxtion.runtime.annotations.ExportService;
import com.fluxtion.runtime.annotations.NoPropagateFunction;
import com.fluxtion.runtime.annotations.builder.FluxtionIgnore;
import com.fluxtion.runtime.dataflow.Tuple;
import lombok.SneakyThrows;
import net.vidageek.mirror.dsl.Mirror;
import org.reflections.ReflectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.atomic.LongAdder;
import java.util.stream.Collectors;

/**
 * @author Greg Higgins
 */
public interface ClassUtils {

    Logger LOGGER = LoggerFactory.getLogger(ClassUtils.class);

    /**
     * finds the CbMethodHandle whose parameter most closely matches the class
     * of the parent in the inheritance tree.
     * 

* If no match is found a null is returned. * * @param parent node to interrogate * @param cbs collection of callbacks * @return The best matched callback handle */ static CbMethodHandle findBestParentCB(Object parent, Collection cbs) { Set> classList = cbs.stream() .filter(cb -> cb.method.getParameterTypes()[0].isAssignableFrom(parent.getClass())) .map(cb -> cb.method.getParameterTypes()[0]) .collect(Collectors.toSet()); if (classList.isEmpty()) { return null; } Optional> bestMatch = classList.stream().sorted((c1, c2) -> { if (c1 == c2) { return 0; } if (c1.isAssignableFrom(c2)) { return 1; } return -1; }).findFirst(); Optional findFirst = cbs.stream() .filter(cb -> cb.method.getParameterTypes()[0] == bestMatch.orElse(null)) .findFirst(); return findFirst.orElse(null); } static boolean isPropertyTransient(PropertyDescriptor property, Field field) throws SecurityException { final Class fieldClass = field.instance.getClass(); final String name = property.getName(); final java.lang.reflect.Field fieldOfProperty; final Set allFields = ReflectionUtils.getAllFields(fieldClass, ReflectionUtils.withName(name)); boolean isTransient = true; if (allFields.isEmpty()) { // } else { fieldOfProperty = allFields.iterator().next(); fieldOfProperty.setAccessible(true); isTransient = Modifier.isTransient(fieldOfProperty.getModifiers()) || fieldOfProperty.getAnnotation(FluxtionIgnore.class) != null; } return isTransient; } static T getField(String name, Object instance) { return (T) new Mirror().on(instance).get().field(name); } static java.lang.reflect.Field getReflectField(Class clazz, String fieldName) throws NoSuchFieldException { try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { Class superClass = clazz.getSuperclass(); if (superClass == null) { throw e; } else { return getReflectField(superClass, fieldName); } } } //sorting by class type most specific first static List> sortClassHierarchy(Set> classSet) { ArrayList> clazzListAlpha = new ArrayList<>(classSet); ArrayList> clazzSorted = new ArrayList<>(); clazzListAlpha.sort(new NaturalOrderComparator<>()); clazzListAlpha.forEach(clazz -> { boolean added = false; for (int i = 0; i < clazzSorted.size(); i++) { Class sortedClazz = clazzSorted.get(i); if (sortedClazz.isAssignableFrom(clazz)) { clazzSorted.add(i, clazz); added = true; break; } } if (!added) { clazzSorted.add(clazz); } }); return clazzSorted; } @SneakyThrows static String wrapExportedFunctionCall(Method delegateMethod, String exportedMethodName, String instanceName) { LongAdder argNumber = new LongAdder(); StringBuilder signature = new StringBuilder("public void " + exportedMethodName); signature.append('('); StringJoiner sj = new StringJoiner(", "); Type[] params = delegateMethod.getGenericParameterTypes(); for (int j = 0; j < params.length; j++) { String param = params[j].getTypeName(); if (delegateMethod.isVarArgs() && (j == params.length - 1)) // replace T[] with T... param = param.replaceFirst("\\[\\]$", "..."); param += " arg" + argNumber.intValue(); sj.add(param); argNumber.increment(); } signature.append(sj.toString()); signature.append(", String identifer"); signature.append("){"); signature.append("try {\n" + " ExportingNode instance = getNodeById(identifer);"); signature.append("\n instance." + delegateMethod.getName() + "("); StringJoiner sjInvoker = new StringJoiner(", "); for (int i = 0; i < argNumber.intValue(); i++) { sjInvoker.add("arg" + i); } signature.append(sjInvoker.toString()); signature.append(");\n"); signature.append("} catch (NoSuchFieldException e) {\n" + " throw new RuntimeException(e);\n" + " }" + " }"); return signature.toString(); } @SneakyThrows static String wrapExportedFunctionCall(Method exportedMethod, List callBackList, SimpleEventProcessorModel model) { String exportedMethodName = exportedMethod.getName(); LongAdder argNumber = new LongAdder(); Method delegateMethod = callBackList.get(0).getMethod(); StringBuilder signature = new StringBuilder("public void " + exportedMethodName); signature.append('('); StringJoiner sj = new StringJoiner(", "); Type[] params = delegateMethod.getGenericParameterTypes(); for (int j = 0; j < params.length; j++) { String param = params[j].getTypeName(); if (delegateMethod.isVarArgs() && (j == params.length - 1)) // replace T[] with T... param = param.replaceFirst("\\[\\]$", "..."); param += " arg" + argNumber.intValue(); sj.add(param); argNumber.increment(); } signature.append(sj); signature.append("){"); //method calls StringJoiner sjInvoker = new StringJoiner(", ", "(", "));"); for (int i = 0; i < argNumber.intValue(); i++) { sjInvoker.add("arg" + i); } callBackList.forEach(cb -> { signature.append("setDirty(").append(cb.getVariableName()).append(", "). append(cb.getVariableName()).append(".").append(cb.getMethod().getName()).append(sjInvoker); }); //close signature.append(" triggerCalculation();\n }"); return signature.toString(); } @SneakyThrows static String wrapExportedFunctionCall(Method exportedMethod, ExportFunctionData exportFunctionData, boolean onEventDispatch) { String exportedMethodName = exportedMethod.getName(); LongAdder argNumber = new LongAdder(); List> callBackList = exportFunctionData.getFunctionCallBackList(); Method delegateMethod = callBackList.get(0).getFirst().getMethod(); boolean booleanReturn = exportFunctionData.isBooleanReturn(); StringBuilder signature = booleanReturn ? new StringBuilder("public boolean " + exportedMethodName) : new StringBuilder("public void " + exportedMethodName); signature.append('('); StringJoiner sj = new StringJoiner(", "); Type[] params = delegateMethod.getGenericParameterTypes(); for (int j = 0; j < params.length; j++) { String param = params[j].getTypeName() .replace("$", ".") .replace("java.lang.", ""); if (delegateMethod.isVarArgs() && (j == params.length - 1)) // replace T[] with T... param = param.replaceFirst("\\[\\]$", "..."); param += " arg" + argNumber.intValue(); sj.add(param); argNumber.increment(); } signature.append(sj); signature.append("){\n\t"); // signature.append("processor.auditNewEvent( functionAudit.setFunctionDescription(\"" + exportFunctionData.getExportedmethod().toGenericString() + "\"));\n" + " if(processor.buffering){\n" + " processor.triggerCalculation();\n" + " }\n" + " processor.processing = false;\n\t"); //method calls StringJoiner sjInvoker = new StringJoiner(", ", "(", "));\n\t"); for (int i = 0; i < argNumber.intValue(); i++) { sjInvoker.add("arg" + i); } callBackList.forEach(tuple -> { CbMethodHandle cb = tuple.getFirst(); boolean isPropagateMethod = tuple.getSecond(); String variableName = cb.getVariableName(); String methodName = cb.getMethod().getName(); signature.append("processor.nodeInvoked(" + variableName + ", \"" + variableName + "\", \"" + methodName + "\", functionAudit);\n"); if (!isPropagateMethod) { signature.append(variableName).append(".").append(methodName).append(sjInvoker.toString().replace("));", ");")); } else if (cb.getMethod().getReturnType() == void.class) { signature.append(variableName).append(".").append(methodName).append(sjInvoker.toString().replace("));", ");")); signature.append("processor.setDirty(").append(variableName).append(", true);\n\t"); } else { signature.append("processor.setDirty("). append(variableName).append(", ").append(variableName).append(".").append(methodName).append(sjInvoker); } }); signature.append("processor.triggerCalculation();\n" + " processor.dispatchQueuedCallbacks();\n" + " processor.processing = false;\n"); if (booleanReturn) { signature.append(" return true;\n"); } signature.append("}"); return signature.toString(); } static List getAllAnnotatedAnnotationTypes(Class clazz, Class annotation) { List interfaceList = new ArrayList<>(); while (clazz != null) { Arrays.asList(clazz.getAnnotatedInterfaces()).stream().filter(a -> a.isAnnotationPresent(annotation)).forEach(interfaceList::add); clazz = clazz.getSuperclass(); } return interfaceList; } static boolean isPropagatingExportService(Class clazz) { return isPropagatingExportService(clazz, null); } static boolean isPropagatingExportService(Class clazz, Class exportedService) { return Arrays.stream(clazz.getAnnotatedInterfaces()) .filter(c -> exportedService == null || c.getType().equals(exportedService)) .filter(a -> a.isAnnotationPresent(ExportService.class)) .filter(c -> c.getAnnotation(ExportService.class).propagate()) .map(AnnotatedType::getType) .filter(Class.class::isInstance) .map(Class.class::cast) .map(Class::getMethods) .flatMap(Arrays::stream) .anyMatch(m -> { try { Method implMethod = clazz.getMethod(m.getName(), m.getParameterTypes()); return !implMethod.isAnnotationPresent(NoPropagateFunction.class); } catch (NoSuchMethodException e) { //cant find method - assume exported } return true; }); } static List getAllAnnotatedTypes(Class clazz, Class annotation) { return ClassUtils.getAllAnnotatedAnnotationTypes(clazz, annotation).stream().map(AnnotatedType::getType).collect(Collectors.toList()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy