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

com.wavemaker.commons.util.ObjectAccess Maven / Gradle / Ivy

There is a newer version: 11.9.4
Show newest version
/**
 * Copyright (C) 2020 WaveMaker, Inc.
 * 

* 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 com.wavemaker.commons.util; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.wavemaker.commons.MessageResource; import com.wavemaker.commons.MethodNotFoundRuntimeException; import com.wavemaker.commons.WMRuntimeException; import com.wavemaker.commons.classloader.ClassLoaderUtils; /** * Encapsulates logic for Class/instance access using reflection. * * Only throws runtime exceptions. * * Has logic for: * * o instantiation. o invoking methods given a String method name and optionally method arguments. o checking annotation * presence. o getting input and output types for properties and methods. o object string representation. * * @author Simon Toens */ public class ObjectAccess { public static ObjectAccess getInstance() { return instance; } private static ObjectAccess instance = new ObjectAccess(); private ObjectAccess() { } public Object newInstance(String className) { return newInstance(forName(className)); } public Object newInstance(Class clazz) { if (List.class.isAssignableFrom(clazz)) { clazz = ArrayList.class; } else if (Collection.class.isAssignableFrom(clazz)) { clazz = HashSet.class; } else if (Map.class.isAssignableFrom(clazz)) { clazz = HashMap.class; } return ClassUtils.newInstance(clazz); } public Class forName(String className) { return ClassLoaderUtils.loadClass(className); } @SuppressWarnings("unchecked") public T invoke(Object o, String methodName) { return invoke(o, methodName, (Object[]) null); } @SuppressWarnings("unchecked") public T invoke(Object o, String methodName, Object... params) { Class[] paramTypes = null; boolean paramIsNull = false; if (params != null) { paramTypes = new Class[params.length]; for (int i = 0; i < params.length; i++) { if (paramTypes[i] == null) { paramIsNull = true; } else { paramTypes[i] = getClassForObject(params[i]); } } } Class c = getClassForObject(o); Method m = null; if (paramIsNull) { m = getMethod(c, methodName, paramTypes.length); } else { m = getMethod(c, methodName, paramTypes); } if (m == null) { throw new MethodNotFoundRuntimeException(methodName, c, paramTypes); } return (T) invokeInternal(o, m, params); } @SuppressWarnings("unchecked") public T getProperty(Object o, String propertyName) { Method m = getGetterMethod(getClassForObject(o), propertyName); if (m != null) { return (T) invokeInternal(o, m, null); } else { throw new WMRuntimeException(MessageResource.create("com.wavemaker.commons.getter.method.not.found"), propertyName, o.getClass().getName()); } } public void setProperty(Object o, String propertyName, Object propertyValue) { invoke(o, ClassUtils.getPropertySetterName(propertyName), propertyValue); } public Class getPropertyType(Class clazz, String propertyName) { if (clazz == null) { throw new IllegalArgumentException("class cannot be null"); } if (propertyName == null) { throw new IllegalArgumentException("property name cannot be null"); } Method m = getMethod(clazz, ClassUtils.getPropertySetterName(propertyName), 1); if (m != null) { return m.getParameterTypes()[0]; } return null; } public boolean propertyIsNull(Object o, String propertyName) { return getProperty(o, propertyName) == null; } public List> getMethodParamTypes(Class clazz, String methodName, int numParams) { Method m = getMethod(clazz, methodName, numParams); if (m != null) { return Arrays.asList(m.getParameterTypes()); } return Collections.emptyList(); } public Class getMethodReturnType(Class clazz, String methodName, int numParams) { Method m = getMethod(clazz, methodName, numParams); if (m != null) { return m.getReturnType(); } return null; } public List> getGenericReturnTypes(Class clazz, String methodName, int numParams) { Method m = getMethod(clazz, methodName, numParams); if (m == null) { return Collections.emptyList(); } return getGenericReturnTypes(m); } private List> getGenericReturnTypes(Method m) { List> rtn = Collections.emptyList(); Type t = m.getGenericReturnType(); if (t instanceof ParameterizedType) { Type[] gt = ((ParameterizedType) t).getActualTypeArguments(); rtn = new ArrayList<>(gt.length); for (Type i : gt) { rtn.add((Class) i); } } return rtn; } public boolean hasAnnotation(Class annotation, Object o, String methodName) { return hasAnnotation(annotation, o, methodName, (Class[]) null); } public boolean hasAnnotation( Class annotation, Object o, String methodName, Class... paramTypes) { Method m = getMethod(getClassForObject(o), methodName, paramTypes); if (m == null) { return false; } return m.getAnnotation(annotation) != null; } public boolean hasAnnotation( Class annotation, Object o, String methodName, int numParams) { Method m = getMethod(getClassForObject(o), methodName, numParams); if (m == null) { return false; } return m.getAnnotation(annotation) != null; } public boolean hasProperty(Class clazz, String propertyName) { try { getGetterMethod(clazz, propertyName); return true; } catch (MethodNotFoundRuntimeException ex) { return false; } } public boolean hasMethod(Class clazz, String methodName, int numParams) { Method m = getMethod(clazz, methodName, numParams); return m != null; } public List getPropertyNames(Class clazz) { Map> m = getProperties(clazz); List rtn = new ArrayList<>(m.size()); for (String s : m.keySet()) { rtn.add(s); } return rtn; } public Map> getProperties(Class clazz) { Map> rtn = new LinkedHashMap<>(); Collection methodNames = new HashSet<>(); for (Method m : getMethods(clazz)) { methodNames.add(m.getName()); } for (String s : methodNames) { if (s.startsWith("get")) { String prop = s.substring(3, s.length()); if (methodNames.contains("set" + prop)) { // also need check method params/rtn types for consistency String propName = StringUtils.lowerCaseFirstLetter(prop); Class type = getPropertyType(clazz, propName); if (type != null) { rtn.put(propName, type); } } } } return rtn; } public String objectToString(Object o) { return objectToString(o, true); } public String objectToString(Object o, boolean excludeContainers) { if (o == null) { return "null"; } StringBuilder sb = new StringBuilder(); sb.append(o.getClass().getName()).append(":"); if (TypeConversionUtils.isPrimitiveOrWrapper(o.getClass())) { sb.append(String.valueOf(o)); return sb.toString(); } sb.append("{"); Map> propNames = getProperties(getClassForObject(o)); int i = 0; for (Map.Entry> e : propNames.entrySet()) { Object v = getProperty(o, e.getKey()); if (excludeContainers) { if (v instanceof Collection) { if (!((Collection) v).isEmpty()) { v = "[...]"; } } else if (v instanceof Map && !((Map) v).isEmpty()) { v = "{...}"; } } sb.append(e.getKey()).append(":").append(v); if (i++ < propNames.size() - 1) { sb.append(","); } } sb.append("}"); return sb.toString(); } private Method getGetterMethod(Class clazz, String propertyName) { String name = ClassUtils.getPropertyGetterName(propertyName); if (hasMethod(clazz, name, 0)) { return getMethod(clazz, name, 0); } else { String altName = ClassUtils.getAltPropertyGetterName(propertyName); if (hasMethod(clazz, altName, 0)) { return getMethod(clazz, altName, 0); } } throw new MethodNotFoundRuntimeException(name, clazz, null); } private Class getClassForObject(Object o) { if (o == null) { throw new IllegalArgumentException("getClassForObject: instance cannot be null"); } return o.getClass(); } // get method by name and number of params only private Method getMethod(Class c, String methodName, int numParams) { for (Method m : getMethods(c)) { if (m.getName().equals(methodName) && m.getParameterTypes().length == numParams) { return m; } } return null; } private Method getMethod(Class c, String methodName, Class... paramTypes) { for (Method m : getMethods(c)) { if (m.getName().equals(methodName) && paramsMatch(m, paramTypes)) { return m; } } return null; } private boolean paramsMatch(Method m, Class... paramTypes) { Class[] methodParams = m.getParameterTypes(); if (methodParams.length == 0) { return (paramTypes == null || paramTypes.length == 0); } if (paramTypes == null || methodParams.length != paramTypes.length) { return false; } for (int i = 0; i < methodParams.length; i++) { if (!methodParams[i].isAssignableFrom(paramTypes[i]) && !TypeConversionUtils .primitivesMatch(methodParams[i], paramTypes[i])) { return false; } } return true; } private Method[] getMethods(Class clazz) { return clazz.getMethods(); } private Object invokeInternal(Object instance, Method m, Object[] params) { try { return m.invoke(instance, params); } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException ex) { throw new WMRuntimeException(ex); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy