Package com.asakusafw.compiler.flow.jobflow

Source Code of com.asakusafw.compiler.flow.jobflow.CleanupStageClientEmitter$Engine

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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.asakusafw.compiler.flow.jobflow;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.asakusafw.compiler.common.Naming;
import com.asakusafw.compiler.common.Precondition;
import com.asakusafw.compiler.flow.FlowCompilingEnvironment;
import com.asakusafw.compiler.flow.Location;
import com.asakusafw.runtime.stage.AbstractCleanupStageClient;
import com.asakusafw.runtime.stage.BaseStageClient;
import com.asakusafw.runtime.stage.StageConstants;
import com.asakusafw.utils.collections.Lists;
import com.asakusafw.utils.java.model.syntax.Comment;
import com.asakusafw.utils.java.model.syntax.CompilationUnit;
import com.asakusafw.utils.java.model.syntax.Expression;
import com.asakusafw.utils.java.model.syntax.FormalParameterDeclaration;
import com.asakusafw.utils.java.model.syntax.Javadoc;
import com.asakusafw.utils.java.model.syntax.MethodDeclaration;
import com.asakusafw.utils.java.model.syntax.ModelFactory;
import com.asakusafw.utils.java.model.syntax.Name;
import com.asakusafw.utils.java.model.syntax.QualifiedName;
import com.asakusafw.utils.java.model.syntax.SimpleName;
import com.asakusafw.utils.java.model.syntax.Type;
import com.asakusafw.utils.java.model.syntax.TypeBodyDeclaration;
import com.asakusafw.utils.java.model.syntax.TypeDeclaration;
import com.asakusafw.utils.java.model.syntax.TypeParameterDeclaration;
import com.asakusafw.utils.java.model.util.AttributeBuilder;
import com.asakusafw.utils.java.model.util.ImportBuilder;
import com.asakusafw.utils.java.model.util.JavadocBuilder;
import com.asakusafw.utils.java.model.util.Models;

/**
* Creates a subclass of {@link AbstractCleanupStageClient}.
* @since 0.2.6
*/
public class CleanupStageClientEmitter {

    static final Logger LOG = LoggerFactory.getLogger(CleanupStageClientEmitter.class);

    private final FlowCompilingEnvironment environment;

    /**
     * Creates a new instance.
     * @param environment current compilation environment
     * @throws IllegalArgumentException if some parameters were {@code null}
     */
    public CleanupStageClientEmitter(FlowCompilingEnvironment environment) {
        Precondition.checkMustNotBeNull(environment, "environment"); //$NON-NLS-1$
        this.environment = environment;
    }

    /**
     * Emits a new cleanup stage client.
     * @return the compiled class info
     * @throws IOException if faled to emit a class
     */
    public CompiledStage emit() throws IOException {
        LOG.debug("Generating cleanup stage client for {}", environment.getFlowId());
        Engine engine = new Engine(environment);
        CompilationUnit source = engine.generate();
        environment.emit(source);
        Name packageName = source.getPackageDeclaration().getName();
        SimpleName simpleName = source.getTypeDeclarations().get(0).getName();
        QualifiedName name = environment
            .getModelFactory()
            .newQualifiedName(packageName, simpleName);
        LOG.debug("Cleanup stage client for {} will be {}", environment.getFlowId(), name);
        return new CompiledStage(name, Naming.getCleanupStageName());
    }

    private static class Engine {

        private static final char PATH_SEPARATOR = '/';

        private final FlowCompilingEnvironment environment;

        private final ModelFactory factory;

        private final ImportBuilder importer;

        private final QualifiedName fqn;

        Engine(FlowCompilingEnvironment environment) {
            assert environment != null;
            this.environment = environment;
            this.factory = environment.getModelFactory();
            this.fqn = (QualifiedName) Models.toName(factory, AbstractCleanupStageClient.IMPLEMENTATION);
            this.importer = new ImportBuilder(
                    factory,
                    factory.newPackageDeclaration(fqn.getQualifier()),
                    ImportBuilder.Strategy.TOP_LEVEL);
        }

        public CompilationUnit generate() {
            TypeDeclaration type = createType();
            return factory.newCompilationUnit(
                    importer.getPackageDeclaration(),
                    importer.toImportDeclarations(),
                    Collections.singletonList(type),
                    Collections.<Comment>emptyList());
        }

        private TypeDeclaration createType() {
            importer.resolvePackageMember(fqn.getSimpleName());
            List<TypeBodyDeclaration> members = Lists.create();
            members.addAll(createIdMethods());
            members.add(createStageOutputPath());
            return factory.newClassDeclaration(
                    createJavadoc(),
                    new AttributeBuilder(factory)
                        .Public()
                        .Final()
                        .toAttributes(),
                    fqn.getSimpleName(),
                    Collections.<TypeParameterDeclaration>emptyList(),
                    t(AbstractCleanupStageClient.class),
                    Collections.<Type>emptyList(),
                    members);
        }

        private List<MethodDeclaration> createIdMethods() {
            List<MethodDeclaration> results = Lists.create();
            results.add(createValueMethod(
                    BaseStageClient.METHOD_BATCH_ID,
                    t(String.class),
                    Models.toLiteral(factory, environment.getBatchId())));
            results.add(createValueMethod(
                    BaseStageClient.METHOD_FLOW_ID,
                    t(String.class),
                    Models.toLiteral(factory, environment.getFlowId())));
            results.add(createValueMethod(
                    BaseStageClient.METHOD_STAGE_ID,
                    t(String.class),
                    Models.toLiteral(factory, Naming.getCleanupStageName())));
            return results;
        }

        private MethodDeclaration createStageOutputPath() {
            Location location = environment.getTargetLocation();
            location = getCleanupTarget(location);
            String path = location.toPath(PATH_SEPARATOR);
            return createValueMethod(
                    AbstractCleanupStageClient.METHOD_CLEANUP_PATH,
                    t(String.class),
                    Models.toLiteral(factory, path));
        }

        private Location getCleanupTarget(Location location) {
            Location candidate = location;
            Location current = location;
            while (current != null) {
                String name = current.getName();
                if (name.indexOf(StageConstants.EXPR_EXECUTION_ID) >= 0) {
                    candidate = current;
                }
                current = current.getParent();
            }
            return candidate;
        }

        private Javadoc createJavadoc() {
            return new JavadocBuilder(factory)
                .text("A cleanup stage client.")
                .toJavadoc();
        }

        private MethodDeclaration createValueMethod(
                String methodName,
                Type returnType,
                Expression expression) {
            return factory.newMethodDeclaration(
                    null,
                    new AttributeBuilder(factory)
                        .annotation(t(Override.class))
                        .Protected()
                        .toAttributes(),
                    returnType,
                    factory.newSimpleName(methodName),
                    Collections.<FormalParameterDeclaration>emptyList(),
                    Collections.singletonList(factory.newReturnStatement(expression)));
        }

        private Type t(java.lang.reflect.Type type, Type...typeArgs) {
            assert type != null;
            assert typeArgs != null;
            Type raw = importer.toType(type);
            if (typeArgs.length == 0) {
                return raw;
            }
            return factory.newParameterizedType(raw, Arrays.asList(typeArgs));
        }
    }
}
TOP

Related Classes of com.asakusafw.compiler.flow.jobflow.CleanupStageClientEmitter$Engine

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.