/*******************************************************************************
* Copyright (c) 2009 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.internal.core.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.texteditor.ITextEditor;
import org.jboss.tools.cdi.core.CDIConstants;
import org.jboss.tools.cdi.core.CDICoreNature;
import org.jboss.tools.cdi.core.CDICorePlugin;
import org.jboss.tools.cdi.core.IBean;
import org.jboss.tools.cdi.core.IInjectionPoint;
import org.jboss.tools.cdi.core.IInterceptorBinding;
import org.jboss.tools.cdi.core.IInterceptorBindingDeclaration;
import org.jboss.tools.cdi.core.IQualifier;
import org.jboss.tools.cdi.core.IQualifierDeclaration;
import org.jboss.tools.cdi.core.IScopeDeclaration;
import org.jboss.tools.cdi.core.IStereotype;
import org.jboss.tools.cdi.core.IStereotypeDeclaration;
import org.jboss.tools.cdi.internal.core.impl.definition.AbstractMemberDefinition;
import org.jboss.tools.cdi.internal.core.impl.definition.AbstractTypeDefinition;
import org.jboss.tools.cdi.internal.core.impl.definition.AnnotationDefinition;
import org.jboss.tools.common.CommonPlugin;
import org.jboss.tools.common.editor.ObjectMultiPageEditor;
import org.jboss.tools.common.java.IAnnotated;
import org.jboss.tools.common.java.IAnnotationDeclaration;
import org.jboss.tools.common.java.IJavaReference;
import org.jboss.tools.common.java.IJavaSourceReference;
import org.jboss.tools.common.java.IParametedType;
import org.jboss.tools.common.java.ITypeDeclaration;
import org.jboss.tools.common.java.ParametedType;
import org.jboss.tools.common.java.TypeDeclaration;
import org.jboss.tools.common.model.ui.editor.EditorPartWrapper;
import org.jboss.tools.common.text.ITextSourceReference;
import org.jboss.tools.common.util.FileUtil;
/**
*
* @author Viacheslav Kabanovich
*
*/
public abstract class AbstractBeanElement extends CDIElement implements IAnnotated {
protected AbstractMemberDefinition definition;
public AbstractBeanElement() {}
@Override
public boolean exists() {
return getDefinition().exists();
}
public void setDefinition(AbstractMemberDefinition definition) {
this.definition = definition;
}
public AbstractMemberDefinition getDefinition() {
return definition;
}
/*
* (non-Javadoc)
* @see org.jboss.tools.cdi.core.IAnnotated#getAnnotations()
*/
public List<IAnnotationDeclaration> getAnnotations() {
if(definition!=null) {
return definition.getAnnotations();
}
return Collections.emptyList();
}
/*
* (non-Javadoc)
* @see org.jboss.tools.cdi.core.IAnnotated#getAnnotation(java.lang.String)
*/
public IAnnotationDeclaration getAnnotation(String annotationTypeName) {
if(definition!=null) {
return definition.getAnnotation(annotationTypeName);
}
return null;
}
/*
* (non-Javadoc)
* @see org.jboss.tools.cdi.core.IAnnotated#getAnnotationPosition(java.lang.String)
*/
public IJavaSourceReference getAnnotationPosition(String annotationTypeName) {
return getAnnotation(annotationTypeName);
}
/*
* (non-Javadoc)
* @see org.jboss.tools.cdi.core.IAnnotated#isAnnotationPresent(java.lang.String)
*/
public boolean isAnnotationPresent(String annotationTypeName) {
return definition!=null && definition.isAnnotationPresent(annotationTypeName);
}
protected AnnotationDeclaration findNamedAnnotation() {
AnnotationDeclaration named = getDefinition().getNamedAnnotation();
if(named != null) return named;
for (IStereotypeDeclaration d: getStereotypeDeclarations(true)) {
StereotypeElement s = (StereotypeElement)d.getStereotype();
if(s != null && s.getNameDeclaration() != null) return s.getNameDeclaration();
}
return null;
}
public boolean isAlternative() {
if(getDefinition().getAlternativeAnnotation() != null) return true;
for (IStereotypeDeclaration d: getStereotypeDeclarations()) {
IStereotype s = d.getStereotype();
if(s != null && s.isAlternative()) return true;
}
return false;
}
public Collection<IStereotypeDeclaration> getStereotypeDeclarations() {
return getStereotypeDeclarations(false);
}
public Collection<IStereotypeDeclaration> getStereotypeDeclarations(boolean includeInherited) {
Set<IStereotypeDeclaration> result = new HashSet<IStereotypeDeclaration>();
Set<IStereotype> ss = new HashSet<IStereotype>();
for (IAnnotationDeclaration d: definition.getAnnotations()) {
if(d instanceof IStereotypeDeclaration) {
IStereotypeDeclaration sd = (IStereotypeDeclaration)d;
result.add(sd);
if(sd.getStereotype() != null) ss.add(sd.getStereotype());
}
}
Set<IStereotypeDeclaration> delta1 = result;
Set<IStereotypeDeclaration> delta2 = new HashSet<IStereotypeDeclaration>();
while(!delta1.isEmpty()) {
for (IStereotypeDeclaration d: delta1) {
IStereotype s = d.getStereotype();
if(s == null) continue;
for (IStereotypeDeclaration d1: s.getStereotypeDeclarations()) {
if(d1.getStereotype() != null) {
if(!result.contains(d1) && !delta2.contains(d1)) delta2.add(d1);
}
}
}
if(delta2.isEmpty()) break;
for (IStereotypeDeclaration d: delta2) {
result.add(d);
if(d.getStereotype() != null) ss.add(d.getStereotype());
}
delta1 = delta2;
delta2 = new HashSet<IStereotypeDeclaration>();
}
if(includeInherited) {
Set<IStereotypeDeclaration> ds = getInheritedStereotypDeclarations();
for (IStereotypeDeclaration d : ds) {
if (d.getStereotype() != null && !ss.contains(d.getStereotype())) {
result.add(d);
}
}
}
return result;
}
public Set<IStereotypeDeclaration> getInheritedStereotypDeclarations() {
return Collections.emptySet();
}
public Collection<IQualifierDeclaration> getQualifierDeclarations() {
return getQualifierDeclarations(false);
}
public Collection<IQualifierDeclaration> getQualifierDeclarations(boolean includeInherited) {
Collection<IQualifierDeclaration> result = new ArrayList<IQualifierDeclaration>();
Set<IQualifier> qs = new HashSet<IQualifier>();
for(IAnnotationDeclaration a: definition.getAnnotations()) {
if(a instanceof IQualifierDeclaration) {
IQualifierDeclaration q = (IQualifierDeclaration)a;
result.add(q);
if(q.getQualifier() != null) qs.add(q.getQualifier());
}
}
if(includeInherited) {
for (IQualifierDeclaration d : getInheritedQualifierDeclarations()) {
if (d.getQualifier() != null && !qs.contains(d.getQualifier())) {
result.add(d);
}
}
// JBIDE-11623 @Named in stereotype is not used as a bean qualifier.
// Do not add it to the qualifier list.
}
return result;
}
protected Collection<IQualifierDeclaration> getInheritedQualifierDeclarations() {
return Collections.emptyList();
}
protected Collection<IInterceptorBindingDeclaration> getInheritedInterceptorBindingDeclarations() {
return Collections.emptyList();
}
public Collection<IQualifier> getQualifiers() {
IQualifier any = getCDIProject().getQualifier(CDIConstants.ANY_QUALIFIER_TYPE_NAME);
IQualifier def = getCDIProject().getQualifier(CDIConstants.DEFAULT_QUALIFIER_TYPE_NAME);
IQualifier name = getCDIProject().getQualifier(CDIConstants.NAMED_QUALIFIER_TYPE_NAME);
Set<IQualifier> result = new HashSet<IQualifier>();
for (IQualifierDeclaration d: getQualifierDeclarations(true)) {
IQualifier q = d.getQualifier();
if(q != null) result.add(q);
}
if(this instanceof IInjectionPoint) {
if(def != null && result.isEmpty()) {
result.add(def);
}
} else if(this instanceof IBean) {
if(def != null) {
if(result.isEmpty() || (name != null && result.size() == 1 && result.contains(name))) {
result.add(def);
}
}
if(any != null) result.add(any);
}
return result;
}
/*
* (non-Javadoc)
* @see org.jboss.tools.cdi.core.IClassBean#getInterceptorBindingDeclarations()
*/
public Collection<IInterceptorBindingDeclaration> getInterceptorBindingDeclarations(boolean includeInherited) {
Collection<IInterceptorBindingDeclaration> result = ClassBean.getInterceptorBindingDeclarations(definition);
if(includeInherited) {
Set<IInterceptorBinding> qs = new HashSet<IInterceptorBinding>();
for (IInterceptorBindingDeclaration d: result) {
if(d.getInterceptorBinding() != null) qs.add(d.getInterceptorBinding());
}
for (IInterceptorBindingDeclaration d : getInheritedInterceptorBindingDeclarations()) {
if (d.getInterceptorBinding() != null && !qs.contains(d.getInterceptorBinding())) {
result.add(d);
}
}
}
return result;
}
public Collection<IScopeDeclaration> getScopeDeclarations() {
return getScopeDeclarations(getCDIProject().getNature(), definition.getAnnotations());
}
public static Collection<IScopeDeclaration> getScopeDeclarations(CDICoreNature n, List<? extends IAnnotationDeclaration> ds) {
Collection<IScopeDeclaration> result = new ArrayList<IScopeDeclaration>(1);
for (IAnnotationDeclaration d: ds) {
int k = n.getDefinitions().getAnnotationKind(d.getType());
if(k > 0 && (k & AnnotationDefinition.SCOPE) > 0 && d instanceof IScopeDeclaration) {
result.add((IScopeDeclaration)d);
}
}
return result;
}
public Collection<ITypeDeclaration> getRestrictedTypeDeclarations(Collection<IParametedType> alltypes) {
AnnotationDeclaration typed = getDefinition().getTypedAnnotation();
if(typed == null) {
return new ArrayList<ITypeDeclaration>(0);
}
Map<String, IParametedType> map = new HashMap<String, IParametedType>();
for (IParametedType t: alltypes) {
map.put(t.getType().getFullyQualifiedName(), t);
}
Collection<ITypeDeclaration> result = new ArrayList<ITypeDeclaration>();
int s = typed.getStartPosition();
int l = typed.getLength();
try {
String txt = null;
if(s >= 0 && typed.getResource() instanceof IFile) {
AbstractTypeDefinition td = getDefinition().getTypeDefinition();
if(getDefinition().getOriginalDefinition() != null) {
ITextSourceReference r = getDefinition().getOriginalDefinition();
String content = FileUtil.readStream((IFile)r.getResource());
if(content != null && content.length() > s + l) {
txt = content.substring(s);
}
} else if(td != null) {
String content = td.getContent();
if(content != null && content.length() > s + l) {
txt = content.substring(s, s + l);
}
}
}
Object value = typed.getMemberValue(null);
if(value == null) return result;
IMember member = (IMember)definition.getMember();
IType declaringType = member instanceof IType ? (IType)member : member.getDeclaringType();
if(value instanceof Object[]) {
Object[] os = (Object[])value;
for (int i = 0; i < os.length; i++) {
String rawTypeName = os[i].toString();
String typeName = rawTypeName;
if(!typeName.endsWith(";")) typeName = "Q" + typeName + ";";
ParametedType p = getCDIProject().getNature().getTypeFactory().getParametedType(declaringType, typeName);
if(p != null) {
int offset = 0;
int length = 0;
if(txt != null) {
int q = txt.indexOf(rawTypeName);
if(q >= 0) {
offset = s + q;
length = rawTypeName.length();
}
}
IParametedType other = p.getType() == null ? null : map.get(p.getType().getFullyQualifiedName());
if(other != null) {
String s1 = p.getSignature();
String s2 = other.getSignature();
if(!s1.equals(s2) && Signature.getArrayCount(s1) == Signature.getArrayCount(s2)) {
p.setSignature(s2);
}
result.add(new TypeDeclaration((ParametedType)other, typed.getResource(), offset, length));
} else {
result.add(new TypeDeclaration(p, typed.getResource(), offset, length));
}
}
}
} else if(value != null) {
String rawTypeName = value.toString();
String typeName = rawTypeName;
if(!typeName.endsWith(";")) typeName = "Q" + typeName + ";";
ParametedType p = getCDIProject().getNature().getTypeFactory().getParametedType(declaringType, typeName);
if(p != null) {
int offset = 0;
int length = 0;
if(txt != null) {
int q = txt.indexOf(rawTypeName);
if(q >= 0) {
offset = s + q;
length = rawTypeName.length();
}
}
IParametedType other = p.getType() == null ? null : map.get(p.getType().getFullyQualifiedName());
if(other != null) {
String s1 = p.getSignature();
String s2 = other.getSignature();
if(!s1.equals(s2) && Signature.getArrayCount(s1) == Signature.getArrayCount(s2)) {
p.setSignature(s2);
}
result.add(new TypeDeclaration((ParametedType)other, typed.getResource(), offset, length));
} else {
result.add(new TypeDeclaration(p, typed.getResource(), offset, length));
}
}
}
} catch (CoreException e) {
CDICorePlugin.getDefault().logError(e);
}
return result;
}
public void open() {
if(getDefinition().getOriginalDefinition() != null) {
IEditorPart part = null;
ITextSourceReference source = getDefinition().getOriginalDefinition();
IFile resource = (IFile)source.getResource();
IWorkbenchWindow window = CDICorePlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
if (window == null) return;
IWorkbenchPage page = window.getActivePage();
try {
part = IDE.openEditor(page, resource);
} catch (PartInitException e) {
CDICorePlugin.getDefault().logError(e);
}
if(part instanceof EditorPartWrapper) {
part = ((EditorPartWrapper)part).getEditor();
}
if(part instanceof ObjectMultiPageEditor) {
ObjectMultiPageEditor mpe = (ObjectMultiPageEditor)part;
ITextEditor textEditor = (ITextEditor)mpe.getAdapter(ITextEditor.class);
if(textEditor != null) {
mpe.setActiveEditor(textEditor);
part = textEditor;
}
}
if(part != null) {
part.getEditorSite().getSelectionProvider().setSelection(new TextSelection(source.getStartPosition(), source.getLength()));
}
} else if (this instanceof IJavaReference) {
IMember member = ((IJavaReference)this).getSourceMember();
try {
JavaUI.openInEditor(member);
} catch (PartInitException e) {
CommonPlugin.getDefault().logError(e);
} catch (JavaModelException e) {
CommonPlugin.getDefault().logError(e);
}
}
}
}