dae949912b96cfe564e018e2b99146597d26d626
[controller.git] / opendaylight / commons / concepts / src / main / java / org / opendaylight / controller / concepts / transform / CompositeClassBasedTransformer.java
1 /*\r
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 \r
9 package org.opendaylight.controller.concepts.transform;\r
10 \r
11 import java.util.ArrayList;\r
12 import java.util.Collection;\r
13 import java.util.Map;\r
14 import java.util.concurrent.ConcurrentHashMap;\r
15 \r
16 \r
17 /**\r
18  * Transformer which aggregates multiple implementations of\r
19  * {@link InputClassBasedTransformer}.\r
20  *\r
21  * The transformation process is driven by {@link Class} of input. The selection\r
22  * of used {@link InputClassBasedTransformer} is done by using the {@link Class}\r
23  * of input as a key to select the transformer.\r
24  *\r
25  * This approach provides quick resolution of transformer, but does not support\r
26  * registering a super type of input to provide transformation support for all\r
27  * subclasses, one must register a new instance of transformer for each valid\r
28  * input class.\r
29  *\r
30  * If you need more flexible selection of transformation consider using\r
31  * {@link CompositeConditionalTransformer} which is slower but most flexible or\r
32  * {@link RuleBasedTransformer} which provides declarative approach for\r
33  * transformation.\r
34  *\r
35  * See {@link #transform(Object)} for more information about tranformation\r
36  * process.\r
37  *\r
38  * @author Tony Tkacik <ttkacik@cisco.com>\r
39  *\r
40  * @param <I>\r
41  *            Input super-type\r
42  * @param <P>\r
43  *            Product\r
44  */\r
45 public abstract class CompositeClassBasedTransformer<I, P> implements\r
46         InputClassBasedTransformer<I, I, P>,\r
47         AggregateTransformer<I, P> {\r
48 \r
49     private Map<Class<? extends I>, InputClassBasedTransformer<I, ? extends I, P>> transformers = new ConcurrentHashMap<Class<? extends I>, InputClassBasedTransformer<I, ? extends I, P>>();\r
50 \r
51     /**\r
52      * Transforms an input into instance of Product class.\r
53      *\r
54      * The final registered transformer is the one which match following\r
55      * condition:\r
56      *\r
57      * <code>input.getClass() == transformer.getInputClass()</code>\r
58      *\r
59      * This means that transformers are not resolved by class hierarchy, only\r
60      * selected based on final class of the input. If you need more flexible\r
61      * selection of transformation consider using\r
62      * {@link CompositeConditionalTransformer} which is slower but more\r
63      * flexible.\r
64      *\r
65      */\r
66     @Override\r
67     public P transform(I input) {\r
68         @SuppressWarnings("unchecked")\r
69         InputClassBasedTransformer<I, I, P> transformer = (InputClassBasedTransformer<I, I, P>) transformers\r
70                 .get(input.getClass());\r
71         if (transformer == null)\r
72             throw new IllegalArgumentException("Transformation of: " + input\r
73                     + " is not supported");\r
74         return transformer.transform(input);\r
75     }\r
76 \r
77     /**\r
78      * Registers a new transformer.\r
79      *\r
80      * The transformer is registered for class returned by\r
81      * {@link InputClassBasedTransformer#getInputClass()}. Only one transformer\r
82      * can be registered for particular input class.\r
83      *\r
84      */\r
85     public void addTransformer(\r
86             InputClassBasedTransformer<I, ? extends I, P> transformer)\r
87             throws IllegalStateException {\r
88         if (transformer == null)\r
89             throw new IllegalArgumentException("Transformer should not be null");\r
90         if (transformer.getInputClass() == null)\r
91             throw new IllegalArgumentException(\r
92                     "Transformer should specify input class.");\r
93         transformers.put(transformer.getInputClass(), transformer);\r
94     }\r
95 \r
96     /**\r
97      * Removes an registered transformer.\r
98      *\r
99      * Note: Removal is currently unsupported.\r
100      *\r
101      * @param transformer\r
102      *            Tranformer to be removed.\r
103      * @throws IllegalArgumentException\r
104      *             If the provided transformer is null or is not registered.\r
105      */\r
106     public void removeTransformer(\r
107             InputClassBasedTransformer<I, ? extends I, P> transformer)\r
108             throws IllegalArgumentException {\r
109         throw new UnsupportedOperationException("Not implemented yet");\r
110     }\r
111 \r
112     @Override\r
113     public Collection<P> transformAll(Collection<? extends I> inputs) {\r
114         Collection<P> ret = new ArrayList<P>();\r
115         for (I i : inputs) {\r
116             ret.add(transform(i));\r
117         }\r
118         return ret;\r
119     }\r
120 \r
121 }\r