/*******************************************************************************
* Copyright (c) 2005, 2012 eBay Inc.
* 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
*
*******************************************************************************/
package org.eclipse.vjet.eclipse.internal.ui.wizards;
import static org.eclipse.vjet.eclipse.internal.ui.wizards.VjetWizardMessages.ClassCreationWizard_file_content;
import java.io.ByteArrayInputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.dltk.mod.core.ModelException;
import org.eclipse.dltk.mod.internal.core.JSSourceModule;
import org.eclipse.dltk.mod.internal.ui.DLTKUIMessages;
import org.eclipse.dltk.mod.ui.CodeFormatterConstants;
import org.eclipse.dltk.mod.ui.DLTKUIPlugin;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.vjet.dsf.jst.IJstMethod;
import org.eclipse.vjet.dsf.jst.IJstType;
import org.eclipse.vjet.dsf.jst.declaration.JstArg;
import org.eclipse.vjet.eclipse.codeassist.CodeassistUtils;
import org.eclipse.vjet.eclipse.internal.ui.wizards.VjoSourceModulePage.InterfaceWrapper;
import org.eclipse.vjet.eclipse.ui.JavaScriptImages;
import org.eclipse.vjet.eclipse.ui.VjetUIPlugin;
import org.eclipse.vjet.vjo.tool.codecompletion.CodeCompletionUtils;
/**
* VJET wizard for creating a new vjo class.
*
*/
public class VjoClassCreationWizard extends VjoSourceModuleWizard {
public static final String PROPS = "props";
public static final String PROTOS = "protos";
public static final String EMPTY = "";
private static final String INHERITS = ".inherits(''{0}'')";
private static final String SATISFIES = ".satisfies(''{0}'')";
private static final String INDENTATION = "\r\n\t";
private static final String ATYPE = "atype";
private static final String TYPE = "ctype";
// private VjoClassCreationPage page;
public VjoClassCreationWizard() {
super();
setDefaultPageImageDescriptor(JavaScriptImages.DESC_WIZBAN_PROJECT_CREATION);
setDialogSettings(DLTKUIPlugin.getDefault().getDialogSettings());
setWindowTitle(VjetWizardMessages.ClassCreationWizard_title);
}
@Override
protected VjoSourceModulePage createVjoSourceModulePage() {
return new VjoClassCreationPage();
// return page;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.vjet.eclipse.internal.ui.wizards.VjoSourceModuleWizard#finishPage(org.eclipse.core.runtime.IProgressMonitor)
*/
public void finishPage(IProgressMonitor monitor)
throws InterruptedException, CoreException {
super.finishPage(monitor);
JSSourceModule module = (JSSourceModule) getCreatedElement();
IFile file = (IFile) module.getResource();
byte[] content = getInitialFileContent(file);
ByteArrayInputStream stream = new ByteArrayInputStream(content);
file.appendContents(stream, false, false, monitor);
}
/**
* Returns the initial file content for creating class.
*
* @param file
* {@link IFile}
*
* @return an array of bytes of the initial content for created class.
*
* @throws {@link ModelException}
*/
protected byte[] getInitialFileContent(IFile file) throws ModelException {
// Add by Oliver. The old file content template is
// "ClassCreationWizard_file_content =
// vjo.{0}(''{1}''){5}{2}{6}\r\n.{4}('{'\r\n {3}
// \r\n'}')\r\n.{7}('{'\r\n{9}{8}\r\n'}')\r\n.endType();"
String content = getFileContentTamplate();
String buffer = CodeassistUtils.getClassName(file);
// Modify by Oliver. This method--"getModifierIndex()" comes from its
// parent wizard.
String modifiers = getModifierIndex();
String modifierDesc = formatModifier(modifiers);
modifierDesc += "\r\n";
String type = getClassType();
// if ("ctype".equals(type) && modifiers.contains("abstract")) {
// type = ATYPE;
// }
String inheritance = getInheritance();
if (inheritance.length() > 0) {
inheritance += "\r\n";
}
String satsifies = getSatisfies();
if (satsifies.length() > 0) {
satsifies += "\r\n";
}
String constStub = getConstructorStub();
if (constStub.length() > 0) {
constStub += "\r\n";
}
String satisfiesMethods = getSastisfiesMethods();
if (satisfiesMethods.length() > 0) {
// If there is constructor after the methods, will add comma.
if (constStub.length() > 0) {
satisfiesMethods += ",";
}
satisfiesMethods += "\r\n";
}
String methodStub = getMethodStub();
String blockName = getBlockName();
// Modify by Oliver. When create etype, the brace that follow by
// '.values' should be '('.
if ("etype".equals(type)) {
String valueSection = ".values('\r\n\t''''\r\n')\r\n";
int position = content.indexOf(".{4}(");
String sufContent = content.substring(0, position);
String newContent = sufContent + valueSection
+ content.substring(content.indexOf(".{4}("));
content = newContent;
// if (content.indexOf("('{'") > 0) {
// content = content.replace("('{'", "(");
// }
// if (content.indexOf("'}')") > 0) {
// content = content.replace("'}')", ")");
// }
// int position = content.indexOf(".{7}(");
// content = content.substring(0, position)
// + ".{7}('{'\r\n {8} \r\n'}')\r\n.endType();";
//
// // Modify by Oliver. 2009-06-09. Add ' ' into the values block of
// // EType.Otherwise there is a validation error about the empty
// // .value block.
// methodStub = "\' \'";
}
// Add by Oliver.2009-06-22. For OType code format.
if ("otype".equals(type)) {
int position = content.indexOf(".{7}(");
content = content.substring(0, position) + ".endType();";
}
IPreferenceStore store = VjetUIPlugin.getDefault().getPreferenceStore();
String tabStyle = store
.getString(CodeFormatterConstants.FORMATTER_TAB_CHAR);
// if (CodeFormatterConstants.SPACE.equals(tabStyle)){
// content = content.replace("\r", "\t").trim();
// }
Object[] objects = new Object[] { type, buffer, inheritance,
methodStub, blockName, modifierDesc, satsifies, PROTOS,
constStub, satisfiesMethods };
return MessageFormat.format(content, objects).getBytes();
}
private static boolean isMethodEquivalent(IJstMethod m1, IJstMethod m2) {
if (!m1.getName().getName().equals(m2.getName().getName())) {
return false;
}
List<JstArg> args1 = m1.getArgs();
List<JstArg> args2 = m2.getArgs();
if (args1.size() == args2.size()) {
for (int i = 0; i < args1.size(); i++) {
if (!args1.get(i).getType().getName().equals(
args2.get(i).getType().getName())) {
return false;
}
}
return true;
}
return false;
}
private static boolean isContainMethod(List<IJstMethod> ms, IJstMethod m) {
for (IJstMethod jstMethod : ms) {
if (isMethodEquivalent(jstMethod, m)) {
return true;
}
}
return false;
}
private String getSastisfiesMethods() {
if (!(page instanceof VjoClassCreationPage)) {
return EMPTY;
}
List elms = page.getSuperInterfacesDialogField().getElements();
IJstType baseType = ((VjoClassCreationPage) page).getBaseType();
List<IJstMethod> canOverrideMethods = new ArrayList<IJstMethod>();
if (baseType != null) {
List baseMethods = baseType.getMethods(false, true);
for (Iterator iterator = baseMethods.iterator(); iterator.hasNext();) {
IJstMethod m = (IJstMethod) iterator.next();
if (m.isProtected() || m.isPublic()) {
canOverrideMethods.add(m);
}
}
}
String satisfiesMethods = EMPTY;
List<IJstMethod> toBeAddedMethods = new ArrayList<IJstMethod>();
for (Object object : elms) {
// InterfaceWrapper
InterfaceWrapper iw = (InterfaceWrapper) object;
IJstType type = iw.getSourceType();
List<? extends IJstMethod> ml = type.getMethods(false, true);
for (IJstMethod jstMethod : ml) {
if ((!isContainMethod(canOverrideMethods, jstMethod))
&& (!isContainMethod(toBeAddedMethods, jstMethod))) {
toBeAddedMethods.add(jstMethod);
}
}
}
for (IJstMethod jstMethod2 : toBeAddedMethods) {
satisfiesMethods += getReplaceStringForOverrideProposal(jstMethod2);
satisfiesMethods += ",\r\n";
}
int length = satisfiesMethods.lastIndexOf(",");
return length == -1 ? satisfiesMethods : satisfiesMethods.substring(0,
length);
}
/**
* Generate a string for a given method. There is also
* org.eclipse.vjet.eclipse.internal.ui.text.completion.VjoProposalLabelUtil.getJstCommentStringR(method)
* for this function. I extract it here to add some indentation.
*
* @param method
* @return
*/
public static String getReplaceStringForOverrideProposal(IJstMethod method) {
StringBuffer buffer = new StringBuffer();
String commStr = CodeCompletionUtils.getJstCommentStringR(method);
buffer.append(INDENTATION + "//>" + commStr);
// buffer.append("\n");
String name = method.getName().getName();
buffer.append(INDENTATION + name);
buffer.append(" : function(");
String aname = CodeCompletionUtils.getJstArgsStringR(method);
if (aname.length() > 0) {
buffer.append(aname);
}
buffer.append(")");
// buffer.append("{\n " + INDENTATION + "}");
// fix bug 3861. Add the return part code.BEGIN.
String returnStatement = null;
String defaultReturnValue = JstTypeDefaultValueHelper
.getDefaultValue(method.getRtnType());
if (defaultReturnValue == null)
returnStatement = "\t\t" + INDENTATION;
else
returnStatement = "\t\treturn " + defaultReturnValue + ";\r\n\t";
buffer.append("{\r\n" + returnStatement + "}");
// Add the return part code.END.
return buffer.toString();
}
protected String getBlockName() {
return PROPS;
}
protected String getFileContentTamplate() {
return ClassCreationWizard_file_content;
}
protected String getInheritance() {
String className = ((VjoClassCreationPage) page)
.getSuperclassFieldText();
String inheritance = EMPTY;
if (className != null && !className.trim().equals(EMPTY)) {
inheritance = MessageFormat.format(INHERITS, className);
}
return inheritance;
}
protected String getSatisfies() {
List elms = page.getSuperInterfacesDialogField().getElements();
String satisfies = EMPTY;
for (Object object : elms) {
String interfacename = object.toString();
if (interfacename != null && !interfacename.trim().equals(EMPTY)) {
if (VjoInterfaceCreationWizard.ITYPE.equals(getClassType())) {
// fix bug 4995
if (satisfies.equals(EMPTY))
satisfies += MessageFormat.format(INHERITS,
interfacename);
else
// Modify by Oliver for the '\r\n' format.2009-06-18
satisfies += "\r\n"
+ MessageFormat.format(INHERITS, interfacename);
} else {
// fix bug 4217
if (satisfies.equals(EMPTY))
satisfies += MessageFormat.format(SATISFIES,
interfacename);
else
// Modify by Oliver for the '\r\n' format.2009-06-18
satisfies += "\r\n"
+ MessageFormat
.format(SATISFIES, interfacename);
}
}
}
return satisfies;
}
protected String getClassType() {
String type = TYPE;
// if (page.isAbstractButtonSelected()) {
// type = ATYPE;
// }
return type;
}
/**
* @param modifier
* @return
*/
protected String formatModifier(String modifier) {
String modDesc = "";
String preFix = " //< ";
if (modifier.contains("public")) {
modDesc = "public";
}
if (modifier.contains("default")) {
// This is for "//< default"
modDesc = "";
}
if (modifier.contains("private")) {
modDesc = "private";
}
if (modifier.contains("protected")) {
modDesc = "protected";
}
if (modifier.contains("abstract")) {
modDesc += " abstract";
}
if (modifier.contains("final")) {
modDesc += " final";
}
// Sometimes no any modifier, so it is empty returned string.
if (modDesc.trim().length() > 0) {
modDesc = preFix + modDesc;
}
return modDesc;
}
protected String getOpenTypeErrorMessage() {
return DLTKUIMessages.OpenTypeAction_errorMessage;
}
protected String getOpenTypeErrorTitle() {
return DLTKUIMessages.OpenTypeAction_errorTitle;
}
private String getMethodStub() {
String content = EMPTY;
// check the selection state of the 'Create Main' checkbox
if (page != null && (page instanceof VjoClassCreationPage)
&& ((VjoClassCreationPage) page).isMethodStubsButtonSelected())
content = VjetWizardMessages.ClassCreationWizard_main_method_content;
return content;
}
private String getConstructorStub() {
String content = EMPTY;
// check the selection state of the 'Constructor' checkbox
if (page != null && (page instanceof VjoClassCreationPage)
&& ((VjoClassCreationPage) page).isConstructorButtonSelected())
content += VjetWizardMessages.ClassCreationWizard_constructor_content;
return content;
}
}