blob: b7a9f2b78d9da2c06286450ccc4f93a47983347e [file] [log] [blame]
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.net.driver;
17
18import com.google.common.collect.ImmutableMap;
alshabib975617b2015-04-09 13:26:53 -070019import com.google.common.collect.Maps;
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080020
21import java.util.Map;
Thomas Vachuska635c2d72015-05-08 14:32:13 -070022import java.util.Objects;
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080023import java.util.Set;
24
25import static com.google.common.base.MoreObjects.toStringHelper;
26import static com.google.common.base.Preconditions.checkArgument;
27import static com.google.common.base.Preconditions.checkNotNull;
28import static com.google.common.collect.ImmutableMap.copyOf;
29
30/**
31 * Default implementation of extensible driver.
32 */
33public class DefaultDriver implements Driver {
34
35 private final String name;
Thomas Vachuska635c2d72015-05-08 14:32:13 -070036 private final Driver parent;
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080037
38 private final String manufacturer;
39 private final String hwVersion;
40 private final String swVersion;
41
42 private final Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours;
43 private final Map<String, String> properties;
44
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080045 /**
46 * Creates a driver with the specified name.
47 *
48 * @param name driver name
Thomas Vachuska635c2d72015-05-08 14:32:13 -070049 * @param parent optional parent driver
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080050 * @param manufacturer device manufacturer
51 * @param hwVersion device hardware version
52 * @param swVersion device software version
53 * @param behaviours device behaviour classes
54 * @param properties properties for configuration of device behaviour classes
55 */
Thomas Vachuska635c2d72015-05-08 14:32:13 -070056 public DefaultDriver(String name, Driver parent, String manufacturer,
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080057 String hwVersion, String swVersion,
58 Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours,
59 Map<String, String> properties) {
60 this.name = checkNotNull(name, "Name cannot be null");
Thomas Vachuska635c2d72015-05-08 14:32:13 -070061 this.parent = parent;
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080062 this.manufacturer = checkNotNull(manufacturer, "Manufacturer cannot be null");
63 this.hwVersion = checkNotNull(hwVersion, "HW version cannot be null");
64 this.swVersion = checkNotNull(swVersion, "SW version cannot be null");
65 this.behaviours = copyOf(checkNotNull(behaviours, "Behaviours cannot be null"));
66 this.properties = copyOf(checkNotNull(properties, "Properties cannot be null"));
67 }
68
Thomas Vachuska5c2f8132015-04-08 23:09:08 -070069 @Override
70 public Driver merge(Driver other) {
Thomas Vachuska635c2d72015-05-08 14:32:13 -070071 checkArgument(parent == null || Objects.equals(parent, other.parent()),
72 "Parent drivers are not the same");
73
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080074 // Merge the behaviours.
alshabib975617b2015-04-09 13:26:53 -070075 Map<Class<? extends Behaviour>, Class<? extends Behaviour>>
76 behaviours = Maps.newHashMap();
Thomas Vachuska5c2f8132015-04-08 23:09:08 -070077 behaviours.putAll(this.behaviours);
78 other.behaviours().forEach(b -> behaviours.put(b, other.implementation(b)));
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080079
80 // Merge the properties.
81 ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
Thomas Vachuska5c2f8132015-04-08 23:09:08 -070082 properties.putAll(this.properties).putAll(other.properties());
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080083
Thomas Vachuska635c2d72015-05-08 14:32:13 -070084 return new DefaultDriver(name, other.parent(), manufacturer, hwVersion, swVersion,
alshabib975617b2015-04-09 13:26:53 -070085 ImmutableMap.copyOf(behaviours), properties.build());
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080086 }
87
88 @Override
89 public String name() {
90 return name;
91 }
92
93 @Override
94 public String manufacturer() {
95 return manufacturer;
96 }
97
98 @Override
99 public String hwVersion() {
100 return hwVersion;
101 }
102
103 @Override
104 public String swVersion() {
105 return swVersion;
106 }
107
108 @Override
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700109 public Driver parent() {
110 return parent;
111 }
112
113 @Override
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800114 public Set<Class<? extends Behaviour>> behaviours() {
115 return behaviours.keySet();
116 }
117
118 @Override
Thomas Vachuska5c2f8132015-04-08 23:09:08 -0700119 public Class<? extends Behaviour> implementation(Class<? extends Behaviour> behaviour) {
120 return behaviours.get(behaviour);
121 }
122
123 @Override
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800124 public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700125 return behaviours.containsKey(behaviourClass) ||
126 (parent != null && parent.hasBehaviour(behaviourClass));
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800127 }
128
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700129 @Override
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800130 public <T extends Behaviour> T createBehaviour(DriverData data,
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700131 Class<T> behaviourClass) {
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700132 T behaviour = createBehaviour(data, null, behaviourClass);
133 if (behaviour != null) {
134 return behaviour;
135 } else if (parent != null) {
136 return parent.createBehaviour(data, behaviourClass);
137 }
138 throw new IllegalArgumentException(behaviourClass.getName() + " not supported");
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700139 }
140
141 @Override
142 public <T extends Behaviour> T createBehaviour(DriverHandler handler,
143 Class<T> behaviourClass) {
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700144 T behaviour = createBehaviour(handler.data(), handler, behaviourClass);
145 if (behaviour != null) {
146 return behaviour;
147 } else if (parent != null) {
148 return parent.createBehaviour(handler, behaviourClass);
149 }
150 throw new IllegalArgumentException(behaviourClass.getName() + " not supported");
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700151 }
152
153 // Creates an instance of behaviour primed with the specified driver data.
154 private <T extends Behaviour> T createBehaviour(DriverData data, DriverHandler handler,
155 Class<T> behaviourClass) {
CNluciusa66c3972015-09-06 20:31:29 +0800156 //checkArgument(handler != null || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
157 // "{} is applicable only to handler context", behaviourClass.getName());
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800158
159 // Locate the implementation of the requested behaviour.
160 Class<? extends Behaviour> implementation = behaviours.get(behaviourClass);
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700161 if (implementation != null) {
162 // Create an instance of the behaviour and apply data as its context.
163 T behaviour = createBehaviour(behaviourClass, implementation);
164 behaviour.setData(data);
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800165
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700166 // If this is a handler behaviour, also apply handler as its context.
167 if (handler != null) {
168 ((HandlerBehaviour) behaviour).setHandler(handler);
169 }
170 return behaviour;
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700171 }
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700172 return null;
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800173 }
174
175 @SuppressWarnings("unchecked")
176 private <T extends Behaviour> T createBehaviour(Class<T> behaviourClass,
177 Class<? extends Behaviour> implementation) {
178 try {
179 return (T) implementation.newInstance();
180 } catch (InstantiationException | IllegalAccessException e) {
181 // TODO: add a specific unchecked exception
182 throw new IllegalArgumentException("Unable to create behaviour", e);
183 }
184 }
185
186 @Override
187 public Set<String> keys() {
188 return properties.keySet();
189 }
190
191 @Override
192 public String value(String key) {
193 return properties.get(key);
194 }
195
196 @Override
197 public Map<String, String> properties() {
198 return properties;
199 }
200
201 @Override
202 public String toString() {
203 return toStringHelper(this)
204 .add("name", name)
Thomas Vachuska635c2d72015-05-08 14:32:13 -0700205 .add("parent", parent)
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800206 .add("manufacturer", manufacturer)
207 .add("hwVersion", hwVersion)
208 .add("swVersion", swVersion)
209 .add("behaviours", behaviours)
210 .add("properties", properties)
211 .toString();
212 }
213
214}