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 }