View Javadoc
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 }