Package com.asakusafw.dmdl.thundergate.driver

Source Code of com.asakusafw.dmdl.thundergate.driver.CacheSupportEmitter

/**
* 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.dmdl.thundergate.driver;

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

import org.apache.hadoop.io.Text;

import com.asakusafw.dmdl.java.emitter.EmitContext;
import com.asakusafw.dmdl.java.spi.JavaDataModelDriver;
import com.asakusafw.dmdl.model.AstLiteral;
import com.asakusafw.dmdl.semantics.ModelDeclaration;
import com.asakusafw.dmdl.semantics.PropertyDeclaration;
import com.asakusafw.dmdl.semantics.PropertySymbol;
import com.asakusafw.dmdl.semantics.type.BasicType;
import com.asakusafw.thundergate.runtime.cache.ThunderGateCacheSupport;
import com.asakusafw.utils.collections.Lists;
import com.asakusafw.utils.java.model.syntax.Expression;
import com.asakusafw.utils.java.model.syntax.FieldDeclaration;
import com.asakusafw.utils.java.model.syntax.FormalParameterDeclaration;
import com.asakusafw.utils.java.model.syntax.MethodDeclaration;
import com.asakusafw.utils.java.model.syntax.ModelFactory;
import com.asakusafw.utils.java.model.syntax.Statement;
import com.asakusafw.utils.java.model.syntax.Type;
import com.asakusafw.utils.java.model.util.AttributeBuilder;
import com.asakusafw.utils.java.model.util.ExpressionBuilder;
import com.asakusafw.utils.java.model.util.Models;
import com.asakusafw.utils.java.model.util.TypeBuilder;

/**
* Emits {@link ThunderGateCacheSupport} implementation.
* @since 0.2.3
*/
public class CacheSupportEmitter extends JavaDataModelDriver {

    private static final String FIELD_DELETE_FLAG_VALUE = "__TGC_DELETE_FLAG_VALUE";

    @Override
    public List<Type> getInterfaces(EmitContext context, ModelDeclaration model) throws IOException {
        if (isTarget(model) == false) {
            return Collections.emptyList();
        }
        return Arrays.asList(context.resolve(ThunderGateCacheSupport.class));
    }

    @Override
    public List<FieldDeclaration> getFields(EmitContext context, ModelDeclaration model) throws IOException {
        if (isTarget(model) == false) {
            return Collections.emptyList();
        }
        CacheSupportTrait trait = model.getTrait(CacheSupportTrait.class);
        assert trait != null;

        List<FieldDeclaration> results = Lists.create();
        if (trait.getDeleteFlagValue() != null) {
            results.add(createDeleteFlagValueField(context, model, trait.getDeleteFlagValue()));
        }
        return results;
    }

    @Override
    public List<MethodDeclaration> getMethods(EmitContext context, ModelDeclaration model) throws IOException {
        if (isTarget(model) == false) {
            return Collections.emptyList();
        }
        CacheSupportTrait trait = model.getTrait(CacheSupportTrait.class);
        assert trait != null;

        List<MethodDeclaration> results = Lists.create();
        results.add(createModelVersionMethod(context, model, trait));
        results.add(createTimestampColumnMethod(context, model, trait.getTimestamp()));
        results.add(createSystemIdMethod(context, model, trait.getSid()));
        results.add(createDeletedMethod(context, model, trait.getDeleteFlag()));
        return results;
    }

    private FieldDeclaration createDeleteFlagValueField(
            EmitContext context,
            ModelDeclaration model,
            AstLiteral deleteFlagValue) {
        assert context != null;
        assert model != null;
        assert deleteFlagValue != null;
        ModelFactory f = context.getModelFactory();
        Type type;
        Expression value;
        switch (deleteFlagValue.kind) {
        case BOOLEAN:
            type = context.resolve(boolean.class);
            value = Models.toLiteral(f, deleteFlagValue.toBooleanValue());
            break;
        case INTEGER:
            type = context.resolve(int.class);
            value = Models.toLiteral(f, deleteFlagValue.toIntegerValue().intValue());
            break;
        case STRING:
            type = context.resolve(Text.class);
            value = new TypeBuilder(f, context.resolve(Text.class))
                .newObject(Models.toLiteral(f, deleteFlagValue.toStringValue()))
                .toExpression();
            break;
        default:
            throw new AssertionError(deleteFlagValue);
        }
        return f.newFieldDeclaration(
                null,
                new AttributeBuilder(f)
                    .Private()
                    .Static()
                    .Final()
                    .toAttributes(),
                type,
                f.newSimpleName(FIELD_DELETE_FLAG_VALUE),
                value);
    }

