com.tactfactory.harmony.platform.android.updater.EntityImplementationAndroid.java Source code

Java tutorial

Introduction

Here is the source code for com.tactfactory.harmony.platform.android.updater.EntityImplementationAndroid.java

Source

/**
 * This file is part of the Harmony package.
 *
 * (c) Mickael Gaillard <mickael.gaillard@tactfactory.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
package com.tactfactory.harmony.platform.android.updater;

import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import com.google.common.base.CaseFormat;
import com.tactfactory.harmony.meta.ApplicationMetadata;
import com.tactfactory.harmony.meta.ClassMetadata;
import com.tactfactory.harmony.meta.EntityMetadata;
import com.tactfactory.harmony.meta.FieldMetadata;
import com.tactfactory.harmony.meta.MethodMetadata;
import com.tactfactory.harmony.platform.IAdapter;
import com.tactfactory.harmony.platform.manipulator.SourceFileManipulator;
import com.tactfactory.harmony.updater.IUpdaterFile;
import com.tactfactory.harmony.utils.ConsoleUtils;
import com.tactfactory.harmony.utils.MetadataUtils;

import freemarker.template.Configuration;

//TODO remove
public class EntityImplementationAndroid implements IUpdaterFile {
    private final IAdapter adapter;
    private final Configuration configuration;
    private final Map<String, Object> dataModel;
    private final File entityFile;
    private final EntityMetadata entity;

    public EntityImplementationAndroid(IAdapter adapter, Configuration cfg, Map<String, Object> dataModel,
            File entityFile, EntityMetadata entity) {
        this.adapter = adapter;
        this.configuration = cfg;
        this.dataModel = dataModel;
        this.entityFile = entityFile;
        this.entity = entity;
    }

    protected void updateEntity() {
        final SourceFileManipulator manipulator = this.adapter.getFileManipulator(entityFile, this.configuration);

        this.implementEmptyConstructor(manipulator, entity);

        manipulator.addImplement(entity, "Serializable");
        manipulator.addImport(entity, "Serializable", "java.io.Serializable");
        this.generateGetterAndSetters(manipulator, entity);
        this.implementParcelable(manipulator, entity);

        // After treatment on entity, write it in the original file
        manipulator.writeFile();
    }

    /**
     * Generate the necessary getters and setters for the class.
     * @param fileString The stringbuffer containing the class java code
     * @param classMeta The Metadata containing the infos on the java class
     */
    private final void generateGetterAndSetters(final SourceFileManipulator manipulator,
            final EntityMetadata classMeta) {

        final Collection<FieldMetadata> fields = classMeta.getFields().values();
        final boolean childClass = MetadataUtils.inheritsFromEntity(classMeta, ApplicationMetadata.INSTANCE);
        for (final FieldMetadata field : fields) {
            final boolean isInheritedId = childClass && classMeta.getIds().containsKey(field.getName());
            if (!field.isInternal() && !isInheritedId) {
                // Getter
                if (!this.alreadyImplementsGet(field, classMeta)) {
                    ConsoleUtils.displayDebug("Add implements getter of " + field.getName(),
                            " => get" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, field.getName()));

                    manipulator.generateFieldAccessor(field, "itemGetter.java");
                }

                // Setter
                if (!this.alreadyImplementsSet(field, classMeta)) {
                    ConsoleUtils.displayDebug("Add implements setter of " + field.getName(),
                            " => set" + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, field.getName()));

                    manipulator.generateFieldAccessor(field, "itemSetter.java");
                }
            }
        }

        manipulator.addImport(classMeta, "ArrayList", "java.util.ArrayList");

        manipulator.addImport(classMeta, "List", "java.util.List");
    }

    /**
     * Check if the class already has a getter for the given field.
     * @param fieldMeta The Metadata of the field
     * @param classMeta The Metadata containing the infos on the java class
     * @return True if it already has getter for this field
     */
    private final boolean alreadyImplementsGet(final FieldMetadata fieldMeta, final ClassMetadata classMeta) {
        boolean ret = false;
        final List<MethodMetadata> methods = classMeta.getMethods();
        final String capitalizedName = fieldMeta.getName().substring(0, 1).toUpperCase()
                + fieldMeta.getName().substring(1);
        String prefix = "get";
        if ("boolean".equalsIgnoreCase(fieldMeta.getHarmonyType())) {
            prefix = "is";
        }
        for (final MethodMetadata m : methods) {
            if (m.getName().equals(prefix + capitalizedName) && m.getArgumentsTypes().size() == 0
                    && m.getType().equals(this.adapter.getNativeType(fieldMeta))) {
                ret = true;

                ConsoleUtils.displayDebug("Already implements getter of " + fieldMeta.getName(),
                        " => " + m.getName());
            }
        }

        return ret;
    }

    /**
     * Check if the class already has a setter for the given field.
     * @param fieldMeta The Metadata of the field
     * @param classMeta The Metadata containing the infos on the java class
     * @return True if it already has setter for this field
     */
    private final boolean alreadyImplementsSet(final FieldMetadata fieldMeta, final ClassMetadata classMeta) {
        boolean result = false;
        final List<MethodMetadata> methods = classMeta.getMethods();
        final String capitalizedName = fieldMeta.getName().substring(0, 1).toUpperCase()
                + fieldMeta.getName().substring(1);

        for (final MethodMetadata method : methods) {
            if (method.getName().equals("set" + capitalizedName) && method.getArgumentsTypes().size() == 1
                    && method.getArgumentsTypes().get(0).equals(this.adapter.getNativeType(fieldMeta))) {
                result = true;

                ConsoleUtils.displayDebug("Already implements setter of " + fieldMeta.getName(),
                        " => " + method.getName());
            }
        }

        return result;
    }

    /**
     * Check if the class already has a getter for the given field.
     * @param classMeta The Metadata containing the infos on the java class
     * @return True if it already has getter for this field
     */
    private final boolean alreadyImplementsDefaultConstructor(final ClassMetadata classMeta) {
        boolean ret = false;

        for (final MethodMetadata methodMeta : classMeta.getMethods()) {
            if (methodMeta.getName().equals(classMeta.getName()) && methodMeta.getArgumentsTypes().size() == 0) {
                ret = true;

                ConsoleUtils.displayDebug("Already implements " + "empty constructor");
            }
        }

        return ret;
    }

    /**
     * Implement all methods needed by parcelable.
     * @param fileString The string buffer representation of the file 
     * @param classMeta The classmetadata
     */
    private final void implementParcelable(final SourceFileManipulator manipulator,
            final EntityMetadata classMeta) {

        manipulator.regenerateMethod("writeToParcelRegen.java", "writeToParcelRegen(Parcel dest, int flags) {",
                this.dataModel);

        manipulator.regenerateMethod("readFromParcel.java", "readFromParcel(Parcel parc) {", this.dataModel);

        if (manipulator.addImplement(classMeta, "Parcelable")) {
            manipulator.addImport(classMeta, "Parcelable", "android.os.Parcelable");
            manipulator.addImport(classMeta, "Parcel", "android.os.Parcel");

            manipulator.generateMethod("parcelConstructor.java", this.dataModel);

            manipulator.generateMethod("writeToParcel.java", this.dataModel);

            manipulator.generateMethod("writeToParcel2.java", this.dataModel);

            manipulator.generateMethod("describeContents.java", this.dataModel);

            manipulator.generateMethod("parcelable.creator.java", this.dataModel);

            if (!(classMeta.getInheritance() != null && classMeta.getInheritance().getSuperclass() != null
                    && classMeta.getInheritance().getSuperclass().hasBeenParsed())) {
                manipulator.generateField("parcelParent.java", this.dataModel);
            }

            boolean hasDateTime = false;
            for (FieldMetadata field : classMeta.getFields().values()) {
                if (field.getHarmonyType().equalsIgnoreCase("DateTime")
                        || field.getHarmonyType().equalsIgnoreCase("Date")
                        || field.getHarmonyType().equalsIgnoreCase("Time")) {
                    hasDateTime = true;
                }
            }
            if (hasDateTime) {
                manipulator.addImport(classMeta, "ISODateTimeFormat", "org.joda.time.format.ISODateTimeFormat");
            }
        }
    }

    /**
     * Implement an empty contructor if it doesn't already exists.
     * @param fileString The string buffer representing the file
     * @param classMeta The classMetadata
     */
    private final void implementEmptyConstructor(final SourceFileManipulator manipulator,
            final ClassMetadata classMeta) {
        if (!this.alreadyImplementsDefaultConstructor(classMeta)) {
            manipulator.generateMethod("defaultConstructor.java", this.dataModel);
        }
    }

    @Override
    public void execute() {
        this.updateEntity();
    }
}