001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.core.model; 007 008import java.util.Collection; 009 010import edu.umd.cs.findbugs.annotations.NonNull; 011 012/** 013 * Walks a Metaschema model. The "visit" methods can be implemented by child 014 * classes to perform processing on a visited node. 015 * 016 * @param <DATA> 017 * state information that is carried through the walk 018 */ 019public abstract class ModelWalker<DATA> { 020 /** 021 * Generate default state information. 022 * 023 * @return the state information 024 */ 025 protected abstract DATA getDefaultData(); 026 027 /** 028 * Will visit the provided Metaschema module flag definition. 029 * 030 * @param flag 031 * the Metaschema module flag definition to walk 032 */ 033 public void walk(@NonNull IFlagDefinition flag) { 034 walk(flag, getDefaultData()); 035 } 036 037 /** 038 * Will visit the provided Metaschema module flag definition. 039 * 040 * @param flag 041 * the Metaschema module flag definition to walk 042 * @param data 043 * additional state information to operate on 044 */ 045 public void walk(@NonNull IFlagDefinition flag, DATA data) { 046 visit(flag, data); 047 } 048 049 /** 050 * Will visit the provided Metaschema module field definition, and then walk the 051 * associated flag instances. 052 * 053 * @param field 054 * the Metaschema module field definition to walk 055 */ 056 public void walk(@NonNull IFieldDefinition field) { 057 walk(field, getDefaultData()); 058 } 059 060 /** 061 * Will visit the provided Metaschema module field definition, and then walk the 062 * associated flag instances. 063 * 064 * @param field 065 * the Metaschema module field definition to walk 066 * @param data 067 * additional state information to operate on 068 */ 069 public void walk(@NonNull IFieldDefinition field, DATA data) { 070 if (visit(field, data)) { 071 walkFlagInstances(field.getFlagInstances(), data); 072 } 073 } 074 075 /** 076 * Will visit the provided Metaschema module assembly definition, and then walk 077 * the associated flag and model instances. 078 * 079 * @param assembly 080 * the Metaschema module assembly definition to walk 081 */ 082 public void walk(@NonNull IAssemblyDefinition assembly) { 083 walk(assembly, getDefaultData()); 084 } 085 086 /** 087 * Will visit the provided Metaschema module assembly definition, and then walk 088 * the associated flag and model instances. 089 * 090 * @param assembly 091 * the Metaschema module assembly definition to walk 092 * @param data 093 * additional state information to operate on 094 */ 095 public void walk(@NonNull IAssemblyDefinition assembly, DATA data) { 096 if (visit(assembly, data)) { 097 walkFlagInstances(assembly.getFlagInstances(), data); 098 walkModelInstances(assembly.getModelInstances(), data); 099 } 100 } 101 102 /** 103 * Will visit the provided Metaschema module flag instance, and then walk the 104 * associated flag definition. 105 * 106 * @param instance 107 * the Metaschema module flag instance to walk 108 * @param data 109 * additional state information to operate on 110 */ 111 public void walk(@NonNull IFlagInstance instance, DATA data) { 112 if (visit(instance, data)) { 113 walk(instance.getDefinition(), data); 114 } 115 } 116 117 /** 118 * Will visit the provided Metaschema module field instance, and then walk the 119 * associated field definition. 120 * 121 * @param instance 122 * the Metaschema module field instance to walk 123 * @param data 124 * additional state information to operate on 125 */ 126 public void walk(@NonNull IFieldInstance instance, DATA data) { 127 if (visit(instance, data)) { 128 walk(instance.getDefinition(), data); 129 } 130 } 131 132 /** 133 * Will visit the provided Metaschema module assembly instance, and then walk 134 * the associated assembly definition. 135 * 136 * @param instance 137 * the Metaschema module assembly instance to walk 138 * @param data 139 * additional state information to operate on 140 */ 141 public void walk(@NonNull IAssemblyInstance instance, DATA data) { 142 if (visit(instance, data)) { 143 walk(instance.getDefinition(), data); 144 } 145 } 146 147 /** 148 * Will visit the provided Metaschema module choice instance, and then walk the 149 * choice's child model instances. 150 * 151 * @param instance 152 * the Metaschema module choice instance to walk 153 * @param data 154 * additional state information to operate on 155 */ 156 public void walk(@NonNull IChoiceInstance instance, DATA data) { 157 if (visit(instance, data)) { 158 walkModelInstances(instance.getModelInstances(), data); 159 } 160 } 161 162 /** 163 * Will visit the provided Metaschema module choice group instance, and then 164 * walk the choice's child model instances. 165 * 166 * @param instance 167 * the Metaschema module choice instance to walk 168 * @param data 169 * additional state information to operate on 170 */ 171 public void walk(@NonNull IChoiceGroupInstance instance, DATA data) { 172 if (visit(instance, data)) { 173 walkModelInstances(instance.getModelInstances(), data); 174 } 175 } 176 177 /** 178 * Will walk the provided model definition. 179 * 180 * @param definition 181 * the definition to walk 182 */ 183 public void walkDefinition(@NonNull IDefinition definition) { 184 walkDefinition(definition, getDefaultData()); 185 } 186 187 /** 188 * Will walk the provided model definition. 189 * 190 * @param definition 191 * the definition to walk 192 * @param data 193 * additional state information to operate on 194 */ 195 public void walkDefinition(@NonNull IDefinition definition, DATA data) { 196 if (definition instanceof IAssemblyDefinition) { 197 walk((IAssemblyDefinition) definition, data); 198 } else if (definition instanceof IFieldDefinition) { 199 walk((IFieldDefinition) definition, data); 200 } else if (definition instanceof IFlagDefinition) { 201 walk((IFlagDefinition) definition, data); 202 } 203 } 204 205 /** 206 * Will walk each of the provided flag instances. 207 * 208 * @param instances 209 * a collection of flag instances to visit 210 * @param data 211 * additional state information to operate on 212 */ 213 protected void walkFlagInstances(@NonNull Collection<? extends IFlagInstance> instances, DATA data) { 214 for (IFlagInstance instance : instances) { 215 assert instance != null; 216 walk(instance, data); 217 } 218 } 219 220 /** 221 * Will walk each of the provided model instances. 222 * 223 * @param instances 224 * a collection of model instances to visit 225 * @param data 226 * additional state information to operate on 227 */ 228 protected void walkModelInstances(@NonNull Collection<? extends IModelInstance> instances, DATA data) { 229 for (IModelInstance instance : instances) { 230 assert instance != null; 231 walkModelInstance(instance, data); 232 } 233 } 234 235 /** 236 * Will walk the provided model instance. 237 * 238 * @param instance 239 * the instance to walk 240 * @param data 241 * additional state information to operate on 242 */ 243 protected void walkModelInstance(@NonNull IModelInstance instance, DATA data) { 244 if (instance instanceof IAssemblyInstance) { 245 walk((IAssemblyInstance) instance, data); 246 } else if (instance instanceof IFieldInstance) { 247 walk((IFieldInstance) instance, data); 248 } else if (instance instanceof IChoiceGroupInstance) { 249 walk((IChoiceGroupInstance) instance, data); 250 } else if (instance instanceof IChoiceInstance) { 251 walk((IChoiceInstance) instance, data); 252 } 253 } 254 255 /** 256 * Will visit the provided model definition. 257 * 258 * @param definition 259 * the definition to visit 260 * @param data 261 * additional state information to operate on 262 */ 263 protected void visitDefinition(@NonNull IDefinition definition, DATA data) { 264 if (definition instanceof IAssemblyDefinition) { 265 visit((IAssemblyDefinition) definition, data); 266 } else if (definition instanceof IFieldDefinition) { 267 visit((IFieldDefinition) definition, data); 268 } else if (definition instanceof IFlagDefinition) { 269 visit((IFlagDefinition) definition, data); 270 } 271 } 272 273 /** 274 * Called when the provided definition is walked. This can be overridden by 275 * child classes to enable processing of the visited definition. 276 * 277 * @param def 278 * the definition that is visited 279 * @param data 280 * additional state information to operate on 281 */ 282 protected abstract void visit(@NonNull IFlagDefinition def, DATA data); 283 284 /** 285 * Called when the provided definition is walked. This can be overridden by 286 * child classes to enable processing of the visited definition. 287 * 288 * @param def 289 * the definition that is visited 290 * @param data 291 * additional state information to operate on 292 * @return {@code true} if child instances are to be walked, or {@code false} 293 * otherwise 294 */ 295 protected boolean visit(@NonNull IFieldDefinition def, DATA data) { 296 return true; 297 } 298 299 /** 300 * Called when the provided definition is walked. This can be overridden by 301 * child classes to enable processing of the visited definition. 302 * 303 * @param def 304 * the definition that is visited 305 * @param data 306 * additional state information to operate on 307 * @return {@code true} if child instances are to be walked, or {@code false} 308 * otherwise 309 */ 310 protected boolean visit(@NonNull IAssemblyDefinition def, DATA data) { 311 return true; 312 } 313 314 /** 315 * Called when the provided instance is walked. This can be overridden by child 316 * classes to enable processing of the visited instance. 317 * 318 * @param instance 319 * the instance that is visited 320 * @param data 321 * additional state information to operate on 322 * @return {@code true} if the associated definition is to be walked, or 323 * {@code false} otherwise 324 */ 325 protected boolean visit(@NonNull IFlagInstance instance, DATA data) { 326 return true; 327 } 328 329 /** 330 * Called when the provided instance is walked. This can be overridden by child 331 * classes to enable processing of the visited instance. 332 * 333 * @param instance 334 * the instance that is visited 335 * @param data 336 * additional state information to operate on 337 * @return {@code true} if the associated definition is to be walked, or 338 * {@code false} otherwise 339 */ 340 protected boolean visit(@NonNull IFieldInstance instance, DATA data) { 341 return true; 342 } 343 344 /** 345 * Called when the provided instance is walked. This can be overridden by child 346 * classes to enable processing of the visited instance. 347 * 348 * @param instance 349 * the instance that is visited 350 * @param data 351 * additional state information to operate on 352 * @return {@code true} if the associated definition is to be walked, or 353 * {@code false} otherwise 354 */ 355 protected boolean visit(@NonNull IAssemblyInstance instance, DATA data) { 356 return true; 357 } 358 359 /** 360 * Called when the provided instance is walked. This can be overridden by child 361 * classes to enable processing of the visited instance. 362 * 363 * @param instance 364 * the instance that is visited 365 * @param data 366 * additional state information to operate on 367 * @return {@code true} if the child instances are to be walked, or 368 * {@code false} otherwise 369 */ 370 protected boolean visit(@NonNull IChoiceInstance instance, DATA data) { 371 return true; 372 } 373 374 /** 375 * Called when the provided instance is walked. This can be overridden by child 376 * classes to enable processing of the visited instance. 377 * 378 * @param instance 379 * the instance that is visited 380 * @param data 381 * additional state information to operate on 382 * @return {@code true} if the child instances are to be walked, or 383 * {@code false} otherwise 384 */ 385 protected boolean visit(@NonNull IChoiceGroupInstance instance, DATA data) { 386 return true; 387 } 388}