import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Construct the transformations.
*/
- public TransformationPaths() {
- transformations = new LinkedHashMap<Id<Transformation>, Transformation>();
- vertices = new ArrayList<String>();
- matrix = new TransformationPath[0][0];
- }
-
- public void replaceTransformations(
+ public TransformationPaths(
Map<Id<Transformation>, Transformation> aTransformations) {
transformations = aTransformations;
+ vertices = new ArrayList<String>();
+ matrix = new TransformationPath[0][0];
computeTransformationSequences();
}
@Override
public Id<RouterConfig> apply(RouterConfig aConfig,
- Id<RouterConfig> aOldConfig) {
- config.startConfigurationChange();
- try {
- return applyImpl(aConfig, aOldConfig);
- } finally {
- config.endConfigurationChange();
- }
- }
-
- private Id<RouterConfig> applyImpl(RouterConfig aConfig,
Id<RouterConfig> aOldConfig) {
if (aOldConfig != null) {
routerConfigs.remove(aOldConfig);
@Override
public void clear(Id<RouterConfig> aConfig) {
- config.startConfigurationChange();
- try {
- clearImpl(aConfig);
- } finally {
- config.endConfigurationChange();
- }
- }
-
- private void clearImpl(Id<RouterConfig> aConfig) {
routerConfigs.remove(aConfig);
update();
}
public interface XMLRouterConfiguration {
/**
- * To be called before the configuration is updated. Corresponds to write
- * lock acquire.
+ * To be called before the configuration is used. Corresponds to read lock
+ * acquire.
*/
- void startConfigurationChange();
+ void startPublishEvent();
/**
- * To be called after the configuration is updated. Corresponds to write
- * lock acquire.
+ * @return Configuration data. {@link #startPublishEvent()} must have been
+ * called before doing this.
*/
- void endConfigurationChange();
+ ExtendedRouterConfig getRouterConfig();
/**
- * To be called before the configuration is used. Corresponds to read lock
- * acquire.
+ * @return Transformation paths (derived data).
*/
- void startPublishEvent();
+ TransformationPaths getTransformations();
/**
* To be called after the configuration is used. Corresponds to read lock
void endPublishEvent();
/**
- * @return Configuration data.
- */
- ExtendedRouterConfig getRouterConfig();
-
- /**
- * Sets the configuration and updates derived data.
+ * Atomically sets the configuration and updates derived data. There will be
+ * a short time during which read attempts will fail.
*
* @param aConfig
* Configuration to set.
*/
void setRouterConfig(ExtendedRouterConfig aConfig);
-
- /**
- * @return Transformation paths (derived data).
- */
- TransformationPaths getTransformations();
}
public XMLRouterConfigurationImpl(ExtendedRouterConfig aConfig) {
config = aConfig;
- transformations = new TransformationPaths();
+ transformations = new TransformationPaths(config.transformationConfig()
+ .map());
}
public XMLRouterConfigurationImpl() {
this(new CompositeRouterConfig(new ArrayList<RouterConfig>()));
}
- @Override
- public void startConfigurationChange() {
- wlock.lock();
- }
-
- @Override
- public void endConfigurationChange() {
- wlock.unlock();
- }
-
@Override
public void startPublishEvent() {
rlock.lock();
@Override
public void setRouterConfig(ExtendedRouterConfig aConfig) {
- config = aConfig;
- transformations.replaceTransformations(config.transformationConfig()
- .map());
+
+ TransformationPaths newTransformations = new TransformationPaths(
+ aConfig.transformationConfig().map());
+
+ wlock.lock();
+ try {
+ config = aConfig;
+ transformations = newTransformations;
+ } finally {
+ wlock.unlock();
+ }
}
@Override
import static junit.framework.Assert.*;
import java.util.Collection;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.xml.transform.dom.DOMSource;
-import org.junit.Before;
import org.junit.Test;
import org.wamblee.xmlrouter.common.Id;
import org.wamblee.xmlrouter.config.Transformation;
private TransformationPaths transformations;
- @Before
- public void setUp() {
- transformations = new TransformationPaths();
- }
-
private Map<Id<Transformation>, Transformation> createTransformations(
long aStartId, Transformation... aTransformations) {
Map<Id<Transformation>, Transformation> res = new LinkedHashMap<Id<Transformation>, Transformation>();
@Test
public void testOneTransformation() {
- transformations.replaceTransformations(createTransformations(10L,
+ transformations = new TransformationPaths(createTransformations(10L,
new MyTransformation("A", "B")));
System.out.println(transformations.toString());
@Test
public void testMultipleTransformations() {
- transformations.replaceTransformations(createTransformations(10L,
+ transformations = new TransformationPaths(createTransformations(10L,
new MyTransformation("A", "B"), new MyTransformation("B", "C"),
new MyTransformation("C", "A")));
System.out.println(transformations);
assertEquals(2, transformations.getPath("C", "B").size());
- transformations.replaceTransformations(createTransformations(10L,
+ transformations = new TransformationPaths(createTransformations(10L,
new MyTransformation("B", "C"), new MyTransformation("C", "A")));
assertNull(transformations.getPath("C", "B"));
@Test
public void testUnknownDestination() {
- transformations.replaceTransformations(createTransformations(10L,
+ transformations = new TransformationPaths(createTransformations(10L,
new MyTransformation("A", "B")));
assertNull(transformations.getPath("A", "D"));
}
@Test
public void testWithoutTransformations() {
+ transformations = new TransformationPaths(
+ new HashMap<Id<Transformation>, Transformation>());
Collection<String> res = transformations.getPossibleTargetTypes("a");
assertEquals(1, res.size());
when(transformation.getToType()).thenReturn("bla");
when(transformation.transform(same(source1))).thenReturn(source2);
routerConfig.transformationConfig().add(transformation);
- config.getTransformations().replaceTransformations(
- routerConfig.transformationConfig().map());
+ config.setRouterConfig(routerConfig);
Destination destination = mock(Destination.class);
when(
source1, null);
routerConfig.transformationConfig().add(transformation);
- config.getTransformations().replaceTransformations(
- routerConfig.transformationConfig().map());
-
+ config.setRouterConfig(routerConfig);
Destination destination = mock(Destination.class);
when(
destination.chooseFromTargetTypes((Collection<String>) anyObject()))
source1, source2);
routerConfig.transformationConfig().add(transformation2);
- config.getTransformations().replaceTransformations(
- routerConfig.transformationConfig().map());
+ config.setRouterConfig(routerConfig);
when(
destination.chooseFromTargetTypes((Collection<String>) anyObject()))
.thenReturn(Arrays.asList("bla", "bla2"));
Transformation transformation = createTransformation("any", "other",
source1, source2);
routerConfig.transformationConfig().add(transformation);
- config.getTransformations().replaceTransformations(
- routerConfig.transformationConfig().map());
+ config.setRouterConfig(routerConfig);
router.publish("source", source1);
verify(listener, times(2)).delivered(any(EventInfo.class),
Transformation t2 = createTransformation("intermediate", "other",
source2, source3);
routerConfig.transformationConfig().add(t2);
- config.getTransformations().replaceTransformations(
- routerConfig.transformationConfig().map());
+ config.setRouterConfig(routerConfig);
router.publish("source", source1);
verify(listener).delivered(any(EventInfo.class),