at.gridtec.lambda4j.generator.processors.impl.MethodProcessor.java Source code

Java tutorial

Introduction

Here is the source code for at.gridtec.lambda4j.generator.processors.impl.MethodProcessor.java

Source

/*
 * Copyright (c) 2016 Gridtec. All rights reserved.
 *
 * 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 at.gridtec.lambda4j.generator.processors.impl;

import at.gridtec.lambda4j.generator.LambdaTypeEnum;
import at.gridtec.lambda4j.generator.entities.LambdaEntity;
import at.gridtec.lambda4j.generator.entities.TypeEntity;
import at.gridtec.lambda4j.generator.processors.Processor;
import at.gridtec.lambda4j.generator.util.LambdaUtils;

import org.apache.commons.lang3.StringUtils;

import javax.annotation.Nonnull;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
 * Represents a {@link Processor} which creates copies of the given lambda to set all possible lambda methods (depending
 * on lambda type) to the lambda. These copies are handed over to next {@code Processor} to do further processing. The
 * result from next step is returned by this step.
 * <p>
 * Requirements by this step are the lambdas type ({@link LambdaEntity#getType()}) and return type ({@link
 * LambdaEntity#getReturnType()}). As this processor relies on lambda throwable flag, this should be called <em>before</em>
 * this one is called.
 */
public final class MethodProcessor extends Processor {

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#COMPARATOR} lambdas.
     */
    public static final String METHOD_COMPARATOR = "compare";

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#CONSUMER} lambdas.
     */
    public static final String METHOD_CONSUMER = "accept";

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#FUNCTION} lambdas.
     */
    public static final String METHOD_FUNCTION = "apply";

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#OPERATOR} lambdas.
     */
    public static final String METHOD_OPERATOR = "apply";

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#PREDICATE} lambdas.
     */
    public static final String METHOD_PREDICATE = "test";

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#RUNNABLE} lambdas.
     */
    public static final String METHOD_RUNNABLE = "run";

    /**
     * Represents the method name constant for {@link LambdaTypeEnum#SUPPLIER} lambdas.
     */
    public static final String METHOD_SUPPLIER = "get";

    /**
     * Represents an identifier for method names where the return is primitive and therefore we need to include this
     * using the scheme {@code methodRootName + "As" + primitivveTypeName}. This is capitalized.
     */
    public static final String AS_IDENTIFIER = "As";

    /**
     * Represents an method identifier for all lambdas which are throwable.  This is capitalized.
     */
    public static final String THROWS_IDENTIFIER = "Throws";

    @Override
    protected boolean processable(@Nonnull LambdaEntity lambda) {
        return lambda.getType() != null && lambda.getReturnType() != null;
    }

    @Nonnull
    @Override
    protected List<LambdaEntity> process(@Nonnull LambdaEntity lambda) {
        final List<LambdaEntity> lambdas = new LinkedList<LambdaEntity>();
        final LambdaEntity copy = LambdaUtils.copy(lambda);
        final StringBuilder methodBuilder = new StringBuilder();

        // Set lambda method name depending on lambda type
        if (LambdaUtils.isOfTypeComparator(lambda)) {
            methodBuilder.append(METHOD_COMPARATOR);
        } else if (LambdaUtils.isOfTypeConsumer(lambda)) {
            methodBuilder.append(METHOD_CONSUMER);
        } else if (LambdaUtils.isOfTypeFunction(lambda)) {
            methodBuilder.append(METHOD_FUNCTION);
        } else if (LambdaUtils.isOfTypeOperator(lambda)) {
            methodBuilder.append(METHOD_OPERATOR);
        } else if (LambdaUtils.isOfTypePredicate(lambda)) {
            methodBuilder.append(METHOD_PREDICATE);
        } else if (LambdaUtils.isOfTypeRunnable(lambda)) {
            methodBuilder.append(METHOD_RUNNABLE);
        } else if (LambdaUtils.isOfTypeSupplier(lambda)) {
            methodBuilder.append(METHOD_SUPPLIER);
        }

        // Special Case: Lambdas of type function, operator and supplier will have "As" identifier if primitive return
        if (LambdaUtils.isOfTypeFunction(lambda) || LambdaUtils.isOfTypeOperator(lambda)
                || LambdaUtils.isOfTypeSupplier(lambda)) {
            asIdentifier(methodBuilder, lambda, lambda.getReturnType());
        }

        // If lambda now is throwable include the "Throws" identifier
        throwsIdentifier(methodBuilder, lambda);

        // Set to copy and handle to next processor for further processing
        copy.setMethod(methodBuilder.toString());
        return next(copy);
    }

    /**
     * A helper method to append {@link #AS_IDENTIFIER} to given {@link StringBuilder}. This happens only, if the given
     * lambda has a primitive return type.
     *
     * @param builder The {@code StringBuilder} to which to append the identifier and the primitive lambda return type
     * name
     * @param lambda The lambda to be used for checking
     * @param lambdaReturnType The return type to be checked for primitiveness
     * @throws NullPointerException If one of the given arguments is {@code null}
     * @implSpec The implementation required the return type be primitive. Only if this occasion is met, the identifier
     * will be appended.
     */
    private void asIdentifier(@Nonnull final StringBuilder builder, @Nonnull final LambdaEntity lambda,
            @Nonnull final TypeEntity lambdaReturnType) {
        Objects.requireNonNull(builder);
        Objects.requireNonNull(lambda);
        Objects.requireNonNull(lambdaReturnType);
        if (LambdaUtils.isPrimitiveType(lambdaReturnType)) {
            builder.append(AS_IDENTIFIER);
            builder.append(StringUtils.capitalize(lambdaReturnType.getTypeSimpleName()));
        }
    }

    /**
     * A helper method to append the {@link #THROWS_IDENTIFIER} to the given {@link StringBuilder}. This happens only,
     * if the given lambda represents a throwable lambda.
     *
     * @param builder The {@code StringBuilder} to which to append the identifier
     * @param lambda The lambda to be used for checking
     * @throws NullPointerException If one of the given arguments is {@code null}
     * @implSpec The implementation required the lambda to be a throwable lambda. Only if this occasion is met, the
     * identifier will be appended.
     */
    private void throwsIdentifier(@Nonnull final StringBuilder builder, @Nonnull final LambdaEntity lambda) {
        Objects.requireNonNull(builder);
        Objects.requireNonNull(lambda);
        if (lambda.isThrowable()) {
            builder.append(THROWS_IDENTIFIER);
        }
    }
}