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 jakarta.json.JsonString;
24 import java.util.LinkedHashSet;
25 import java.util.List;
26 import java.util.Set;
27 import org.mal_lang.langspec.AttackStepType;
28 import org.mal_lang.langspec.Risk;
29 import org.mal_lang.langspec.ttc.TtcExpression;
30
31 /**
32 * A builder for creating {@link org.mal_lang.langspec.AttackStep} objects.
33 *
34 * @since 1.0.0
35 */
36 public final class AttackStepBuilder {
37 private final String name;
38 private final MetaBuilder meta = new MetaBuilder();
39 private final AttackStepType type;
40 private final Set<String> tags = new LinkedHashSet<>();
41 private final Risk risk;
42 private final TtcExpression ttc;
43 private final StepsBuilder requires;
44 private final StepsBuilder reaches;
45
46 /**
47 * Constructs a new {@code AttackStepBuilder} object.
48 *
49 * @param name the name of the attack step
50 * @param type the type of the attack step
51 * @param risk the risk of the attack step, or {@code null}
52 * @param ttc the TTC of the attack step, or {@code null}
53 * @param requires the requires steps of the attack step, or {@code null}
54 * @param reaches the reaches steps of the attack step, or {@code null}
55 * @throws java.lang.NullPointerException if {@code name} or {@code type} is {@code null}
56 * @throws java.lang.IllegalArgumentException if {@code name} is not a valid identifier
57 * @since 1.0.0
58 */
59 public AttackStepBuilder(
60 String name,
61 AttackStepType type,
62 Risk risk,
63 TtcExpression ttc,
64 StepsBuilder requires,
65 StepsBuilder reaches) {
66 this.name = requireIdentifier(name);
67 this.type = requireNonNull(type);
68 this.risk = risk;
69 this.ttc = ttc;
70 this.requires = requires;
71 this.reaches = reaches;
72 }
73
74 /**
75 * Returns the name of this {@code AttackStepBuilder} object.
76 *
77 * @return the name of this {@code AttackStepBuilder} object
78 * @since 1.0.0
79 */
80 public String getName() {
81 return this.name;
82 }
83
84 /**
85 * Returns the meta info of this {@code AttackStepBuilder} object.
86 *
87 * @return the meta info of this {@code AttackStepBuilder} object
88 * @since 1.0.0
89 */
90 public MetaBuilder getMeta() {
91 return this.meta;
92 }
93
94 /**
95 * Returns the type of this {@code AttackStepBuilder} object.
96 *
97 * @return the type of this {@code AttackStepBuilder} object
98 * @since 1.0.0
99 */
100 public AttackStepType getType() {
101 return this.type;
102 }
103
104 /**
105 * Returns a list of all tags in this {@code AttackStepBuilder} object.
106 *
107 * @return a list of all tags in this {@code AttackStepBuilder} object
108 * @since 1.0.0
109 */
110 public List<String> getTags() {
111 return List.copyOf(this.tags);
112 }
113
114 /**
115 * Adds a tag to this {@code AttackStepBuilder} object.
116 *
117 * @param tag the tag to add
118 * @return this {@code AttackStepBuilder} object
119 * @throws java.lang.NullPointerException if {@code tag} is {@code null}
120 * @throws java.lang.IllegalArgumentException if {@code tag} is not a valid identifier
121 * @since 1.0.0
122 */
123 public AttackStepBuilder addTag(String tag) {
124 this.tags.add(requireIdentifier(tag));
125 return this;
126 }
127
128 /**
129 * Returns the risk of this {@code AttackStepBuilder} object, or {@code null} if no risk has been
130 * set.
131 *
132 * @return the risk of this {@code AttackStepBuilder} object, or {@code null} if no risk has been
133 * set
134 * @since 1.0.0
135 */
136 public Risk getRisk() {
137 return this.risk;
138 }
139
140 /**
141 * Returns the TTC of this {@code AttackStepBuilder} object, or {@code null} if no TTC has been
142 * set.
143 *
144 * @return the TTC of this {@code AttackStepBuilder} object, or {@code null} if no TTC has been
145 * set
146 * @since 1.0.0
147 */
148 public TtcExpression getTtc() {
149 return this.ttc;
150 }
151
152 /**
153 * Returns the requires steps of this {@code AttackStepBuilder} object, or {@code null} if no
154 * requires steps have been set.
155 *
156 * @return the requires steps of this {@code AttackStepBuilder} object, or {@code null} if no
157 * requires steps have been set
158 * @since 1.0.0
159 */
160 public StepsBuilder getRequires() {
161 return this.requires;
162 }
163
164 /**
165 * Returns the reaches steps of this {@code AttackStepBuilder} object, or {@code null} if no
166 * reaches steps has been set.
167 *
168 * @return the reaches steps of this {@code AttackStepBuilder} object, or {@code null} if no
169 * reaches steps has been set
170 * @since 1.0.0
171 */
172 public StepsBuilder getReaches() {
173 return this.reaches;
174 }
175
176 /**
177 * Creates a new {@code AttackStepBuilder} from a {@link jakarta.json.JsonObject}.
178 *
179 * @param jsonAttackStep the {@link jakarta.json.JsonObject}
180 * @return a new {@code AttackStepBuilder}
181 * @throws java.lang.NullPointerException if {@code jsonAttackStep} is {@code null}
182 * @since 1.0.0
183 */
184 public static AttackStepBuilder fromJson(JsonObject jsonAttackStep) {
185 requireNonNull(jsonAttackStep);
186 var name = jsonAttackStep.getString("name");
187 var type = AttackStepType.fromString(jsonAttackStep.getString("type"));
188 var risk =
189 jsonAttackStep.isNull("risk") ? null : Risk.fromJson(jsonAttackStep.getJsonObject("risk"));
190 var ttc =
191 jsonAttackStep.isNull("ttc")
192 ? null
193 : TtcExpression.fromJson(jsonAttackStep.getJsonObject("ttc"));
194 var requires =
195 jsonAttackStep.isNull("requires")
196 ? null
197 : StepsBuilder.fromJson(jsonAttackStep.getJsonObject("requires"));
198 var reaches =
199 jsonAttackStep.isNull("reaches")
200 ? null
201 : StepsBuilder.fromJson(jsonAttackStep.getJsonObject("reaches"));
202 var builder = new AttackStepBuilder(name, type, risk, ttc, requires, reaches);
203 builder.getMeta().fromJson(jsonAttackStep.getJsonObject("meta"));
204 for (var jsonTag : jsonAttackStep.getJsonArray("tags")) {
205 builder.addTag(((JsonString) jsonTag).getString());
206 }
207 return builder;
208 }
209 }