/******************************************************************************* * Copyright (c) 2010 Ovidio Mallo 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: * Ovidio Mallo - initial API and implementation (bug 305367) ******************************************************************************/ package org.eclipse.core.tests.internal.databinding.observable.masterdetail; import java.util.HashMap; import java.util.Map; import junit.framework.Test; import junit.framework.TestSuite; import org.eclipse.core.databinding.beans.BeansObservables; import org.eclipse.core.databinding.observable.IObservable; import org.eclipse.core.databinding.observable.map.WritableMap; import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory; import org.eclipse.core.databinding.observable.value.WritableValue; import org.eclipse.core.internal.databinding.observable.masterdetail.MapDetailValueObservableMap; import org.eclipse.jface.databinding.conformance.util.MapChangeEventTracker; import org.eclipse.jface.examples.databinding.model.SimplePerson; import org.eclipse.jface.tests.databinding.AbstractDefaultRealmTestCase; /** * @since 1.3 */ public class MapDetailValueObservableMapTest extends AbstractDefaultRealmTestCase { public static Test suite() { TestSuite suite = new TestSuite( MapDetailValueObservableMapTest.class.getName()); suite.addTestSuite(MapDetailValueObservableMapTest.class); return suite; } public void testGetKeyType() { MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( new WritableMap(SimplePerson.class, SimplePerson.class), BeansObservables.valueFactory("name"), String.class); assertSame(SimplePerson.class, mdom.getKeyType()); } public void testGetValueType() { MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( new WritableMap(), BeansObservables.valueFactory("name"), String.class); assertSame(String.class, mdom.getValueType()); } public void testGetObserved() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // The observed object is the master key set. assertSame(masterMap, mdom.getObserved()); } public void testMasterSetInitiallyNotEmpty() { WritableMap masterMap = new WritableMap(); SimplePerson person = new SimplePerson(); person.setName("name"); masterMap.put(person, person); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Make sure that a non-empty master key set is initialized correctly. assertEquals(masterMap.size(), mdom.size()); assertEquals(person.getName(), mdom.get(person)); } public void testAddRemove() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Initially, the detail map is empty. assertTrue(mdom.isEmpty()); // Add a first person and check that its name is in the detail map. SimplePerson p1 = new SimplePerson(); p1.setName("name1"); masterMap.put(p1, p1); assertEquals(masterMap.size(), mdom.size()); assertEquals(p1.getName(), mdom.get(p1)); // Add a second person and check that it's name is in the detail map. SimplePerson p2 = new SimplePerson(); p2.setName("name2"); masterMap.put(p2, p2); assertEquals(masterMap.size(), mdom.size()); assertEquals(p2.getName(), mdom.get(p2)); // Remove the first person from the master map and check that we still // have the name of the second person in the detail map. masterMap.remove(p1); assertEquals(masterMap.size(), mdom.size()); assertEquals(p2.getName(), mdom.get(p2)); // Remove the second person as well. masterMap.remove(p2); assertTrue(mdom.isEmpty()); } public void testChangeDetail() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Change the detail attribute explicitly. SimplePerson p1 = new SimplePerson(); p1.setName("name1"); masterMap.put(p1, p1); assertEquals(p1.getName(), mdom.get(p1)); p1.setName("name2"); assertEquals(p1.getName(), mdom.get(p1)); // Change the detail attribute by changing the master. SimplePerson p2 = new SimplePerson(); p2.setName("name3"); masterMap.put(p1, p2); assertEquals(p2.getName(), mdom.get(p1)); } public void testPut() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Change the detail attribute explicitly. SimplePerson person = new SimplePerson(); person.setName("name1"); masterMap.put(person, person); assertEquals(person.getName(), mdom.get(person)); // Set a new name on the detail map. mdom.put(person, "name2"); // Check that the name has been propagated to the master. assertEquals("name2", person.getName()); assertEquals(person.getName(), mdom.get(person)); } public void testContainsValue() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Add a person with a given name. SimplePerson person = new SimplePerson(); person.setName("name"); masterMap.put(person, person); // Make sure the name of the person is contained. assertTrue(mdom.containsValue(person.getName())); // Remove the person and make sure that it's name cannot be found // anymore. masterMap.remove(person); assertFalse(mdom.containsValue(person.getName())); } public void testRemove() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Add two person objects to the map. SimplePerson p1 = new SimplePerson(); SimplePerson p2 = new SimplePerson(); masterMap.put(p1, p1); masterMap.put(p2, p2); // Initially, both person objects should be contained in the detail map. assertTrue(mdom.containsKey(p1)); assertTrue(mdom.containsKey(p2)); // Remove one person and check that it is not contained anymore. mdom.remove(p1); assertFalse(mdom.containsKey(p1)); assertTrue(mdom.containsKey(p2)); // Trying to remove a non-existent is allowed but has no effect. mdom.remove(p1); assertFalse(mdom.containsKey(p1)); assertTrue(mdom.containsKey(p2)); } public void testDetailObservableChangeEvent() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); MapChangeEventTracker changeTracker = MapChangeEventTracker .observe(mdom); SimplePerson person = new SimplePerson(); person.setName("old name"); // Initially, we should not have received any event. assertEquals(0, changeTracker.count); // Add the person and check that we receive an addition event on the // correct index and with the correct value. masterMap.put(person, person); assertEquals(1, changeTracker.count); assertEquals(1, changeTracker.event.diff.getAddedKeys().size()); assertEquals(0, changeTracker.event.diff.getRemovedKeys().size()); assertEquals(0, changeTracker.event.diff.getChangedKeys().size()); assertSame(person, changeTracker.event.diff.getAddedKeys().iterator() .next()); assertNull(changeTracker.event.diff.getOldValue(person)); assertEquals("old name", changeTracker.event.diff.getNewValue(person)); // Change the detail property and check that we receive a replace person.setName("new name"); assertEquals(2, changeTracker.count); assertEquals(0, changeTracker.event.diff.getAddedKeys().size()); assertEquals(0, changeTracker.event.diff.getRemovedKeys().size()); assertEquals(1, changeTracker.event.diff.getChangedKeys().size()); assertSame(person, changeTracker.event.diff.getChangedKeys().iterator() .next()); assertEquals("old name", changeTracker.event.diff.getOldValue(person)); assertEquals("new name", changeTracker.event.diff.getNewValue(person)); } public void testMasterNull() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Make sure null values are handled gracefully. masterMap.put(null, null); assertEquals(1, mdom.size()); assertNull(mdom.get(null)); } public void testDetailObservableValuesAreDisposed() { final Map detailObservables = new HashMap(); IObservableFactory detailValueFactory = new IObservableFactory() { @Override public IObservable createObservable(Object target) { WritableValue detailObservable = new WritableValue(); // Remember the created observables. detailObservables.put(target, detailObservable); return detailObservable; } }; WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, detailValueFactory, null); Object master1 = new Object(); Object master2 = new Object(); masterMap.put(master1, master1); masterMap.put(master2, master2); // Attach a listener in order to ensure that all detail observables are // actually created. MapChangeEventTracker.observe(mdom); assertEquals(mdom.size(), detailObservables.size()); // No detail observables should be disposed yet. assertFalse(((WritableValue) detailObservables.get(master1)) .isDisposed()); assertFalse(((WritableValue) detailObservables.get(master2)) .isDisposed()); // Only the detail observable for the removed master should be disposed. masterMap.remove(master2); assertFalse(((WritableValue) detailObservables.get(master1)) .isDisposed()); assertTrue(((WritableValue) detailObservables.get(master2)) .isDisposed()); // After disposing the detail map, all detail observables should be // disposed. mdom.dispose(); assertTrue(((WritableValue) detailObservables.get(master1)) .isDisposed()); assertTrue(((WritableValue) detailObservables.get(master2)) .isDisposed()); } public void testDisposeOnMasterDisposed() { WritableMap masterMap = new WritableMap(); MapDetailValueObservableMap mdom = new MapDetailValueObservableMap( masterMap, BeansObservables.valueFactory("name"), String.class); // Initially, nothing should be disposed. assertFalse(masterMap.isDisposed()); assertFalse(mdom.isDisposed()); // Upon disposing the master map, the detail map should be disposed as // well. masterMap.dispose(); assertTrue(masterMap.isDisposed()); assertTrue(mdom.isDisposed()); } }