blob: 9edcba9a968632676972b936026c5834fbe7f213 [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;
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -070019import org.slf4j.Logger;
20import org.slf4j.LoggerFactory;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080021
22import java.io.InputStream;
Simon Hunte05cae42015-07-23 17:35:24 -070023import java.util.ArrayList;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080024import java.util.List;
25
Simon Hunte05cae42015-07-23 17:35:24 -070026import static com.google.common.base.Preconditions.checkArgument;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080027import static com.google.common.base.Preconditions.checkNotNull;
28
29/**
Simon Hunt8add9ee2016-09-20 17:05:07 -070030 * Immutable representation of a user interface extension.
31 * <p>
32 * Note that the {@link Builder} class is used to create a user
33 * interface extension instance, and that these instances are immutable.
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080034 */
Simon Hunte05cae42015-07-23 17:35:24 -070035public final class UiExtension {
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080036
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -070037 private final Logger log = LoggerFactory.getLogger(getClass());
38
Thomas Vachuska529db0a2015-02-23 16:42:14 -080039 private static final String VIEW_PREFIX = "app/view/";
Simon Hunte05cae42015-07-23 17:35:24 -070040 private static final String EMPTY = "";
41 private static final String SLASH = "/";
42 private static final String CSS_HTML = "css.html";
43 private static final String JS_HTML = "js.html";
Thomas Vachuska529db0a2015-02-23 16:42:14 -080044
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080045 private final ClassLoader classLoader;
Simon Hunte05cae42015-07-23 17:35:24 -070046 private final String resourcePath;
Simon Hunt8add9ee2016-09-20 17:05:07 -070047 private final List<UiView> viewList;
Thomas Vachuska3553b302015-03-07 14:49:43 -080048 private final UiMessageHandlerFactory messageHandlerFactory;
Simon Hunte05cae42015-07-23 17:35:24 -070049 private final UiTopoOverlayFactory topoOverlayFactory;
Simon Hunt22c35df2017-04-26 17:28:42 -070050 private final UiTopo2OverlayFactory topo2OverlayFactory;
Steven Burrows3a9a6442016-05-05 15:31:16 +010051 private final UiTopoMapFactory topoMapFactory;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080052
Thomas Vachuskac4178cc2015-12-10 11:43:32 -080053 private boolean isValid = true;
Simon Hunte05cae42015-07-23 17:35:24 -070054
55 // private constructor - only the builder calls this
56 private UiExtension(ClassLoader cl, String path, List<UiView> views,
57 UiMessageHandlerFactory mhFactory,
Steven Burrows3a9a6442016-05-05 15:31:16 +010058 UiTopoOverlayFactory toFactory,
Simon Hunt22c35df2017-04-26 17:28:42 -070059 UiTopo2OverlayFactory to2Factory,
Steven Burrows3a9a6442016-05-05 15:31:16 +010060 UiTopoMapFactory tmFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -070061 classLoader = cl;
62 resourcePath = path;
63 viewList = views;
64 messageHandlerFactory = mhFactory;
65 topoOverlayFactory = toFactory;
Simon Hunt22c35df2017-04-26 17:28:42 -070066 topo2OverlayFactory = to2Factory;
Simon Hunt8add9ee2016-09-20 17:05:07 -070067 topoMapFactory = tmFactory;
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080068 }
69
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080070
71 /**
72 * Returns input stream containing CSS inclusion statements.
73 *
74 * @return CSS inclusion statements
75 */
76 public InputStream css() {
Simon Hunte05cae42015-07-23 17:35:24 -070077 return getStream(resourcePath + CSS_HTML);
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080078 }
79
80 /**
81 * Returns input stream containing JavaScript inclusion statements.
82 *
83 * @return JavaScript inclusion statements
84 */
85 public InputStream js() {
Thomas Vachuskad894b5d2015-07-30 11:59:07 -070086 return getStream(resourcePath + JS_HTML);
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080087 }
88
89 /**
90 * Returns list of user interface views contributed by this extension.
91 *
92 * @return contributed view descriptors
93 */
94 public List<UiView> views() {
Simon Hunt8add9ee2016-09-20 17:05:07 -070095 return isValid ? viewList : ImmutableList.of();
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -080096 }
97
98 /**
99 * Returns input stream containing specified view-specific resource.
100 *
101 * @param viewId view identifier
102 * @param path resource path, relative to the view directory
103 * @return resource input stream
104 */
105 public InputStream resource(String viewId, String path) {
Simon Hunte05cae42015-07-23 17:35:24 -0700106 return getStream(VIEW_PREFIX + viewId + SLASH + path);
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -0800107 }
108
Thomas Vachuska3553b302015-03-07 14:49:43 -0800109 /**
Simon Hunte05cae42015-07-23 17:35:24 -0700110 * Returns message handler factory, if one was defined.
Thomas Vachuska3553b302015-03-07 14:49:43 -0800111 *
Simon Hunte05cae42015-07-23 17:35:24 -0700112 * @return message handler factory
Thomas Vachuska3553b302015-03-07 14:49:43 -0800113 */
114 public UiMessageHandlerFactory messageHandlerFactory() {
115 return messageHandlerFactory;
116 }
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -0700117
Simon Hunte05cae42015-07-23 17:35:24 -0700118 /**
119 * Returns the topology overlay factory, if one was defined.
120 *
121 * @return topology overlay factory
122 */
123 public UiTopoOverlayFactory topoOverlayFactory() {
124 return topoOverlayFactory;
125 }
126
Steven Burrows3a9a6442016-05-05 15:31:16 +0100127 /**
Simon Hunt22c35df2017-04-26 17:28:42 -0700128 * Returns the topology-2 overlay factory, if one was defined.
129 *
130 * @return topology-2 overlay factory
131 */
132 public UiTopo2OverlayFactory topo2OverlayFactory() {
133 return topo2OverlayFactory;
134 }
135
136 /**
Steven Burrows3a9a6442016-05-05 15:31:16 +0100137 * Returns the topology map factory, if one was defined.
138 *
139 * @return topology map factory
140 */
141 public UiTopoMapFactory topoMapFactory() {
142 return topoMapFactory;
143 }
144
Simon Hunte05cae42015-07-23 17:35:24 -0700145
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -0700146 // Returns the resource input stream from the specified class-loader.
147 private InputStream getStream(String path) {
148 InputStream stream = classLoader.getResourceAsStream(path);
149 if (stream == null) {
Thomas Vachuskac4178cc2015-12-10 11:43:32 -0800150 isValid = false;
Thomas Vachuska3ccb9eb2015-04-29 23:33:56 -0700151 log.warn("Unable to find resource {}", path);
152 }
153 return stream;
154 }
155
156
Simon Hunte05cae42015-07-23 17:35:24 -0700157 /**
158 * UI Extension Builder.
159 */
160 public static class Builder {
161 private ClassLoader classLoader;
162
163 private String resourcePath = EMPTY;
Simon Hunt8add9ee2016-09-20 17:05:07 -0700164 private List<UiView> viewList = new ArrayList<>();
Simon Hunte05cae42015-07-23 17:35:24 -0700165 private UiMessageHandlerFactory messageHandlerFactory = null;
166 private UiTopoOverlayFactory topoOverlayFactory = null;
Simon Hunt22c35df2017-04-26 17:28:42 -0700167 private UiTopo2OverlayFactory topo2OverlayFactory = null;
Steven Burrows3a9a6442016-05-05 15:31:16 +0100168 private UiTopoMapFactory topoMapFactory = null;
Simon Hunte05cae42015-07-23 17:35:24 -0700169
170 /**
171 * Create a builder with the given class loader.
172 * Resource path defaults to "".
173 * Views defaults to an empty list.
Simon Hunt8add9ee2016-09-20 17:05:07 -0700174 * MessageHandler, TopoOverlay, and TopoMap factories default to null.
Simon Hunte05cae42015-07-23 17:35:24 -0700175 *
Thomas Vachuskad894b5d2015-07-30 11:59:07 -0700176 * @param cl the class loader
177 * @param views list of views contributed by this extension
Simon Hunte05cae42015-07-23 17:35:24 -0700178 */
179 public Builder(ClassLoader cl, List<UiView> views) {
180 checkNotNull(cl, "Must provide a class loader");
Jon Hallcbd1b392017-01-18 20:15:44 -0800181 checkArgument(!views.isEmpty(), "Must provide at least one view");
Simon Hunt8add9ee2016-09-20 17:05:07 -0700182 classLoader = cl;
183 viewList = views;
Simon Hunte05cae42015-07-23 17:35:24 -0700184 }
185
186 /**
Simon Hunt8add9ee2016-09-20 17:05:07 -0700187 * Set the resource path. That is, the path to where the CSS and JS
188 * files are located.
Simon Hunte05cae42015-07-23 17:35:24 -0700189 *
190 * @param path resource path
191 * @return self, for chaining
192 */
193 public Builder resourcePath(String path) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700194 resourcePath = path == null ? EMPTY : path + SLASH;
Simon Hunte05cae42015-07-23 17:35:24 -0700195 return this;
196 }
197
198 /**
199 * Sets the message handler factory for this extension.
200 *
201 * @param mhFactory message handler factory
202 * @return self, for chaining
203 */
204 public Builder messageHandlerFactory(UiMessageHandlerFactory mhFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700205 messageHandlerFactory = mhFactory;
Simon Hunte05cae42015-07-23 17:35:24 -0700206 return this;
207 }
208
209 /**
210 * Sets the topology overlay factory for this extension.
211 *
212 * @param toFactory topology overlay factory
213 * @return self, for chaining
214 */
215 public Builder topoOverlayFactory(UiTopoOverlayFactory toFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700216 topoOverlayFactory = toFactory;
Simon Hunte05cae42015-07-23 17:35:24 -0700217 return this;
218 }
219
220 /**
Simon Hunt22c35df2017-04-26 17:28:42 -0700221 * Sets the topology-2 overlay factory for this extension.
222 *
223 * @param to2Factory topology-2 overlay factory
224 * @return self, for chaining
225 */
226 public Builder topo2OverlayFactory(UiTopo2OverlayFactory to2Factory) {
227 topo2OverlayFactory = to2Factory;
228 return this;
229 }
230
231 /**
Steven Burrows3a9a6442016-05-05 15:31:16 +0100232 * Sets the topology map factory for this extension.
233 *
234 * @param tmFactory topology map factory
235 * @return self, for chaining
236 */
237 public Builder topoMapFactory(UiTopoMapFactory tmFactory) {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700238 topoMapFactory = tmFactory;
Steven Burrows3a9a6442016-05-05 15:31:16 +0100239 return this;
240 }
241
242 /**
Simon Hunt8add9ee2016-09-20 17:05:07 -0700243 * Builds the user interface extension.
Simon Hunte05cae42015-07-23 17:35:24 -0700244 *
245 * @return UI extension instance
246 */
247 public UiExtension build() {
Simon Hunt8add9ee2016-09-20 17:05:07 -0700248 return new UiExtension(classLoader, resourcePath, viewList,
Simon Hunt22c35df2017-04-26 17:28:42 -0700249 messageHandlerFactory, topoOverlayFactory,
250 topo2OverlayFactory, topoMapFactory);
Simon Hunte05cae42015-07-23 17:35:24 -0700251 }
Simon Hunte05cae42015-07-23 17:35:24 -0700252 }
Thomas Vachuskafe8c98a2015-02-04 01:24:32 -0800253}