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.LinkedHashMap;
24  import java.util.List;
25  import java.util.Map;
26  
27  /**
28   * A builder for creating {@link org.mal_lang.langspec.Asset} objects.
29   *
30   * @since 1.0.0
31   */
32  public final class AssetBuilder {
33    private final String name;
34    private final MetaBuilder meta = new MetaBuilder();
35    private final String category;
36    private final boolean isAbstract;
37    private final String superAsset;
38    private final Map<String, VariableBuilder> variables = new LinkedHashMap<>();
39    private final Map<String, AttackStepBuilder> attackSteps = new LinkedHashMap<>();
40    private byte[] svgIcon = null;
41    private byte[] pngIcon = null;
42  
43    /**
44     * Constructs a new {@code AssetBuilder} object.
45     *
46     * @param name the name of the asset
47     * @param category the category of the asset
48     * @param isAbstract whether the asset is abstract
49     * @param superAsset the super asset of the asset, or {@code null}
50     * @throws java.lang.NullPointerException if {@code name} or {@code category} is {@code null}
51     * @throws java.lang.IllegalArgumentException if {@code name} or {@code category} is not a valid
52     *     identifier
53     * @since 1.0.0
54     */
55    public AssetBuilder(String name, String category, boolean isAbstract, String superAsset) {
56      this.name = requireIdentifier(name);
57      this.category = requireIdentifier(category);
58      this.isAbstract = isAbstract;
59      this.superAsset = superAsset;
60    }
61  
62    /**
63     * Returns the name of this {@code AssetBuilder} object.
64     *
65     * @return the name of this {@code AssetBuilder} object
66     * @since 1.0.0
67     */
68    public String getName() {
69      return this.name;
70    }
71  
72    /**
73     * Returns the meta info of this {@code AssetBuilder} object.
74     *
75     * @return the meta info of this {@code AssetBuilder} object
76     * @since 1.0.0
77     */
78    public MetaBuilder getMeta() {
79      return this.meta;
80    }
81  
82    /**
83     * Returns the category of this {@code AssetBuilder} object.
84     *
85     * @return the category of this {@code AssetBuilder} object
86     * @since 1.0.0
87     */
88    public String getCategory() {
89      return this.category;
90    }
91  
92    /**
93     * Returns whether this {@code AssetBuilder} object is abstract.
94     *
95     * @return whether this {@code AssetBuilder} object is abstract
96     * @since 1.0.0
97     */
98    public boolean isAbstract() {
99      return this.isAbstract;
100   }
101 
102   /**
103    * Returns the super asset of this {@code AssetBuilder} object, or {@code null} if no super asset
104    * has been set.
105    *
106    * @return the super asset of this {@code AssetBuilder} object, or {@code null} if no super asset
107    *     has been set
108    * @since 1.0.0
109    */
110   public String getSuperAsset() {
111     return this.superAsset;
112   }
113 
114   /**
115    * Returns a list of all variables in this {@code AssetBuilder} object.
116    *
117    * @return a list of all variables in this {@code AssetBuilder} object
118    * @since 1.0.0
119    */
120   public List<VariableBuilder> getVariables() {
121     return List.copyOf(this.variables.values());
122   }
123 
124   /**
125    * Adds a variable to this {@code AssetBuilder} object.
126    *
127    * @param variable the variable to add
128    * @return this {@code AssetBuilder} object
129    * @throws java.lang.NullPointerException if {@code variable} is {@code null}
130    * @since 1.0.0
131    */
132   public AssetBuilder addVariable(VariableBuilder variable) {
133     requireNonNull(variable);
134     this.variables.put(variable.getName(), variable);
135     return this;
136   }
137 
138   /**
139    * Returns a list of all attack steps in this {@code AssetBuilder} object.
140    *
141    * @return a list of all attack steps in this {@code AssetBuilder} object
142    * @since 1.0.0
143    */
144   public List<AttackStepBuilder> getAttackSteps() {
145     return List.copyOf(this.attackSteps.values());
146   }
147 
148   /**
149    * Adds an attack step to this {@code AssetBuilder} object.
150    *
151    * @param attackStep the attack step to add
152    * @return this {@code AssetBuilder} object
153    * @throws java.lang.NullPointerException if {@code attackStep} is {@code null}
154    * @since 1.0.0
155    */
156   public AssetBuilder addAttackStep(AttackStepBuilder attackStep) {
157     requireNonNull(attackStep);
158     this.attackSteps.put(attackStep.getName(), attackStep);
159     return this;
160   }
161 
162   /**
163    * Returns the SVG icon of this {@code AssetBuilder} object, or {@code null} if no SVG icon has
164    * been set.
165    *
166    * @return the SVG icon of this {@code AssetBuilder} object, or {@code null} if no SVG icon has
167    *     been set
168    * @since 1.0.0
169    */
170   public byte[] getSvgIcon() {
171     return this.svgIcon == null ? null : this.svgIcon.clone();
172   }
173 
174   /**
175    * Sets the SVG icon of this {@code AssetBuilder} object.
176    *
177    * @param svgIcon the SVG icon to set
178    * @return this {@code AssetBuilder} object
179    * @throws java.lang.NullPointerException if {@code svgIcon} is {@code null}
180    * @since 1.0.0
181    */
182   public AssetBuilder setSvgIcon(byte[] svgIcon) {
183     this.svgIcon = requireNonNull(svgIcon).clone();
184     return this;
185   }
186 
187   /**
188    * Returns the PNG icon of this {@code AssetBuilder} object, or {@code null} if no PNG icon has
189    * been set.
190    *
191    * @return the PNG icon of this {@code AssetBuilder} object, or {@code null} if no PNG icon has
192    *     been set
193    * @since 1.0.0
194    */
195   public byte[] getPngIcon() {
196     return this.pngIcon == null ? null : this.pngIcon.clone();
197   }
198 
199   /**
200    * Sets the PNG icon of this {@code AssetBuilder} object.
201    *
202    * @param pngIcon the PNG icon to set
203    * @return this {@code AssetBuilder} object
204    * @throws java.lang.NullPointerException if {@code pngIcon} is {@code null}
205    * @since 1.0.0
206    */
207   public AssetBuilder setPngIcon(byte[] pngIcon) {
208     this.pngIcon = requireNonNull(pngIcon).clone();
209     return this;
210   }
211 
212   /**
213    * Creates a new {@code AssetBuilder} from a {@link jakarta.json.JsonObject}.
214    *
215    * @param jsonAsset the {@link jakarta.json.JsonObject}
216    * @param svgIcons the SVG icons of the language
217    * @param pngIcons the PNG icons of the language
218    * @return a new {@code AssetBuilder} from a {@link jakarta.json.JsonObject}
219    * @throws java.lang.NullPointerException if {@code jsonAsset}, {@code svgIcons}, or {@code
220    *     pngIcons} is {@code null}
221    * @since 1.0.0
222    */
223   public static AssetBuilder fromJson(
224       JsonObject jsonAsset, Map<String, byte[]> svgIcons, Map<String, byte[]> pngIcons) {
225     requireNonNull(jsonAsset);
226     requireNonNull(svgIcons);
227     requireNonNull(pngIcons);
228     var builder =
229         new AssetBuilder(
230             jsonAsset.getString("name"),
231             jsonAsset.getString("category"),
232             jsonAsset.getBoolean("isAbstract"),
233             jsonAsset.isNull("superAsset") ? null : jsonAsset.getString("superAsset"));
234     builder.getMeta().fromJson(jsonAsset.getJsonObject("meta"));
235     for (var jsonVariable : jsonAsset.getJsonArray("variables")) {
236       builder.addVariable(VariableBuilder.fromJson(jsonVariable.asJsonObject()));
237     }
238     for (var jsonAttackStep : jsonAsset.getJsonArray("attackSteps")) {
239       builder.addAttackStep(AttackStepBuilder.fromJson(jsonAttackStep.asJsonObject()));
240     }
241     if (svgIcons.containsKey(builder.getName())) {
242       builder.setSvgIcon(svgIcons.get(builder.getName()));
243     }
244     if (pngIcons.containsKey(builder.getName())) {
245       builder.setPngIcon(pngIcons.get(builder.getName()));
246     }
247     return builder;
248   }
249 }