Java tutorial
/** * 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; } }