/*******************************************************************************
 * 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.tests.beaninfo;
/*
 *  $RCSfile: TestStandard.java,v $
 *  $Revision: 1.14 $  $Date: 2006/05/17 20:13:56 $ 
 */

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.*;

import org.eclipse.jem.internal.beaninfo.*;
import org.eclipse.jem.internal.beaninfo.core.Utilities;

import org.eclipse.jem.java.*;

/**
 * @author richkulp
 *
 * Standard BeanInfo tests.
 */
public class TestStandard extends AbstractBeanInfoTestCase {

	public TestStandard() {
		super();
	}

	public TestStandard(String name) {
		super(name);
	}
		
	public void testArrayClassType() {
		// Test one dimension array type for a class as final component
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("org.eclipse.jem.tests.beaninfo.Test1Class[]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.CLASS_LITERAL, at.getKind());
		assertEquals(1, ((ArrayType) at).getArrayDimensions());
		assertTrue(at.isPublic());
		assertTrue("java.lang.Object".equals(at.getSupertype().getQualifiedName()));
		assertTrue(at.getImplementsInterfaces().size() == 2);
		assertTrue(at.getMethods().isEmpty());
		assertTrue(at.getFields().isEmpty());
		assertTrue(at.getProperties().isEmpty());
		assertTrue(at.getEvents().isEmpty());
		assertTrue(at.getEOperations().isEmpty());
	}

	public void testArrayPrimitiveType() {
		// Test one dimension array type for a class as final component
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("int[]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.CLASS_LITERAL, at.getKind());
		assertEquals(1, ((ArrayType) at).getArrayDimensions());		
		assertTrue(at.isPublic());
		assertTrue("java.lang.Object".equals(at.getSupertype().getQualifiedName()));
		assertTrue(at.getImplementsInterfaces().size() == 2);
		assertTrue(at.getMethods().isEmpty());
		assertTrue(at.getFields().isEmpty());
		assertTrue(at.getProperties().isEmpty());
		assertTrue(at.getEvents().isEmpty());
		assertTrue(at.getEOperations().isEmpty());
	}

	public void testArrayUndefined() {
		// Test one dimension array type for a class as final component that is undefined.
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("XYZ[]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.UNDEFINED_LITERAL, at.getKind());
	}

	public void testArrayClassType2Dim() {
		// Test one dimension array type for a class as final component
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("org.eclipse.jem.tests.beaninfo.Test1Class[][]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.CLASS_LITERAL, at.getKind());
		assertEquals(2, ((ArrayType) at).getArrayDimensions());
		assertTrue(at.isPublic());
		assertTrue("java.lang.Object".equals(at.getSupertype().getQualifiedName()));
		assertTrue(at.getImplementsInterfaces().size() == 2);
		assertTrue(at.getMethods().isEmpty());
		assertTrue(at.getFields().isEmpty());
		assertTrue(at.getProperties().isEmpty());
		assertTrue(at.getEvents().isEmpty());
		assertTrue(at.getEOperations().isEmpty());
	}

	public void testArrayPrimitiveType2Dim() {
		// Test one dimension array type for a class as final component
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("int[][]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.CLASS_LITERAL, at.getKind());
		assertEquals(2, ((ArrayType) at).getArrayDimensions());		
		assertTrue(at.isPublic());
		assertTrue("java.lang.Object".equals(at.getSupertype().getQualifiedName()));
		assertTrue(at.getImplementsInterfaces().size() == 2);
		assertTrue(at.getMethods().isEmpty());
		assertTrue(at.getFields().isEmpty());
		assertTrue(at.getProperties().isEmpty());
		assertTrue(at.getEvents().isEmpty());
		assertTrue(at.getEOperations().isEmpty());
	}

	public void testArrayUndefined2Dim() {
		// Test one dimension array type for a class as final component that is undefined.
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("XYZ[][]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.UNDEFINED_LITERAL, at.getKind());
	}

	public void testArrayInnerClassType() {
		// Test one dimension array type for a class as final component
		JavaClass at = (JavaClass) JavaRefFactory.eINSTANCE.reflectType("org.eclipse.jem.tests.beaninfo.Customer$Account[]", rset);
		
		assertTrue(at.isArray());
		assertSame(TypeKind.CLASS_LITERAL, at.getKind());
		assertEquals(1, ((ArrayType) at).getArrayDimensions());
		assertTrue(at.isPublic());
		assertTrue("java.lang.Object".equals(at.getSupertype().getQualifiedName()));
		assertTrue(at.getImplementsInterfaces().size() == 2);
		assertTrue(at.getMethods().isEmpty());
		assertTrue(at.getFields().isEmpty());
		assertTrue(at.getProperties().isEmpty());
		assertTrue(at.getEvents().isEmpty());
		assertTrue(at.getEOperations().isEmpty());
	}
	
	public void testBeanDecoratorReflected() {
		JavaClass test1Class = getTest1Class();

		// Test the bean decorator.
		BeanDecorator bd = Utilities.getBeanDecorator(test1Class);
		assertEquals("Test1Class", bd.getName()); //$NON-NLS-1$
		assertNull(bd.getCustomizerClass());
	}

	protected JavaClass getTest1Class() {
		JavaClass test1Class =
			(JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test1Class"), true); //$NON-NLS-1$
		return test1Class;
	}
	
	public void testLocalReflectedProperties() {
		EList allLocalFeatures = getTest1Class().getProperties();
		assertEquals(2, allLocalFeatures.size());
		
		Iterator itr = Utilities.getPropertiesIterator(allLocalFeatures);
		boolean found = false;
		while (itr.hasNext()) {
			PropertyDecorator pd = (PropertyDecorator) itr.next();
			if (pd.getName().equals("foo")) { //$NON-NLS-1$
				found = true;
				assertTrue(pd instanceof IndexedPropertyDecorator);
				IndexedPropertyDecorator ip = (IndexedPropertyDecorator) pd;
				JavaHelpers type = (JavaHelpers) ip.getPropertyType();
				assertEquals("java.lang.String[]", type.getQualifiedName());
				if (!type.getQualifiedName().equals("java.lang.String[]")); //$NON-NLS-1$
					
				Method mthd = ip.getReadMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test1Class.getFoo("), true), mthd);
				
				mthd = ip.getWriteMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test1Class.setFoo(java.lang.String[]"), true), mthd);
				
				mthd = ip.getIndexedReadMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test1Class.getFoo(int"), true), mthd);
				
				mthd = ip.getIndexedWriteMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test1Class.setFoo(int,java.lang.String"), true), mthd);
				
				break;
			}
		}

		assertTrue(found);		
	}
	
	public void testLocalReflectedOperations() {
		JavaClass test1Class = getTest1Class();
		
		// Test local operations.
		EList allLocalOperations = test1Class.getEOperations();
		assertEquals(10, allLocalOperations.size());
		Iterator itr = allLocalOperations.iterator();
		// This is the desired method that the operation of interest points to.
		Method desired =
			(Method) rset.getEObject(URI.createURI(
				"java:/org.eclipse.jem.tests.beaninfo#Test1Class.setFoo(int,java.lang.String"), true); //$NON-NLS-1$
		boolean found = false;
		while (itr.hasNext()) {
			MethodProxy bhav = (MethodProxy) itr.next();
			if (bhav.getMethod() == desired) {
				found = true;
				List parms = Utilities.getMethodDecorator(bhav).getParameterDescriptors();
				assertEquals(2, parms.size());
				ParameterDecorator pmd = (ParameterDecorator) parms.get(0);
				assertEquals("index", pmd.getName());
				
				break;
			}
		}
		assertTrue(found);		
	}
	
	public void testLocalReflectedEvents() {
		JavaClass test1Class = getTest1Class();
		
		// Test event set reflected.
		List events = test1Class.getEvents();
		assertEquals(2, events.size());
		Iterator itr = events.iterator();
		boolean foundevt1 = false, foundevt2 = false;
		while (itr.hasNext()) {
			JavaEvent event = (JavaEvent) itr.next();
			if ("test1ClassEvent".equals(event.getName())) { //$NON-NLS-1$
				foundevt1 = true;
				EventSetDecorator edec = Utilities.getEventSetDecorator(event);
				List mlist = edec.getListenerMethods();
				assertEquals(2, mlist.size());
			} else if ("test1ClassUnicastEvent".equals(event.getName())) { //$NON-NLS-1$
				foundevt2 = true;
				EventSetDecorator edec = Utilities.getEventSetDecorator(event);
				assertTrue(edec.isUnicast());
			}
		}
		assertTrue(foundevt1);
		assertTrue(foundevt2);
	}
	
	protected JavaClass getTest2ClassB() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2ClassB"), true); //$NON-NLS-1$
	}

	public void testBeanDecoratorIntrospected() {
		// Test one with a beaninfo.
		JavaClass test2ClassB = getTest2ClassB();
		BeanDecorator bd = Utilities.getBeanDecorator(test2ClassB);
		assertEquals("Test2ClassB", bd.getName());
		
		// The following will test if search across beaninfo search path worked. It would fail if it didn't work.
		assertEquals("A name for this class.", bd.getDisplayName()); //$NON-NLS-1$
		assertFalse(bd.isExpert());
		// Customizer class set in BeanInfo, but bogus for now to same class as being introspected.
		assertSame(test2ClassB, bd.getCustomizerClass());
	}
	
	public void testLocalIntrospectedProperties() {
		JavaClass test2ClassB = getTest2ClassB();
		EList allLocalFeatures = test2ClassB.getProperties();
		assertEquals(2, allLocalFeatures.size());
		
		Iterator itr = Utilities.getPropertiesIterator(allLocalFeatures);
		boolean gotSet = false, gotFoo = false;
		while (itr.hasNext()) {
			PropertyDecorator pd = (PropertyDecorator) itr.next();
			Method mthd = null;
			if (pd.getName().equals("setA")) { //$NON-NLS-1$
				gotSet = true;
				mthd = pd.getReadMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2ClassB.isSetA("), true), mthd);
			} else if (pd.getName().equals("foo")) { //$NON-NLS-1$
				gotFoo = true;
				IndexedPropertyDecorator ipd = (IndexedPropertyDecorator) pd;
				mthd = ipd.getIndexedReadMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2ClassB.getFoo(int"), true), mthd);
			}
		}
		assertTrue(gotSet);
		assertTrue(gotFoo);
	}
	
	public void testLocalIntrospectedOperations() {
		JavaClass test2ClassB = getTest2ClassB();
		
		EList allLocalOperations = test2ClassB.getEOperations();
		assertEquals(2, allLocalOperations.size()); 

		boolean found = false;
		Iterator itr = test2ClassB.getEOperations().iterator();
		while (itr.hasNext()) {
			EOperation bhav = (EOperation) itr.next();
			if (bhav.getName().equals("setSetA")) { //$NON-NLS-1$
				List parms = Utilities.getMethodDecorator(bhav).getParameterDescriptors();
				assertEquals(1, parms.size());
				ParameterDecorator pmd = (ParameterDecorator) parms.get(0);
				assertEquals("aBooleanSetting", pmd.getName());
				found = true;
				break;
			}
		}
		assertTrue(found);
	}
	
	public void testLocalIntrospectedEvents() {
		JavaClass test2ClassB = getTest2ClassB();
		
		// Test event set introspected.
		EList events = test2ClassB.getEvents();
		assertEquals(1, events.size());
		JavaEvent event = (JavaEvent) events.get(0);
		assertEquals("overrideName", event.getName());  //$NON-NLS-1$
		EventSetDecorator edec = Utilities.getEventSetDecorator(event);
		assertEquals("ITest1ClassEventListener", edec.getListenerType().getName());
		List mlist = edec.getListenerMethods();
		assertEquals(1, mlist.size());
		MethodProxy mproxy = (MethodProxy) mlist.get(0);
		MethodDecorator mdec = Utilities.getMethodDecorator(mproxy);
		assertEquals("event1", mdec.getName()); //$NON-NLS-1$
		assertEquals("Event 1", mdec.getDisplayName()); //$NON-NLS-1$
	}
	
	public void testSuperTypes() {
		JavaClass testClass = getTest1Class();
		objFeaturesSetup();	// Get number of features for Object. This can vary depending on extensions, so that is why we compute it.
		
		// Now do the testing of merging with super types.
		assertEquals(2+objFeatures, testClass.getAllProperties().size());
		JavaClass test1ClassA = getTest1ClassA(); //$NON-NLS-1$
		assertNotNull(test1ClassA);
		assertEquals(3+objFeatures, test1ClassA.getAllProperties().size());
	}

	protected JavaClass getTest1ClassA() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test1ClassA"), true);
	}
	
	public void testSuperTypesEvents() {
		JavaClass test1ClassA = getTest1ClassA(); 
			
		// Test merging supertypes event set.
		List events = test1ClassA.getAllEvents();
		assertEquals(2, events.size());
		Iterator itr = events.iterator();
		boolean foundevt1 = false;
		boolean foundevt2 = false;
		while (itr.hasNext()) {
			JavaEvent event = (JavaEvent) itr.next();
			if ("test1ClassEvent".equals(event.getName())) { //$NON-NLS-1$
				foundevt1 = true;
				EventSetDecorator edec = Utilities.getEventSetDecorator(event);
				List mlist = edec.getListenerMethods();
				assertEquals(2, mlist.size());
			} else if ("test1ClassUnicastEvent".equals(event.getName())) { //$NON-NLS-1$
				foundevt2 = true;
				EventSetDecorator edec = Utilities.getEventSetDecorator(event);
				assertTrue(edec.isUnicast());
			}
		}
		assertTrue(foundevt1);
		assertTrue(foundevt2);
	}
	
	protected JavaClass getTest2Class() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2Class"), true); //$NON-NLS-1$
	}
	
	protected JavaClass getTest2ClassA() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2ClassA"), true); //$NON-NLS-1$
	}	
	
	public void testSuperTypeHideProperty() {
		JavaClass test2Class = getTest2Class();
		objFeaturesSetup();
		
		// Test2ClassBeanInfo explicitly hides Object (super) from its BeanInfo, so only the non-BeanInfo properties will show.		
		assertEquals(2+objNonProperties, test2Class.getAllProperties().size());
		
		// Try with subclasses. Make sure that Test2ClassBeanInfo is used with the subclasses.
		JavaClass test2ClassA = getTest2ClassA();		
		assertEquals(3+objNonProperties, test2ClassA.getAllProperties().size());
		
		JavaClass test2ClassB = getTest2ClassB();		
		assertEquals(4+objNonProperties, test2ClassB.getAllProperties().size());
	}
	
	public void testIndexedBeanInfo() {
		JavaClass test2Class = getTest2Class();
		
		// Test that Indexed thru beaninfo works
		Iterator itr = Utilities.getPropertiesIterator(test2Class.getProperties());
		boolean found = false;
		while (itr.hasNext()) {		
			PropertyDecorator pd = (PropertyDecorator) itr.next();			
			if (pd.getName().equals("fooBar")) { //$NON-NLS-1$
				found = true;
				assertTrue(pd instanceof IndexedPropertyDecorator);
				IndexedPropertyDecorator ip = (IndexedPropertyDecorator) pd;
				JavaHelpers type = (JavaHelpers) ip.getPropertyType();
				assertEquals("java.lang.String[]", type.getQualifiedName()); //$NON-NLS-1$
				Method mthd = ip.getReadMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2Class.getFooBar("), true), mthd); //$NON-NLS-1$
				mthd = ip.getWriteMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2Class.setFooBar(java.lang.String[]"), true), mthd); //$NON-NLS-1$
				mthd = ip.getIndexedReadMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2Class.getFooBar(int"), true), mthd); //$NON-NLS-1$
				mthd = ip.getIndexedWriteMethod();
				assertSame(rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2Class.setFooBar(int,java.lang.String"), true), mthd); //$NON-NLS-1$
				break;
			}
		}

		assertTrue(found);
	}

	protected JavaClass getTest2ClassC() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Test2ClassC"), true); //$NON-NLS-1$
	}
	
	public void testBeanInfoProject() {
		JavaClass test2ClassC = getTest2ClassC();
		
		// This will test that we could find Test2ClassC BeanInfo that is in another BeanInfo project (i.e. a project
		// that is specifically for BeanInfo's for a specific code project).
		BeanDecorator bd = Utilities.getBeanDecorator(test2ClassC);
		assertNotNull(bd);
		assertEquals("Test2ClassC from BeanInfo", bd.getDisplayName());
		
	}
	
	public void testOverride() {
		
		// Test that the local property is expert because it overrode from Test2ClassB and made it expert.
		JavaClass test2ClassB = getTest2ClassB();
		
		// Test that the local property is not expert in Test2ClassB.
		EStructuralFeature p = test2ClassB.getEStructuralFeature("setA");
		assertNotNull(p);
		PropertyDecorator pd = Utilities.getPropertyDecorator(p);
		assertFalse(pd.isExpert());

		// Now get subclass with override.
		JavaClass test2ClassC = getTest2ClassC();
		
		// Test that the local property is now expert because it overrode from Test2ClassB and made it expert.
		p = test2ClassC.getEStructuralFeature("setA");
		assertNotNull(p);
		pd = Utilities.getPropertyDecorator(p);
		assertTrue(pd.isExpert());		
	}
	
	protected JavaClass getTest2ClassPreq() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo.prereq#Test2ClassPreq"), true); //$NON-NLS-1$
	}
		
	public void testPrereqedProjects() {
		JavaClass test2ClassPrereq = getTest2ClassPreq();
		objFeaturesSetup();
		 
		// Test finding beaninfos for classes in another project (pre-reqed project).		
		assertEquals(1+objFeatures, test2ClassPrereq.getAllProperties().size());
		// Verify BeanInfo and not jsut introspection.
		EStructuralFeature f = test2ClassPrereq.getEStructuralFeature("aSet");
		assertNotNull(f);
		PropertyDecorator pd = Utilities.getPropertyDecorator(f);
		assertTrue(pd.isExpert());
	}
	
	public void testRemovePropRebuild() throws CoreException {
		objFeaturesSetup();
		
		// Test removing a property directly from a super class causes the subclasses to re-build their properties.
		JavaClass test1Class = getTest1Class();
		JavaClass test1ClassA = getTest1ClassA();
		// Get and test the properties first to cause introspection for both BEFORE the modification.
		assertEquals(2+objFeatures, test1Class.getAllProperties().size());
		assertEquals(3+objFeatures, test1ClassA.getAllProperties().size());
		try {
			test1Class.getEStructuralFeatures().remove(0); // Remove the first one. They should both now rebuild.
			assertEquals(1+objFeatures, test1Class.getAllProperties().size());
			assertEquals(2+objFeatures, test1ClassA.getAllProperties().size());
		} finally {
			// Need to close and reopen the project so that to restore the correct shape for test1Class for other tests.
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			final IProject project = nature.getProject();
			ISchedulingRule projectRule = workspace.getRuleFactory().modifyRule(project);
			workspace.run(new IWorkspaceRunnable () {
				public void run(IProgressMonitor monitor) throws CoreException {
					project.close(monitor);
					project.open(monitor);
				}
			}, projectRule, 0, null);
		}
	}
	
	public void testRemoveEventRebuild() throws CoreException {
		// Test removing an event directly from a super class causes the subclasses to re-build their allEvents.
		JavaClass test1Class = getTest1Class();
		JavaClass test1ClassA = getTest1ClassA();
		// Get and test the events first to cause introspection for both BEFORE the modification.
		assertEquals(2, test1Class.getAllEvents().size());
		assertEquals(2, test1ClassA.getAllEvents().size());		
		try {
			test1Class.getEvents().remove(0); // Remove the first one. They should now both rebuild.
			assertEquals(1, test1Class.getAllEvents().size());
			assertEquals(1, test1ClassA.getAllEvents().size());			
		} finally {
			// Need to close and reopen the project so that to restore the correct shape for test1Class for other tests.
			final IProject project = nature.getProject();
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			ISchedulingRule projectRule = workspace.getRuleFactory().modifyRule(project);
			workspace.run(new IWorkspaceRunnable () {
				public void run(IProgressMonitor monitor) throws CoreException {
					project.close(monitor);
					project.open(monitor);
				}
			}, projectRule, 0, null);
		}
	}
	
	protected JavaClass getCustomer() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#Customer"), true); //$NON-NLS-1$
	}
	
	public void testInnerClass() {
		JavaClass customer = getCustomer();
		
		// Now test customer to make sure that it introspects correctly, plus the inner class of one of its properties does too.
		List allLocalFeatures = customer.getProperties();
		assertEquals(2, allLocalFeatures.size());
		Iterator itr = allLocalFeatures.iterator();
		boolean found = false;
		while (itr.hasNext()) {
			EStructuralFeature ea = (EStructuralFeature) itr.next();
			if ("savings".equals(ea.getName())) { //$NON-NLS-1$
				found = true;
				JavaClass innerClass = (JavaClass) ea.getEType();	// This property type is an innerclass of Customer
				assertEquals("Customer$Account", innerClass.getName());
				allLocalFeatures = innerClass.getProperties();
				assertEquals(2, allLocalFeatures.size());
			}
		}
		
		assertTrue(found);
	}

	protected JavaClass getTestBoundNotBound() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#TestBoundNotBound"), true); //$NON-NLS-1$
	}
	
	public void testNotBoundReflection() {
		JavaClass testBoundNotBound = getTestBoundNotBound();
		
		// Now test that properties are bound correctly on reflection. First test reflect not bound correct.
		// This is determined by no addPropertyChangeListener method on class.		
		List allLocalFeatures = testBoundNotBound.getProperties();
		assertEquals(1, allLocalFeatures.size());
		EStructuralFeature ea = (EStructuralFeature) allLocalFeatures.get(0);
		PropertyDecorator pd = Utilities.getPropertyDecorator(ea);
		assertNotNull(pd);
		assertFalse(pd.isBound());
	}
	
	protected JavaClass getTestBoundSuper() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#TestBoundSuper"), true); //$NON-NLS-1$
	}
	
	public void testBoundReflection() {
		JavaClass testBoundSuper = getTestBoundSuper();
		
		// Test that reflection can find bound property.
		// This is determined by finding add/remove PropertyChangeListener method on class.		
		List allLocalFeatures = testBoundSuper.getProperties();
		assertEquals(1, allLocalFeatures.size());
		EStructuralFeature ea = (EStructuralFeature) allLocalFeatures.get(0);
		PropertyDecorator pd = Utilities.getPropertyDecorator(ea);
		assertNotNull(pd);
		assertTrue(pd.isBound());
	}

	protected JavaClass getTestBoundSub() {
		return (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#TestBoundSub"), true); //$NON-NLS-1$
	}
	
	public void testBoundReflectionSubclass() {
		JavaClass testBoundSub = getTestBoundSub();

		// Test that reflection can find bound property due to inherit from a bound class.
		// This is determined by finding add/remove PropertyChangeListener method on class (but from a super class).						
		List allLocalFeatures = testBoundSub.getProperties();
		assertEquals(1, allLocalFeatures.size());		
		EStructuralFeature ea = (EStructuralFeature) allLocalFeatures.get(0);
		PropertyDecorator pd = Utilities.getPropertyDecorator(ea);
		assertNotNull(pd);
		assertTrue(pd.isBound());
	}
	
	public void testOverridesFile() {
		// Test that override files get applied correctly.
		JavaClass testOverride = (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#TestOverrides"), true); //$NON-NLS-1$
		assertNotNull(testOverride);
		EStructuralFeature xyz = testOverride.getEStructuralFeature("xyz");
		assertNotNull(xyz);
		// Test that it has the correct type so that we know it was reflected correctly.
		assertEquals(rset.getEObject(URI.createURI("java:/#int"), true), xyz.getEType());
		
		// Test that we have the annotation we added.
		assertNotNull(xyz.getEAnnotation("Override Annotation"));
	}
	
	public void test79083() {
		// Test bug 79083: Null ETypes from overrides that didn't have a reflection to give it the type. BeanInfo should make it EObject type.
		JavaClass testOverride = (JavaClass) rset.getEObject(URI.createURI("java:/org.eclipse.jem.tests.beaninfo#TestOverrides"), true); //$NON-NLS-1$
		assertNotNull(testOverride);
		EStructuralFeature test79083 = testOverride.getEStructuralFeature("test79083");
		assertNotNull(test79083);
		assertEquals(EcorePackage.eINSTANCE.getEObject(), test79083.getEType());
	}
}
