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

br.com.objectos.way.code.MethodInfo Maven / Gradle / Ivy

There is a newer version: 0.6.0
Show newest version
/*
 * Copyright 2014 Objectos, Fábrica de Software LTDA.
 *
 * 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 br.com.objectos.way.code;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import br.com.objectos.way.pojo.Pojo;
import br.com.objectos.way.testable.Equality;
import br.com.objectos.way.testable.Testable;
import br.com.objectos.way.testable.Tester;

/**
 * @author [email protected] (Marcio Endo)
 */
@Pojo
public abstract class MethodInfo
    implements
    CanGenerateCompilationError,
    HasAnnotationInfoList,
    Testable {

  public abstract AccessInfo accessInfo();
  abstract Set modifierInfoSet();
  public abstract String name();
  @Override
  public abstract List annotationInfoList();
  public abstract SimpleTypeInfo returnTypeInfo();
  abstract List parameterInfoList();

  MethodInfo() {
  }

  public static Predicate distinctSignature() {
    Set signatureSet = new HashSet<>();
    return (MethodInfo m) -> signatureSet.add(m.signature());
  }

  public static MethodInfoBuilder newPojo() {
    return new MethodInfoBuilderPojo();
  }

  public String className() {
    return Code.upperCaseFirstChar(name());
  }

  public boolean hasAccessInfo(AccessInfo accessInfo) {
    return accessInfo().equals(accessInfo);
  }

  public boolean hasModifierInfo(ModifierInfo modifierInfo) {
    return modifierInfoSet().contains(modifierInfo);
  }

  public boolean hasName(String name) {
    return name().equals(name);
  }

  public boolean hasNamePrefix(String prefix) {
    return name().startsWith(prefix);
  }

  public boolean hasParameterInfoListSize(int size) {
    return parameterInfoList().size() == size;
  }

  public boolean hasParameterInfoTypes(Class... types) {
    Objects.requireNonNull(types);
    if (!hasParameterInfoListSize(types.length)) {
      return false;
    }

    int index = 0;
    Iterator iterator = parameterInfoList().iterator();
    while (iterator.hasNext()) {
      ParameterInfo parameterInfo = iterator.next();
      Class type = types[index++];
      if (!parameterInfo.isInfoOf(type)) {
        return false;
      }
    }

    return true;
  }

  public boolean hasReturnTypeInfo(SimpleTypeInfo typeInfo) {
    return returnTypeInfo().equals(typeInfo);
  }

  public boolean hasReturnTypeInfoInstanceOf(Class type) {
    return returnTypeInfo().isSubType(type);
  }

  @Override
  public Equality isEqualTo(Object that) {
    return Tester.of(MethodInfo.class)
        .add("name", o -> o.name())
        .add("accessInfo", o -> o.accessInfo())
        .add("modifierInfoSet", o -> o.modifierInfoSet())
        .add("returnTypeInfo", o -> o.returnTypeInfo())
        .add("annotationInfoList", o -> o.annotationInfoList())
        .add("parameterInfoList", o -> o.parameterInfoList())
        .test(this, that);
  }

  @Override
  public Stream annotationInfoStream() {
    Set nameSet = annotationInfoList().stream()
        .map(AnnotationInfo::qualifiedName)
        .collect(Collectors.toSet());

    Stream enclosingStream = enclosingTypeInfoAnnotationStream()
        .filter(m -> nameSet.add(m.qualifiedName()));
    return Stream.concat(enclosingStream, annotationInfoList().stream());
  }

  public MethodInfoCodeWriter codeWriter() {
    return MethodInfoCodeWriter.codeWriter(this);
  }

  @Override
  public void compilationError(String message) {
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (!(obj instanceof MethodInfo)) {
      return false;
    }
    MethodInfo that = (MethodInfo) obj;
    return toString().equals(that.toString());
  }

  public String fieldName() {
    String prefix = getterPrefix();
    String field = name().replace(prefix, "");
    return Code.lowerCaseFirstChar(field);
  }

  public MethodInfoFieldWriter fieldWriter() {
    return new MethodInfoFieldWriter(this);
  }

  @Override
  public int hashCode() {
    return toString().hashCode();
  }

  public Object invoke(Object instance) {
    try {
      Method method = instance.getClass().getDeclaredMethod(name());

      if (!method.isAccessible()) {
        method.setAccessible(true);
      }

      return method.invoke(instance);

    } catch (SecurityException e) {
      throw new RuntimeException(e);

    } catch (NoSuchMethodException e) {
      throw new AssertionError(e);

    } catch (IllegalArgumentException e) {
      throw new RuntimeException(e);

    } catch (IllegalAccessException e) {
      throw new AssertionError(e);

    } catch (InvocationTargetException e) {
      throw new RuntimeException(e);

    }
  }

  public MethodInfoOverloadWriter overloadWriter() {
    return new MethodInfoOverloadWriter(this);
  }

  public MethodInfoOverrideWriter overrideWriter() {
    return new MethodInfoOverrideWriter(this);
  }

  public Stream parameterInfoStream() {
    return parameterInfoList().stream();
  }

  public MethodInfoCodeWriter statementWriter() {
    return MethodInfoCodeWriter.statementWriter(this);
  }

  public FieldInfo toFieldInfo() {
    return FieldInfo.newPojo()
        .annotationInfoList(Collections. emptyList())
        .simpleTypeInfo(returnTypeInfo())
        .name(fieldName())
        .build();
  }

  @Override
  public String toString() {
    StringBuilder toString = new StringBuilder();
    toString.append(accessInfo().declaration());

    Iterator modifierInfo = modifierInfoSet().iterator();
    while (modifierInfo.hasNext()) {
      toString.append(modifierInfo.next());
      toString.append(" ");
    }

    toString.append(returnTypeInfo().qualifiedName());
    toString.append(" ");

    toString.append(name());
    toString.append("(");
    Iterator parameters = parameterInfoList().iterator();
    if (parameters.hasNext()) {
      parameters.next().toString(toString);
      while (parameters.hasNext()) {
        toString.append(", ");
        parameters.next().toString(toString);
      }
    }
    toString.append(")");

    return toString.toString();
  }

  Optional enclosingTypeInfo() {
    return Optional.empty();
  }

  String signature() {
    StringBuilder sig = new StringBuilder();
    sig.append(name());
    sig.append("(");
    Iterator parameters = parameterInfoList().iterator();
    if (parameters.hasNext()) {
      parameters.next().signature(sig);
      while (parameters.hasNext()) {
        sig.append(",");
        parameters.next().signature(sig);
      }
    }
    sig.append(")");
    return sig.toString();
  }

  private Stream enclosingTypeInfoAnnotationStream() {
    String signature = signature();
    return enclosingTypeInfo()
        .map(TypeInfo::superMethodInfoStream)
        .map(stream -> stream
            .filter(m -> m.signature().equals(signature))
            .flatMap(MethodInfo::annotationInfoStream))
        .orElse(Stream.empty());
  }

  private String getterPrefix() {
    return returnTypeInfo().getGetterPrefix();
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy