--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
+ <modelVersion>4.0.0</modelVersion>\r
+ <parent>\r
+ <groupId>org.opendaylight.controller</groupId>\r
+ <artifactId>commons.opendaylight</artifactId>\r
+ <version>1.4.0-SNAPSHOT</version>\r
+ <relativePath>../../commons/opendaylight</relativePath>\r
+ </parent>\r
+\r
+ <artifactId>concepts</artifactId>\r
+ <version>0.5.0-SNAPSHOT</version>\r
+ <packaging>bundle</packaging>\r
+\r
+ <build>\r
+ <plugins>\r
+ <plugin>\r
+ <groupId>org.apache.felix</groupId>\r
+ <artifactId>maven-bundle-plugin</artifactId>\r
+ <version>2.3.6</version>\r
+ <extensions>true</extensions>\r
+ <configuration>\r
+ <instructions>\r
+ <Import-Package>\r
+ org.slf4j,\r
+ org.osgi.framework,\r
+ org.apache.commons.lang3.builder,\r
+ org.apache.felix.dm,\r
+ org.apache.commons.lang3.tuple,\r
+ javax.xml.bind.annotation,\r
+ javax.xml.bind.annotation.adapters\r
+ </Import-Package>\r
+ <Export-Package>\r
+ org.opendaylight.controller.concepts.transform\r
+ </Export-Package>\r
+ </instructions>\r
+ <manifestLocation>${project.basedir}/META-INF</manifestLocation>\r
+ </configuration>\r
+ </plugin>\r
+ </plugins>\r
+ </build>\r
+ <dependencies>\r
+ <dependency>\r
+ <groupId>junit</groupId>\r
+ <artifactId>junit</artifactId>\r
+ <version>4.8.1</version>\r
+ <scope>test</scope>\r
+ </dependency>\r
+ </dependencies>\r
+</project>\r
--- /dev/null
+\r
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+public interface Acceptor<I> {\r
+\r
+ /**\r
+ * \r
+ * @param input\r
+ * @return true if input is accepted.\r
+ */\r
+ boolean isAcceptable(I input);\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+import java.util.Collection;\r
+/**\r
+ * \r
+ * @author Tony Tkacik\r
+ *\r
+ * @param <I>\r
+ * @param <P>\r
+ */\r
+public interface AggregateTransformer<I,P> extends Transformer<I,P> {\r
+\r
+ Collection<P> transformAll(Collection<? extends I> inputs);\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Map;\r
+import java.util.concurrent.ConcurrentHashMap;\r
+\r
+\r
+/**\r
+ * Transformer which aggregates multiple implementations of\r
+ * {@link InputClassBasedTransformer}.\r
+ * \r
+ * The transformation process is driven by {@link Class} of input. The selection\r
+ * of used {@link InputClassBasedTransformer} is done by using the {@link Class}\r
+ * of input as a key to select the transformer.\r
+ * \r
+ * This approach provides quick resolution of transformer, but does not support\r
+ * registering a super type of input to provide transformation support for all\r
+ * subclasses, one must register a new instance of transformer for each valid\r
+ * input class.\r
+ * \r
+ * If you need more flexible selection of transformation consider using\r
+ * {@link CompositeConditionalTransformer} which is slower but most flexible or\r
+ * {@link RuleBasedTransformer} which provides declarative approach for\r
+ * transformation.\r
+ * \r
+ * See {@link #transform(Object)} for more information about tranformation\r
+ * process.\r
+ * \r
+ * @author Tony Tkacik <ttkacik@cisco.com>\r
+ * \r
+ * @param <I>\r
+ * Input super-type\r
+ * @param <P>\r
+ * Product\r
+ */\r
+public abstract class CompositeClassBasedTransformer<I, P> implements\r
+ InputClassBasedTransformer<I, I, P>,\r
+ AggregateTransformer<I, P> {\r
+\r
+ private Map<Class<? extends I>, InputClassBasedTransformer<I, ? extends I, P>> transformers = new ConcurrentHashMap<Class<? extends I>, InputClassBasedTransformer<I, ? extends I, P>>();\r
+\r
+ /**\r
+ * Transforms an input into instance of Product class.\r
+ * \r
+ * The final registered transformer is the one which match following\r
+ * condition:\r
+ * \r
+ * <code>input.getClass() == transformer.getInputClass()</code>\r
+ * \r
+ * This means that transformers are not resolved by class hierarchy, only\r
+ * selected based on final class of the input. If you need more flexible\r
+ * selection of transformation consider using\r
+ * {@link CompositeConditionalTransformer} which is slower but more\r
+ * flexible.\r
+ * \r
+ */\r
+ @Override\r
+ public P transform(I input) {\r
+ @SuppressWarnings("unchecked")\r
+ InputClassBasedTransformer<I, I, P> transformer = (InputClassBasedTransformer<I, I, P>) transformers\r
+ .get(input.getClass());\r
+ if (transformer == null)\r
+ throw new IllegalArgumentException("Transformation of: " + input\r
+ + " is not supported");\r
+ return transformer.transform(input);\r
+ }\r
+\r
+ /**\r
+ * Registers a new transformer.\r
+ * \r
+ * The transformer is registered for class returned by\r
+ * {@link InputClassBasedTransformer#getInputClass()}. Only one transformer\r
+ * can be registered for particular input class.\r
+ * \r
+ */\r
+ public void addTransformer(\r
+ InputClassBasedTransformer<I, ? extends I, P> transformer)\r
+ throws IllegalStateException {\r
+ if (transformer == null)\r
+ throw new IllegalArgumentException("Transformer should not be null");\r
+ if (transformer.getInputClass() == null)\r
+ throw new IllegalArgumentException(\r
+ "Transformer should specify input class.");\r
+ transformers.put(transformer.getInputClass(), transformer);\r
+ }\r
+\r
+ /**\r
+ * Removes an registered transformer.\r
+ * \r
+ * Note: Removal is currently unsupported.\r
+ * \r
+ * @param transformer\r
+ * Tranformer to be removed.\r
+ * @throws IllegalArgumentException\r
+ * If the provided transformer is null or is not registered.\r
+ */\r
+ public void removeTransformer(\r
+ InputClassBasedTransformer<I, ? extends I, P> transformer)\r
+ throws IllegalArgumentException {\r
+ throw new UnsupportedOperationException("Not implemented yet");\r
+ }\r
+ \r
+ @Override\r
+ public Collection<P> transformAll(Collection<? extends I> inputs) {\r
+ Collection<P> ret = new ArrayList<P>();\r
+ for (I i : inputs) {\r
+ ret.add(transform(i));\r
+ }\r
+ return ret;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Comparator;\r
+import java.util.Set;\r
+import java.util.TreeSet;\r
+\r
+/**\r
+ * Composite transformer which aggregates multiple implementation and selects\r
+ * the one which accepts the input.\r
+ * \r
+ * \r
+ * @author Tony Tkacik\r
+ * \r
+ * @param <I>\r
+ * Input class for transformation\r
+ * @param <P>\r
+ * Product of transformation\r
+ */\r
+public class CompositeConditionalTransformer<I, P> implements\r
+ SimpleConditionalTransformer<I, P>,\r
+ AggregateTransformer<I,P> {\r
+\r
+ private final Comparator<TransformerWithPriority<I, P>> comparator = new Comparator<TransformerWithPriority<I, P>>() {\r
+\r
+ @Override\r
+ public int compare(TransformerWithPriority<I, P> o1,\r
+ TransformerWithPriority<I, P> o2) {\r
+ return Integer.compare(o1.priority, o2.priority);\r
+ }\r
+\r
+ };\r
+ private final Set<TransformerWithPriority<I, P>> transformers;\r
+\r
+ public CompositeConditionalTransformer() {\r
+ // FIXME: Add Ordering\r
+ transformers = new TreeSet<TransformerWithPriority<I, P>>(comparator);\r
+ }\r
+\r
+ @Override\r
+ public boolean isAcceptable(I input) {\r
+ for (SimpleConditionalTransformer<I, P> trans : transformers) {\r
+ if (trans.isAcceptable(input)) {\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ public P transform(I input) {\r
+ for (SimpleConditionalTransformer<I, P> trans : transformers) {\r
+ if (trans.isAcceptable(input)) {\r
+ return trans.transform(input);\r
+ }\r
+ }\r
+ throw new IllegalStateException(\r
+ "Transformer for provided input is not available.");\r
+ }\r
+\r
+ public void addTransformer(SimpleConditionalTransformer<I, P> transformer,\r
+ int priority) throws IllegalStateException {\r
+ if (transformer == null) {\r
+ throw new IllegalArgumentException(\r
+ "transformer should not be null.");\r
+ }\r
+ TransformerWithPriority<I, P> withPriority = new TransformerWithPriority<I, P>(\r
+ transformer, priority);\r
+ if (false == transformers.add(withPriority)) {\r
+ throw new IllegalStateException("transformer " + transformer\r
+ + "already registered");\r
+ }\r
+ }\r
+\r
+ public void removeTransformer(SimpleConditionalTransformer<I, P> transformer)\r
+ throws IllegalArgumentException {\r
+ if (transformer == null) {\r
+ throw new IllegalArgumentException(\r
+ "transformer should not be null.");\r
+ }\r
+ if (false == transformers.remove(transformer)) {\r
+ throw new IllegalStateException("transformer " + transformer\r
+ + "already registered");\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public Collection<P> transformAll(Collection<? extends I> inputs) {\r
+ Collection<P> ret = new ArrayList<P>();\r
+ for (I i : inputs) {\r
+ ret.add(transform(i));\r
+ }\r
+ return ret;\r
+ }\r
+\r
+ private static class TransformerWithPriority<I, P> implements\r
+ SimpleConditionalTransformer<I, P> {\r
+ final int priority;\r
+ final SimpleConditionalTransformer<I, P> transformer;\r
+ \r
+ public TransformerWithPriority(\r
+ SimpleConditionalTransformer<I, P> transformer, int priority) {\r
+ this.priority = priority;\r
+ this.transformer = transformer;\r
+ }\r
+ \r
+ @Override\r
+ public int hashCode() {\r
+ final int prime = 31;\r
+ int result = 1;\r
+ result = prime * result\r
+ + ((transformer == null) ? 0 : transformer.hashCode());\r
+ return result;\r
+ }\r
+ \r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (this == obj)\r
+ return true;\r
+ if (obj == null)\r
+ return false;\r
+ if (getClass() != obj.getClass())\r
+ return false;\r
+ TransformerWithPriority<?,?> other = (TransformerWithPriority<?,?>) obj;\r
+ if (transformer == null) {\r
+ if (other.transformer != null)\r
+ return false;\r
+ } else if (!transformer.equals(other.transformer))\r
+ return false;\r
+ return true;\r
+ }\r
+ \r
+ @Override\r
+ public boolean isAcceptable(I input) {\r
+ return transformer.isAcceptable(input);\r
+ }\r
+ \r
+ @Override\r
+ public P transform(I input) {\r
+ return transformer.transform(input);\r
+ }\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+/**\r
+ * Input class based transformer\r
+ * \r
+ * {@link Transformer} which accepts / transforms only specific classes of\r
+ * input, and is useful if the selection of transformer should be based on the\r
+ * class of the input and there is one-to-one mapping between input class and\r
+ * transformer.\r
+ * \r
+ * \r
+ * @author Tony Tkacik\r
+ * \r
+ * @param <S>\r
+ * Common supertype of input\r
+ * @param <I>\r
+ * Concrete type of input\r
+ * @param <P>\r
+ * Product\r
+ */\r
+public interface InputClassBasedTransformer<S, I extends S, P> extends\r
+ Transformer<I, P> {\r
+\r
+ /**\r
+ * Returns an {@link Class} of input which is acceptable for transformation.\r
+ * \r
+ * @return {@link Class} of input which is acceptable for transformation.\r
+ */\r
+ Class<? extends S> getInputClass();\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+import java.util.Set;\r
+\r
+/**\r
+ * Transformer with set of acceptance rules\r
+ * \r
+ * The transformer provides a set of {@link Acceptor}s, which could be used to\r
+ * verify if the input will produce result using the transformer.\r
+ * \r
+ * The transormer is able to produce result if ANY of associated\r
+ * {@link Acceptor}s accepted result.\r
+ * \r
+ * @author Tony Tkacik\r
+ * \r
+ * @param <I>\r
+ * Input class for transformation\r
+ * @param <P>\r
+ * Product of transformation\r
+ */\r
+public interface RuleBasedTransformer<I, P> extends Transformer<I, P> {\r
+\r
+ /**\r
+ * Set of {@link Acceptor}, which could be used to verify if the input is\r
+ * usable by transformer.\r
+ * \r
+ * The transformer is able to produce result if ANY of associated\r
+ * {@link Acceptor}s accepted result.\r
+ * \r
+ * @return Set of input acceptance rules associated to this transformer.\r
+ */\r
+ Set<Acceptor<I>> getRules();\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+/**\r
+ * Simple condition-based transformer\r
+ * \r
+ * The transformer provides {@link #isAcceptable(Object)} method,\r
+ * which could be used to query transformer if the input will produce\r
+ * result.\r
+ * \r
+ * This interface is simplified version of {@link RuleBasedTransformer} - does not\r
+ * provide decoupling of Acceptance rule from transformer, and should be used only\r
+ * for simple use-cases.\r
+ * \r
+ * @author Tony Tkacik\r
+ *\r
+ * @param <I> Input class for transformation\r
+ * @param <P> Product of transformation\r
+ */\r
+public interface SimpleConditionalTransformer<I,P> extends Transformer<I, P>, Acceptor<I> {\r
+\r
+\r
+ /**\r
+ * Checks if the input is acceptable \r
+ * for processing by the transformer.\r
+ * \r
+ * @return true it the input is acceptable for processing by transformer.\r
+ */\r
+ @Override\r
+ public boolean isAcceptable(I input);\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.concepts.tranform;\r
+\r
+/**\r
+ * Factory which produces product based on input object\r
+ * \r
+ * @author Tony Tkacik\r
+ *\r
+ * @param <I> Input\r
+ * @param <P> Product\r
+ */\r
+public interface Transformer<I,P> {\r
+ /**\r
+ * Transforms input into instance of product.\r
+ * \r
+ * @param input Input which drives transformation\r
+ * @return Instance of product which was created from supplied input.\r
+ */\r
+ P transform(I input);\r
+}\r
<module>../../samples/simpleforwarding</module>
<module>../../samples/loadbalancer</module>
<module>../../samples/northbound/loadbalancer</module>
+ <module>../../commons/concepts</module>
</modules>
<build>