1 /*
2 * Copyright 2020-2022 Foreseeti AB <https://foreseeti.com>
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 package org.mal_lang.langspec.builders;
18
19 import static java.util.Objects.requireNonNull;
20 import static org.mal_lang.langspec.Utils.requireIdentifier;
21
22 import jakarta.json.JsonObject;
23 import java.util.ArrayList;
24 import java.util.LinkedHashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 /**
29 * A builder for creating {@link org.mal_lang.langspec.Lang} objects.
30 *
31 * @since 1.0.0
32 */
33 public final class LangBuilder {
34 private final Map<String, String> defines = new LinkedHashMap<>();
35 private final Map<String, CategoryBuilder> categories = new LinkedHashMap<>();
36 private final Map<String, AssetBuilder> assets = new LinkedHashMap<>();
37 private final List<AssociationBuilder> associations = new ArrayList<>();
38 private String license = null;
39 private String notice = null;
40
41 /**
42 * Constructs a new {@code LangBuilder} object.
43 *
44 * @since 1.0.0
45 */
46 public LangBuilder() {}
47
48 /**
49 * Returns all defines in this {@code LangBuilder} object.
50 *
51 * @return all defines in this {@code LangBuilder} object
52 * @since 1.0.0
53 */
54 public Map<String, String> getDefines() {
55 return Map.copyOf(this.defines);
56 }
57
58 /**
59 * Adds a define to this {@code LangBuilder} object.
60 *
61 * @param key the key of the define
62 * @param value the value of the define
63 * @return this {@code LangBuilder} object
64 * @throws java.lang.NullPointerException if {@code key} or {@code value} is {@code null}
65 * @throws java.lang.IllegalArgumentException if {@code key} is not a valid identifier
66 * @since 1.0.0
67 */
68 public LangBuilder addDefine(String key, String value) {
69 this.defines.put(requireIdentifier(key), requireNonNull(value));
70 return this;
71 }
72
73 /**
74 * Returns a list of all categories in this {@code LangBuilder} object.
75 *
76 * @return a list of all categories in this {@code LangBuilder} object
77 * @since 1.0.0
78 */
79 public List<CategoryBuilder> getCategories() {
80 return List.copyOf(this.categories.values());
81 }
82
83 /**
84 * Adds a category to this {@code LangBuilder} object.
85 *
86 * @param category the category to add
87 * @return this {@code LangBuilder} object
88 * @throws java.lang.NullPointerException if {@code category} is {@code null}
89 * @since 1.0.0
90 */
91 public LangBuilder addCategory(CategoryBuilder category) {
92 requireNonNull(category);
93 this.categories.put(category.getName(), category);
94 return this;
95 }
96
97 /**
98 * Returns a list of all assets in this {@code LangBuilder} object.
99 *
100 * @return a list of all assets in this {@code LangBuilder} object
101 * @since 1.0.0
102 */
103 public List<AssetBuilder> getAssets() {
104 return List.copyOf(this.assets.values());
105 }
106
107 /**
108 * Adds an asset to this {@code LangBuilder} object.
109 *
110 * @param asset the asset to add
111 * @return this {@code LangBuilder} object
112 * @throws java.lang.NullPointerException if {@code asset} is {@code null}
113 * @since 1.0.0
114 */
115 public LangBuilder addAsset(AssetBuilder asset) {
116 requireNonNull(asset);
117 this.assets.put(asset.getName(), asset);
118 return this;
119 }
120
121 /**
122 * Returns a list of all associations in this {@code LangBuilder} object.
123 *
124 * @return a list of all associations in this {@code LangBuilder} object
125 * @since 1.0.0
126 */
127 public List<AssociationBuilder> getAssociations() {
128 return List.copyOf(this.associations);
129 }
130
131 /**
132 * Adds an association to this {@code LangBuilder} object.
133 *
134 * @param association the association to add
135 * @return this {@code LangBuilder} object
136 * @throws java.lang.NullPointerException if {@code association} is {@code null}
137 * @since 1.0.0
138 */
139 public LangBuilder addAssociation(AssociationBuilder association) {
140 this.associations.add(requireNonNull(association));
141 return this;
142 }
143
144 /**
145 * Returns the license of this {@code LangBuilder} object, or {@code null} if no license has been
146 * set.
147 *
148 * @return the license of this {@code LangBuilder} object, or {@code null} if no license has been
149 * set
150 * @since 1.0.0
151 */
152 public String getLicense() {
153 return this.license;
154 }
155
156 /**
157 * Sets the license of this {@code LangBuilder} object.
158 *
159 * @param license the license to set
160 * @return this {@code LangBuilder} object
161 * @throws java.lang.NullPointerException if {@code license} is {@code null}
162 * @since 1.0.0
163 */
164 public LangBuilder setLicense(String license) {
165 this.license = requireNonNull(license);
166 return this;
167 }
168
169 /**
170 * Returns the notice of this {@code LangBuilder} object, or {@code null} if no notice has been
171 * set.
172 *
173 * @return the notice of this {@code LangBuilder} object, or {@code null} if no notice has been
174 * set
175 * @since 1.0.0
176 */
177 public String getNotice() {
178 return this.notice;
179 }
180
181 /**
182 * Sets the notice of this {@code LangBuilder} object.
183 *
184 * @param notice the notice to set
185 * @return this {@code LangBuilder} object
186 * @throws java.lang.NullPointerException if {@code notice} is {@code null}
187 * @since 1.0.0
188 */
189 public LangBuilder setNotice(String notice) {
190 this.notice = requireNonNull(notice);
191 return this;
192 }
193
194 /**
195 * Creates a new {@code LangBuilder} from a {@link jakarta.json.JsonObject}.
196 *
197 * @param jsonLang the {@link jakarta.json.JsonObject}
198 * @return a new {@code LangBuilder}
199 * @throws java.lang.NullPointerException if {@code jsonLang} is {@code null}
200 * @since 1.0.0
201 */
202 public static LangBuilder fromJson(JsonObject jsonLang) {
203 return LangBuilder.fromJson(jsonLang, Map.of(), Map.of(), null, null);
204 }
205
206 /**
207 * Creates a new {@code LangBuilder} from a {@link jakarta.json.JsonObject}.
208 *
209 * @param jsonLang the {@link jakarta.json.JsonObject}
210 * @param svgIcons the SVG icons of the language
211 * @param pngIcons the PNG icons of the language
212 * @return a new {@code LangBuilder}
213 * @throws java.lang.NullPointerException if {@code jsonLang}, {@code svgIcons}, or {@code
214 * pngIcons} is {@code null}
215 * @since 1.0.0
216 */
217 public static LangBuilder fromJson(
218 JsonObject jsonLang, Map<String, byte[]> svgIcons, Map<String, byte[]> pngIcons) {
219 return LangBuilder.fromJson(jsonLang, svgIcons, pngIcons, null, null);
220 }
221
222 /**
223 * Creates a new {@code LangBuilder} from a {@link jakarta.json.JsonObject}.
224 *
225 * @param jsonLang the {@link jakarta.json.JsonObject}
226 * @param license the license of the language, or {@code null}
227 * @param notice the notice of the language, or {@code null}
228 * @return a new {@code LangBuilder}
229 * @throws java.lang.NullPointerException if {@code jsonLang} is {@code null}
230 * @since 1.0.0
231 */
232 public static LangBuilder fromJson(JsonObject jsonLang, String license, String notice) {
233 return LangBuilder.fromJson(jsonLang, Map.of(), Map.of(), license, notice);
234 }
235
236 /**
237 * Creates a new {@code LangBuilder} from a {@link jakarta.json.JsonObject}.
238 *
239 * @param jsonLang the {@link jakarta.json.JsonObject}
240 * @param svgIcons the SVG icons of the language
241 * @param pngIcons the PNG icons of the language
242 * @param license the license of the language, or {@code null}
243 * @param notice the notice of the language, or {@code null}
244 * @return a new {@code LangBuilder}
245 * @throws java.lang.NullPointerException if {@code jsonLang}, {@code svgIcons}, or {@code
246 * pngIcons} is {@code null}
247 * @since 1.0.0
248 */
249 public static LangBuilder fromJson(
250 JsonObject jsonLang,
251 Map<String, byte[]> svgIcons,
252 Map<String, byte[]> pngIcons,
253 String license,
254 String notice) {
255 requireNonNull(jsonLang);
256 requireNonNull(svgIcons);
257 requireNonNull(pngIcons);
258 var builder = new LangBuilder();
259 var jsonDefines = jsonLang.getJsonObject("defines");
260 for (var key : jsonDefines.keySet()) {
261 builder.addDefine(key, jsonDefines.getString(key));
262 }
263 for (var jsonCategory : jsonLang.getJsonArray("categories")) {
264 builder.addCategory(CategoryBuilder.fromJson(jsonCategory.asJsonObject()));
265 }
266 for (var jsonAsset : jsonLang.getJsonArray("assets")) {
267 builder.addAsset(AssetBuilder.fromJson(jsonAsset.asJsonObject(), svgIcons, pngIcons));
268 }
269 for (var jsonAssociation : jsonLang.getJsonArray("associations")) {
270 builder.addAssociation(AssociationBuilder.fromJson(jsonAssociation.asJsonObject()));
271 }
272 if (license != null) {
273 builder.setLicense(license);
274 }
275 if (notice != null) {
276 builder.setNotice(notice);
277 }
278 return builder;
279 }
280 }