blob: c57af46fb6a8ca07061dea11a4dffdfd60f20546 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2009 Oracle. 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:
* Oracle - initial API and implementation
******************************************************************************/
package org.eclipse.jpt.utility.tests.internal.model.value.prefs;
import java.util.HashMap;
import java.util.Map;
import java.util.prefs.NodeChangeEvent;
import java.util.prefs.NodeChangeListener;
import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import org.eclipse.jpt.utility.internal.ClassTools;
import org.eclipse.jpt.utility.internal.model.value.SimplePropertyValueModel;
import org.eclipse.jpt.utility.internal.model.value.prefs.PreferencePropertyValueModel;
import org.eclipse.jpt.utility.internal.model.value.prefs.PreferencesCollectionValueModel;
import org.eclipse.jpt.utility.model.event.CollectionAddEvent;
import org.eclipse.jpt.utility.model.event.CollectionChangeEvent;
import org.eclipse.jpt.utility.model.event.CollectionClearEvent;
import org.eclipse.jpt.utility.model.event.CollectionEvent;
import org.eclipse.jpt.utility.model.event.CollectionRemoveEvent;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.model.listener.ChangeAdapter;
import org.eclipse.jpt.utility.model.listener.ChangeListener;
import org.eclipse.jpt.utility.model.listener.CollectionChangeListener;
import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;
@SuppressWarnings("nls")
public class PreferencesCollectionValueModelTests extends PreferencesTestCase {
private Map<String, String> expectedValues;
private WritablePropertyValueModel<Preferences> nodeHolder;
PreferencesCollectionValueModel<String> preferencesAdapter;
CollectionEvent event;
CollectionChangeListener listener;
private PropertyChangeListener itemListener;
boolean listenerRemoved = false;
private static final String KEY_NAME_1 = "foo 1";
private static final String KEY_NAME_2 = "foo 2";
private static final String KEY_NAME_3 = "foo 3";
private static final String STRING_VALUE_1 = "original string value 1";
private static final String STRING_VALUE_2 = "original string value 2";
private static final String STRING_VALUE_3 = "original string value 3";
public PreferencesCollectionValueModelTests(String name) {
super(name);
}
@Override
protected void setUp() throws Exception {
super.setUp();
this.expectedValues = new HashMap<String, String>();
this.testNode.put(KEY_NAME_1, STRING_VALUE_1); this.expectedValues.put(KEY_NAME_1, STRING_VALUE_1);
this.testNode.put(KEY_NAME_2, STRING_VALUE_2); this.expectedValues.put(KEY_NAME_2, STRING_VALUE_2);
this.testNode.put(KEY_NAME_3, STRING_VALUE_3); this.expectedValues.put(KEY_NAME_3, STRING_VALUE_3);
this.nodeHolder = new SimplePropertyValueModel<Preferences>(this.testNode);
this.preferencesAdapter = new PreferencesCollectionValueModel<String>(this.nodeHolder);
this.listener = this.buildCollectionChangeListener();
this.itemListener = this.buildItemListener();
this.preferencesAdapter.addCollectionChangeListener(CollectionValueModel.VALUES, this.listener);
this.event = null;
}
private CollectionChangeListener buildCollectionChangeListener() {
return new CollectionChangeListener() {
public void collectionChanged(CollectionChangeEvent e) {
this.logEvent(e);
}
public void collectionCleared(CollectionClearEvent e) {
this.logEvent(e);
}
public void itemsAdded(CollectionAddEvent e) {
this.logEvent(e);
}
public void itemsRemoved(CollectionRemoveEvent e) {
this.logEvent(e);
}
private void logEvent(CollectionEvent e) {
if (PreferencesCollectionValueModelTests.this.event != null) {
throw new IllegalStateException("unexpected this.event: " + e);
}
PreferencesCollectionValueModelTests.this.event = e;
}
};
}
private PropertyChangeListener buildItemListener() {
return new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent e) {
throw new IllegalStateException("unexpected this.event: " + e);
}
};
}
public void testSubjectHolder() throws Exception {
this.verifyAdapter(this.preferencesAdapter);
assertNull(this.event);
String ANOTHER_KEY_NAME_1 = "another key 1";
String ANOTHER_KEY_NAME_2 = "another key 2";
String ANOTHER_KEY_NAME_3 = "another key 3";
String ANOTHER_STRING_VALUE_1 = "another string value 1";
String ANOTHER_STRING_VALUE_2 = "another string value 2";
String ANOTHER_STRING_VALUE_3 = "another string value 3";
Preferences anotherNode = this.classNode.node("another test node");
this.expectedValues.clear();
anotherNode.put(ANOTHER_KEY_NAME_1, ANOTHER_STRING_VALUE_1); this.expectedValues.put(ANOTHER_KEY_NAME_1, ANOTHER_STRING_VALUE_1);
anotherNode.put(ANOTHER_KEY_NAME_2, ANOTHER_STRING_VALUE_2); this.expectedValues.put(ANOTHER_KEY_NAME_2, ANOTHER_STRING_VALUE_2);
anotherNode.put(ANOTHER_KEY_NAME_3, ANOTHER_STRING_VALUE_3); this.expectedValues.put(ANOTHER_KEY_NAME_3, ANOTHER_STRING_VALUE_3);
this.nodeHolder.setValue(anotherNode);
// collectionChanged does not pass any items in the this.event
this.verifyEvent();
this.verifyAdapter(this.preferencesAdapter);
this.event = null;
this.expectedValues.clear();
this.nodeHolder.setValue(null);
this.verifyEvent();
assertFalse(this.preferencesAdapter.iterator().hasNext());
this.event = null;
this.nodeHolder.setValue(this.testNode);
this.verifyEvent();
this.expectedValues.clear();
this.expectedValues.put(KEY_NAME_1, STRING_VALUE_1);
this.expectedValues.put(KEY_NAME_2, STRING_VALUE_2);
this.expectedValues.put(KEY_NAME_3, STRING_VALUE_3);
this.verifyAdapter(this.preferencesAdapter);
}
public void testAddPreference() throws Exception {
this.verifyAdapter(this.preferencesAdapter);
assertNull(this.event);
String ANOTHER_KEY_NAME = "another key";
String ANOTHER_STRING_VALUE = "another string value";
this.testNode.put(ANOTHER_KEY_NAME, ANOTHER_STRING_VALUE);
this.waitForEventQueueToClear();
Map<String, String> expectedItems = new HashMap<String, String>();
expectedItems.put(ANOTHER_KEY_NAME, ANOTHER_STRING_VALUE);
this.verifyEvent(expectedItems);
this.expectedValues.put(ANOTHER_KEY_NAME, ANOTHER_STRING_VALUE);
this.verifyAdapter(this.preferencesAdapter);
}
public void testRemovePreference() throws Exception {
this.verifyAdapter(this.preferencesAdapter);
assertNull(this.event);
this.testNode.remove(KEY_NAME_2);
this.waitForEventQueueToClear();
assertNotNull(this.event);
assertEquals(this.preferencesAdapter, this.event.getSource());
assertEquals(CollectionValueModel.VALUES, this.event.getCollectionName());
assertEquals(1, ((CollectionRemoveEvent) this.event).getItemsSize());
@SuppressWarnings("unchecked")
String key = ((PreferencePropertyValueModel<String>) ((CollectionRemoveEvent) this.event).getItems().iterator().next()).getKey();
assertEquals(KEY_NAME_2, key);
this.expectedValues.remove(KEY_NAME_2);
this.verifyAdapter(this.preferencesAdapter);
}
public void testChangePreference() throws Exception {
this.verifyAdapter(this.preferencesAdapter);
assertNull(this.event);
String DIFFERENT = "something completely different";
this.testNode.put(KEY_NAME_2, DIFFERENT);
this.waitForEventQueueToClear();
assertNull(this.event);
this.expectedValues.put(KEY_NAME_2, DIFFERENT);
this.verifyAdapter(this.preferencesAdapter);
}
public void testValues() throws Exception {
this.verifyNode(this.testNode);
this.verifyAdapter(this.preferencesAdapter);
}
/**
* test a situation where
* - we are listening to the node when it gets removed from the preferences "repository"
* - we get notification that it has been removed
* - we try to remove our this.listener
* - the node will throw an IllegalStateException - the adapter should handle it OK...
*/
public void testRemoveNode() throws Exception {
assertTrue(this.preferencesAdapter.hasAnyCollectionChangeListeners(CollectionValueModel.VALUES));
Preferences parent = this.testNode.parent();
parent.addNodeChangeListener(this.buildParentNodeChangeListener());
this.testNode.removeNode();
this.testNode.flush(); // this seems to be required for the this.event to trigger...
this.waitForEventQueueToClear();
assertTrue(this.listenerRemoved);
assertFalse(this.preferencesAdapter.hasAnyCollectionChangeListeners(CollectionValueModel.VALUES));
}
private NodeChangeListener buildParentNodeChangeListener() {
return new NodeChangeListener() {
public void childAdded(NodeChangeEvent e) {
throw new IllegalStateException("unexpected this.event: " + e);
}
public void childRemoved(NodeChangeEvent e) {
if (e.getChild() == PreferencesCollectionValueModelTests.this.testNode) {
PreferencesCollectionValueModelTests.this.preferencesAdapter.removeCollectionChangeListener(CollectionValueModel.VALUES, PreferencesCollectionValueModelTests.this.listener);
// this line of code will not execute if the line above triggers an exception
PreferencesCollectionValueModelTests.this.listenerRemoved = true;
}
}
};
}
public void testHasListeners() throws Exception {
assertTrue(this.preferencesAdapter.hasAnyCollectionChangeListeners(CollectionValueModel.VALUES));
assertTrue(this.nodeHasAnyPrefListeners(this.testNode));
this.preferencesAdapter.removeCollectionChangeListener(CollectionValueModel.VALUES, this.listener);
assertFalse(this.nodeHasAnyPrefListeners(this.testNode));
assertFalse(this.preferencesAdapter.hasAnyCollectionChangeListeners(CollectionValueModel.VALUES));
ChangeListener listener2 = this.buildChangeListener();
this.preferencesAdapter.addChangeListener(listener2);
assertTrue(this.preferencesAdapter.hasAnyCollectionChangeListeners(CollectionValueModel.VALUES));
assertTrue(this.nodeHasAnyPrefListeners(this.testNode));
this.preferencesAdapter.removeChangeListener(listener2);
assertFalse(this.nodeHasAnyPrefListeners(this.testNode));
assertFalse(this.preferencesAdapter.hasAnyCollectionChangeListeners(CollectionValueModel.VALUES));
}
private ChangeListener buildChangeListener() {
return new ChangeAdapter() {
@Override
public void collectionChanged(CollectionChangeEvent e) {
this.logEvent(e);
}
@Override
public void collectionCleared(CollectionClearEvent e) {
this.logEvent(e);
}
@Override
public void itemsAdded(CollectionAddEvent e) {
this.logEvent(e);
}
@Override
public void itemsRemoved(CollectionRemoveEvent e) {
this.logEvent(e);
}
private void logEvent(CollectionEvent e) {
if (PreferencesCollectionValueModelTests.this.event != null) {
throw new IllegalStateException("unexpected this.event: " + e);
}
PreferencesCollectionValueModelTests.this.event = e;
}
};
}
private void verifyEvent(Map<String, String> items) {
this.verifyEvent();
assertEquals(items.size(), ((CollectionAddEvent) this.event).getItemsSize());
@SuppressWarnings("unchecked")
Iterable<PreferencePropertyValueModel<String>> eventItems = (Iterable<PreferencePropertyValueModel<String>>) ((CollectionAddEvent) this.event).getItems();
this.verifyItems(items, eventItems);
}
private void verifyEvent() {
assertNotNull(this.event);
assertEquals(this.preferencesAdapter, this.event.getSource());
assertEquals(CollectionValueModel.VALUES, this.event.getCollectionName());
}
private void verifyNode(Preferences node) throws Exception {
String[] keys = node.keys();
assertEquals(this.expectedValues.size(), keys.length);
for (int i = 0; i < keys.length; i++) {
assertEquals(this.expectedValues.get(keys[i]), node.get(keys[i], "<missing preference>"));
}
}
private void verifyAdapter(PreferencesCollectionValueModel<String> cvm) {
assertEquals(this.expectedValues.size(), cvm.size());
this.verifyItems(this.expectedValues, cvm);
}
private void verifyItems(Map<String, String> expected, Iterable<PreferencePropertyValueModel<String>> actual) {
for (PreferencePropertyValueModel<String> model : actual) {
model.addPropertyChangeListener(PropertyValueModel.VALUE, this.itemListener);
assertEquals(expected.get(model.getKey()), model.getValue());
model.removePropertyChangeListener(PropertyValueModel.VALUE, this.itemListener);
}
}
private boolean nodeHasAnyPrefListeners(Preferences node) throws Exception {
PreferenceChangeListener[] prefListeners = (PreferenceChangeListener[]) ClassTools.fieldValue(node, "prefListeners");
return prefListeners.length > 0;
}
}