/******************************************************************************* * Copyright (c) 2011 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.seam.config.core.util; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.IMember; 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.jboss.tools.cdi.core.CDICoreNature; import org.jboss.tools.cdi.core.IRootDefinitionContext; import org.jboss.tools.cdi.seam.config.core.CDISeamConfigConstants; import org.jboss.tools.cdi.seam.config.core.definition.SeamMethodDefinition; import org.jboss.tools.cdi.seam.config.core.definition.SeamParameterDefinition; import org.jboss.tools.cdi.seam.config.core.xml.SAXElement; import org.jboss.tools.cdi.seam.config.core.xml.SAXText; import org.jboss.tools.common.java.IParametedType; /** * * @author Viacheslav Kabanovich * */ public class Util implements CDISeamConfigConstants { public static Map<String, String> EE_TYPES = new HashMap<String, String>(); public static Map<String, String> EE_TYPES_30 = new HashMap<String, String>(); static { EE_TYPES.put("int", "java.lang.Integer"); EE_TYPES.put("short", "java.lang.Short"); EE_TYPES.put("long", "java.lang.Long"); EE_TYPES.put("char", "java.lang.Character"); EE_TYPES.put("byte", "java.lang.Byte"); EE_TYPES.put("boolean", "java.lang.Boolean"); EE_TYPES.put("double", "java.lang.Double"); EE_TYPES.put("float", "java.lang.Float"); String[] JAVA_LANG = {"Integer", "Short", "Long", "String", "Character", "Byte", "Boolean", "Double", "Float"}; for (String s: JAVA_LANG) EE_TYPES.put(s, "java.lang." + s); String[] JAVA_UTIL = {"List", "Map", "Set"}; for (String s: JAVA_UTIL) EE_TYPES.put(s, "java.util." + s); String[] JAVAX_ANNOTATION = {"Generated", "PostConstruct", "PreDestroy", "Resource", "Resources"}; for (String s: JAVAX_ANNOTATION) EE_TYPES.put(s, "javax.annotation." + s); String[] JAVAX_INJECT = {"Inject", "Named", "Provider", "Qualifier", "Scope", "Singleton"}; for (String s: JAVAX_INJECT) EE_TYPES.put(s, "javax.inject." + s); String[] JAVAX_ENTERPRISE_INJECT = {"Alternative", "AmbiguousResolutionException", "Any", "CreationException", "Default", "Disposes", "IllegalProductException", "InjectionException", "Instance", "Model", "New", "Produces", "ResolutionException", "Specializes", "Stereotype", "Typed", "UnproxyableResolutionException", "UnsatisfiedResolutionException"}; for (String s: JAVAX_ENTERPRISE_INJECT) EE_TYPES.put(s, "javax.enterprise.inject." + s); String[] JAVAX_ENTERPRISE_CONTEXT = {"ApplicationScoped", "BusyConversationException", "ContextException", "ContextNotActiveException", "Conversation", "ConversationScoped", "Dependent", "NonexistentConversationException", "NormalScope", "RequestScoped", "SessionScoped"}; for (String s: JAVAX_ENTERPRISE_CONTEXT) EE_TYPES.put(s, "javax.enterprise.context." + s); String[] JAVAX_ENTERPRISE_EVENT = {"Event", "ObserverException", "Observes", "Reception", "TransactionPhase"}; for (String s: JAVAX_ENTERPRISE_EVENT) EE_TYPES.put(s, "javax.enterprise.event." + s); String[] JAVAX_DECORAROR = {"Decorator", "Delegate"}; for (String s: JAVAX_DECORAROR) EE_TYPES.put(s, "javax.decorator." + s); String[] JAVAX_INTERCEPTOR = {"AroundInvoke", "AroundTimeout", "ExcludeClassInterceptors", "ExcludeDefaultInterceptors", "Interceptor", "InterceptorBinding", "Interceptors", "InvocationContext"}; for (String s: JAVAX_INTERCEPTOR) EE_TYPES.put(s, "javax.interceptor." + s); //It is not clear. // In Seam3 doc, item 6.7. Overriding the type of an injection point is devoted to @Exact, // but item 6.1 does not mentions its package in namespace urn:java:ee. String[] SEAM_SOLDER = {"Exact"}; for (String s: SEAM_SOLDER) { EE_TYPES.put(s, "org.jboss.solder.core." + s); EE_TYPES_30.put(s, "org.jboss.seam.solder.core." + s); } } public static boolean isConfigRelevant(SAXElement element) { String uri = element.getURI(); return (uri != null && uri.startsWith(CDISeamConfigConstants.URI_PREFIX)); } public static IType resolveType(SAXElement element, CDICoreNature project) { return resolveType(element.getLocalName(), element.getURI(), project); } public static IType resolveType(String name, String uri, CDICoreNature project) { if(uri == null || !uri.startsWith(CDISeamConfigConstants.URI_PREFIX)) { return null; } String[] packages = getPackages(uri); for (String pkg: packages) { if(pkg.length() == 0) continue; IType type = null; if(pkg.equals(PACKAGE_EE)) { type = project.getType(Util.EE_TYPES.get(name)); if(type == null) { type = project.getType(Util.EE_TYPES_30.get(name)); } } else { type = project.getType(pkg + "." + name); } if(type != null) { return type; } } return null; } /** * Computes possible type names that could resolve type for the element, * if one of these types existed. * Returns empty set if a) element has no prefix, b) uri is not urn:java:, * c) package is 'ee'. * * @param element * @return */ public static Set<String> getPossibleTypeNames(SAXElement element) { Set<String> result = new HashSet<String>(); String name = element.getLocalName(); String uri = element.getURI(); if(uri != null && uri.startsWith(CDISeamConfigConstants.URI_PREFIX)) { String[] packages = getPackages(uri); for (String pkg: packages) { if(pkg.length() > 0 && !pkg.equals(PACKAGE_EE)) { result.add(pkg + "." + name); } } } return result; } public static IMember resolveMember(IType type, SAXElement element) throws JavaModelException { String name = element.getLocalName(); IField f = type.getField(name); if(f != null && f.exists() && !hasParametersOrArrayChild(element)) { return f; } IMethod[] ms = type.getMethods(); for (IMethod m: ms) { if(name.equals(m.getElementName())) { //that is only a preliminary resolving. Exact method will be found on loading parameters. return m; } } return null; } public static String[] getPackages(String uri) { if(uri == null || !uri.startsWith(CDISeamConfigConstants.URI_PREFIX)) { return new String[0]; } uri = uri.substring(CDISeamConfigConstants.URI_PREFIX.length()); return uri.split(":"); } public static boolean containsEEPackage(SAXElement element) { return containsEEPackage(element.getURI()); } public static boolean containsEEPackage(String uri) { String[] ps = getPackages(uri); for (String p: ps) if(CDISeamConfigConstants.PACKAGE_EE.equals(p)) { return true; } return false; } public static boolean isArray(SAXElement element) { return isKeyword(element, KEYWORD_ARRAY); } public static boolean isEntry(SAXElement element) { return isKeyword(element, KEYWORD_ENTRY, KEYWORD_E); } public static boolean isKey(SAXElement element) { return isKeyword(element, KEYWORD_KEY, KEYWORD_K); } public static boolean isValue(SAXElement element) { return isKeyword(element, KEYWORD_VALUE, KEYWORD_V); } public static boolean isParameters(SAXElement element) { return isKeyword(element, KEYWORD_PARAMETERS); } public static boolean isKeyword(SAXElement element, String keyword) { return keyword.equals(element.getLocalName()) && containsEEPackage(element); } public static boolean isKeyword(SAXElement element, String keyword1, String keyword2) { String n = element.getLocalName(); return (keyword1.equals(n) || keyword2.equals(n)) && containsEEPackage(element); } public static boolean hasText(SAXElement element) { SAXText t = element.getTextNode(); return t != null && t.getValue() != null && t.getValue().trim().length() > 0; } public static boolean hasProducesChild(SAXElement element) { List<SAXElement> cs = element.getChildElements(); for (SAXElement c: cs) { if(containsEEPackage(c) && "Produces".equals(c.getLocalName())) { return true; } } return false; } public static boolean hasParametersOrArrayChild(SAXElement element) { List<SAXElement> cs = element.getChildElements(); for (SAXElement c: cs) { if(isParameters(c) || isArray(c)) return true; } return false; } /** * * @param def * @param type * @param name method name or null for constructor * @return */ public static IMethod findMethod(SeamMethodDefinition def, IType type, String name, IRootDefinitionContext context) throws JavaModelException { IMethod[] ms = type.getMethods(); for (IMethod m: ms) { if((name == null && m.isConstructor()) || (name != null && name.equals(m.getElementName()))) { if(sameParameterTypes(def, m, context)) return m; } } return null; } static boolean sameParameterTypes(SeamMethodDefinition def, IMethod m, IRootDefinitionContext context) throws JavaModelException { String[] paramTypes = m.getParameterTypes(); if(paramTypes.length != def.getParameters().size()) return false; if(paramTypes.length == 0) return true; for (int i = 0; i < paramTypes.length; i++) { String paramType = paramTypes[i]; SeamParameterDefinition p = def.getParameters().get(i); if(p.getDimensions() != Signature.getArrayCount(paramType)) { return false; } IParametedType pt = context.getProject().getTypeFactory().getParametedType(m, paramType); if(pt == null || p.getType() == null) return false; if(!pt.getType().getFullyQualifiedName().equals(p.getType().getFullyQualifiedName())) return false; } return true; } }