fr.atelechev.buildergen.plugin.TopLevelClassWriter.java Source code

Java tutorial

Introduction

Here is the source code for fr.atelechev.buildergen.plugin.TopLevelClassWriter.java

Source

/**
 *
Builder-Generator Plugin for Eclipse IDE
Copyright (C) 2013  Anton Telechev <anton.teleshev at wanadoo.fr>
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program.  If not, see [http://www.gnu.org/licenses/].
 *
 */
package fr.atelechev.buildergen.plugin;

import java.nio.file.Files;
import java.nio.file.Path;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;

import fr.atelechev.buildergen.generator.BuilderGenerator;
import fr.atelechev.buildergen.generator.CompilationUnitAnalyzer;
import fr.atelechev.buildergen.generator.Generator;

/**
 * Implementation of {@code AbstractBuilderWriter} that
 * generates the code for a class of the first level (non inner/nested).
 * @author Anton Telechev <anton.teleshev at wanadoo.fr>
 */
class TopLevelClassWriter extends AbstractBuilderWriter {

    TopLevelClassWriter(Options options, Shell shell) {
        super(options, shell);
    }

    @Override
    void writeCode() {
        if (getSelectedFile() == null || getTargetClassName() == null) {
            throw new IllegalStateException(
                    "AbstractBuilderWriter not ready: selectedFile and/or targetClassName is/are null.");
        }
        final Path absFilePath = getTargetFileAsPath();
        if (!isPreconditionsFilled(absFilePath)) {
            return;
        }
        if (writeTopLevelClass()) {
            MessageDialog.openInformation(getContainer(), I18n.DIALOG_SUCCESS_TITLE.getText(),
                    String.format(I18n.DIALOG_SUCCESS_MESSAGE.getText(), getTargetClassName()));
        } else {
            MessageDialog.openError(getContainer(), I18n.DIALOG_FAIL_TITLE.getText(),
                    String.format(I18n.DIALOG_FAIL_MESSAGE.getText()));
        }
    }

    private boolean isPreconditionsFilled(Path absFilePath) {
        // check if the target file exists and ask to override
        if (!canWriteSelectedFile(absFilePath)) {
            return false;
        }
        // check if there is a default constructor
        if (!canWriteWithDefaultOriginalClassConstructor()) {
            return false;
        }
        return true;
    }

    private boolean writeTopLevelClass() {
        final IProgressMonitor progressMonitor = new NullProgressMonitor();
        progressMonitor.beginTask("Generating Builder class code", 5);
        progressMonitor.subTask("Accessing the parent package.");
        final IPackageFragment parentPackage = getParentPackage();
        if (parentPackage == null) {
            return false;
        }
        progressMonitor.worked(1);
        progressMonitor.subTask("Generating Java code.");
        final String generatedCode = getGeneratedJavaCode();
        if (generatedCode == null) {
            return false;
        }
        progressMonitor.worked(1);
        try {
            progressMonitor.subTask("Creating Eclipse compilation unit.");
            final ICompilationUnit builderClassUnit = parentPackage.createCompilationUnit(
                    getTargetClassName() + ".java", generatedCode, true,
                    new SubProgressMonitor(progressMonitor, 1));
            progressMonitor.worked(1);
            builderClassUnit.becomeWorkingCopy(new SubProgressMonitor(progressMonitor, 1));
            progressMonitor.worked(1);
            builderClassUnit.commitWorkingCopy(true, new SubProgressMonitor(progressMonitor, 1));
            progressMonitor.worked(1);
        } catch (JavaModelException ex) {
            progressMonitor.setCanceled(true);
            BuilderGenerateHandler.showErrorMessage(getContainer(), ex);
            return false;
        } finally {
            progressMonitor.done();
        }
        return true;
    }

    private IPackageFragment getParentPackage() {
        final IJavaElement parentElement = getSelectedFile().getParent();
        if (parentElement instanceof IPackageFragment) {
            return (IPackageFragment) parentElement;
        }
        MessageDialog.openError(getContainer(), I18n.DIALOG_FAIL_TITLE.getText(),
                String.format(I18n.DIALOG_FAIL_MESSAGE.getText()));
        return null;
    }

    private String getGeneratedJavaCode() {
        try {
            return buildGenerator().generate();
        } catch (IllegalStateException ex) {
            BuilderGenerateHandler.showErrorMessage(getContainer(), ex);
            return null;
        }
    }

    private Generator buildGenerator() {
        final BuilderGenerator generator = new BuilderGenerator();
        generator.setClassAnalyzer(new CompilationUnitAnalyzer(getReferenceToSelectedIType()));
        generator.setOptions(getOptions());
        generator.setBuilderClassName(getTargetClassName());
        generator.setOriginalClass(getSourceClassAsJavaType());
        return generator;
    }

    private IType getReferenceToSelectedIType() {
        try {
            final IJavaElement[] allElements = getSelectedFile().getChildren();
            if (allElements == null || allElements.length == 0) {
                throw new IllegalStateException("Failed to get the type metadata.");
            }
            for (IJavaElement element : allElements) {
                if (elementIsTypeWithTargetName(element)) {
                    return (IType) element;
                }
            }
        } catch (JavaModelException ex) {
            throw new IllegalStateException(ex);
        }
        throw new IllegalStateException("Type metadata not found.");
    }

    private boolean elementIsTypeWithTargetName(IJavaElement element) {
        final int javaExtensionIndex = getSelectedFile().getElementName().indexOf(".java");
        final String analyzedUnitName = getSelectedFile().getElementName().substring(0, javaExtensionIndex);
        return element.getElementType() == IJavaElement.TYPE && element.getElementName().equals(analyzedUnitName);
    }

    private boolean canWriteSelectedFile(Path absFilePath) {
        if (!Files.exists(absFilePath)) {
            return true;
        }
        return MessageDialog.openConfirm(getContainer(), I18n.DIALOG_CONFIRM_FILE_OVERWRITE_TITLE.getText(),
                String.format(I18n.DIALOG_CONFIRM_FILE_OVERWRITE_MESSAGE.getText(), absFilePath.getFileName()));
    }

    private boolean canWriteWithDefaultOriginalClassConstructor() {
        final IType itype = getReferenceToSelectedIType();
        final IMethod constructor = itype.getMethod(getOriginalClassSimpleName(), null);
        boolean shouldAskConfirmation = !constructor.exists();
        if (!shouldAskConfirmation) {
            try {
                final int flags = constructor.getFlags();
                if (Flags.isPrivate(flags)) {
                    shouldAskConfirmation = true;
                }
            } catch (JavaModelException ex) {
                throw new IllegalStateException("Failed to access constructor data in the original class.", ex);
            }
        }
        if (shouldAskConfirmation) {
            return MessageDialog.openConfirm(getContainer(), I18n.DIALOG_CONFIRM_CONSTRUCTOR_TITLE.getText(),
                    I18n.DIALOG_CONFIRM_CONSTRUCTOR_MESSAGE.getText());
        }
        return true;
    }

}