blob: 84da212e7211fdcdfb4b8e523abc307e1fa29f5b [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;
22import java.util.Set;
23
24import static com.google.common.base.MoreObjects.toStringHelper;
25import static com.google.common.base.Preconditions.checkArgument;
26import static com.google.common.base.Preconditions.checkNotNull;
27import static com.google.common.collect.ImmutableMap.copyOf;
28
29/**
30 * Default implementation of extensible driver.
31 */
32public class DefaultDriver implements Driver {
33
34 private final String name;
35
36 private final String manufacturer;
37 private final String hwVersion;
38 private final String swVersion;
39
40 private final Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours;
41 private final Map<String, String> properties;
42
43
44 /**
45 * Creates a driver with the specified name.
46 *
47 * @param name driver name
48 * @param manufacturer device manufacturer
49 * @param hwVersion device hardware version
50 * @param swVersion device software version
51 * @param behaviours device behaviour classes
52 * @param properties properties for configuration of device behaviour classes
53 */
54 public DefaultDriver(String name, String manufacturer,
55 String hwVersion, String swVersion,
56 Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours,
57 Map<String, String> properties) {
58 this.name = checkNotNull(name, "Name cannot be null");
59 this.manufacturer = checkNotNull(manufacturer, "Manufacturer cannot be null");
60 this.hwVersion = checkNotNull(hwVersion, "HW version cannot be null");
61 this.swVersion = checkNotNull(swVersion, "SW version cannot be null");
62 this.behaviours = copyOf(checkNotNull(behaviours, "Behaviours cannot be null"));
63 this.properties = copyOf(checkNotNull(properties, "Properties cannot be null"));
64 }
65
Thomas Vachuska5c2f8132015-04-08 23:09:08 -070066 @Override
67 public Driver merge(Driver other) {
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080068 // Merge the behaviours.
alshabib975617b2015-04-09 13:26:53 -070069 Map<Class<? extends Behaviour>, Class<? extends Behaviour>>
70 behaviours = Maps.newHashMap();
Thomas Vachuska5c2f8132015-04-08 23:09:08 -070071 behaviours.putAll(this.behaviours);
72 other.behaviours().forEach(b -> behaviours.put(b, other.implementation(b)));
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080073
74 // Merge the properties.
75 ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
Thomas Vachuska5c2f8132015-04-08 23:09:08 -070076 properties.putAll(this.properties).putAll(other.properties());
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080077
78 return new DefaultDriver(name, manufacturer, hwVersion, swVersion,
alshabib975617b2015-04-09 13:26:53 -070079 ImmutableMap.copyOf(behaviours), properties.build());
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -080080 }
81
82 @Override
83 public String name() {
84 return name;
85 }
86
87 @Override
88 public String manufacturer() {
89 return manufacturer;
90 }
91
92 @Override
93 public String hwVersion() {
94 return hwVersion;
95 }
96
97 @Override
98 public String swVersion() {
99 return swVersion;
100 }
101
102 @Override
103 public Set<Class<? extends Behaviour>> behaviours() {
104 return behaviours.keySet();
105 }
106
107 @Override
Thomas Vachuska5c2f8132015-04-08 23:09:08 -0700108 public Class<? extends Behaviour> implementation(Class<? extends Behaviour> behaviour) {
109 return behaviours.get(behaviour);
110 }
111
112 @Override
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800113 public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
114 return behaviours.containsKey(behaviourClass);
115 }
116
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700117 @Override
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800118 public <T extends Behaviour> T createBehaviour(DriverData data,
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700119 Class<T> behaviourClass) {
120 return createBehaviour(data, null, behaviourClass);
121 }
122
123 @Override
124 public <T extends Behaviour> T createBehaviour(DriverHandler handler,
125 Class<T> behaviourClass) {
126 return createBehaviour(handler.data(), handler, behaviourClass);
127 }
128
129 // Creates an instance of behaviour primed with the specified driver data.
130 private <T extends Behaviour> T createBehaviour(DriverData data, DriverHandler handler,
131 Class<T> behaviourClass) {
132 checkArgument(handler != null || !HandlerBehaviour.class.isAssignableFrom(behaviourClass),
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800133 "{} is applicable only to handler context", behaviourClass.getName());
134
135 // Locate the implementation of the requested behaviour.
136 Class<? extends Behaviour> implementation = behaviours.get(behaviourClass);
137 checkArgument(implementation != null, "{} not supported", behaviourClass.getName());
138
139 // Create an instance of the behaviour and apply data as its context.
140 T behaviour = createBehaviour(behaviourClass, implementation);
141 behaviour.setData(data);
Thomas Vachuskafacc3f52015-04-10 08:58:36 -0700142
143 // If this is a handler behaviour, also apply handler as its context.
144 if (handler != null) {
145 ((HandlerBehaviour) behaviour).setHandler(handler);
146 }
Thomas Vachuskaa8f4e7d2015-01-08 17:31:55 -0800147 return behaviour;
148 }
149
150 @SuppressWarnings("unchecked")
151 private <T extends Behaviour> T createBehaviour(Class<T> behaviourClass,
152 Class<? extends Behaviour> implementation) {
153 try {
154 return (T) implementation.newInstance();
155 } catch (InstantiationException | IllegalAccessException e) {
156 // TODO: add a specific unchecked exception
157 throw new IllegalArgumentException("Unable to create behaviour", e);
158 }
159 }
160
161 @Override
162 public Set<String> keys() {
163 return properties.keySet();
164 }
165
166 @Override
167 public String value(String key) {
168 return properties.get(key);
169 }
170
171 @Override
172 public Map<String, String> properties() {
173 return properties;
174 }
175
176 @Override
177 public String toString() {
178 return toStringHelper(this)
179 .add("name", name)
180 .add("manufacturer", manufacturer)
181 .add("hwVersion", hwVersion)
182 .add("swVersion", swVersion)
183 .add("behaviours", behaviours)
184 .add("properties", properties)
185 .toString();
186 }
187
188}