/*******************************************************************************
* Copyright (c) 2017 Rogue Wave Software Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Rogue Wave Software Inc. - initial implementation
*******************************************************************************/
package org.eclipse.php.internal.ui.wizards.types;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.dltk.core.*;
import org.eclipse.php.core.PHPVersion;
import org.eclipse.php.internal.core.typeinference.PHPModelUtils;
import org.eclipse.php.internal.ui.Logger;
import org.eclipse.php.internal.ui.PHPUiPlugin;
import org.eclipse.ui.INewWizard;
/**
* This class represents the Wizard for creating a new PHP Class
*/
public class NewPHPClassWizard extends NewPHPTypeWizard implements INewWizard {
private ArrayList<IMethod> funcsToAdd = new ArrayList<>();
public NewPHPClassWizard() {
super();
setWindowTitle(Messages.NewPHPClassWizard_0);
setDefaultPageImageDescriptor(PHPUiPlugin.getImageDescriptor(TypeWizardConstants.CLASS_ICON_WIZBAN));
setNeedsProgressMonitor(true);
}
public NewPHPClassWizard(NewPHPTypePage page) {
this();
this.page = page;
addPage(page);
}
@Override
public void addPages() {
if (page == null) {
page = new NewPHPClassPage();
addPage(page);
page.init(getSelection());
}
}
@Override
public boolean performFinish() {
if (page.isInExistingPHPFile()) {
// add the existing file's name to the already existings requires !
existingPHPFile = DLTKCore.createSourceModuleFrom(page.getExisitngFile());
}
// populate data members from the UI's values using the Post Finish
// validator
final PostFinishValidator validator = new ClassPostFinishValidator();
validator.packAndValidate();
final String containerName = page.getSourceText();
final String fileName = page.getNewFileName();
// ///TEMPLATE///////////////
PHPElementTemplate templateEngine = new PHPClassTemplate();
try {
templateEngine.resolveTemplate();
} catch (IOException ioe) {
Logger.logException(ioe);
}
// The data object that will be passed to the template engine
NewPHPElementData data = populatePHPElementData();
final String contents = templateEngine.processTemplate(data);
compilationResult = contents;
// Create the class in a new file :
// Create an interface in a new file
if (!page.isInExistingPHPFile()) {
// create a new file and inject the code
createNewPHPFile(containerName, fileName, contents);
} else { // an existing file
injectCodeIntoExistingFile();
}
if (validator.hasWarnings()) {
getShell().getDisplay().asyncExec(() -> showWarningsDialog(validator.getWarnings()));
}
page.saveGeneratedGroupValues();
return true;
}
// populate data object that is passed to the template engine
private NewPHPElementData populatePHPElementData() {
PHPVersion phpVersion = page.getPHPVersion();
NewPHPClassPage page = (NewPHPClassPage) this.page;
NewPHPElementData data = new NewPHPElementData();
data.phpVersion = phpVersion;
data.isGeneratePHPDoc = page.isCheckboxCreationChecked(NewPHPClassPage.PHP_DOC_BLOCKS);
data.isGenerateTODOs = page.isCheckboxCreationChecked(NewPHPClassPage.TODOS);
data.superClass = page.getSuperClassData();
List<IType> interfacesList = page.getInterfaces();
IType[] interfaces = new IType[interfacesList.size()];
interfacesList.toArray(interfaces);
data.interfaces = interfaces;
List<IType> traitsList = page.getTraits();
IType[] traits = new IType[traitsList.size()];
traitsList.toArray(traits);
data.traits = traits;
List<String> existingImports = getExistingImports();
data.existingImports = existingImports.toArray(new String[0]);
List<String> imports = new ArrayList<>();
for (IType type : interfaces) {
addImport(imports, type, existingImports);
}
if (data.superClass != null) {
addImport(imports, data.superClass, existingImports);
}
for (IType type : traits) {
addImport(imports, type, existingImports);
}
data.isGenerateConstructor = page.isCheckboxCreationChecked(NewPHPClassPage.CONSTRUCTOR);
data.isGenerateDestructor = page.isCheckboxCreationChecked(NewPHPClassPage.DESTRUCTOR);
data.isFinal = page.isCreateModifierChecked(1);
data.isAbstract = page.isCreateModifierChecked(2);
IMethod[] funcs = new IMethod[funcsToAdd.size()];
funcsToAdd.toArray(funcs);
for (IMethod method : funcs) {
try {
IParameter[] parameters = method.getParameters();
for (IParameter parameter : parameters) {
if (parameter.getType() != null) {
IType[] parameterTypes = PHPModelUtils.getTypes(parameter.getType(), method.getSourceModule(),
method.getSourceRange().getOffset(), null);
for (IType parameterType : parameterTypes) {
addImport(imports, parameterType, existingImports);
}
}
}
} catch (ModelException e) {
}
}
data.funcsToAdd = funcs;
data.className = page.getElementName();
data.namespace = page.getNamespace();
data.realNamespace = page.getRealNamespace();
data.isExistingFile = page.isInExistingPHPFile();
data.requiredToAdd = getRequires();
if (data.isExistingFile) {
data.isInFirstBlock = page.isInFirstPHPBlock();
data.hasFirstBlock = true;
}
data.imports = imports.toArray(new String[0]);
return data;
}
/**
* Processes this wizard's data after 'Finish' is clicked. This validator
* retrieves required information for generating code and validates it.
*
* @author yaronm
*/
class ClassPostFinishValidator extends PostFinishValidator {
@Override
public void packAndValidate() {
super.packAndValidate();
// run over all requested interfaces and add their functions and
// requires in order to be overriden
handleInterfaces();
// run over all super class hierarchy
// add abstract method to be overriden
IType superClassData = ((NewPHPClassPage) page).getSuperClassData();
if (superClassData != null) {
extractReqruiresInclude(superClassData);
addRequiredFuns(superClassData);
}
}
private void addRequiredFuns(IType superClassData) {
if (((NewPHPClassPage) page).isCheckboxCreationChecked(NewPHPClassPage.INHERITED_ABSTRACT_METHODS)) {
try {
funcsToAdd.addAll(Arrays.asList(PHPModelUtils.getUnimplementedMethods(superClassData, null)));
} catch (ModelException e) {
}
}
}
// adds all the methods to override from the hierarchy of Interfaces
// recursively
// plus adds all the required php files
private void handleInterfaces() {
for (IType currentInterface : page.getInterfaces()) {
if (currentInterface != null) {
extractReqruiresInclude(currentInterface);
addRequiredFuns(currentInterface);
}
}
for (IType currentInterface : page.getTraits()) {
if (currentInterface != null) {
extractReqruiresInclude(currentInterface);
}
}
}
}
}