blob: a6fc39026ab4fdeed9a0abdeb45bd817c889fb06 [file] [log] [blame]
Simon Hunt00b369a2017-06-20 19:46:40 -07001/*
2 * Copyright 2017-present 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 *
16 */
17
18package org.onosproject.ui.impl.lion;
19
20import com.google.common.collect.ImmutableList;
21import org.onosproject.ui.lion.LionBundle;
22import org.onosproject.ui.lion.LionUtils;
23import org.slf4j.Logger;
24import org.slf4j.LoggerFactory;
25
26import java.util.ArrayList;
27import java.util.List;
Simon Huntd8754652017-06-21 11:45:22 -070028import java.util.MissingResourceException;
Simon Hunt00b369a2017-06-20 19:46:40 -070029import java.util.ResourceBundle;
30import java.util.Set;
31
32/**
33 * Gathers and stitches together a localization bundle according to a
34 * "lion" configuration file.
35 */
36public class BundleStitcher {
37
38 private static final Logger log =
39 LoggerFactory.getLogger(BundleStitcher.class);
40
41 private static final String CONFIG_DIR = "_config";
42 private static final String SUFFIX = ".lioncfg";
43 private static final String SLASH = "/";
44 private static final String DOT = ".";
45
46
47 private final String base;
48
49 /**
50 * Creates a bundle stitcher, configured with the specified base resource
51 * path.
52 *
53 * @param base the base resource path
54 */
55 public BundleStitcher(String base) {
56 this.base = base;
57 }
58
59 @Override
60 public String toString() {
61 return "BundleStitcher{base=\"" + base + "\"}";
62 }
63
64 /**
65 * Stitches together a LionBundle, based on the bundle configuration data
66 * for the given bundle ID.
67 *
68 * @param id the bundle ID
69 * @return a corresponding lion bundle
Simon Huntd8754652017-06-21 11:45:22 -070070 * @throws IllegalArgumentException if the config cannot be loaded
71 * or the bundle cannot be stitched
Simon Hunt00b369a2017-06-20 19:46:40 -070072 */
73 public LionBundle stitch(String id) {
74 String source = base + SLASH + CONFIG_DIR + SLASH + id + SUFFIX;
Simon Huntd8754652017-06-21 11:45:22 -070075
76 // the following may throw IllegalArgumentException...
Simon Hunt00b369a2017-06-20 19:46:40 -070077 LionConfig cfg = new LionConfig().load(source);
Simon Huntd8754652017-06-21 11:45:22 -070078
Simon Hunt00b369a2017-06-20 19:46:40 -070079 LionBundle.Builder builder = new LionBundle.Builder(id);
Simon Huntd8754652017-06-21 11:45:22 -070080 int total = 0;
81 int added = 0;
Simon Hunt00b369a2017-06-20 19:46:40 -070082
83 for (LionConfig.CmdFrom from : cfg.entries()) {
Simon Huntd8754652017-06-21 11:45:22 -070084 total += 1;
85 log.debug(" processing: {}", from.orig());
86 if (addItemsToBuilder(builder, from)) {
87 added += 1;
88 }
Simon Hunt00b369a2017-06-20 19:46:40 -070089 }
Simon Huntd8754652017-06-21 11:45:22 -070090 log.debug(" added items for {}/{} FROM entries", added, total);
Simon Hunt00b369a2017-06-20 19:46:40 -070091 return builder.build();
92 }
93
Simon Huntd8754652017-06-21 11:45:22 -070094 private boolean addItemsToBuilder(LionBundle.Builder builder,
95 LionConfig.CmdFrom from) {
Simon Hunt00b369a2017-06-20 19:46:40 -070096 String resBundleName = base + SLASH + from.res();
97 String resFqbn = convertToFqbn(resBundleName);
Simon Huntd8754652017-06-21 11:45:22 -070098 ResourceBundle bundle = null;
99 boolean ok = true;
Simon Hunt00b369a2017-06-20 19:46:40 -0700100
Simon Huntd8754652017-06-21 11:45:22 -0700101 try {
102 bundle = LionUtils.getBundledResource(resFqbn);
103 } catch (MissingResourceException e) {
104 log.warn("Cannot find resource bundle: {}", resFqbn);
105 log.debug("BOOM!", e);
106 ok = false;
Simon Hunt00b369a2017-06-20 19:46:40 -0700107 }
Simon Huntd8754652017-06-21 11:45:22 -0700108
109 if (ok) {
110 Set<String> keys = from.starred() ? bundle.keySet() : from.keys();
111 addItems(builder, bundle, keys);
112 log.debug(" added {} item(s) from {}", keys.size(), from.res());
113 }
114
115 return ok;
Simon Hunt00b369a2017-06-20 19:46:40 -0700116 }
117
118 // to fully-qualified-bundle-name
119 private String convertToFqbn(String path) {
120 if (!path.startsWith(SLASH)) {
121 throw new IllegalArgumentException("path should start with '/'");
122 }
123 return path.substring(1).replaceAll(SLASH, DOT);
124 }
125
Simon Hunt00b369a2017-06-20 19:46:40 -0700126 private void addItems(LionBundle.Builder builder, ResourceBundle bundle,
127 Set<String> keys) {
128 keys.forEach(k -> builder.addItem(k, bundle.getString(k)));
129 }
130
131 /**
132 * Generates an immutable list of localization bundles, using the specified
133 * resource tree (base) and localization configuration file names (tags).
134 * <p>
135 * As an example, you might invoke:
136 * <pre>
137 * private static final String LION_BASE = "/org/onosproject/ui/lion";
138 *
139 * private static final String[] LION_TAGS = {
140 * "core.view.App",
141 * "core.view.Settings",
142 * "core.view.Cluster",
143 * "core.view.Processor",
144 * "core.view.Partition",
145 * };
146 *
147 * List&lt;LionBundle&gt; bundles =
148 * LionUtils.generateBundles(LION_BASE, LION_TAGS);
149 * </pre>
150 * It is expected that in the "LION_BASE" directory there is a subdirectory
151 * named "_config" which contains the configuration files listed in the
152 * "LION_TAGS" array, each with a ".lioncfg" suffix...
153 * <pre>
154 * /org/onosproject/ui/lion/
155 * |
156 * +-- _config
157 * |
158 * +-- core.view.App.lioncfg
159 * +-- core.view.Settings.lioncfg
160 * :
161 * </pre>
162 * These files collate a localization bundle for their particular view
163 * by referencing resource bundles and their keys.
164 *
165 * @param base the base resource directory path
166 * @param tags the list of bundles to generate
167 * @return a list of generated localization bundles
168 */
Simon Huntd8754652017-06-21 11:45:22 -0700169 public static List<LionBundle> generateBundles(String base, String... tags) {
170 List<LionBundle> bundles = new ArrayList<>(tags.length);
Simon Hunt00b369a2017-06-20 19:46:40 -0700171 BundleStitcher stitcher = new BundleStitcher(base);
172 for (String tag : tags) {
173 try {
Simon Huntd8754652017-06-21 11:45:22 -0700174 LionBundle lion = stitcher.stitch(tag);
175 bundles.add(lion);
176 log.info("Generated LION bundle: {}", lion);
Simon Hunt00b369a2017-06-20 19:46:40 -0700177
178 } catch (IllegalArgumentException e) {
179 log.warn("Unable to generate bundle: {} / {}", base, tag);
Simon Huntd8754652017-06-21 11:45:22 -0700180 log.debug("BOOM!", e);
Simon Hunt00b369a2017-06-20 19:46:40 -0700181 }
182 }
Simon Huntd8754652017-06-21 11:45:22 -0700183 return ImmutableList.copyOf(bundles);
Simon Hunt00b369a2017-06-20 19:46:40 -0700184 }
185}