blob: f15587059063aacc2983bb72df967f85493f981f [file] [log] [blame]
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -08003 *
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;
17
18import com.google.common.annotations.Beta;
19import org.onlab.util.ItemNotFoundException;
20import org.onosproject.net.driver.Behaviour;
21import org.onosproject.net.driver.Driver;
22import org.onosproject.net.driver.DriverData;
23import org.onosproject.net.driver.DriverService;
24import org.onosproject.net.driver.Projectable;
25import org.onosproject.net.provider.ProviderId;
26import org.slf4j.Logger;
27import org.slf4j.LoggerFactory;
28
29import java.util.Set;
30
31import static com.google.common.base.Preconditions.checkState;
32
33/**
34 * Base model entity, capable of being extended via projection mechanism.
35 */
36@Beta
37public abstract class AbstractProjectableModel extends AbstractModel implements Projectable {
38
39 private static Logger log = LoggerFactory.getLogger(AbstractProjectableModel.class);
40
41 protected static final String NO_DRIVER_SERVICE = "Driver service not bound yet";
42 protected static final String NO_DRIVER = "Driver has not been bound to %s";
43
44 // Static reference to the driver service; injected via setDriverService
45 private static DriverService driverService;
46
47 private Driver driver;
48
49 // For serialization
50 public AbstractProjectableModel() {
51 }
52
53 /**
54 * Creates a model entity attributed to the specified provider and
55 * optionally annotated.
56 *
57 * @param providerId identity of the provider
58 * @param annotations optional key/value annotations
59 */
60 public AbstractProjectableModel(ProviderId providerId, Annotations[] annotations) {
61 super(providerId, annotations);
62 }
63
64 /**
65 * Injects the driver service reference for use during projections into
66 * various behaviours.
67 * <p>
68 * This is a privileged call; unauthorized invocations will result in
69 * illegal state exception
70 *
71 * @param key opaque admin key object
72 * @param driverService injected driver service
73 * @throws IllegalStateException when invoked sans authorization
74 */
75 public static void setDriverService(Object key, DriverService driverService) {
76 // TODO: Rework this once we have means to enforce access to admin services in general
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080077// checkState(AbstractProjectableModel.driverService == key, "Unauthorized invocation");
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -080078 AbstractProjectableModel.driverService = driverService;
79 }
80
81 /**
82 * Returns the currently bound driver service reference.
83 *
84 * @return driver service
85 */
86 protected static DriverService driverService() {
87 return driverService;
88 }
89
90 /**
Thomas Vachuskae3ea9a42016-02-10 17:54:59 -080091 * Returns the currently bound driver or null if no driver is bound.
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -080092 *
93 * @return bound driver; null if none
94 */
Thomas Vachuskac4ee7372016-02-02 16:10:09 -080095 public Driver driver() {
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -080096 return driver;
97 }
98
99 @Override
100 public <B extends Behaviour> B as(Class<B> projectionClass) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800101 bindAndCheckDriver();
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -0800102 return driver.createBehaviour(asData(), projectionClass);
103 }
104
105 @Override
106 public <B extends Behaviour> boolean is(Class<B> projectionClass) {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800107 bindDriver();
108 return driver != null && driver.hasBehaviour(projectionClass);
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -0800109 }
110
111 /**
112 * Locates the driver to be used by this entity.
113 * <p>
114 * The default implementation derives the driver based on the {@code driver}
115 * annotation value.
116 *
117 * @return driver for alternate projections of this model entity or null
118 * if no driver is expected or driver is not found
119 */
120 protected Driver locateDriver() {
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800121 Annotations annotations = annotations();
122 String driverName = annotations != null ? annotations.value(AnnotationKeys.DRIVER) : null;
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -0800123 if (driverName != null) {
124 try {
125 return driverService.getDriver(driverName);
126 } catch (ItemNotFoundException e) {
127 log.warn("Driver {} not found.", driverName);
128 }
129 }
130 return null;
131 }
132
133 /**
Thomas Vachuskac4ee7372016-02-02 16:10:09 -0800134 * Attempts to binds the driver, if not already bound.
135 */
136 protected final void bindDriver() {
137 checkState(driverService != null, NO_DRIVER_SERVICE);
138 if (driver == null) {
139 driver = locateDriver();
140 }
141 }
142
143 /**
144 * Attempts to bind the driver, if not already bound and checks that the
145 * driver is bound.
146 *
147 * @throws IllegalStateException if driver cannot be bound
148 */
149 protected final void bindAndCheckDriver() {
150 bindDriver();
151 checkState(driver != null, NO_DRIVER, this);
152 }
153
154 /**
Thomas Vachuska3afbc7f2016-02-01 15:55:38 -0800155 * Returns self as an immutable driver data instance.
156 *
157 * @return self as driver data
158 */
159 protected DriverData asData() {
160 return new AnnotationDriverData();
161 }
162
163
164 /**
165 * Projection of the parent entity as a driver data entity.
166 */
167 protected class AnnotationDriverData implements DriverData {
168 @Override
169 public Driver driver() {
170 return driver;
171 }
172
173 @Override
174 public DeviceId deviceId() {
175 throw new UnsupportedOperationException("Entity not a device");
176 }
177
178 @Override
179 public MutableAnnotations set(String key, String value) {
180 throw new UnsupportedOperationException("Entity is immutable");
181 }
182
183 @Override
184 public MutableAnnotations clear(String... keys) {
185 throw new UnsupportedOperationException("Entity is immutable");
186 }
187
188 @Override
189 public Set<String> keys() {
190 return annotations().keys();
191 }
192
193 @Override
194 public String value(String key) {
195 return annotations().value(key);
196 }
197 }
198
199}