/******************************************************************************* * 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 org.eclipse.core.resources.IResource; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.ILocalVariable; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.ISourceReference; import org.eclipse.jdt.core.JavaModelException; import org.jboss.tools.cdi.core.CDICorePlugin; import org.jboss.tools.cdi.core.IBeanMember; import org.jboss.tools.cdi.core.IClassBean; import org.jboss.tools.cdi.internal.core.impl.definition.AbstractMemberDefinition; import org.jboss.tools.cdi.internal.core.impl.definition.BeanMemberDefinition; import org.jboss.tools.common.java.IParametedType; import org.jboss.tools.common.java.ParametedType; import org.jboss.tools.common.java.ParametedTypeFactory; import org.jboss.tools.common.java.TypeDeclaration; import org.jboss.tools.common.java.TypeDeclaration.Lazy; /** * * @author Viacheslav Kabanovich * */ public abstract class BeanMember extends AbstractBeanElement implements IBeanMember { protected IClassBean classBean; protected TypeDeclaration typeDeclaration; public BeanMember() {} @Override public BeanMemberDefinition getDefinition() { return (BeanMemberDefinition)definition; } protected void setMember(IJavaElement member) { typeDeclaration = getTypeDeclaration(getDefinition(), getCDIProject().getNature().getTypeFactory()); } @Override public IJavaElement getSourceElement() { return (IJavaElement)getDefinition().getMember(); } public static TypeDeclaration getTypeDeclaration(final AbstractMemberDefinition definition, ParametedTypeFactory typeFactory) { final IJavaElement member = (IJavaElement)definition.getMember(); try { String returnType = null; IMember currentMember = null; if (member instanceof IField) { returnType = ((IField)member).getTypeSignature(); currentMember = (IMember)member; } else if (member instanceof IMethod) { returnType = ((IMethod)member).getReturnType(); currentMember = (IMember)member; } else if (member instanceof ILocalVariable) { returnType = ((ILocalVariable)member).getTypeSignature(); currentMember = ((ILocalVariable)member).getDeclaringMember(); } if(returnType != null) { ParametedType p = typeFactory.getParametedType(currentMember, returnType); if(p != null) { Lazy lazy = new Lazy() { @Override public void init(TypeDeclaration d) { int offset = -1; int length = 0; String content = definition.getTypeDefinition().getContent(); if(content != null) { ISourceRange sr = null; ISourceRange nr = null; try { sr = ((ISourceReference)member).getSourceRange(); nr = ((ISourceReference)member).getNameRange(); } catch (JavaModelException e) { CDICorePlugin.getDefault().logError(e); } if(sr != null && nr != null && sr.getOffset() < nr.getOffset() && nr.getOffset() < content.length()) { String start = content.substring(sr.getOffset(), nr.getOffset()); int off = -1; int off0 = -1; int bc = 0; for (int i = start.length() - 1; i >= 0; i--) { char ch = start.charAt(i); if(ch == '>') bc++; else if(ch == '<') bc--; if(Character.isWhitespace(ch)) { if(off >= 0 && bc <= 0) break; } else if(Character.isJavaIdentifierPart(ch) || ch == '.' || ch == '$' || ch == '<' || ch == '>') { off = i; if(off0 < 0) off0 = i + 1; } } if(off >= 0) { offset = sr.getOffset() + off; length = off0 - off; } } } d.init(offset, length); } }; return new TypeDeclaration(p, member.getResource(), lazy); } } } catch (JavaModelException e) { CDICorePlugin.getDefault().logError(e); } return null; } /** * These method is used to construct fake members that get all * annotations from this member, but should have another type; * e.g. in implementation of Seam 3 persistence extension. * @param d */ public void setTypeDeclaration(TypeDeclaration typeDeclaration) { this.typeDeclaration = typeDeclaration; } public TypeDeclaration getTypeDeclaration() { return typeDeclaration; } public IClassBean getClassBean() { return classBean; } public void setClassBean(ClassBean classBean) { this.classBean = classBean; setParent(classBean); } public IParametedType getType() { return typeDeclaration; } public IParametedType getMemberType() { return typeDeclaration; } public IResource getResource() { if(definition.getOriginalDefinition() != null) { return definition.getOriginalDefinition().getResource(); } return super.getResource(); } protected ISourceReference getSourceReference() { return getSourceMember(); } protected ISourceRange getSourceRange() { ISourceRange result = null; try { result = getSourceReference().getSourceRange(); } catch (JavaModelException e) { CDICorePlugin.getDefault().logError(e); } return result; } public int getLength() { if(definition.getOriginalDefinition() != null) { return definition.getOriginalDefinition().getLength(); } ISourceRange r = getSourceRange(); return r == null ? 0 : r.getLength(); } public int getStartPosition() { if(definition.getOriginalDefinition() != null) { return definition.getOriginalDefinition().getStartPosition(); } ISourceRange r = getSourceRange(); return r == null ? 0 : r.getOffset(); } public boolean isNullable() { return typeDeclaration == null ? false : !typeDeclaration.isPrimitive(); } }