/*
* Copyright (c) 2012 Diamond Light Source Ltd.
*
* 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
*/
package uk.ac.diamond.scisoft.analysis.rpc.flattening;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.junit.Assert;
import org.junit.Test;
/**
* One of three tests that demonstrate creating custom flatteners and unflatteners.
* <ul>
* <li> {@link AddHelperSimpleFlatteningTest} - Flattener for a simple class.
* <li> {@link AddHelperSpecializedMapFlatteningTest} - Flattener for a class that is a specialisation of a class that
* flattening is already supported for, in this example a specialised {@link Map}.
* <li> {@link AddHelperSimpleWithInterfaceFlatteningTest} - Flattener for a simple class. Demonstrates use of
* {@link IFlattens}.
* </ul>
*/
public class AddHelperSpecializedMapFlatteningTest {
/**
* Dummy class that doesn't do anything, only exists to verify flattening and unflattening
* <p>
* This is an implementation of Map which does the silly operation of only supporting mapping a string to itself.
* (This is not a complete example of a custom Map, only enough functionality is provided to demonstrate writing a
* custom flattener for it.)
*/
private static class MySpecialMap extends AbstractMap<String, String> {
private Map<String, String> map = new HashMap<String, String>();
public void putIdentity(String id) {
map.put(id, id);
}
@Override
public Set<java.util.Map.Entry<String, String>> entrySet() {
return map.entrySet();
}
}
private static class AddHelperIFlattener implements IFlattener<MySpecialMap> {
private static final String CONTENTS = "contents";
@Override
public Object flatten(Object obj, IRootFlattener root) {
MySpecialMap myObj = (MySpecialMap) obj;
Map<String, Object> hashMap = new HashMap<String, Object>();
hashMap.put(IFlattener.TYPE_KEY, MySpecialMap.class.getCanonicalName());
hashMap.put(CONTENTS, myObj.keySet().toArray()); // we only need to save the keys
return hashMap;
}
@Override
public MySpecialMap unflatten(Object obj, IRootFlattener root) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) obj;
MySpecialMap mySpecialMap = new MySpecialMap();
Object[] contents = (Object[]) map.get(CONTENTS);
for (Object object : contents) {
mySpecialMap.putIdentity((String) object);
}
return mySpecialMap;
}
@Override
public boolean canFlatten(Object obj) {
return obj instanceof MySpecialMap;
}
@Override
public boolean canUnFlatten(Object obj) {
if (obj instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> map = (Map<String, Object>) obj;
if (MySpecialMap.class.getCanonicalName().equals(map.get(IFlattener.TYPE_KEY))) {
return true;
}
}
return false;
}
}
@Test
public void testAddNewHelper() {
IRootFlattener root = new RootFlattener();
// create an instance to work with
MySpecialMap myMap = new MySpecialMap();
try {
// Demonstrate that this class is writable via the putIdentity method
myMap.put("hello", "goodbye");
Assert.fail();
} catch (UnsupportedOperationException e) {
}
myMap.putIdentity("foo");
myMap.putIdentity("bar");
// because the default flatteners already contain a generic map flattener, we can flatten/unflatten
// myMap, but we don't get out a MySpecialMap, but rather just a Map
Assert.assertTrue(root.canFlatten(myMap));
@SuppressWarnings("unchecked")
Map<String, String> simpleMap = (Map<String, String>) root.unflatten(root.flatten(myMap));
// this can be demonstrated by attempting the same operation that just failed
simpleMap.put("hello", "goodbye");
// Now register our own flattener and check what we get out is a MySpecialMap that put throws an exception for
root.addHelper(new AddHelperIFlattener());
// flatten and unflatten with my new helper, it will now give us a MySpecialMap which correctly
// doesn't support put
@SuppressWarnings("unchecked")
Map<String, String> mySpecialMap = (Map<String, String>) root.unflatten(root.flatten(myMap));
Assert.assertTrue(mySpecialMap instanceof MySpecialMap);
try {
mySpecialMap.put("hello", "goodbye");
Assert.fail();
} catch (UnsupportedOperationException e) {
}
}
}