blob: cb05c1305c1aeceb6a4c91af64693b789387e120 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 2004 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jem.internal.java.adapters;
/*
* $RCSfile: JavaReflectionKey.java,v $
* $Revision: 1.4 $ $Date: 2005/02/15 22:37:02 $
*/
import java.util.*;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.eclipse.jem.java.*;
/**
* This key handles Java Reflection. It creates the appropriate type of entries if
* they are not already in the resource. There is an extension mechanism for other
* types of ids that are not recognized by this key. They are registered with the
* JavaXMIFactory that is used to create these keys, and the factory will pass in
* a List of these registered extension processers (IJavaReflectionKeyExtension).
*
* Creation date: (10/4/2000 8:24:36 AM)
* @author: Administrator
*/
public class JavaReflectionKey {
/* Constants for the primitive type names
* These are the values which are used to refer to a primitive type,
* i.e. new JavaURL("int") or new URL("java://#int")
* These types are cached by pre-loading documents for the primitives,
* in "java://", and for the java.lang (Object and String) classes
*/
static final public String N_VOID = "void"; //$NON-NLS-1$
static final public String N_INT = "int";//$NON-NLS-1$
static final public String N_BOOLEAN = "boolean";//$NON-NLS-1$
static final public String N_CHAR = "char";//$NON-NLS-1$
static final public String N_BYTE = "byte";//$NON-NLS-1$
static final public String N_LONG = "long";//$NON-NLS-1$
static final public String N_FLOAT = "float";//$NON-NLS-1$
static final public String N_DOUBLE = "double";//$NON-NLS-1$
static final public String N_SHORT = "short";//$NON-NLS-1$
private static final Collection PRIMITIVES = new ArrayList(8);
static { initializePrimitivesCollection(); }
protected XMIResource resource; //FB
protected List extensions;
//FB /**
//FB * JavaReflectionKey constructor comment.
//FB */
//FB public JavaReflectionKey() {
//FB super();
//FB }
//FB /**
//FB * Method JavaReflectionKey.
//FB * @param extensions
//FB */
//FB public JavaReflectionKey(List extensions) {
//FB super();
//FB setExtensions(extensions);
//FB }
//FB /**
//FB * Method JavaReflectionKey.
//FB * @param extensions
//FB * @param extent
//FB */
//FB public JavaReflectionKey(List extensions, Extent extent) {
//FB this(extent);
//FB setExtensions(extensions);
//FB }
//FB /**
//FB * JavaReflectionKey constructor comment.
//FB * @param e com.ibm.etools.emf.ref.Extent
//FB */
//FB public JavaReflectionKey(com.ibm.etools.emf.ref.Extent e) {
//FB super(e);
//FB }
//FB /**
//FB * Set the extensions to use. Typically only called by JavaXMIFactoryImpl.
//FB */
//FB public void setExtensions(List extensions) {
//FB this.extensions = extensions;
//FB }
//FB ADDED
public JavaReflectionKey(List extensions, XMIResource resource) {
this.extensions = extensions;
this.resource = resource;
}
//FB END
/*
* Create an ArrayType instance in the current document
* Handles the push and pop of the current document.
*/
public ArrayType createArrayType() {
return getJavaFactory().createArrayType();
}
/*
* Create a JavaClass instance in the current document
* Handles the push and pop of the current document.
*/
public JavaClass createJavaClass() {
return getJavaFactory().createJavaClass();
}
/**
* Create a data type and put it in the primitives resource
*/
protected EClassifier getJavaDataType(String typeName) {
JavaDataType result = getJavaFactory().createJavaDataType();
result.setName(typeName);
// ((InternalEObject)result).eSetID(typeName);
//result.eSetUUID((UUID) null);
//result.setEPackage(getPackage());
getPackage().getEClassifiers().add(result);
resource.setID(result, typeName);
return result;
}
/*
* Create a Field instance in the current document
* Handles the push and pop of the current document.
*/
public Field createJavaField() {
return getJavaFactory().createField();
}
/*
* Create a Method instance in the current document
* Handles the push and pop of the current document.
*/
public Method createJavaMethod() {
return getJavaFactory().createMethod();
}
/*
* Create a JavaParameter instance in the current document
*/
public JavaParameter createJavaParameter() {
return getJavaFactory().createJavaParameter();
}
//FB/**
//FB * Override to try to introspect objects
//FB * that aren't found using the default mechanism.
//FB */
//FBpublic Object get(Object key) {
//FB Object javaObject = super.get(key);
//FB if (javaObject == null) {
//FB javaObject = getObjectFromExtensions((String) key);
//FB if (javaObject == null)
//FB javaObject = getJavaObject((String) key);
//FB }
//FB return javaObject;
//FB}
//FB ADDED
public Object get(String key) {
Object javaObject = getObjectFromExtensions(key);
if (javaObject == null)
javaObject = getJavaObject(key);
return javaObject;
}
//FB END
/*
* Instantiate the named class.
* If we make it to this point, the class has not yet been instantiated or reflected.
*/
public EClassifier getArrayType(String typeName) {
ArrayType arrayType = this.createArrayType();
arrayType.setName(typeName);
// ((InternalEObject)arrayType).eSetID(typeName);
//arrayType.eSetUUID((UUID) null);
int pos = -1, braces = 0;
do {
pos = typeName.indexOf("[", pos+1);//$NON-NLS-1$
if (pos != -1)
braces++;
} while (pos != -1);
arrayType.setArrayDimensions(braces);
//arrayType.setEPackage(getPackage());
getPackage().getEClassifiers().add(arrayType);
resource.setID(arrayType, typeName);
return arrayType;
}
/*
* Instantiate the named class.
* If we make it to this point, teh class has not yet been instantiated or reflected.
*/
public EClassifier getJavaClass(String typeName) {
JavaClass javaClass = this.createJavaClass();
javaClass.setName(typeName);
// ((InternalEObject)javaClass).eSetID(javaClass.getName());
//javaClass.eSetUUID((UUID) null);
// javaClass.setEPackage(getPackage());
getPackage().getEClassifiers().add(javaClass);
resource.setID(javaClass, typeName);
return javaClass;
}
/* Get the Java Factory
*/
protected static JavaRefFactory getJavaFactory() {
return JavaRefFactory.eINSTANCE;
}
/**
* This allows for the direct retrieval of fields with the following notation:
* field: java:/com.ibm.foo#Test.foo
*
*/
protected Field getJavaField(String keyValue) {
Field result = null;
String className, memberName;
int memberDelimiter = keyValue.indexOf(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER);
className = keyValue.substring(0, memberDelimiter);
memberName = keyValue.substring(memberDelimiter + 1);
EClassifier javaClass = (EClassifier) primGet(className);
// if we haven't already instantiated the containing class, then go do it.
if (javaClass == null)
javaClass = getJavaType(className);
if ((javaClass != null) && !((JavaHelpers) javaClass).isPrimitive()) {
// We have a class. Now we need to force reflection, this will cause
// the JavaReflectionKey to be updated and have the member added to the
// list.
((JavaClass) javaClass).getFields();
//FB result = (Field) super.get(keyValue); // It should now be registered.
result = (Field) primGet(keyValue); // It should now be registered.
if (result == null) {
Field tempField = createJavaField();
tempField.setName(memberName);
// ((InternalEObject)tempField).eSetID(keyValue);
//tempField.eSetUUID((UUID) null);
((JavaClass) javaClass).getFields().add(tempField);
result = tempField;
}
}
return result;
}
/**
* This allows for the retrieval of methods with the following notation:
* method: java:/com.ibm.foo#Test.foofoo(
*
*/
protected Method getJavaMethod(String keyValue) {
Method result = null;
String className, memberName;
int memberDelimiter = keyValue.indexOf(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER);
className = keyValue.substring(0, memberDelimiter);
int parmDelimiter = keyValue.indexOf(ReflectionAdaptor.C_METHOD_PARM_DELIMITER, memberDelimiter);
memberName = keyValue.substring(memberDelimiter + 1, parmDelimiter);
EClassifier javaClass = (EClassifier) primGet(className);
// if we haven't already instantiated the containing class, then go do it.
if (javaClass == null)
javaClass = getJavaType(className);
if ((javaClass != null) && !((JavaHelpers) javaClass).isPrimitive()) {
// We have a class. Now we need to force reflection, this will cause
// the JavaReflectionKey to be updated and have the member added to the
// list.
((JavaClass) javaClass).getMethods();
result = (Method) primGet(keyValue); // It should now be registered.
if (result == null) {
Method tempMethod = createJavaMethod();
tempMethod.setName(memberName);
resource.setID(tempMethod, keyValue);
((JavaClass) javaClass).getMethods().add(tempMethod);
result = tempMethod;
}
}
return result;
}
/**
* This allows for the retrieval of attributes/methods with the following notation:
* field: java:/com.ibm.foo#Test.foo
* method: java:/com.ibm.foo#Test.foofoo(
* parameter: java:/com.ibm.foo#Test.foofoo(-arg0
*
*/
public EObject getJavaObject(String keyValue) {
EObject result = null;
int index = keyValue.indexOf(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER);
if (index > 0) {
// The reference is to a member: field, method, or parameter.
// Take the most specific case first, a parameter.
// Only a parameter should contain the methodID to parmID delimiter.
boolean isParameter = (keyValue.indexOf(ReflectionAdaptor.C_METHODID_PARMID_DELIMITER, index) != -1);
if (isParameter) {
result = getJavaParameter(keyValue);
} else {
// The target is a field or method. If it has a "(", then it is a method.
// If it is not found, then we will create a temporary object.
int parmStart = keyValue.indexOf(ReflectionAdaptor.C_METHOD_PARM_DELIMITER, index);
boolean isField = parmStart == -1;
if (isField) {
result = getJavaField(keyValue);
} else {
result = getJavaMethod(keyValue);
}
}
} else {
result = (EObject) getJavaType(keyValue);
}
return result;
}
/**
* See if the extensions can resolve this first.
*/
protected Object getObjectFromExtensions(String keyValue) {
if (extensions != null) {
for (Iterator iter = extensions.iterator(); iter.hasNext();) {
IJavaReflectionKeyExtension extension = (IJavaReflectionKeyExtension) iter.next();
Object obj = extension.getObject(keyValue, this);
if (obj != null)
return obj;
}
}
return null;
}
/**
* This allows for the retrieval of parameters with the following notation:
* parameter: java:/com.ibm.foo#Test.foofoo(-arg0
*
*/
protected JavaParameter getJavaParameter(String keyValue) {
JavaParameter result = null;
String parmName;
int memberDelimiter = keyValue.indexOf(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER);
int parmDelimiter = keyValue.indexOf(ReflectionAdaptor.C_METHODID_PARMID_DELIMITER, memberDelimiter);
parmName = keyValue.substring(parmDelimiter + 1);
// getMethod() will find or create a method
Method method = this.getJavaMethod(keyValue.substring(parmDelimiter));
if (method != null) {
result = method.getParameter(parmName);
if (result == null) {
JavaParameter tempParameter = createJavaParameter();
tempParameter.setName(parmName);
// ((InternalEObject)tempParameter).eSetID(keyValue);
// tempParameter.eSetUUID((UUID) null);
method.getParameters().add(tempParameter);
result = tempParameter;
}
}
return result;
}
/**
* Insert the method's description here.
* Creation date: (10/4/2000 9:52:28 AM)
* @return org.eclipse.emf.ecore.EClassifier
* @param typeName java.lang.String
*/
public EClassifier getJavaType(String typeName) {
if (isPrimitive(typeName))
return getJavaDataType(typeName);
else if (isArray(typeName))
return getArrayType(typeName);
else if (isValidJavaIdentifier(typeName))
return getJavaClass(typeName);
return null;
}
protected boolean isValidJavaIdentifier(String typeName) {
if (typeName.length() > 0) {
if (Character.isJavaIdentifierStart(typeName.charAt(0))) {
// Starts with a valid java identifier character.
// Now see if the rest are valid.
for (int i = 1; i < typeName.length(); i++) {
if (!Character.isJavaIdentifierPart(typeName.charAt(i)))
return false; // Not valid
}
return true;
}
}
return false;
}
/**
* Get the object from the key but don't do any
* tries at creation of the key if not found.
* The Key must be an ID for it to be found.
*/
public Object primGet(String key) {
return resource.getIDToEObjectMap().get(key);
}
protected EPackage getPackage() {
//FB return (EPackage) super.get(JavaPackage.PACKAGE_ID);
// return (EPackage) resource.getEObject(JavaPackage.PACKAGE_ID); //FB
//return (EPackage) resource.getEObject(JavaPackage.PACKAGE_ID); //FB
return (EPackage)EcoreUtil.getObjectByType(resource.getContents(), EcorePackage.eINSTANCE.getEPackage());
}
/**
* Insert the method's description here.
* Creation date: (10/4/2000 9:56:53 AM)
*/
private static void initializePrimitivesCollection() {
PRIMITIVES.add(N_VOID);
PRIMITIVES.add(N_BOOLEAN);
PRIMITIVES.add(N_BYTE);
PRIMITIVES.add(N_CHAR);
PRIMITIVES.add(N_DOUBLE);
PRIMITIVES.add(N_FLOAT);
PRIMITIVES.add(N_INT);
PRIMITIVES.add(N_LONG);
PRIMITIVES.add(N_SHORT);
}
/**
* Return true if the passed type represents a Java Array type
*/
public boolean isArray(String typeName) {
return typeName.endsWith("[]");//$NON-NLS-1$
}
/**
* Insert the method's description here.
* Creation date: (10/4/2000 9:54:23 AM)
* @return boolean
* @param typeName java.lang.String
*/
private boolean isPrimitive(String typeName) {
return PRIMITIVES.contains(typeName);
}
}