Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogtreecommitdiffstats
blob: 1a1f7cda71cfee7c9a4875e689afda498f11df90 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*******************************************************************************
 * Copyright (c) 2001, 2006 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;
/*


 */
import java.util.List;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.impl.ENotificationImpl;

import org.eclipse.jem.java.*;
import org.eclipse.jem.util.logger.proxy.Logger;
	
/**
 * 
 */
public abstract class JavaReflectionAdaptor extends ReflectionAdaptor {
	private static final String C_METHOD_DEFAULT_CTOR = String.valueOf(C_METHOD_PARM_DELIMITER) + S_CONSTRUCTOR_TOKEN;
	protected static final String LEFT_BRACKET = "[";//$NON-NLS-1$
	
	/**
	 * Special notification event type. This is sent against a JavaClass (as the target) whenever flush of the reflection occurs. It will be
	 * sent under the notification event type of REFLECTION_EVENT.
	 * @since 1.1.0
	 */
	public static final EAttribute FLUSH_REFLECTION_EVENT = EcorePackage.eINSTANCE.getEcoreFactory().createEAttribute();
	
	/**
	 * Special notification event type. This is sent against a JavaClass (as the target) whenever flush of a new class (i.e. 
	 * no source was found) of the reflection occurs. It will be
	 * sent under the notification event type of REFLECTION_EVENT.
	 * @since 1.1.0
	 */
	public static final EAttribute FLUSH_NEW_REFLECTION_EVENT = EcorePackage.eINSTANCE.getEcoreFactory().createEAttribute();