    private MethodDeclaration createModelVersionMethod(
            EmitContext context,
            ModelDeclaration model,
            CacheSupportTrait trait) {
        assert context != null;
        assert model != null;
        assert trait != null;
        ModelFactory f = context.getModelFactory();
        List<Statement> statements = Lists.create();
        statements.add(new ExpressionBuilder(f, Models.toLiteral(f, computeModelVersion(context, model, trait)))
            .toReturnStatement());
        return f.newMethodDeclaration(
                null,
                new AttributeBuilder(f)
                    .annotation(context.resolve(Override.class))
                    .Public()
                    .toAttributes(),
                context.resolve(long.class),
                f.newSimpleName("__tgc__DataModelVersion"),
                Collections.<FormalParameterDeclaration>emptyList(),
                statements);
    }

    private long computeModelVersion(EmitContext context, ModelDeclaration model, CacheSupportTrait trait) {
        assert context != null;
        assert model != null;
        assert trait != null;
        long hash = 1;
        final long prime = 31;
        hash = hash * prime + context.getQualifiedTypeName().toNameString().hashCode();
        hash = hash * prime + trait.getSid().getName().identifier.hashCode();
        hash = hash * prime + trait.getTimestamp().getName().identifier.hashCode();
        for (PropertyDeclaration property : model.getDeclaredProperties()) {
            hash = hash * prime + property.getName().identifier.hashCode();
            com.asakusafw.dmdl.semantics.Type type = property.getType();
            assert type instanceof BasicType;
            hash = hash * prime + ((BasicType) type).getKind().name().hashCode();
        }
        return hash;
    }

    private MethodDeclaration createTimestampColumnMethod(
            EmitContext context,
            ModelDeclaration model,
            PropertySymbol timestamp) {
        assert context != null;
        assert model != null;
        assert timestamp != null;
        ModelFactory f = context.getModelFactory();
        String name = OriginalNameEmitter.getOriginalName(timestamp.findDeclaration());
        List<Statement> statements = Lists.create();
        statements.add(new ExpressionBuilder(f, Models.toLiteral(f, name))
            .toReturnStatement());
        return f.newMethodDeclaration(
                null,
                new AttributeBuilder(f)
                    .annotation(context.resolve(Override.class))
                    .Public()
                    .toAttributes(),
                context.resolve(String.class),
                f.newSimpleName("__tgc__TimestampColumn"),
                Collections.<FormalParameterDeclaration>emptyList(),
                statements);
    }

    private MethodDeclaration createSystemIdMethod(
            EmitContext context,
            ModelDeclaration model,
            PropertySymbol sid) {
        assert context != null;
        assert model != null;
        assert sid != null;
        ModelFactory f = context.getModelFactory();
        List<Statement> statements = Lists.create();
        statements.add(new ExpressionBuilder(f, f.newThis())
            .method(context.getValueGetterName(sid.findDeclaration()))
            .toReturnStatement());
        return f.newMethodDeclaration(
                null,
                new AttributeBuilder(f)
                    .annotation(context.resolve(Override.class))
                    .Public()
                    .toAttributes(),
                context.resolve(long.class),
                f.newSimpleName("__tgc__SystemId"),
                Collections.<FormalParameterDeclaration>emptyList(),
                statements);
    }

    private MethodDeclaration createDeletedMethod(
            EmitContext context,
            ModelDeclaration model,
            PropertySymbol deleteFlagOrNull) {
        assert context != null;
        assert model != null;
        ModelFactory f = context.getModelFactory();
        List<Statement> statements = Lists.create();
        if (deleteFlagOrNull == null) {
            statements.add(new ExpressionBuilder(f, Models.toLiteral(f, false))
                .toReturnStatement());
        } else {
            statements.add(new ExpressionBuilder(f, f.newThis())
                .method(context.getOptionGetterName(deleteFlagOrNull.findDeclaration()))
                .method("has", f.newSimpleName(FIELD_DELETE_FLAG_VALUE))
                .toReturnStatement());
        }
        return f.newMethodDeclaration(
                null,
                new AttributeBuilder(f)
                    .annotation(context.resolve(Override.class))
                    .Public()
                    .toAttributes(),
                context.resolve(boolean.class),
                f.newSimpleName("__tgc__Deleted"),
                Collections.<FormalParameterDeclaration>emptyList(),
                statements);
    }

    private boolean isTarget(ModelDeclaration model) {
        assert model != null;
        return model.getTrait(CacheSupportTrait.class) != null;
    }
}
TOP

Related Classes of com.asakusafw.dmdl.thundergate.driver.CacheSupportEmitter

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.