Skip to main content
summaryrefslogtreecommitdiffstats
blob: b001299f892e81266b8e6d09853b04d389984e3a (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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
/*******************************************************************************
 * Copyright (c) 2003, 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.beaninfo.core;
/*


 */
import java.util.Iterator;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.*;
import org.eclipse.emf.ecore.resource.ResourceSet;

import org.eclipse.jem.internal.beaninfo.*;
import org.eclipse.jem.internal.beaninfo.adapters.BeaninfoNature;
import org.eclipse.jem.internal.beaninfo.adapters.BeaninfoProxyConstants;
import org.eclipse.jem.internal.java.adapters.ReflectionAdaptor;
import org.eclipse.jem.internal.proxy.core.*;
import org.eclipse.jem.java.*;

/**
 * Beaninfo (introspection) utilities methods
 */

public final class Utilities {
	
	private Utilities() {
	}

	/**
	 * Utility to return the class as a JavaClass. If it actually is a JavaType this will
	 * fail with a ClassCastException.
	 * @param className
	 * @param rset
	 * @return java class
	 * 
	 * @throws ClassCastException if not a java class, but instead a java primitive.
	 * @since 1.1.0
	 */
	public static JavaClass getJavaClass(String className, ResourceSet rset) {
		return (JavaClass) getJavaType(className, rset);
	}
	
	/**
	 * Utility to return the class as a JavaHelpers.
	 * 
	 * @param className
	 * @param rset
	 * @return java helpers.
	 * 
	 * @since 1.1.0
	 */
	public static JavaHelpers getJavaType(String className, ResourceSet rset) {
		return (JavaHelpers) rset.getEObject(getJavaClassURI(className), true);
	}
	
	/**
	 * Create a URI to the given classname.
	 * <p>
	 * Note: It must be in normal form, i.e. fully-qualified, if primitive spelled out (e.g. "int" not I), and if
	 * arrays it must readable form (e.g. "java.lang.String[]" and not "[Ljava.lang.String;").
	 * 
	 * @param className
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public static URI getJavaClassURI(String className) {
		return JavaRefFactory.eINSTANCE.createTypeURI(className);
	}

	/** 
	 * Utility to return the EClassifier from the given IBeanTypeProxy.
	 */
	public static EClassifier getJavaClass(IBeanTypeProxy type, ResourceSet rset) {
		if (type != null) {
			return getJavaType(type.getFormalTypeName(), rset);
		} else
			return null;
	}

	/**
	 * Utility to return the Method from the given IMethodProxy.
	 */
	public static Method getMethod(IMethodProxy method, ResourceSet rset) {
		return method != null ? (Method) rset.getEObject(URI.createURI(getMethodURL(method)), true) : null;
	}

	/**
	 * Answer the URL String for Method from the given IMethodProxy
	 */
	public static String getMethodURL(IMethodProxy method) {
		String className = method.getClassType().getTypeName();
		IBeanTypeProxy[] parms = method.getParameterTypes();
		String[] parmTypes = parms.length > 0 ? new String[parms.length] : null;
		for (int i = 0; i < parms.length; i++) {
			parmTypes[i] = parms[i].getFormalTypeName();
		}
		return computeMethodURL(className, method.getName(), parmTypes);
	}
	
	protected static String computeMethodURL(String fullyQualifiedClassName, String methodName, String[] parmTypes) {
		int classStart = fullyQualifiedClassName.lastIndexOf('.');
		StringBuffer url = new StringBuffer(50);
		url.append("java:/"); //$NON-NLS-1$
		if (classStart > -1)
			url.append(fullyQualifiedClassName.substring(0, classStart));
		url.append('#');
		url.append(computeMethodID(fullyQualifiedClassName.substring(classStart + 1), methodName, parmTypes));
		return url.toString();
	}
	
	protected static String computeFieldURL(String fullyQualifiedClassName, String fieldName) {
		int classStart = fullyQualifiedClassName.lastIndexOf('.');
		StringBuffer url = new StringBuffer(50);
		url.append("java:/"); //$NON-NLS-1$
		if (classStart > -1)
			url.append(fullyQualifiedClassName.substring(0, classStart));
		url.append('#');
		url.append(fullyQualifiedClassName.substring(classStart + 1));
		url.append(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER);
		url.append(fieldName);
		return url.toString();
	}
	
	/**
	 * Return the field uri for the given classname, fieldname.
	 * @param fullyQualifiedClassName
	 * @param fieldName
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public static URI getFieldURI(String fullyQualifiedClassName, String fieldName) {
		return URI.createURI(computeFieldURL(fullyQualifiedClassName, fieldName));
	}
	/**
	 * Return the method uri for the given classname, methodname, parm types.
	 * @param fullyQualifiedClassName
	 * @param methodName
	 * @param parmTypes <code>null</code> if there are no parms.
	 * @return
	 * 
	 * @since 1.1.0
	 */
	public static URI getMethodURI(String fullyQualifiedClassName, String methodName, String[] parmTypes) {
		return URI.createURI(computeMethodURL(fullyQualifiedClassName, methodName, parmTypes));
	}

	/**
	 * Turn it into an URI.
	 */
	public static URI getMethodURI(IMethodProxy method) {
		return URI.createURI(getMethodURL(method));
	}

	/**
	 * Utility to compute the Java Modeling METHODID from method declaring class name,
	 * method name, and parameter class names.
	 */
	public static String computeMethodID(String className, String methodName, String[] parameterTypes) {
		StringBuffer out = new StringBuffer(50);
		out.append(className);
		out.append(ReflectionAdaptor.C_CLASS_MEMBER_DELIMITER);
		out.append(methodName);
		out.append(ReflectionAdaptor.C_METHOD_PARM_DELIMITER);
		if (parameterTypes != null)
			for (int i = 0; i < parameterTypes.length; i++) {
				out.append(parameterTypes[i]);
				if (i < parameterTypes.length - 1)
					out.append(ReflectionAdaptor.C_PARM_PARM_DELIMITER);
			}
		if (className.equals(methodName))
			out.append(ReflectionAdaptor.S_CONSTRUCTOR_TOKEN); //It's a constructor
		return out.toString();
	}

	/**
	 * Utility to retrieve the BeanDecorator.
	 */
	public static BeanDecorator getBeanDecorator(EModelElement model) {
		return (BeanDecorator) getDecorator(model, BeanDecorator.class);
	}
	/**
	 * Utility to retrieve a decorator of the specified class.
	 */
	public static EAnnotation getDecorator(EModelElement model, Class decoratorClass) {
		Iterator itr = model.getEAnnotations().iterator();
		while (itr.hasNext()) {
			EAnnotation decr = (EAnnotation) itr.next();
			if (decoratorClass.isInstance(decr))
				return decr;
		}
		return null;
	}

	/**
	 * Utility to retrieve the EventSetDecorator.
	 */
	public static EventSetDecorator getEventSetDecorator(EModelElement model) {
		return (EventSetDecorator) getDecorator(model, EventSetDecorator.class);
	}

	/**
	 * Utility to retrieve the MethodDecorator.
	 */
	public static MethodDecorator getMethodDecorator(EModelElement model) {
		return (MethodDecorator) getDecorator(model, MethodDecorator.class);
	}

	/**
	 * Utility to retrieve the PropertyDecorator.
	 */
	public static PropertyDecorator getPropertyDecorator(EModelElement model) {
		return (PropertyDecorator) getDecorator(model, PropertyDecorator.class);
	}

	/**
	 * Utility to return an iterator on the list which will return the property decorators
	 * of only the properties in the EList passed in. If the property does not have a
	 * property decorator, then it is not a beaninfo property.
	 */
	public static Iterator getPropertiesIterator(final EList properties) {
		return new Iterator() {
			private Iterator itr = properties.iterator();
			private boolean hasNext = true;
			private PropertyDecorator next;
			{
				findNext();
			}
			public boolean hasNext() {
				return hasNext;
			}

			public Object next() {
				PropertyDecorator temp = next;
				findNext();
				return temp;
			}

			public void remove() {
				throw new UnsupportedOperationException();
			}

			private void findNext() {
				while (itr.hasNext()) {
					EModelElement nextOne = (EModelElement) itr.next();
					next = getPropertyDecorator(nextOne);
					if (next != null) {
						return;
					}
				}
				hasNext = false;
			}
		};
	}

	/**
	 * Utility to return an iterator on the list which will return the EventSet decorators
	 * of only the BeanEvents in the EList passed in.
	 */
	public static Iterator getEventSetsIterator(final EList events) {
		return new Iterator() {
			private Iterator itr = events.iterator();
			private boolean hasNext = true;
			private EventSetDecorator next;
			{
				findNext();
			}
			public boolean hasNext() {
				return hasNext;
			}

			public Object next() {
				EventSetDecorator temp = next;
				findNext();
				return temp;
			}

			public void remove() {
				throw new UnsupportedOperationException();
			}

			private void findNext() {
				while (itr.hasNext()) {
					EModelElement nextOne = (EModelElement) itr.next();
					next = getEventSetDecorator(nextOne);
					if (next != null) {
						return;
					}
				}
				hasNext = false;
			}
		};
	}

	/**
	 * Utility to return an iterator on the list which will return the Method decorators
	 * of only the Methods in the EList passed in.
	 */
	public static Iterator getMethodsIterator(final EList methods) {
		return new Iterator() {
			private Iterator itr = methods.iterator();
			private boolean hasNext = true;
			private MethodDecorator next;
			{
				findNext();
			}
			public boolean hasNext() {
				return hasNext;
			}

			public Object next() {
				MethodDecorator temp = next;
				findNext();
				return temp;
			}

			public void remove() {
				throw new UnsupportedOperationException();
			}

			private void findNext() {
				while (itr.hasNext()) {
					EModelElement nextOne = (EModelElement) itr.next();
					next = getMethodDecorator(nextOne);
					if (next != null) {
						return;
					}
				}
				hasNext = false;
			}
		};
	}

	/**
	 * Get the search path from the remote vm. 
	 * 
	 * Note: This shouldn't be used when working with a BeaninfoNature. Use the
	 * accessors taking the nature  instead. Otherwise there will be inconsistencies since the search path won't be
	 * saved across invocations of the workspace if it is not updated through the nature).
	 */
	public static IArrayBeanProxy getBeanInfoSearchPath(ProxyFactoryRegistry registry) {
		BeaninfoProxyConstants biconstants = BeaninfoProxyConstants.getConstants(registry);
		if (biconstants != null)
			return (IArrayBeanProxy) biconstants
				.getGetBeanInfoSearchPathProxy()
				.invokeCatchThrowableExceptions(
				null);
		else
			return null;
	}

	/**
	 * Set the search path to the array of strings passed in on the remote vm.
	 *
	 * Note: This shouldn't be used when working with a BeaninfoNature. Use the
	 * accessors taking the nature  instead. Otherwise there will be inconsistencies since the search path won't be
	 * saved across invocations of the workspace if it is not updated through the nature).	 
	 */
	public static void setBeanInfoSearchPath(ProxyFactoryRegistry registry, String[] paths) {

		try {
			BeaninfoProxyConstants biConstants = BeaninfoProxyConstants.getConstants(registry);
			if (biConstants != null) {
				JavaStandardBeanProxyConstants jConstants = JavaStandardBeanProxyConstants.getConstants(registry);
				IStandardBeanProxyFactory proxyFactory = registry.getBeanProxyFactory();
				IArrayBeanProxy newPath = proxyFactory.createBeanProxyWith(jConstants.getStringType(), paths != null ? paths.length : 0);
				if (paths != null)
					for (int i = 0; i < paths.length; i++)
						newPath.set(proxyFactory.createBeanProxyWith(paths[i]), i);
				biConstants.getSetBeanInfoSearchPathProxy().invoke(null, newPath);
			}			
		} catch (ThrowableProxy e) {
		}
	}

	/**
	 * From the Beaninfo Nature, insert a path to the beaninfo path at the given index, -1 means at the end.
	 * If index is larger than the current path, it will also add at the end.
	 */
	public static void insertBeanInfoSearchPath(BeaninfoNature nature, IBeaninfosDocEntry path, int index) throws CoreException {
		BeaninfosDoc infoPath = nature.getSearchPath();
		IBeaninfosDocEntry[] oldPath = infoPath.getSearchpath();

		IBeaninfosDocEntry[] newPath = new IBeaninfosDocEntry[oldPath.length + 1];

		if (index == -1 || index >= oldPath.length) {
			// At the end or past end
			System.arraycopy(oldPath, 0, newPath, 0, oldPath.length);
			newPath[oldPath.length] = path;
		} else {
			// In the middle
			System.arraycopy(oldPath, 0, newPath, 0, index);
			newPath[index] = path;
			System.arraycopy(oldPath, index, newPath, index + 1, oldPath.length - index);
		}

		infoPath.setSearchpath(newPath);
		nature.setSearchPath(infoPath);
	}

	/**
	 * Insert a path to the beaninfo path at the given index, -1 means at the end.
	 * If index is larger than the current path, it will also add at the end.
	 *
	 * Note: This shouldn't be used when working with a BeaninfoNature. Use the
	 * accessors taking the nature  instead. Otherwise there will be inconsistencies since the search path won't be
	 * saved across invocations of the workspace if it is not updated through the nature).	 
	 */
	public static void insertBeanInfoSearchPath(ProxyFactoryRegistry registry, String path, int index) {
		try {
			BeaninfoProxyConstants biConstants = BeaninfoProxyConstants.getConstants(registry);
			if (biConstants != null) {
				IArrayBeanProxy infoPath = (IArrayBeanProxy) biConstants.getGetBeanInfoSearchPathProxy().invoke(null);
				int pathLength = infoPath.getLength();
				IStandardBeanProxyFactory proxyFactory = registry.getBeanProxyFactory();
				IArrayBeanProxy newPath = proxyFactory.createBeanProxyWith(infoPath.getTypeProxy(), pathLength + 1);
				IBeanProxy stringProxy = proxyFactory.createBeanProxyWith(path);
				JavaStandardBeanProxyConstants constants = JavaStandardBeanProxyConstants.getConstants(registry);
				if (index == -1 || index >= pathLength) {
					// At the end or past end
					constants.arraycopy(infoPath, 0, newPath, 0, infoPath.getLength());
					newPath.set(stringProxy, pathLength);
				} else {
					// In the middle
					constants.arraycopy(infoPath, 0, newPath, 0, index);
					newPath.set(stringProxy, index);
					constants.arraycopy(infoPath, index, newPath, index + 1, pathLength - index);
				}
				biConstants.getSetBeanInfoSearchPathProxy().invoke(null, newPath);
			}			
		} catch (ThrowableProxy e) {
		}
	}

	/**
	 * From the Beaninfo Nature, remove the specified path from the beaninfo search path.
	 * Not an error if not found.
	 */
	public static void removeBeanInfoPath(BeaninfoNature nature, IBeaninfosDocEntry path) throws CoreException {
		BeaninfosDoc infoPath = nature.getSearchPath();
		IBeaninfosDocEntry[] oldPath = infoPath.getSearchpath();

		for (int i = 0; i < oldPath.length; i++) {
			if (path.equals(oldPath[i])) {
				// We found it, so remove it.
				IBeaninfosDocEntry[] newPath = new IBeaninfosDocEntry[oldPath.length - 1];
				System.arraycopy(oldPath, 0, newPath, 0, i);
				if (i < oldPath.length - 1)
					System.arraycopy(oldPath, i + 1, newPath, i, oldPath.length - i - 1);
				infoPath.setSearchpath(newPath);
				nature.setSearchPath(infoPath);
				return;
			}
		}
	}

	/**
	 * Remove the specified path from the beaninfo search path.
	 * Not an error if not found.
	 *
	 * Note: This shouldn't be used when working with a BeaninfoNature. Use the
	 * accessors taking the nature  instead. Otherwise there will be inconsistencies since the search path won't be
	 * saved across invocations of the workspace if it is not updated through the nature).	 	 
	 */
	public static void removeBeanInfoPath(ProxyFactoryRegistry registry, String path) {
		try {
			BeaninfoProxyConstants biConstants = BeaninfoProxyConstants.getConstants(registry);
			if (biConstants != null) {
				IArrayBeanProxy infoPath = (IArrayBeanProxy) biConstants.getGetBeanInfoSearchPathProxy().invoke(null);
				int pathLength = infoPath.getLength();
				for (int i = 0; i < pathLength; i++) {
					IStringBeanProxy aPath = (IStringBeanProxy) infoPath.get(i);
					if (path.equals(aPath.stringValue())) {
						// We found it, so remove it.
						IArrayBeanProxy newPath = registry.getBeanProxyFactory().createBeanProxyWith(infoPath.getTypeProxy(), pathLength - 1);
						JavaStandardBeanProxyConstants constants = JavaStandardBeanProxyConstants.getConstants(registry);
						constants.arraycopy(infoPath, 0, newPath, 0, i);
						if (i < pathLength - 1)
							constants.arraycopy(infoPath, i + 1, newPath, i, pathLength - i - 1);
						biConstants.getSetBeanInfoSearchPathProxy().invoke(null, newPath);
						return;
					}
				}
			}			
		} catch (ThrowableProxy e) {
		}
	};

}

Back to the top