/*******************************************************************************
* Copyright (c) 2010 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.cdi.ui.wizard;
import java.beans.BeanDescriptor;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.jdt.ui.wizards.NewClassWizardPage;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.PlatformUI;
import org.jboss.tools.cdi.core.CDIConstants;
import org.jboss.tools.cdi.core.CDICorePlugin;
import org.jboss.tools.cdi.core.CDIImages;
import org.jboss.tools.cdi.core.ICDIAnnotation;
import org.jboss.tools.cdi.core.ICDIProject;
import org.jboss.tools.cdi.core.IQualifier;
import org.jboss.tools.cdi.core.IScope;
import org.jboss.tools.cdi.internal.core.scanner.lib.BeanArchiveDetector;
import org.jboss.tools.cdi.ui.CDIUIMessages;
import org.jboss.tools.cdi.xml.beans.model.CDIBeansConstants;
import org.jboss.tools.common.ui.widget.editor.CheckBoxFieldEditor;
import org.jboss.tools.common.ui.widget.editor.CompositeEditor;
import org.jboss.tools.common.ui.widget.editor.IFieldEditor;
import org.jboss.tools.common.ui.widget.editor.IFieldEditorFactory;
import org.jboss.tools.common.ui.widget.editor.ITaggedFieldEditor;
import org.jboss.tools.common.ui.widget.editor.LabelFieldEditor;
import org.jboss.tools.common.ui.widget.editor.ListFieldEditor;
import org.jboss.tools.common.ui.widget.editor.TextFieldEditor;
/**
*
* @author Viacheslav Kabanovich
*
*/
public class NewBeanWizardPage extends NewClassWizardPage {
protected CheckBoxEditorWrapper alternative = null;
protected boolean mayBeRegisteredInBeansXML = true;
protected BeansXMLAccess registerInBeansXML = new BeansXMLAccess(this, "Alternatives", CDIBeansConstants.ENT_CDI_CLASS, CDIBeansConstants.ATTR_CLASS);
protected CheckBoxEditorWrapper isNamed;
protected BeanNameEditorWrapper beanName;
protected ITaggedFieldEditor scope = null;
protected Map<String, String> scopes = new TreeMap<String, String>();
protected QualifierSelectionProvider qualifiersProvider = new QualifierSelectionProvider();
protected ListFieldEditor qualifiers = null;
protected StatusInfo fieldNameStatus = new StatusInfo();
protected StatusInfo scopeStatus = new StatusInfo();
boolean isAlternativeInitialValue = false;
public NewBeanWizardPage() {
setTitle(CDIUIMessages.NEW_BEAN_WIZARD_PAGE_NAME);
setDescription(CDIUIMessages.NEW_BEAN_WIZARD_DESCRIPTION);
setImageDescriptor(CDIImages.getImageDescriptor(CDIImages.CDI_CLASS_IMAGE));
}
public void setMayBeRegisteredInBeansXML(boolean b) {
mayBeRegisteredInBeansXML = b;
}
public void init(IStructuredSelection selection) {
super.init(selection);
if (selection != null && !selection.isEmpty()) {
Object o = selection.iterator().next();
IType type = null;
if (o instanceof IType) {
type = (IType) o;
} else if (o instanceof ICompilationUnit) {
ICompilationUnit cu = (ICompilationUnit) o;
try {
IType[] ts = cu.getTypes();
if (ts != null && ts.length > 0)
type = ts[0];
} catch (JavaModelException e) {
CDICorePlugin.getDefault().logError(e);
}
}
boolean isInterface = false;
try {
isInterface = type != null && type.isInterface();
} catch (JavaModelException e) {
CDICorePlugin.getDefault().logError(e);
}
ArrayList<String> interfacesNames = new ArrayList<String>();
if (isInterface) {
String name = "";
try {
name = type.getFullyQualifiedParameterizedName();
} catch (JavaModelException e) {
name = type.getFullyQualifiedName();
}
interfacesNames.add(name);
setDefaultTypeName(name);
}
// interfacesNames.add("java.io.Serializable");
setSuperInterfaces(interfacesNames, true);
superInterfacesChanged();
}
doStatusUpdate();
}
void setDefaultTypeName(String interfaceName) {
}
public void createControl(Composite parent) {
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NONE);
composite.setFont(parent.getFont());
int nColumns = 4;
GridLayout layout = new GridLayout();
layout.numColumns = nColumns;
composite.setLayout(layout);
// pick & choose the wanted UI components
createContainerControls(composite, nColumns);
createPackageControls(composite, nColumns);
// createEnclosingTypeControls(composite, nColumns);
createSeparator(composite, nColumns);
createTypeNameControls(composite, nColumns);
createModifierControls(composite, nColumns);
createSuperClassControls(composite, nColumns);
createSuperInterfacesControls(composite, nColumns);
// createMethodStubSelectionControls(composite, nColumns);
createCustomFields(composite);
createCommentControls(composite, nColumns);
enableCommentControl(true);
setControl(composite);
Dialog.applyDialogFont(composite);
PlatformUI.getWorkbench().getHelpSystem()
.setHelp(composite, IJavaHelpContextIds.NEW_CLASS_WIZARD_PAGE);
// onInterceptorBindingChange();
computeScopeStatus();
doStatusUpdate();
}
protected void createTypeMembers(IType newType,
final ImportsManager imports, IProgressMonitor monitor)
throws CoreException {
createInheritedMethods(newType, true, true, imports,
new SubProgressMonitor(monitor, 1));
ISourceRange range = newType.getSourceRange();
IBuffer buf = newType.getCompilationUnit().getBuffer();
String lineDelimiter = StubUtility.getLineDelimiterUsed(newType
.getJavaProject());
StringBuffer sb = new StringBuffer();
addAnnotations(imports, sb, lineDelimiter);
buf.replace(range.getOffset(), 0, sb.toString());
}
void addAnnotations(ImportsManager imports, StringBuffer sb,
String lineDelimiter) {
addAlternativeAnnotation(imports, sb, lineDelimiter);
addNamedAnnotation(imports, sb, lineDelimiter);
addScopeAnnotation(imports, sb, lineDelimiter);
addQualifiersAnnotations(imports, sb, lineDelimiter);
}
protected void addAlternativeAnnotation(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(alternative != null && alternative.composite.getValue() == Boolean.TRUE) {
NewCDIAnnotationWizardPage.addAnnotation(CDIConstants.ALTERNATIVE_ANNOTATION_TYPE_NAME, imports, sb, lineDelimiter);
}
}
protected void addNamedAnnotation(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(isNamed.checkBox != null && isNamed.checkBox.getValue() != null && "true".equals(isNamed.checkBox.getValueAsString())) {
if(beanName.text.getValue() != null && beanName.text.getValueAsString().length() > 0) {
addAnnotation(CDIConstants.NAMED_QUALIFIER_TYPE_NAME, imports, sb, lineDelimiter, beanName.text.getValueAsString());
} else {
NewCDIAnnotationWizardPage.addAnnotation(CDIConstants.NAMED_QUALIFIER_TYPE_NAME, imports, sb, lineDelimiter);
}
}
}
static void addAnnotation(String typeName, ImportsManager imports, StringBuffer sb, String lineDelimiter, String value) {
int i = typeName.lastIndexOf('.');
String name = typeName.substring(i + 1);
imports.addImport(typeName);
sb.append("@").append(name).append("(\"").append(value).append("\")").append(lineDelimiter);
}
protected void addScopeAnnotation(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(scope != null && scope.getValue() != null && scope.getValue().toString().length() > 0) {
String scopeName = scope.getValue().toString();
String qScopeName = scopes.get(scopeName);
NewCDIAnnotationWizardPage.addAnnotation(qScopeName, imports, sb, lineDelimiter);
}
}
protected void addQualifiersAnnotations(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(qualifiers != null) {
List list = (List)qualifiers.getValue();
for (Object o: list) {
if(o instanceof ICDIAnnotation) {
ICDIAnnotation a = (ICDIAnnotation)o;
String typeName = a.getSourceType().getFullyQualifiedName();
NewCDIAnnotationWizardPage.addAnnotation(typeName, imports, sb, lineDelimiter);
}
}
}
}
protected void createCustomFields(Composite composite) {
createBeanNameField(composite);
createAlternativeField(composite);
createRegisterInBeansXML(composite);
createScopeField(composite);
createQualifiersField(composite);
}
private void doStatusUpdate() {
// status of all used components
IStatus[] status = new IStatus[] {
fContainerStatus,
isEnclosingTypeSelected() ? fEnclosingTypeStatus
: fPackageStatus, fTypeNameStatus, fModifierStatus,
fSuperClassStatus, fSuperInterfacesStatus };
// the mode severe status will be displayed and the OK button
// enabled/disabled.
updateStatus(status);
}
protected void updateStatus(IStatus[] status) {
IStatus[] ns = new IStatus[status.length + 2];
System.arraycopy(status, 0, ns, 0, status.length);
ns[status.length] = fieldNameStatus;
ns[status.length + 1] = scopeStatus;
status = ns;
updateStatus(StatusUtil.getMostSevere(status));
}
public void setPackageFragmentRoot(IPackageFragmentRoot root, boolean canBeModified) {
super.setPackageFragmentRoot(root, canBeModified);
setScopes(root);
setQualifiers(root);
}
void setScopes(IPackageFragmentRoot root) {
if(root != null) {
IJavaProject jp = root.getJavaProject();
ICDIProject cdi = NewCDIAnnotationWizardPage.getCDIProject(jp);
if(cdi != null) {
setScopes(cdi.getScopeNames().toArray(new String[0]));
} else {
setScopes(new String[]{""});
}
} else {
setScopes(new String[]{""});
}
}
void setScopes(String[] tags) {
scopes.clear();
scopes.put("", "");
for (String tag: tags) {
if(tag.length() == 0) continue;
int i = tag.lastIndexOf('.');
String name = "@" + tag.substring(i + 1);
scopes.put(name, tag);
}
if(scope != null) {
scope.setTags(scopes.keySet().toArray(new String[0]));
scope.setValue("");
}
}
void setQualifiers(IPackageFragmentRoot root) {
qualifiersProvider.setProject(null);
if(root != null) {
IJavaProject jp = root.getJavaProject();
ICDIProject cdi = CDICorePlugin.getCDIProject(jp.getProject(), true);
if(cdi != null) qualifiersProvider.setProject(cdi);
}
}
protected void createQualifiersField(Composite composite) {
qualifiers = new ListFieldEditor("qualifiers", CDIUIMessages.FIELD_EDITOR_QUALIFIER_LABEL, new ArrayList<Object>());
qualifiers.setProvider(qualifiersProvider);
qualifiersProvider.setEditorField(qualifiers);
qualifiers.doFillIntoGrid(composite);
setQualifiers(getPackageFragmentRoot());
qualifiers.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
// validateTargetAndStereotype();
}});
Object data = qualifiers.getLabelControl().getLayoutData();
if(data instanceof GridData) {
GridData d = (GridData)data;
d.verticalAlignment = SWT.BEGINNING;
qualifiers.getLabelControl().setData(d);
}
}
public void addQualifier(IQualifier s) {
List vs = (List)qualifiers.getValue();
List nvs = new ArrayList();
if(vs != null) nvs.addAll(vs);
nvs.add(s);
qualifiers.setValue(nvs);
}
public void setBeanName(String name) {
isNamed.composite.setValue(Boolean.valueOf(true));
beanName.composite.setValue(name);
}
protected static class BeanNameEditorWrapper {
protected IFieldEditor composite = null;
protected TextFieldEditor text = null;
}
protected void createBeanNameField(Composite composite) {
isNamed = createCheckBoxField(composite, "isNamed", "Add @Named", false);
beanName = createTextField(composite, "name", "Bean Name:", "");
beanName.composite.setEnabled(false);
isNamed.checkBox.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
boolean named = "true".equals(isNamed.checkBox.getValueAsString());
beanName.composite.setEnabled(named);
}});
}
protected void createAlternativeField(Composite composite) {
String label = "Add @Alternative";
alternative = createCheckBoxField(composite, "isAlternative", label, isAlternativeInitialValue);
if(mayBeRegisteredInBeansXML) {
alternative.checkBox.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
boolean isAlternative = "true".equals(alternative.checkBox.getValueAsString());
registerInBeansXML.setEnabled(isAlternative);
}});
}
}
protected void createRegisterInBeansXML(Composite composite) {
if(!mayBeRegisteredInBeansXML) return;
registerInBeansXML.create(composite, isAlternativeInitialValue);
registerInBeansXML.setEnabled(isAlternativeInitialValue);
}
protected static CheckBoxEditorWrapper createCheckBoxField(Composite composite, String name, String label, boolean defaultValue) {
CheckBoxEditorWrapper wrapper = new CheckBoxEditorWrapper();
wrapper.checkBox = new CheckBoxFieldEditor(name,"",Boolean.valueOf(defaultValue));
CompositeEditor editor = new CompositeEditor(name,"", defaultValue);
editor.addFieldEditors(new IFieldEditor[]{new LabelFieldEditor(name, ""), wrapper.checkBox});
wrapper.composite = editor;
wrapper.composite.doFillIntoGrid(composite);
((Button)wrapper.checkBox.getCheckBoxControl()).setText(label);
return wrapper;
}
protected BeanNameEditorWrapper createTextField(Composite composite, String name, String label, String defaultValue) {
BeanNameEditorWrapper wrapper = new BeanNameEditorWrapper();
wrapper.text = new TextFieldEditor(name,"",defaultValue);
CompositeEditor editor = new CompositeEditor(name,"", defaultValue);
LabelFieldEditor l = new LabelFieldEditor(name, label);
editor.addFieldEditors(new IFieldEditor[]{l, wrapper.text, new LabelFieldEditor(name, "")});
wrapper.composite = editor;
wrapper.composite.doFillIntoGrid(composite);
return wrapper;
}
protected void createScopeField(Composite composite) {
ArrayList<String> values = new ArrayList<String>();
values.add("");
scope = createComboField("Scope", CDIUIMessages.FIELD_EDITOR_SCOPE_LABEL, composite, values);
scope.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
onScopeModified();
}
});
setScopes(getPackageFragmentRoot());
}
void onScopeModified() {
fSuperInterfacesStatus = superInterfacesChanged();
computeScopeStatus();
doStatusUpdate();
}
void computeScopeStatus() {
scopeStatus = new StatusInfo();
if(scope.getValueAsString().length() == 0) {
IJavaProject jp = getJavaProject();
if(jp != null) {
ICDIProject cdi = NewCDIAnnotationWizardPage.getCDIProject(jp);
if(cdi != null && cdi.getNature().getBeanDiscoveryMode() == BeanArchiveDetector.ANNOTATED) {
scopeStatus.setError(CDIUIMessages.SCOPE_SHOULD_BE_SET_IN_ARCHIVE_WITH_DISCOVERY_MODE_ANNOTATED);
}
}
}
}
protected IStatus superInterfacesChanged() {
StatusInfo result = (StatusInfo)super.superClassChanged();
if(!checkScopeAndSerializable())
if (!result.isError() && !result.isWarning() && !checkScopeAndSerializable()) {
result.setWarning(CDIUIMessages.MESSAGE_BEAN_SHOULD_BE_SERIALIZABLE);
}
return result;
}
boolean checkScopeAndSerializable() {
if(scope == null) return true;
IJavaProject jp = getJavaProject();
if(jp == null) return true;
boolean isPassivating = false;
String scopeName = scope.getValueAsString();
String qScopeName = scopes.get(scopeName);
if(CDIConstants.SESSION_SCOPED_ANNOTATION_TYPE_NAME.equals(qScopeName)) {
isPassivating = true;
} else {
ICDIProject cdi = NewCDIAnnotationWizardPage.getCDIProject(jp);
if(cdi != null) {
IScope s = cdi.getScope(qScopeName);
if(s != null && s.isNorlmalScope() && cdi.isPassivatingScope(s.getSourceType())) {
isPassivating = true;
}
}
}
if(isPassivating) {
boolean result = false;
List list = getSuperInterfaces();
if(list != null) {
for (int i = 0; i < list.size() && !result; i++) {
if("java.io.Serializable".equals(list.get(i).toString())) {
result = true;
}
}
}
return result;
}
return true;
}
protected ITaggedFieldEditor createComboField(String name, String label, Composite composite, List<String> values) {
ITaggedFieldEditor result = IFieldEditorFactory.INSTANCE.createComboEditor(name, label, values, values.get(0));
((CompositeEditor)result).addFieldEditors(new IFieldEditor[]{new LabelFieldEditor(name, "")});
result.doFillIntoGrid(composite);
Combo combo = (Combo)result.getEditorControls()[1];
Object layoutData = combo.getLayoutData();
if(layoutData instanceof GridData) {
((GridData)layoutData).horizontalAlignment = GridData.FILL;
}
return result;
}
public void setAlternative(boolean value) {
if(alternative != null) {
alternative.composite.setValue(Boolean.valueOf(value));
} else {
isAlternativeInitialValue = value;
}
}
public boolean isToBeRegisteredInBeansXML() {
if(registerInBeansXML != null && alternative != null ) {
return alternative.composite.getValue() == Boolean.TRUE && registerInBeansXML.isSelected();
}
return false;
}
public void setScope(String qScopeName) {
String[] tags = scope.getTags();
for (String t: tags) {
String n = scopes.get(t);
if(qScopeName.equals(n)) {
scope.setValue(t);
doStatusUpdate();
return;
}
}
}
protected IStatus packageChanged() {
IStatus result = super.packageChanged();
registerInBeansXML.validate();
return result;
}
protected IStatus typeNameChanged() {
IStatus result = super.typeNameChanged();
registerInBeansXML.validate();
return result;
}
}