/*******************************************************************************
* 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.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.IStatus;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.dialogs.StatusUtil;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Composite;
import org.jboss.tools.cdi.core.CDIConstants;
import org.jboss.tools.cdi.core.CDICorePlugin;
import org.jboss.tools.cdi.core.CDIUtil;
import org.jboss.tools.cdi.core.CDIVersion;
import org.jboss.tools.cdi.core.ICDIAnnotation;
import org.jboss.tools.cdi.core.ICDIProject;
import org.jboss.tools.cdi.core.IStereotype;
import org.jboss.tools.cdi.internal.core.validation.AnnotationValidationDelegate;
import org.jboss.tools.cdi.ui.CDIUIMessages;
import org.jboss.tools.cdi.ui.CDIUIPlugin;
import org.jboss.tools.common.java.IAnnotationDeclaration;
import org.jboss.tools.common.ui.widget.editor.ITaggedFieldEditor;
import org.jboss.tools.common.ui.widget.editor.ListFieldEditor;
/**
*
* @author Viacheslav Kabanovich
*
*/
public class NewStereotypeWizardPage extends NewCDIAnnotationWizardPage {
protected CheckBoxEditorWrapper alternative = null;
protected boolean mayBeRegisteredInBeansXML = true;
protected BeansXMLAccess registerInBeansXML = new BeansXMLAccess(this,"Alternatives", "CDIStereotype", "stereotype");
protected CheckBoxEditorWrapper named = null;
protected ITaggedFieldEditor scope = null;
protected Map<String, String> scopes = new TreeMap<String, String>();
protected StereotypesSelectionProvider stereotypesProvider = new StereotypesSelectionProvider();
protected InterceptorBindingSelectionProvider interceptorBindingsProvider = new InterceptorBindingSelectionProvider();
protected ListFieldEditor stereotypes = null;
protected ListFieldEditor interceptorBindings = null;
boolean isAlternativeInitialValue = false;
protected StatusInfo targetStatus = new StatusInfo();
public NewStereotypeWizardPage() {
setTitle(CDIUIMessages.NEW_STEREOTYPE_WIZARD_PAGE_NAME);
}
public void setMayBeRegisteredInBeansXML(boolean b) {
mayBeRegisteredInBeansXML = b;
}
@Override
protected void addAnnotations(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
addStereotypeAnnotation(imports, sb, lineDelimiter);
addInheritedAnnotation(imports, sb, lineDelimiter);
addAlternativeAnnotation(imports, sb, lineDelimiter);
addScopeAnnotation(imports, sb, lineDelimiter);
addNamedAnnotation(imports, sb, lineDelimiter);
addInterceptorBindingAnnotations(imports, sb, lineDelimiter);
addSuperStereotypeAnnotations(imports, sb, lineDelimiter);
addTargetAnnotation(imports, sb, lineDelimiter, getTargets());
addRetentionAnnotation(imports, sb, lineDelimiter);
addDocumentedAnnotation(imports, sb, lineDelimiter);
}
protected void addStereotypeAnnotation(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
addAnnotation(CDIConstants.STEREOTYPE_ANNOTATION_TYPE_NAME, imports, sb, lineDelimiter);
}
protected void addAlternativeAnnotation(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(alternative != null && alternative.composite.getValue() == Boolean.TRUE) {
addAnnotation(CDIConstants.ALTERNATIVE_ANNOTATION_TYPE_NAME, imports, sb, lineDelimiter);
}
}
protected void addNamedAnnotation(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(named != null && named.composite.getValue() == Boolean.TRUE) {
addAnnotation(CDIConstants.NAMED_QUALIFIER_TYPE_NAME, imports, sb, 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);
addAnnotation(qScopeName, imports, sb, lineDelimiter);
}
}
@SuppressWarnings("unchecked")
protected void addSuperStereotypeAnnotations(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(stereotypes != null) {
List list = (List)stereotypes.getValue();
for (Object o: list) {
if(o instanceof ICDIAnnotation) {
ICDIAnnotation a = (ICDIAnnotation)o;
String typeName = a.getSourceType().getFullyQualifiedName();
addAnnotation(typeName, imports, sb, lineDelimiter);
}
}
}
}
@SuppressWarnings("unchecked")
protected void addInterceptorBindingAnnotations(ImportsManager imports, StringBuffer sb, String lineDelimiter) {
if(interceptorBindings != null) {
List list = (List)interceptorBindings.getValue();
for (Object o: list) {
if(o instanceof ICDIAnnotation) {
ICDIAnnotation a = (ICDIAnnotation)o;
String typeName = a.getSourceType().getFullyQualifiedName();
addAnnotation(typeName, imports, sb, lineDelimiter);
}
}
}
}
@Override
protected void createCustomFields(Composite composite) {
createInheritedField(composite, false);
createAlternativeField(composite);
createRegisterInBeansXML(composite);
createNamedField(composite);
createScopeField(composite);
createTargetField(composite);
createInterceptorBindingField(composite);
createStereotypeField(composite);
}
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 void createNamedField(Composite composite) {
String label = "Add @Named";
named = createCheckBoxField(composite, "isNamed", label, false);
}
protected void createScopeField(Composite composite) {
List<String> vs = new ArrayList<String>();
vs.add("");
scope = createComboField("scope", CDIUIMessages.FIELD_EDITOR_SCOPE_LABEL, composite, vs);
setScopes(getPackageFragmentRoot());
}
String[] CDI_10_TARGETS = {
"TYPE,METHOD,FIELD",
"METHOD,FIELD",
"TYPE",
"METHOD",
"FIELD"
};
String[] CDI_11_TARGETS = {
"",
"TYPE,METHOD,FIELD",
"METHOD,FIELD",
"TYPE",
"METHOD",
"FIELD"
};
protected void createTargetField(Composite composite) {
List<String> targetOptions = new ArrayList<String>();
for (String t: CDI_10_TARGETS) {
targetOptions.add(t);
}
createTargetField(composite, targetOptions);
target.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
validateTargetAndStereotype();
}});
setTargets(getPackageFragmentRoot());
}
protected void createInterceptorBindingField(Composite composite) {
interceptorBindings = new ListFieldEditor("interceptorBindings", CDIUIMessages.FIELD_EDITOR_INTERCEPTOR_BINDINGS_LABEL, new ArrayList<Object>());
interceptorBindings.setProvider(interceptorBindingsProvider);
interceptorBindingsProvider.setEditorField(interceptorBindings);
interceptorBindings.doFillIntoGrid(composite);
setInterceptorBindings(getPackageFragmentRoot());
interceptorBindings.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
Object o = evt.getNewValue();
if(o instanceof List && !((List)o).isEmpty()) {
target.setValue(AnnotationValidationDelegate.TARGET_TYPE);
target.setEnabled(false);
} else {
target.setEnabled(true);
}
}});
}
protected void createStereotypeField(Composite composite) {
stereotypes = new ListFieldEditor("stereotypes", CDIUIMessages.FIELD_EDITOR_STEREOTYPES_LABEL, new ArrayList<Object>());
stereotypes.setProvider(stereotypesProvider);
stereotypesProvider.setEditorField(stereotypes);
stereotypes.doFillIntoGrid(composite);
setStereotypes(getPackageFragmentRoot());
stereotypes.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
validateTargetAndStereotype();
}});
}
@Override
public void setPackageFragmentRoot(IPackageFragmentRoot root, boolean canBeModified) {
super.setPackageFragmentRoot(root, canBeModified);
setScopes(root);
setTargets(root);
}
void setScopes(IPackageFragmentRoot root) {
if(root != null) {
IJavaProject jp = root.getJavaProject();
ICDIProject cdi = getCDIProject(jp);
if(cdi != null) {
setScopes(cdi.getScopeNames().toArray(new String[0]));
} else {
setScopes(new String[]{""});
}
} else {
setScopes(new String[]{""});
}
}
void setTargets(IPackageFragmentRoot root) {
if(target instanceof ITaggedFieldEditor) {
ITaggedFieldEditor f = (ITaggedFieldEditor)target;
boolean cdi10 = true;
String[] currentTargets = f.getTags();
if(root != null) {
IJavaProject jp = root.getJavaProject();
ICDIProject cdi = getCDIProject(jp);
if(cdi != null) {
cdi10 = cdi.getVersion() == CDIVersion.CDI_1_0;
}
}
String[] newTargets = cdi10 ? CDI_10_TARGETS : CDI_11_TARGETS;
if (newTargets.length != currentTargets.length) {
f.setTags(newTargets);
}
if(cdi10 && f.getValueAsString().length() == 0) {
f.setValue(CDI_10_TARGETS[0]);
}
}
}
void setInterceptorBindings(IPackageFragmentRoot root) {
interceptorBindingsProvider.setProject(null);
if(root != null) {
IJavaProject jp = root.getJavaProject();
ICDIProject cdi = getCDIProject(jp);
if(cdi != null) {
interceptorBindingsProvider.setProject(cdi);
}
}
}
void setStereotypes(IPackageFragmentRoot root) {
stereotypesProvider.setProject(null);
if(root != null) {
IJavaProject jp = root.getJavaProject();
ICDIProject cdi = CDICorePlugin.getCDIProject(jp.getProject(), true);
if(cdi != null) stereotypesProvider.setProject(cdi);
}
}
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("");
}
}
public void setNamed(boolean b) {
if(named != null) named.composite.setValue(b);
}
void validateTargetAndStereotype() {
try {
getTargetAndStereotypeError();
} catch (JavaModelException e) {
CDIUIPlugin.getDefault().logError(e);
}
doStatusUpdate();
}
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);
}
@Override
protected void updateStatus(IStatus[] status) {
IStatus[] ns = new IStatus[status.length + 1];
System.arraycopy(status, 0, ns, 0, status.length);
ns[status.length] = targetStatus;
status = ns;
updateStatus(StatusUtil.getMostSevere(status));
}
void getTargetAndStereotypeError() throws JavaModelException {
targetStatus = new StatusInfo();
if(stereotypes != null && target != null) {
String value = (String)target.getValue();
boolean hasMethodOrField = value != null && (value.indexOf(AnnotationValidationDelegate.TARGET_METHOD) >= 0 || value.indexOf(AnnotationValidationDelegate.TARGET_FIELD) >= 0);
List list = (List)stereotypes.getValue();
for (Object o: list) {
if(o instanceof IStereotype) {
IStereotype a = (IStereotype)o;
IAnnotationDeclaration target = a.getAnnotationDeclaration(CDIConstants.TARGET_ANNOTATION_TYPE_NAME);
if(target != null) {
Set<String> targets = CDIUtil.getTargetAnnotationValues(target);
if(targets != null && targets.size() == 1 && targets.contains(AnnotationValidationDelegate.TARGET_TYPE) && hasMethodOrField) {
String message = NLS.bind(CDIUIMessages.MESSAGE_STEREOTYPE_IS_NOT_COMPATIBLE, a.getSourceType().getElementName());
// String message = a.getSourceType().getElementName() + " annotated with @Target({TYPE}) is not compatible with target";
targetStatus.setWarning(message);
}
if(targets != null && !targets.contains(AnnotationValidationDelegate.TARGET_TYPE)) {
String message = NLS.bind(CDIUIMessages.MESSAGE_STEREOTYPE_CANNOT_BE_APPLIED_TO_TYPE, a.getSourceType().getElementName());
targetStatus.setError(message);
return;
}
}
}
}
}
}
public void addStereotype(IStereotype s) {
List vs = (List)stereotypes.getValue();
List nvs = new ArrayList();
if(vs != null) nvs.addAll(vs);
nvs.add(s);
stereotypes.setValue(nvs);
}
public void setAlternative(boolean value) {
if(alternative != null) {
alternative.composite.setValue(Boolean.valueOf(value));
} else {
isAlternativeInitialValue = value;
}
}
public void setToBeRegisteredInBeansXML(boolean value) {
if(registerInBeansXML != null) {
registerInBeansXML.check.composite.setValue(Boolean.valueOf(value));
}
}
public boolean isToBeRegisteredInBeansXML() {
if(registerInBeansXML != null && alternative != null ) {
return alternative.composite.getValue() == Boolean.TRUE && registerInBeansXML.isSelected();
}
return false;
}
@Override
protected IStatus packageChanged() {
IStatus result = super.packageChanged();
registerInBeansXML.validate();
return result;
}
@Override
protected IStatus typeNameChanged() {
IStatus result = super.typeNameChanged();
registerInBeansXML.validate();
return result;
}
}