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