	/*
	 * Fill in the name. Not really needed but it would be nice.
	 */
	static {
		FLUSH_REFLECTION_EVENT.setName("flushReflectedValues");    //$NON-NLS-1$
		FLUSH_NEW_REFLECTION_EVENT.setName("flushNewReflectedValues"); //$NON-NLS-1$
	}
	protected boolean hasFlushed = false;
	protected boolean isFlushing = false;
/**
 * JavaReflectionAdapter constructor comment.
 */
public JavaReflectionAdaptor() {
	super();
}
/**
 * JavaReflectionAdapter constructor comment.
 * @param target org.eclipse.emf.common.notify.Notifier
 */
public JavaReflectionAdaptor(org.eclipse.emf.common.notify.Notifier target) {
	super(target);
}
/**
 * createBlock - instantiate a Block containing the passed source
 */
public Block createBlock(String name, String sourceString) {
	Block newBlock = getJavaFactory().createBlock();
	newBlock.setName(name + "_" + "block");//$NON-NLS-2$//$NON-NLS-1$
	newBlock.setSource(sourceString);
	return newBlock;
}
/**
 * setSuper - set our supertype here, implemented interface are handled separately
 */
public JavaClass createJavaClassRef(String targetName) {
	return JavaRefFactory.eINSTANCE.createClassRef(targetName);
}
/**
 * createJavaParameter - instantiate a Java Parameter based on the passed name and type name (a simple name, NOT A SIGNATURE!!!)
 * The id for a parameter has to be complex in order to be parsable into class, method, and parm.
 * It is created by appending the parm name to the method id, with a known separator.
 * It will look something like "Foo.doSomething(java.lang.Integer-arg0"
 */
public JavaParameter createJavaParameter(Method parentMethod, String parmName, String parmTypeName) {
	JavaParameter newParm = getJavaFactory().createJavaParameter();
	if (parmName!=null)
	   newParm.setName(parmName);
// ((InternalEObject)newParm).eSetID(parentMethod.eID() + C_METHODID_PARMID_DELIMITER + parmName);
	String classRefString = parmTypeName;
	newParm.setEType(createJavaClassRef(classRefString));
	return newParm;
}
/**
 * This method will return a List of dimensions for a typeName.
 * For example "foo[][]" would return a List of Integers
 * 1, 1.  At some point we may want to actually capture the size
 * for Fields but we would need the initializer source to determine that.
 */
public List getArrayDimensions(String typeName) {
	List dimensions = new java.util.ArrayList();
	if (typeName != null) {
		int begin = 0;
		int index = -1;
		while (begin < typeName.length()) {
			index = typeName.indexOf(LEFT_BRACKET, begin);
			if (index > -1) {
				dimensions.add(new Integer(1));
				begin = index + 1;
			} else {
				begin = typeName.length();
			}
		}
	}
	return dimensions;
}
/* Get the Java Factory
 */
protected static JavaRefFactory getJavaFactory() {
	return ((org.eclipse.jem.java.JavaRefPackage)EPackage.Registry.INSTANCE.getEPackage(org.eclipse.jem.java.JavaRefPackage.eNS_URI)).getJavaRefFactory();
}
public abstract Object getReflectionSource();
/**
 * getTypeNamesFromMethodUUID - Pull the parm type names out of a method ID
 * 		It will be in the form: "simpleclass.methodName(com.fronk.Parm1_type,parm2type"
 */
protected static String[] getTypeNamesFromMethodID(String methodID) {
	if (methodID.charAt(methodID.length()-1) == C_METHOD_PARM_DELIMITER || methodID.endsWith(C_METHOD_DEFAULT_CTOR))
		return emptyStringArray;
		
	// Count the parms first.  The number of parms is the number of occurrences of ',' + 1
	int numParms = 1;
	int pos = -1;
	// Skip the '.' after classname
	pos = methodID.indexOf(C_CLASS_MEMBER_DELIMITER, ++pos);
	// Look for the start of the parms
	int parmPos = methodID.indexOf(C_METHOD_PARM_DELIMITER, ++pos);
	pos = parmPos;
	while ((pos = methodID.indexOf(C_PARM_PARM_DELIMITER, ++pos)) != -1)
		numParms++;
	String[] parmTypeNames = new String[numParms];
	// now collect the parm names
	// skip the method name
	pos = parmPos;
	int i = 0, end;
	do {
		end = methodID.indexOf(C_PARM_PARM_DELIMITER, pos + 1);
		// This is the last parameter, we may need to strip a trailing &V for a constructor
		if (end == -1)
			end = methodID.indexOf(S_CONSTRUCTOR_TOKEN, pos + 1);
		// otherwise take the rest of the ID
		if (end == -1)
			end = methodID.length();
		parmTypeNames[i++] = methodID.substring(pos + 1, end);
	} while ((pos = methodID.indexOf(C_PARM_PARM_DELIMITER, ++pos)) != -1);
	return parmTypeNames;
}
public abstract boolean hasCachedReflectionSource();

public boolean hasReflectionSource() {
    return getReflectionSource() != null;
}

/**
 * Subclasses should override.
 *
 */
public void releaseSourceType(){
}

/**
 * Subclasses should override.
 * @return
 */
public Notification releaseSourceTypeNoNotification() {
	return null;
}

public static void releaseSourceType(JavaClass javaClass) {
	if (javaClass == null)
		return;

	JavaReflectionAdaptor existing = (JavaReflectionAdaptor) retrieveAdaptorFrom(javaClass);
	if (existing != null)
		existing.releaseSourceType();
}
/*
 * This method is called by a Field Adaptor to set the type of aField
 * to be aTypeName.  aTypeName may contain array brackets which need
 * to be detected in order to set the array dimensions on aField.
 */
protected void setFieldType(Field aField, String aTypeName) {
	if (aField != null && aTypeName != null) {
		String classRefString = aTypeName;
		aField.setEType(createJavaClassRef(classRefString));
	}
}
public final boolean flushReflectedValuesIfNecessary() {
	return flushReflectedValuesIfNecessary(false);
}
public final boolean flushReflectedValuesIfNecessary(boolean clearCachedModelObject) {
	Notification not = flushReflectedValuesIfNecessaryNoNotification(clearCachedModelObject);
	if (not != null)
		getTarget().eNotify(not);
	return hasFlushed;
}

public synchronized Notification flushReflectedValuesIfNecessaryNoNotification(boolean clearCachedModelObject) {
	if (!hasFlushed && !isFlushing) {
		boolean isExisting = hasCachedReflectionSource();
		try {
			isFlushing = true;
			hasReflected = false;
			hasFlushed = flushReflectedValues(clearCachedModelObject);
		} catch (Throwable e) {
			hasFlushed = false;
			Logger.getLogger().log(e);
			if (e instanceof RuntimeException)
				throw (RuntimeException) e;
			else if (e instanceof Error)
				throw (Error) e;
			else
				throw new RuntimeException(e.getMessage());
		} finally {
			isFlushing = false;
			postFlushReflectedValuesIfNecessary(isExisting);
		}
		return createFlushNotification(isExisting);
	}
	return null;
}

/**
 * @param isExisting
 * @return
 */
protected Notification createFlushNotification(boolean isExisting) {
	EStructuralFeature feature = isExisting ? FLUSH_REFLECTION_EVENT : FLUSH_NEW_REFLECTION_EVENT;
	return new ENotificationImpl((InternalEObject)getTarget(),EVENT, feature, null, null);
}
protected void postFlushReflectedValuesIfNecessary(boolean isExisting) {
}
/**
 * Subclasses should override to perform the actual clearing of the values.
 */
protected boolean flushReflectedValues(boolean clearCachedModelObject) {
	return true;
}
/**
 * Return a boolean indicating whether reflection had occurred.
 */
public boolean reflectValuesIfNecessary() {
	if (isFlushing)
		return false;
	return super.reflectValuesIfNecessary();
}

/**
 * reflectValues - template method, subclasses override to pump values into target
 */
public boolean reflectValues() {
	hasFlushed = false;
	return true;
}
}




Back to the top