001/* 002 * Copyright (c) 2012-2018 Institut National des Sciences Appliquées de Lyon (INSA Lyon) and others 003 * 004 * This program and the accompanying materials are made available under the 005 * terms of the Eclipse Public License 2.0 which is available at 006 * http://www.eclipse.org/legal/epl-2.0. 007 * 008 * SPDX-License-Identifier: EPL-2.0 009 */ 010 011package org.eclipse.golo.runtime; 012 013import java.lang.reflect.*; 014import java.util.function.Predicate; 015import java.util.stream.Stream; 016 017import static org.eclipse.golo.runtime.TypeMatching.compareTypes; 018import static org.eclipse.golo.runtime.DecoratorsHelper.isMethodDecorated; 019import static org.eclipse.golo.runtime.TypeMatching.argumentsNumberMatches; 020 021public final class Extractors { 022 private Extractors() { 023 throw new UnsupportedOperationException("don't instantiate"); 024 } 025 026 public static Stream<Constructor<?>> getConstructors(Class<?> klass) { 027 if (klass == null) { 028 return Stream.empty(); 029 } 030 return Stream.of(klass.getConstructors()); 031 } 032 033 public static Stream<Method> getFunctions(Class<?> klass) { 034 return getMethods(klass).filter(Extractors::isFunction); 035 } 036 037 public static Stream<Method> getMethods(Class<?> klass) { 038 if (klass == null) { 039 return Stream.empty(); 040 } 041 return Stream.concat( 042 Stream.of(klass.getDeclaredMethods()), 043 Stream.of(klass.getMethods())) 044 .distinct() 045 .sorted((m1, m2) -> { 046 if (m1.isVarArgs() && !m2.isVarArgs()) { 047 return 1; 048 } 049 if (m2.isVarArgs() && !m1.isVarArgs()) { 050 return -1; 051 } 052 return compareTypes(m1.getParameterTypes(), m2.getParameterTypes()); 053 }); 054 } 055 056 public static Stream<Field> getFields(Class<?> klass) { 057 if (klass == null) { 058 return Stream.empty(); 059 } 060 return Stream.concat( 061 Stream.of(klass.getDeclaredFields()), 062 Stream.of(klass.getFields())) 063 .distinct(); 064 } 065 066 public static Stream<String> getImportedNames(Class<?> klass) { 067 if (klass == null) { 068 return Stream.empty(); 069 } 070 return Stream.of(Module.imports(klass)); 071 } 072 073 public static Stream<Member> getMembers(Class<?> klass) { 074 if (klass == null) { 075 return Stream.empty(); 076 } 077 return Stream.concat(getMethods(klass), getFields(klass)); 078 } 079 080 public static boolean isPublic(Member m) { 081 return Modifier.isPublic(m.getModifiers()); 082 } 083 084 public static boolean isStatic(Member m) { 085 return Modifier.isStatic(m.getModifiers()); 086 } 087 088 public static boolean isConcrete(Member m) { 089 return !Modifier.isAbstract(m.getModifiers()); 090 } 091 092 public static boolean isFunction(Method m) { 093 return isConcrete(m) && isPublic(m) && isStatic(m); 094 } 095 096 public static Predicate<Member> isNamed(String name) { 097 return m -> m.getName().equals(name); 098 } 099 100 public static Predicate<Method> matchFunctionReference(String name, int arity, boolean varargs) { 101 return m -> 102 m.getName().equals(name) 103 && (isMethodDecorated(m) || argumentsNumberMatches(m.getParameterCount(), arity, varargs)) 104 && (arity < 0 || m.isVarArgs() == varargs); 105 } 106 107 public static <T extends AnnotatedElement & Member> T checkDeprecation(Class<?> caller, T object) { 108 if (object.isAnnotationPresent(Deprecated.class)) { 109 Warnings.deprecatedElement( 110 (object instanceof Executable ? ((Executable) object).toGenericString() 111 : object instanceof Field ? ((Field) object).toGenericString() 112 : object.getName()), 113 caller.getName()); 114 } 115 return object; 116 } 117 118}