/** * Copyright (c) 2009 BestSolution and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * Tom Schindl - Initial API and implementation */ package org.eclipse.emf.test.databinding.edit; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.List; import org.eclipse.core.databinding.observable.Realm; import org.eclipse.core.databinding.observable.list.IListChangeListener; import org.eclipse.core.databinding.observable.list.IObservableList; import org.eclipse.core.databinding.observable.list.ListChangeEvent; import org.eclipse.core.databinding.observable.list.ListDiff; import org.eclipse.core.databinding.observable.list.ListDiffEntry; import org.eclipse.core.databinding.observable.set.IObservableSet; import org.eclipse.core.databinding.observable.set.ISetChangeListener; import org.eclipse.core.databinding.observable.set.SetChangeEvent; import org.eclipse.core.databinding.observable.set.SetDiff; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.emf.common.command.BasicCommandStack; import org.eclipse.emf.common.command.CompoundCommand; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.databinding.IEMFListProperty.ListElementAccess; import org.eclipse.emf.databinding.edit.EMFEditProperties; import org.eclipse.emf.databinding.edit.IEMFEditListProperty; import org.eclipse.emf.databinding.edit.IEMFEditSetProperty; import org.eclipse.emf.databinding.edit.IEMFEditValueProperty; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.test.common.TestUtil; import org.eclipse.emf.test.databinding.emfdb.A; import org.eclipse.emf.test.databinding.emfdb.B; import org.eclipse.emf.test.databinding.emfdb.EmfdbFactory; import org.eclipse.emf.test.databinding.emfdb.EmfdbPackage; import org.junit.Before; import org.junit.Test; public class EMFEditPropertiesTest { private Resource resource; private EditingDomain editingDomain; private Realm testRealm; private boolean flag; private ListDiffEntry[] listEntries; private ListDiff listDiff; private SetDiff diff; private BasicCommandStack commandStack; @Before public void setUp() throws Exception { ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); ResourceSet resourceSet = new ResourceSetImpl(); commandStack = new BasicCommandStack(); resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put( Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl()); editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack, resourceSet); URI uri = URI.createFileURI(TestUtil.getPluginDirectory("org.eclipse.emf.test.databinding") + "/model/A.xmi"); resource = resourceSet.getResource(uri, true); testRealm = new Realm() { @Override public boolean isCurrent() { return true; } }; flag = false; listEntries = null; } // public void testValueEditingDomainEStructuralFeature() // { // fail("Not yet implemented"); // } // // public void testValueEditingDomainFeaturePath() // { // fail("Not yet implemented"); // } // // public void testValuesEditingDomainEStructuralFeatureArray() // { // fail("Not yet implemented"); // } // // public void testValuesEditingDomainFeaturePathArray() // { // fail("Not yet implemented"); // } @Test public void testListEditingDomainEStructuralFeature() { Realm.runWithDefault(testRealm, new Runnable() { public void run() { _testListEditingDomainEStructuralFeature(); } }); } public void _testListEditingDomainEStructuralFeature() { A a = (A)resource.getContents().get(0); IEMFEditListProperty prop = EMFEditProperties.list(editingDomain, EmfdbPackage.Literals.A__BLIST); IObservableList list = prop.observe(a); list.addListChangeListener(new IListChangeListener() { public void handleListChange(ListChangeEvent event) { flag = true; listEntries = event.diff.getDifferences(); } }); assertEquals(a.getBlist().size(), list.size()); B b = EmfdbFactory.eINSTANCE.createB(); list.add(b); // a.getBlist().add(b); assertEquals(a.getBlist().size(), list.size()); assertTrue(flag); assertNotNull(listEntries); assertEquals(1, listEntries.length); assertTrue(listEntries[0].isAddition()); assertSame(b, listEntries[0].getElement()); assertEquals(a.getBlist().size() - 1, listEntries[0].getPosition()); assertEquals(list.get(0), a.getBlist().get(0)); } @Test public void testSetProperty() { Realm.runWithDefault(testRealm, new Runnable() { public void run() { _testSetProperty(); } }); } public void _testSetProperty() { A a = (A)resource.getContents().get(0); IEMFEditSetProperty prop = EMFEditProperties.set(editingDomain, EmfdbPackage.Literals.A__BLIST); IObservableSet set = prop.observe(a); assertNotNull(set); set.addSetChangeListener(new ISetChangeListener() { public void handleSetChange(SetChangeEvent event) { diff = event.diff; } }); assertNull(diff); assertFalse(commandStack.canUndo()); B b = EmfdbFactory.eINSTANCE.createB(); // a.getBlist().add(b); set.add(b); assertNotNull(diff); assertEquals(1, diff.getAdditions().size()); assertSame(b, diff.getAdditions().iterator().next()); assertTrue(commandStack.canUndo()); assertFalse(commandStack.canRedo()); diff = null; commandStack.undo(); assertNotNull(diff); assertEquals(1, diff.getRemovals().size()); assertSame(b, diff.getRemovals().iterator().next()); assertFalse(commandStack.canUndo()); assertTrue(commandStack.canRedo()); } // public void testListEditingDomainFeaturePath() // { // fail("Not yet implemented"); // } // // public void testMultiListEditingDomainEStructuralFeatureArray() // { // fail("Not yet implemented"); // } @Test public void testMultiListEditingDomainEStructuralFeatureArray() { Realm.runWithDefault(testRealm, new Runnable() { public void run() { A a = (A)resource.getContents().get(0); IEMFEditListProperty prop = EMFEditProperties.multiList( editingDomain, EmfdbPackage.Literals.A__STRING, EmfdbPackage.Literals.A__BLIST); IObservableList list = prop.observe(a); list.addListChangeListener(new IListChangeListener() { public void handleListChange(ListChangeEvent event) { flag = true; listEntries = event.diff.getDifferences(); } }); assertEquals(a.getString(), list.get(0)); assertEquals(a.getBlist().size() + 1, list.size()); B b = EmfdbFactory.eINSTANCE.createB(); a.getBlist().add(b); assertEquals(a.getBlist().size() + 1, list.size()); assertTrue(flag); assertNotNull(listEntries); assertEquals(1, listEntries.length); assertTrue(listEntries[0].isAddition()); assertSame(b, listEntries[0].getElement()); assertEquals(a.getBlist().size(), listEntries[0].getPosition()); assertEquals(list.get(1), a.getBlist().get(0)); a.setString(null); assertEquals(a.getBlist().size(), list.size()); assertEquals(list.get(0), a.getBlist().get(0)); } }); } @Test public void testResourceProperty() { Realm.runWithDefault(testRealm, new Runnable() { public void run() { _testResourceProperty(); } }); } private void _testResourceProperty() { IEMFEditListProperty prop = EMFEditProperties.resource(editingDomain); IObservableList list = prop.observe(resource); list.addListChangeListener(new IListChangeListener() { public void handleListChange(ListChangeEvent event) { listDiff = event.diff; } }); assertNull(listDiff); // Adding A a = EmfdbFactory.eINSTANCE.createA(); A a1 = EmfdbFactory.eINSTANCE.createA(); resource.getContents().add(a); assertNotNull(listDiff); assertEquals(1, listDiff.getDifferences().length); assertSame(a, listDiff.getDifferences()[0].getElement()); assertEquals(1, listDiff.getDifferences()[0].getPosition()); assertTrue(listDiff.getDifferences()[0].isAddition()); // Moving resource.getContents().move(0, a); assertEquals(2, listDiff.getDifferences().length); assertFalse(listDiff.getDifferences()[0].isAddition()); // Removal assertEquals(1, listDiff.getDifferences()[0].getPosition()); assertTrue(listDiff.getDifferences()[1].isAddition()); // Addition assertEquals(0, listDiff.getDifferences()[1].getPosition()); // Removing resource.getContents().remove(a); assertEquals(1, listDiff.getDifferences().length); assertFalse(listDiff.getDifferences()[0].isAddition()); // Removal assertEquals(0, listDiff.getDifferences()[0].getPosition()); // Adding many resource.getContents().addAll(Arrays.asList(a, a1)); assertEquals(2, listDiff.getDifferences().length); // Remove many resource.getContents().removeAll(Arrays.asList(a, a1)); assertEquals(2, listDiff.getDifferences().length); // ============================================================= // Changed through IObservableList // Add assertNull(commandStack.getUndoCommand()); list.add(a); assertNotNull(listDiff); assertEquals(1, listDiff.getDifferences().length); assertSame(a, listDiff.getDifferences()[0].getElement()); assertEquals(1, listDiff.getDifferences()[0].getPosition()); assertTrue(listDiff.getDifferences()[0].isAddition()); assertNotNull(commandStack.getUndoCommand()); assertTrue(commandStack.canUndo()); assertTrue(commandStack.getUndoCommand() instanceof CompoundCommand); CompoundCommand cmd = (CompoundCommand)commandStack.getUndoCommand(); assertEquals(1, cmd.getCommandList().size()); assertTrue(cmd.getCommandList().get(0) instanceof AddCommand); commandStack.undo(); assertFalse(commandStack.canUndo()); commandStack.redo(); commandStack.flush(); // Moving list.move(1, 0); assertEquals(2, listDiff.getDifferences().length); assertFalse(listDiff.getDifferences()[0].isAddition()); // Removal assertEquals(1, listDiff.getDifferences()[0].getPosition()); assertTrue(listDiff.getDifferences()[1].isAddition()); // Addition assertEquals(0, listDiff.getDifferences()[1].getPosition()); assertTrue(commandStack.canUndo()); assertTrue(commandStack.getUndoCommand() instanceof CompoundCommand); commandStack.undo(); assertFalse(commandStack.canUndo()); commandStack.redo(); commandStack.flush(); // Removing list.remove(a); assertEquals(1, listDiff.getDifferences().length); assertFalse(listDiff.getDifferences()[0].isAddition()); // Removal assertEquals(0, listDiff.getDifferences()[0].getPosition()); assertTrue(commandStack.canUndo()); assertTrue(commandStack.getUndoCommand() instanceof CompoundCommand); commandStack.undo(); assertFalse(commandStack.canUndo()); commandStack.redo(); commandStack.flush(); // Adding many list.addAll(Arrays.asList(a, a1)); assertEquals(2, listDiff.getDifferences().length); assertTrue(commandStack.canUndo()); assertTrue(commandStack.getUndoCommand() instanceof CompoundCommand); commandStack.undo(); assertFalse(commandStack.canUndo()); commandStack.redo(); commandStack.flush(); // Remove many list.removeAll(Arrays.asList(a, a1)); assertEquals(2, listDiff.getDifferences().length); assertTrue(commandStack.canUndo()); assertTrue(commandStack.getUndoCommand() instanceof CompoundCommand); commandStack.undo(); assertFalse(commandStack.canUndo()); commandStack.redo(); commandStack.flush(); } @Test public void testListPropertyOnSingleFeature() { Realm.runWithDefault(testRealm, new Runnable() { public void run() { _testListPropertyOnSingleFeature(); } }); } public void _testListPropertyOnSingleFeature() { A a = (A)resource.getContents().get(0); IEMFEditListProperty prop = EMFEditProperties.list(editingDomain, EmfdbPackage.Literals.A__STRING); IObservableList l = prop.observe(a); assertEquals(1, l.size()); assertEquals("Instance 1", l.get(0)); a.setString("Bla"); assertEquals("Bla", l.get(0)); l.addListChangeListener(new IListChangeListener() { public void handleListChange(ListChangeEvent event) { assertEquals(2, event.diff.getDifferences().length); assertEquals(0, event.diff.getDifferences()[0].getPosition()); assertFalse(event.diff.getDifferences()[0].isAddition()); assertEquals("Bla", event.diff.getDifferences()[0].getElement()); assertEquals(0, event.diff.getDifferences()[1].getPosition()); assertTrue(event.diff.getDifferences()[1].isAddition()); assertEquals("Instance 1", event.diff.getDifferences()[1].getElement()); } }); a.setString("Instance 1"); } @Test public void testListElementProperty() { Realm.runWithDefault(testRealm, new Runnable() { public void run() { _testListElementProperty(); } }); } public void _testListElementProperty() { IEMFEditListProperty prop = EMFEditProperties.list(editingDomain, EmfdbPackage.Literals.A__BLIST); IEMFEditValueProperty valueProp = prop.value(new ListElementAccess<Object>() { @Override public int getReadValueIndex(List< Object > list) { return 0; } @Override public int getWriteValueIndex(List< Object > list) { return 0; } }); IEMFEditValueProperty detailValue = valueProp.value(EmfdbPackage.Literals.B__STRING); IObservableValue value = detailValue.observe(resource.getContents().get(0)); assertEquals("Instance 1", value.getValue()); A a = (A)resource.getContents().get(0); a.getBlist().get(0).setString("Bla Bla"); assertEquals("Bla Bla", value.getValue()); B b = EmfdbFactory.eINSTANCE.createB(); b.setString("New Element"); a.getBlist().add(0, b); assertEquals("New Element", value.getValue()); b = EmfdbFactory.eINSTANCE.createB(); b.setString("New Element 2"); IObservableValue aObservable = valueProp.observe(a); try { aObservable.setValue(b); } finally { aObservable.dispose(); } assertEquals("New Element 2", value.getValue()); } // // public void testMultiListEditingDomainFeaturePathEStructuralFeatureArray() // { // fail("Not yet implemented"); // } // // public void testMultiListEditingDomainFeaturePathArray() // { // fail("Not yet implemented"); // } // // public void testMultiListEditingDomainIEMFEditListPropertyArray() // { // fail("Not yet implemented"); // } // // public void testMap() // { // fail("Not yet implemented"); // } }