blob: 5255fa0f494283eaf2c75303b7f322392d672302 [file] [log] [blame]
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -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.ui;
17
Thomas Vachuskac4178cc2015-12-10 11:43:32 -080018import com.google.common.collect.ImmutableList;
Simon Hunt7379a3d2017-06-20 16:50:39 -070019import org.onosproject.ui.lion.LionBundle;
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -070020import org.slf4j.Logger;
21import org.slf4j.LoggerFactory;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080022
23import java.io.InputStream;
Simon Hunte05cae42015-07-23 17:35:24 -070024import java.util.ArrayList;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080025import java.util.List;
26
Simon Hunte05cae42015-07-23 17:35:24 -070027import static com.google.common.base.Preconditions.checkArgument;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080028import static com.google.common.base.Preconditions.checkNotNull;
29
30/**
Simon Hunt8add9ee2016-09-20 17:05:07 -070031 * Immutable representation of a user interface extension.
32 * <p>
33 * Note that the {@link Builder} class is used to create a user
34 * interface extension instance, and that these instances are immutable.
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080035 */
Simon Hunte05cae42015-07-23 17:35:24 -070036public final class UiExtension {
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080037
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -070038 private final Logger log = LoggerFactory.getLogger(getClass());
39
Thomas Vachuska529db0a2015-02-23 16:42:14 -080040 private static final String VIEW_PREFIX = "app/view/";
Simon Hunte05cae42015-07-23 17:35:24 -070041 private static final String EMPTY = "";
42 private static final String SLASH = "/";
43 private static final String CSS_HTML = "css.html";
44 private static final String JS_HTML = "js.html";
Thomas Vachuska529db0a2015-02-23 16:42:14 -080045
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080046 private final ClassLoader classLoader;
Simon Hunte05cae42015-07-23 17:35:24 -070047 private final String resourcePath;
Simon Hunt8add9ee2016-09-20 17:05:07 -070048 private final List<UiView> viewList;
Simon Hunt7379a3d2017-06-20 16:50:39 -070049 private final List<LionBundle> lionBundles;
Thomas Vachuska3553b302015-03-07 14:49:43 -080050 private final UiMessageHandlerFactory messageHandlerFactory;
Simon Hunte05cae42015-07-23 17:35:24 -070051 private final UiTopoOverlayFactory topoOverlayFactory;
Simon Hunt22c35df2017-04-26 17:28:42 -070052 private final UiTopo2OverlayFactory topo2OverlayFactory;
Steven Burrows3a9a6442016-05-05 15:31:16 +010053 private final UiTopoMapFactory topoMapFactory;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080054
Thomas Vachuskac4178cc2015-12-10 11:43:32 -080055 private boolean isValid = true;
Simon Hunte05cae42015-07-23 17:35:24 -070056
57 // private constructor - only the builder calls this
58 private UiExtension(ClassLoader cl, String path, List<UiView> views,
Simon Hunt7379a3d2017-06-20 16:50:39 -070059 List<LionBundle> bundles,
Simon Hunte05cae42015-07-23 17:35:24 -070060 UiMessageHandlerFactory mhFactory,
Steven Burrows3a9a6442016-05-05 15:31:16 +010061 UiTopoOverlayFactory toFactory,
Simon Hunt22c35df2017-04-26 17:28:42 -070062 UiTopo2OverlayFactory to2Factory,
Steven Burrows3a9a6442016-05-05 15:31:16 +010063 UiTopoMapFactory tmFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -070064 classLoader = cl;
65 resourcePath = path;
66 viewList = views;
Simon Hunt7379a3d2017-06-20 16:50:39 -070067 lionBundles = bundles;
Simon Hunt8add9ee2016-09-20 17:05:07 -070068 messageHandlerFactory = mhFactory;
69 topoOverlayFactory = toFactory;
Simon Hunt22c35df2017-04-26 17:28:42 -070070 topo2OverlayFactory = to2Factory;
Simon Hunt8add9ee2016-09-20 17:05:07 -070071 topoMapFactory = tmFactory;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080072 }
73
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080074
75 /**
76 * Returns input stream containing CSS inclusion statements.
77 *
78 * @return CSS inclusion statements
79 */
80 public InputStream css() {
Simon Hunte05cae42015-07-23 17:35:24 -070081 return getStream(resourcePath + CSS_HTML);
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080082 }
83
84 /**
85 * Returns input stream containing JavaScript inclusion statements.
86 *
87 * @return JavaScript inclusion statements
88 */
89 public InputStream js() {
Thomas Vachuskad894b5d2015-07-30 11:59:07 -070090 return getStream(resourcePath + JS_HTML);
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080091 }
92
93 /**
94 * Returns list of user interface views contributed by this extension.
95 *
96 * @return contributed view descriptors
97 */
98 public List<UiView> views() {
Simon Hunt8add9ee2016-09-20 17:05:07 -070099 return isValid ? viewList : ImmutableList.of();
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -0800100 }
101
102 /**
Simon Hunt7379a3d2017-06-20 16:50:39 -0700103 * Returns the list of localization bundles that this extension is
104 * contributing.
105 *
106 * @return contributed localization bundles
107 */
108 public List<LionBundle> lionBundles() {
109 return ImmutableList.copyOf(lionBundles);
110 }
111
112 /**
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -0800113 * Returns input stream containing specified view-specific resource.
114 *
115 * @param viewId view identifier
116 * @param path resource path, relative to the view directory
117 * @return resource input stream
118 */
119 public InputStream resource(String viewId, String path) {
Simon Hunte05cae42015-07-23 17:35:24 -0700120 return getStream(VIEW_PREFIX + viewId + SLASH + path);
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -0800121 }
122
Thomas Vachuska3553b302015-03-07 14:49:43 -0800123 /**
Simon Hunte05cae42015-07-23 17:35:24 -0700124 * Returns message handler factory, if one was defined.
Thomas Vachuska3553b302015-03-07 14:49:43 -0800125 *
Simon Hunte05cae42015-07-23 17:35:24 -0700126 * @return message handler factory
Thomas Vachuska3553b302015-03-07 14:49:43 -0800127 */
128 public UiMessageHandlerFactory messageHandlerFactory() {
129 return messageHandlerFactory;
130 }
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -0700131
Simon Hunte05cae42015-07-23 17:35:24 -0700132 /**
133 * Returns the topology overlay factory, if one was defined.
134 *
135 * @return topology overlay factory
136 */
137 public UiTopoOverlayFactory topoOverlayFactory() {
138 return topoOverlayFactory;
139 }
140
Steven Burrows3a9a6442016-05-05 15:31:16 +0100141 /**
Simon Hunt22c35df2017-04-26 17:28:42 -0700142 * Returns the topology-2 overlay factory, if one was defined.
143 *
144 * @return topology-2 overlay factory
145 */
146 public UiTopo2OverlayFactory topo2OverlayFactory() {
147 return topo2OverlayFactory;
148 }
149
150 /**
Steven Burrows3a9a6442016-05-05 15:31:16 +0100151 * Returns the topology map factory, if one was defined.
152 *
153 * @return topology map factory
154 */
155 public UiTopoMapFactory topoMapFactory() {
156 return topoMapFactory;
157 }
158
Simon Hunte05cae42015-07-23 17:35:24 -0700159
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -0700160 // Returns the resource input stream from the specified class-loader.
161 private InputStream getStream(String path) {
162 InputStream stream = classLoader.getResourceAsStream(path);
163 if (stream == null) {
Thomas Vachuskac4178cc2015-12-10 11:43:32 -0800164 isValid = false;
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -0700165 log.warn("Unable to find resource {}", path);
166 }
167 return stream;
168 }
169
170
Simon Hunte05cae42015-07-23 17:35:24 -0700171 /**
172 * UI Extension Builder.
173 */
174 public static class Builder {
175 private ClassLoader classLoader;
176
177 private String resourcePath = EMPTY;
Simon Hunt8add9ee2016-09-20 17:05:07 -0700178 private List<UiView> viewList = new ArrayList<>();
Simon Hunt7379a3d2017-06-20 16:50:39 -0700179 private List<LionBundle> lionBundles = new ArrayList<>();
Simon Hunte05cae42015-07-23 17:35:24 -0700180 private UiMessageHandlerFactory messageHandlerFactory = null;
181 private UiTopoOverlayFactory topoOverlayFactory = null;
Simon Hunt22c35df2017-04-26 17:28:42 -0700182 private UiTopo2OverlayFactory topo2OverlayFactory = null;
Steven Burrows3a9a6442016-05-05 15:31:16 +0100183 private UiTopoMapFactory topoMapFactory = null;
Simon Hunte05cae42015-07-23 17:35:24 -0700184
185 /**
186 * Create a builder with the given class loader.
187 * Resource path defaults to "".
188 * Views defaults to an empty list.
Simon Hunt8add9ee2016-09-20 17:05:07 -0700189 * MessageHandler, TopoOverlay, and TopoMap factories default to null.
Simon Hunte05cae42015-07-23 17:35:24 -0700190 *
Thomas Vachuskad894b5d2015-07-30 11:59:07 -0700191 * @param cl the class loader
192 * @param views list of views contributed by this extension
Simon Hunte05cae42015-07-23 17:35:24 -0700193 */
194 public Builder(ClassLoader cl, List<UiView> views) {
195 checkNotNull(cl, "Must provide a class loader");
Jon Hallcbd1b392017-01-18 20:15:44 -0800196 checkArgument(!views.isEmpty(), "Must provide at least one view");
Simon Hunt8add9ee2016-09-20 17:05:07 -0700197 classLoader = cl;
198 viewList = views;
Simon Hunte05cae42015-07-23 17:35:24 -0700199 }
200
201 /**
Simon Hunt7379a3d2017-06-20 16:50:39 -0700202 * Sets the localization bundles (aka {@code LionBundle}s) that this
203 * UI extension is contributing.
204 *
205 * @param bundles the bundles to register
206 * @return self, for chaining
207 */
208 public Builder lionBundles(List<LionBundle> bundles) {
209 checkNotNull(bundles, "Must provide a list");
210 lionBundles = bundles;
211 return this;
212 }
213
214 /**
Simon Hunt8add9ee2016-09-20 17:05:07 -0700215 * Set the resource path. That is, the path to where the CSS and JS
216 * files are located.
Simon Hunte05cae42015-07-23 17:35:24 -0700217 *
218 * @param path resource path
219 * @return self, for chaining
220 */
221 public Builder resourcePath(String path) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700222 resourcePath = path == null ? EMPTY : path + SLASH;
Simon Hunte05cae42015-07-23 17:35:24 -0700223 return this;
224 }
225
226 /**
227 * Sets the message handler factory for this extension.
228 *
229 * @param mhFactory message handler factory
230 * @return self, for chaining
231 */
232 public Builder messageHandlerFactory(UiMessageHandlerFactory mhFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700233 messageHandlerFactory = mhFactory;
Simon Hunte05cae42015-07-23 17:35:24 -0700234 return this;
235 }
236
237 /**
238 * Sets the topology overlay factory for this extension.
239 *
240 * @param toFactory topology overlay factory
241 * @return self, for chaining
242 */
243 public Builder topoOverlayFactory(UiTopoOverlayFactory toFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700244 topoOverlayFactory = toFactory;
Simon Hunte05cae42015-07-23 17:35:24 -0700245 return this;
246 }
247
248 /**
Simon Hunt22c35df2017-04-26 17:28:42 -0700249 * Sets the topology-2 overlay factory for this extension.
250 *
251 * @param to2Factory topology-2 overlay factory
252 * @return self, for chaining
253 */
254 public Builder topo2OverlayFactory(UiTopo2OverlayFactory to2Factory) {
255 topo2OverlayFactory = to2Factory;
256 return this;
257 }
258
259 /**
Steven Burrows3a9a6442016-05-05 15:31:16 +0100260 * Sets the topology map factory for this extension.
261 *
262 * @param tmFactory topology map factory
263 * @return self, for chaining
264 */
265 public Builder topoMapFactory(UiTopoMapFactory tmFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700266 topoMapFactory = tmFactory;
Steven Burrows3a9a6442016-05-05 15:31:16 +0100267 return this;
268 }
269
270 /**
Simon Hunt8add9ee2016-09-20 17:05:07 -0700271 * Builds the user interface extension.
Simon Hunte05cae42015-07-23 17:35:24 -0700272 *
273 * @return UI extension instance
274 */
275 public UiExtension build() {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700276 return new UiExtension(classLoader, resourcePath, viewList,
Simon Hunt7379a3d2017-06-20 16:50:39 -0700277 lionBundles,
Simon Hunt22c35df2017-04-26 17:28:42 -0700278 messageHandlerFactory, topoOverlayFactory,
279 topo2OverlayFactory, topoMapFactory);
Simon Hunte05cae42015-07-23 17:35:24 -0700280 }
Simon Hunte05cae42015-07-23 17:35:24 -0700281 }
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -0800282}