| /******************************************************************************* |
| * Copyright (c) 2008 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: |
| * Matthias Fuessel -- extracted from https://bugs.eclipse.org/bugs/show_bug.cgi?id=215461 |
| * Cameron Bateman/Oracle - integrated. |
| * |
| ********************************************************************************/ |
| |
| package org.eclipse.jst.jsf.context.symbol; |
| |
| import java.util.Arrays; |
| import java.util.Collections; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IType; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.Signature; |
| import org.eclipse.jst.jsf.common.internal.types.TypeConstants; |
| import org.eclipse.jst.jsf.common.internal.types.ValueType; |
| import org.eclipse.jst.jsf.common.util.TypeUtil; |
| |
| /** |
| * Creates purpose-built symbols and descriptors fully initialized (unlike the |
| * EMF factory that simply creates empty instances. |
| * |
| * This class is for convenience only and should not do anything that clients |
| * could not do by hand (though with more work). |
| * |
| * Clients may use or subclass. |
| * |
| * @author cbateman |
| * |
| */ |
| public class InitializedSymbolFactory |
| { |
| /** |
| * If fullyQualifiedClass can be resolved to an IType, then a bean instance |
| * symbol will be created. If the type cannot be resolved, then |
| * createUnknownInstanceSymbol is called with the type descriptor on the |
| * returned symbol forced to fullyQualifiedClass. |
| * |
| * @param project |
| * @param fullyQualifiedClass |
| * @param symbolName |
| * @param source |
| * @return a symbol |
| */ |
| public final ISymbol createBeanOrUnknownInstanceSymbol( |
| final IProject project, final String fullyQualifiedClass, |
| final String symbolName, final ERuntimeSource source) |
| { |
| final IJavaProject javaProject = JavaCore.create(project); |
| try |
| { |
| final IType type = javaProject.findType(fullyQualifiedClass); |
| |
| // TODO: this is a high-bred since it consists of a java instance |
| // but also has properties we can populate at designtime such as |
| // the maps. Need to add the second part |
| if (type != null) |
| { |
| final IJavaTypeDescriptor2 typeDesc = SymbolFactory.eINSTANCE |
| .createIJavaTypeDescriptor2(); |
| typeDesc.setType(type); |
| final IBeanInstanceSymbol facesContextVar = SymbolFactory.eINSTANCE |
| .createIBeanInstanceSymbol(); |
| facesContextVar.setTypeDescriptor(typeDesc); |
| facesContextVar.setName(symbolName); |
| facesContextVar.setRuntimeSource(source); |
| return facesContextVar; |
| } |
| } |
| catch (final JavaModelException jme) |
| { |
| // fall-through and fail with unresolved map |
| } |
| |
| final ISymbol symbol = createUnknownInstanceSymbol(symbolName, source); |
| ((IInstanceSymbol) symbol) |
| .getTypeDescriptor() |
| .setTypeSignatureDelegate( |
| Signature |
| .createTypeSignature(fullyQualifiedClass, true)); |
| |
| return symbol; |
| } |
| |
| /** |
| * @param symbolName |
| * @param source |
| * @return a symbol for a variable of unknown type |
| */ |
| public final IComponentSymbol createUnknownComponentSymbol( |
| final String symbolName, final ERuntimeSource source) |
| { |
| final IComponentSymbol symbol = SymbolFactory.eINSTANCE |
| .createIComponentSymbol(); |
| populateUnknownInstanceSymbol(symbol, symbolName, source); |
| return symbol; |
| } |
| |
| /** |
| * @param symbolName |
| * @param source |
| * @return the unknown instance symbol as an IInstanceSymbol |
| */ |
| public final IInstanceSymbol createUnknownInstanceSymbol( |
| final String symbolName, final ERuntimeSource source) |
| { |
| final IInstanceSymbol symbol = SymbolFactory.eINSTANCE |
| .createIInstanceSymbol(); |
| populateUnknownInstanceSymbol(symbol, symbolName, source); |
| return symbol; |
| } |
| |
| /** |
| * @param name |
| * may NOT be null. |
| * @param typeDesc |
| * may NOT be null. |
| * @param description |
| * may be null |
| * @return a component symbol using the java type descriptor |
| * @throws IllegalArgumentException |
| * if non-null argument is null |
| */ |
| public final IComponentSymbol createJavaComponentSymbol(final String name, |
| final IJavaTypeDescriptor2 typeDesc, final String description) |
| { |
| if (name == null || typeDesc == null) |
| { |
| throw new IllegalArgumentException( |
| "name and typeDesc must not be null"); |
| } |
| |
| final IComponentSymbol symbol = SymbolFactory.eINSTANCE |
| .createIComponentSymbol(); |
| symbol.setName(name); |
| symbol.setTypeDescriptor(typeDesc); |
| symbol.setRuntimeSource(ERuntimeSource.TAG_INSTANTIATED_SYMBOL_LITERAL); |
| return symbol; |
| } |
| |
| /** |
| * @param name |
| * @param valueType |
| * @param description |
| * @param javaProject |
| * @return an IComponentSymbol that uses valueType to derive the type |
| * of its type descriptor |
| */ |
| public final IComponentSymbol createJavaComponentSymbol(final String name, |
| final ValueType valueType, final String description, |
| final IJavaProject javaProject) |
| { |
| final IJavaTypeDescriptor2 typeDesc = createTypeDescriptorFromSignature( |
| valueType.getSignature(), javaProject); |
| return createJavaComponentSymbol(name, typeDesc, description); |
| } |
| |
| private void populateUnknownInstanceSymbol(final IInstanceSymbol symbol, |
| final String symbolName, final ERuntimeSource source) |
| { |
| final IMapTypeDescriptor typeDesc = SymbolFactory.eINSTANCE |
| .createIBoundedMapTypeDescriptor(); |
| // empty map source |
| typeDesc.setMapSource(Collections.emptyMap()); |
| symbol.setName(symbolName); |
| symbol.setTypeDescriptor(typeDesc); |
| symbol.setRuntimeSource(source); |
| } |
| |
| /** |
| * @param type |
| * @return the signature of the element type of a collection/array, |
| * <code>null</code>, if untyped Collection or no container type |
| * at all. |
| */ |
| public final String getElementSignatureFromContainerType(ValueType type) |
| { |
| if (type.isArray()) |
| { |
| // TODO full signature |
| String signature = type.getSignature(); |
| int arrayCount = Signature.getArrayCount(signature); |
| String elementSig = Signature.getElementType(signature); |
| return Signature.createArraySignature(elementSig, arrayCount - 1); |
| } |
| if (type.isInstanceOf(TypeConstants.TYPE_COLLECTION)) |
| { |
| final String[] typeArguments = type.getTypeArguments(); |
| if (typeArguments.length > 0) |
| { |
| return typeArguments[0]; |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * @param signature |
| * @param javaProject |
| * @return a java type descriptor based on the fully qualified type |
| * specified by signature using javaProject as the lookup classpath. |
| * If the IType for signature cannot be found, the descriptor's |
| * typeSignatureDelegate will be used. |
| */ |
| public final IJavaTypeDescriptor2 createTypeDescriptorFromSignature( |
| final String signature, final IJavaProject javaProject) |
| { |
| final String elementType = Signature.getElementType(signature); |
| |
| IJavaTypeDescriptor2 desc = SymbolFactory.eINSTANCE |
| .createIJavaTypeDescriptor2(); |
| final int arrayCount = Signature.getArrayCount(signature); |
| if (arrayCount > 0) |
| { |
| desc.setArrayCount(arrayCount); |
| } |
| |
| IType type = TypeUtil.resolveType(javaProject, elementType); |
| if (type != null) |
| { |
| desc.setType(type); |
| } |
| else |
| { |
| desc.setTypeSignatureDelegate(Signature.getTypeErasure(signature)); |
| } |
| desc.getTypeParameterSignatures().addAll( |
| Arrays.asList(Signature.getTypeArguments(signature))); |
| return desc; |
| } |
| } |