blob: dde647c919d32285050ea0f373a1f96be2e0d40a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 Oracle Corporation.
* 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
*
* Contributors:
* Cameron Bateman/Oracle - initial API and implementation
*
********************************************************************************/
package org.eclipse.jst.jsf.context.symbol.internal.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jst.jsf.common.JSFCommonPlugin;
import org.eclipse.jst.jsf.common.internal.types.TypeInfoCache;
import org.eclipse.jst.jsf.common.util.JDTBeanIntrospector;
import org.eclipse.jst.jsf.common.util.JDTBeanProperty;
import org.eclipse.jst.jsf.common.util.TypeUtil;
import org.eclipse.jst.jsf.context.symbol.IBeanMethodSymbol;
import org.eclipse.jst.jsf.context.symbol.IBeanPropertySymbol;
import org.eclipse.jst.jsf.context.symbol.IJavaTypeDescriptor2;
import org.eclipse.jst.jsf.context.symbol.IObjectSymbol;
import org.eclipse.jst.jsf.context.symbol.IPropertySymbol;
import org.eclipse.jst.jsf.context.symbol.SymbolFactory;
import org.eclipse.jst.jsf.context.symbol.SymbolPackage;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>IJava Type Descriptor2</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* <ul>
* <li>{@link org.eclipse.jst.jsf.context.symbol.internal.impl.IJavaTypeDescriptor2Impl#getType <em>Type</em>}</li>
* <li>{@link org.eclipse.jst.jsf.context.symbol.internal.impl.IJavaTypeDescriptor2Impl#getBeanProperties <em>Bean Properties</em>}</li>
* <li>{@link org.eclipse.jst.jsf.context.symbol.internal.impl.IJavaTypeDescriptor2Impl#getBeanMethods <em>Bean Methods</em>}</li>
* <li>{@link org.eclipse.jst.jsf.context.symbol.internal.impl.IJavaTypeDescriptor2Impl#getArrayCount <em>Array Count</em>}</li>
* </ul>
* </p>
*
* @generated
*/
public class IJavaTypeDescriptor2Impl extends ITypeDescriptorImpl implements IJavaTypeDescriptor2 {
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@SuppressWarnings("hiding")
public static final String copyright = "Copyright 2006 Oracle"; //$NON-NLS-1$
/**
* The default value of the '{@link #getType() <em>Type</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getType()
* @generated
* @ordered
*/
protected static final IType TYPE_EDEFAULT = null;
/**
* The cached value of the '{@link #getType() <em>Type</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getType()
* @generated
* @ordered
*/
protected IType type = TYPE_EDEFAULT;
/**
* The default value of the '{@link #getArrayCount() <em>Array Count</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getArrayCount()
* @generated
* @ordered
*/
protected static final int ARRAY_COUNT_EDEFAULT = 0;
/**
* The cached value of the '{@link #getArrayCount() <em>Array Count</em>}' attribute.
* <!-- begin-user-doc -->
* records the array nesting of the type. IType doesn't encapsulate
* array types. So if this type is an array then type will represent
* the base element and this value will be > 0. If not an array, then
* _arrayCount is always 0.
* <!-- end-user-doc -->
* @see #getArrayCount()
* @generated
* @ordered
*/
protected int arrayCount = ARRAY_COUNT_EDEFAULT;
/**
* The default value of the '{@link #getJdtContext() <em>Jdt Context</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getJdtContext()
* @generated
* @ordered
*/
@SuppressWarnings("hiding")
protected static final IJavaElement JDT_CONTEXT_EDEFAULT = null;
/**
* The cached value of the '{@link #getJdtContext() <em>Jdt Context</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getJdtContext()
* @generated
* @ordered
*/
@SuppressWarnings("hiding")
protected IJavaElement jdtContext = JDT_CONTEXT_EDEFAULT;
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected IJavaTypeDescriptor2Impl() {
super();
}
/**
* <!-- begin-user-doc -->
* @return the static class
* <!-- end-user-doc -->
* @generated
*/
protected EClass eStaticClass() {
return SymbolPackage.Literals.IJAVA_TYPE_DESCRIPTOR2;
}
/**
* <!-- begin-user-doc -->
* @return the JDT type descriptor; if type is an array then this type
* represent's the array base type only
* <!-- end-user-doc -->
* @generated
*/
public IType getType() {
return type;
}
/**
* <!-- begin-user-doc -->
* @param newType
* <!-- end-user-doc -->
* @generated
*/
public void setType(IType newType) {
IType oldType = type;
type = newType;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE, oldType, type));
}
/**
* @see org.eclipse.jst.jsf.context.symbol.internal.impl.ITypeDescriptorImpl#getInterfaceTypeSignatures()
* @generated NOT
*/
public EList getInterfaceTypeSignatures()
{
EList interfaces = new BasicEList();
IType type_ = getType();
if (type_ != null)
{
final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
IType[] interfaceTypes = typeInfoCache.getCachedInterfaceTypes(type_);
if (interfaceTypes == null) {
interfaceTypes = typeInfoCache.cacheInterfaceTypesFor(type_);
}
copySignatures(interfaces, interfaceTypes);
}
return interfaces;
}
/**
* @see org.eclipse.jst.jsf.context.symbol.internal.impl.ITypeDescriptorImpl#getSuperTypeSignatures()
* @generated NOT
*/
public EList getSuperTypeSignatures()
{
EList interfaces = new BasicEList();
IType type_ = getType();
if (type_ != null)
{
final TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
IType[] interfaceTypes = typeInfoCache.getCachedSupertypes(type_);
if (interfaceTypes == null)
{
interfaceTypes = typeInfoCache.cacheSupertypesFor(type_);
}
copySignatures(interfaces, interfaceTypes);
}
return interfaces;
}
private void copySignatures(List list, IType[] types)
{
for (int i = 0; i < types.length; i++)
{
final IType type_ = types[i];
final String signature = TypeUtil.getSignature(type_);
if (signature != null)
{
list.add(signature);
}
}
}
public EList getProperties()
{
return getBeanProperties();
}
public EList getMethods()
{
return getBeanMethods();
}
/**
* <!-- begin-user-doc -->
* @return the bean props for this java type
* <!-- end-user-doc -->
* @generated NOT
*/
public EList getBeanProperties()
{
TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
IBeanPropertySymbol[] properties = typeInfoCache.getCachedPropertySymbols(type);
Collection propertyColl;
if (properties == null) {
propertyColl = getPropertiesInternal();
properties = (IBeanPropertySymbol[]) propertyColl.toArray(new IBeanPropertySymbol[propertyColl.size()]);
typeInfoCache.cachePropertySymbols(type, properties);
}
else
{
propertyColl = new ArrayList(properties.length);
Collections.addAll(propertyColl, (Object[])properties);
}
BasicEList list = new BasicEList(propertyColl);
return list;
}
/**
* <!-- begin-user-doc -->
* @return the bean methods for this type
* <!-- end-user-doc -->
* @generated NOT
*/
public EList getBeanMethods() {
TypeInfoCache typeInfoCache = TypeInfoCache.getInstance();
IBeanMethodSymbol[] methods = typeInfoCache.getCachedMethodSymbols(type);
Collection methodColl;
if (methods == null)
{
methodColl = getMethodsInternal();
methods = (IBeanMethodSymbol[]) methodColl.toArray(new IBeanMethodSymbol[methodColl.size()]);
typeInfoCache.cacheMethodSymbols(type, methods);
} else {
methodColl = new ArrayList(methods.length);
Collections.addAll(methodColl, (Object[])methods);
}
BasicEList list = new BasicEList(methodColl);
return list;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public int getArrayCount() {
return arrayCount;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setArrayCount(int newArrayCount) {
int oldArrayCount = arrayCount;
arrayCount = newArrayCount;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__ARRAY_COUNT, oldArrayCount, arrayCount));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public IJavaElement getJdtContext() {
return jdtContext;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setJdtContext(IJavaElement newJdtContext) {
IJavaElement oldJdtContext = jdtContext;
jdtContext = newJdtContext;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__JDT_CONTEXT, oldJdtContext, jdtContext));
}
/**
* <!-- begin-user-doc -->
*
* Tries to load an IType for a fully resolved (i.e. starts with L not Q)
* type signature using the current jdtContext.
*
* @return the resolved IType or null if none could be resolved.
*
* <!-- end-user-doc -->
* @generated NOT
*/
public IType resolveType(String resolvedTypeSignature)
{
IType resolvedType = null;
// we need to obtain an IJavaProject within which to resolve
// the type.
IJavaProject project = null;
// first, see if we have an IType
if (getType() != null)
{
// optimize: if the type sig is my type sig, then return getType()
if (resolvedTypeSignature.equals(getTypeSignature()))
{
resolvedType = getType();
}
else
{
project = getType().getJavaProject();
if (project != null)
{
resolvedType = TypeUtil.resolveType(project, resolvedTypeSignature);
}
}
}
// if not, see if a jdtContext hint has been set
if (resolvedType == null && getJdtContext() != null)
{
resolvedType = super.resolveType(resolvedTypeSignature);
}
return resolvedType;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public Object eGet(int featureID, boolean resolve, boolean coreType) {
switch (featureID) {
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE:
return getType();
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_PROPERTIES:
return getBeanProperties();
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_METHODS:
return getBeanMethods();
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__ARRAY_COUNT:
return Integer.valueOf(getArrayCount());
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void eSet(int featureID, Object newValue) {
switch (featureID) {
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE:
setType((IType)newValue);
return;
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_PROPERTIES:
getBeanProperties().clear();
getBeanProperties().addAll((Collection)newValue);
return;
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_METHODS:
getBeanMethods().clear();
getBeanMethods().addAll((Collection)newValue);
return;
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__ARRAY_COUNT:
setArrayCount(((Integer)newValue).intValue());
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void eUnset(int featureID) {
switch (featureID) {
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE:
setType(TYPE_EDEFAULT);
return;
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_PROPERTIES:
getBeanProperties().clear();
return;
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_METHODS:
getBeanMethods().clear();
return;
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__ARRAY_COUNT:
setArrayCount(ARRAY_COUNT_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public boolean eIsSet(int featureID) {
switch (featureID) {
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE:
return TYPE_EDEFAULT == null ? type != null : !TYPE_EDEFAULT.equals(type);
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_PROPERTIES:
return !getBeanProperties().isEmpty();
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__BEAN_METHODS:
return !getBeanMethods().isEmpty();
case SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__ARRAY_COUNT:
return arrayCount != ARRAY_COUNT_EDEFAULT;
}
return super.eIsSet(featureID);
}
public boolean isArray()
{
return getArrayCount() > 0;
}
/**
* @generated NOT
*/
public IObjectSymbol getArrayElement()
{
if (isArray())
{
final String typeSignature = getTypeSignature();
final int arrayCount_ = Signature.getArrayCount(typeSignature);
final String baseType = Signature.getElementType(typeSignature);
final String elementTypeSignature = Signature.createArraySignature(baseType, arrayCount_-1);
final IJavaTypeDescriptor2 elementTypeDesc =
SymbolFactory.eINSTANCE.createIJavaTypeDescriptor2();
final String fullyQualifiedElementType = TypeUtil.getFullyQualifiedName(baseType);
IType elementType = null;
try
{
IType myType = getType();
if (myType != null)
{
elementType = getType().getJavaProject()
.findType(fullyQualifiedElementType);
}
}
catch (JavaModelException e)
{
// suppress
}
if (elementType != null)
{
elementTypeDesc.setType(elementType);
}
else
{
elementTypeDesc.setTypeSignatureDelegate(elementTypeSignature);
}
elementTypeDesc.setArrayCount(Signature.getArrayCount(elementTypeSignature));
IPropertySymbol newPropertySymbol =
SymbolFactory.eINSTANCE.createIPropertySymbol();
newPropertySymbol.setTypeDescriptor(elementTypeDesc);
newPropertySymbol.setWritable(true);
newPropertySymbol.setReadable(true);
newPropertySymbol.setName(fullyQualifiedElementType);
return newPropertySymbol;
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jst.jsf.context.symbol.internal.impl.ITypeDescriptorImpl#getTypeSignature()
* @generated NOT
*/
public String getTypeSignature()
{
if (getType() == null)
{
if (eIsSet(SymbolPackage.IJAVA_TYPE_DESCRIPTOR2__TYPE_SIGNATURE_DELEGATE))
{
return getTypeSignatureDelegate();
}
return null;
}
// make sure to array type nesting if using IType
return Signature.createArraySignature(
TypeUtil.getSignature(getType()), getArrayCount());
}
private Collection getPropertiesInternal()
{
// if I'm an array then I have no bean properties
if (isArray())
{
return Collections.EMPTY_LIST;
}
final JDTBeanIntrospector introspector =
new JDTBeanIntrospector(getType());
final Map<String, JDTBeanProperty> properties = introspector.getProperties();
final Collection calculatedProps = new ArrayList(properties.size());
for (final Iterator<Map.Entry<String, JDTBeanProperty>> it = properties.entrySet().iterator(); it.hasNext();)
{
Map.Entry<String, JDTBeanProperty> entry = it.next();
final String propertyName = entry.getKey();
final JDTBeanProperty property = entry.getValue();
final IBeanPropertySymbol workingCopy =
SymbolFactory.eINSTANCE.createIBeanPropertySymbol();
workingCopy.setName(propertyName);
workingCopy.setOwner(this);
final IJavaTypeDescriptor2 workingCopyDesc =
SymbolFactory.eINSTANCE.createIJavaTypeDescriptor2();
workingCopy.setTypeDescriptor(workingCopyDesc);
workingCopy.setReadable(property.isReadable());
workingCopy.setWritable(property.isWritable());
workingCopyDesc.setArrayCount(property.getArrayCount());
workingCopyDesc.getTypeParameterSignatures().addAll(property.getTypeParameterSignatures());
workingCopyDesc.setEnumType(property.isEnumType());
final IType newType = property.getType();
final String signature = property.getTypeSignature();
if (newType != null)
{
workingCopyDesc.setType(newType);
}
else
{
workingCopyDesc.setTypeSignatureDelegate(signature);
}
calculatedProps.add(workingCopy);
}
return calculatedProps;
}
private Collection getMethodsInternal()
{
JDTBeanIntrospector introspector =
new JDTBeanIntrospector(getType());
IMethod[] methods = introspector.getAllMethods();
List methodSymbols = new ArrayList();
for (int i = 0; i < methods.length; i++)
{
IMethod method = methods[i];
try
{
// to be a bean method, it must not a constructor, must be public
// and must not be static
if (!method.isConstructor()
&& Flags.isPublic(method.getFlags())
&& !Flags.isStatic(method.getFlags()))
{
String methodName = method.getElementName();
IBeanMethodSymbol workingCopy = SymbolFactory.eINSTANCE.createIBeanMethodSymbol();
workingCopy.setName(methodName);
workingCopy.setOwner(this);
workingCopy.setSignature(TypeUtil.
resolveMethodSignature
(getType(),
method.getSignature()));
methodSymbols.add(workingCopy);
}
}
catch (JavaModelException jme)
{
// error reading meta-data. Skip to next one
JSFCommonPlugin.log(jme);
}
}
return methodSymbols;
}
/**
* <!-- begin-user-doc -->
* @return the default string rep
* <!-- end-user-doc -->
* @generated
*/
public String toString() {
if (eIsProxy()) return super.toString();
StringBuffer result = new StringBuffer(super.toString());
result.append(" (type: "); //$NON-NLS-1$
result.append(type);
result.append(", arrayCount: "); //$NON-NLS-1$
result.append(arrayCount);
result.append(')');
return result.toString();
}
} //IJavaTypeDescriptor2Impl