001/*
002 * Portions of this software was developed by employees of the National Institute
003 * of Standards and Technology (NIST), an agency of the Federal Government and is
004 * being made available as a public service. Pursuant to title 17 United States
005 * Code Section 105, works of NIST employees are not subject to copyright
006 * protection in the United States. This software may be subject to foreign
007 * copyright. Permission in the United States and in foreign countries, to the
008 * extent that NIST may hold copyright, to use, copy, modify, create derivative
009 * works, and distribute this software and its documentation without fee is hereby
010 * granted on a non-exclusive basis, provided that this notice and disclaimer
011 * of warranty appears in all copies.
012 *
013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
025 */
026
027package gov.nist.secauto.metaschema.core.model;
028
029import java.util.Collection;
030
031import edu.umd.cs.findbugs.annotations.NonNull;
032
033/**
034 * Walks a Metaschema model. The "visit" methods can be implemented by child
035 * classes to perform processing on a visited node.
036 *
037 * @param <DATA>
038 *          state information that is carried through the walk
039 */
040public abstract class ModelWalker<DATA> {
041  /**
042   * Generate default state information.
043   *
044   * @return the state information
045   */
046  protected abstract DATA getDefaultData();
047
048  /**
049   * Will visit the provided metaschema flag definition.
050   *
051   * @param flag
052   *          the metaschema flag definition to walk
053   */
054  public void walk(@NonNull IFlagDefinition flag) {
055    walk(flag, getDefaultData());
056  }
057
058  /**
059   * Will visit the provided metaschema flag definition.
060   *
061   * @param flag
062   *          the metaschema flag definition to walk
063   * @param data
064   *          additional state information to operate on
065   */
066  public void walk(@NonNull IFlagDefinition flag, DATA data) {
067    visit(flag, data);
068  }
069
070  /**
071   * Will visit the provided metaschema field definition, and then walk the
072   * associated flag instances.
073   *
074   * @param field
075   *          the metaschema field definition to walk
076   */
077  public void walk(@NonNull IFieldDefinition field) {
078    walk(field, getDefaultData());
079  }
080
081  /**
082   * Will visit the provided metaschema field definition, and then walk the
083   * associated flag instances.
084   *
085   * @param field
086   *          the metaschema field definition to walk
087   * @param data
088   *          additional state information to operate on
089   */
090  public void walk(@NonNull IFieldDefinition field, DATA data) {
091    if (visit(field, data)) {
092      walkFlagInstances(field.getFlagInstances(), data);
093    }
094  }
095
096  /**
097   * Will visit the provided metaschema assembly definition, and then walk the
098   * associated flag and model instances.
099   *
100   * @param assembly
101   *          the metaschema assembly definition to walk
102   */
103  public void walk(@NonNull IAssemblyDefinition assembly) {
104    walk(assembly, getDefaultData());
105  }
106
107  /**
108   * Will visit the provided metaschema assembly definition, and then walk the
109   * associated flag and model instances.
110   *
111   * @param assembly
112   *          the metaschema assembly definition to walk
113   * @param data
114   *          additional state information to operate on
115   */
116  public void walk(@NonNull IAssemblyDefinition assembly, DATA data) {
117    if (visit(assembly, data)) {
118      walkFlagInstances(assembly.getFlagInstances(), data);
119      walkModelInstances(assembly.getModelInstances(), data);
120    }
121  }
122
123  /**
124   * Will visit the provided metaschema flag instance, and then walk the
125   * associated flag definition.
126   *
127   * @param instance
128   *          the metaschema flag instance to walk
129   * @param data
130   *          additional state information to operate on
131   */
132  public void walk(@NonNull IFlagInstance instance, DATA data) {
133    if (visit(instance, data)) {
134      walk(instance.getDefinition(), data);
135    }
136  }
137
138  /**
139   * Will visit the provided metaschema field instance, and then walk the
140   * associated field definition.
141   *
142   * @param instance
143   *          the metaschema field instance to walk
144   * @param data
145   *          additional state information to operate on
146   */
147  public void walk(@NonNull IFieldInstance instance, DATA data) {
148    if (visit(instance, data)) {
149      walk(instance.getDefinition(), data);
150    }
151  }
152
153  /**
154   * Will visit the provided metaschema assembly instance, and then walk the
155   * associated assembly definition.
156   *
157   * @param instance
158   *          the metaschema assembly instance to walk
159   * @param data
160   *          additional state information to operate on
161   */
162  public void walk(@NonNull IAssemblyInstance instance, DATA data) {
163    if (visit(instance, data)) {
164      walk(instance.getDefinition(), data);
165    }
166  }
167
168  /**
169   * Will visit the provided metaschema choice instance, and then walk the
170   * choice's child model instances.
171   *
172   * @param instance
173   *          the metaschema choice instance to walk
174   * @param data
175   *          additional state information to operate on
176   */
177  public void walk(@NonNull IChoiceInstance instance, DATA data) {
178    if (visit(instance, data)) {
179      walkModelInstances(instance.getModelInstances(), data);
180    }
181  }
182
183  /**
184   * Will walk the provided model definition.
185   *
186   * @param definition
187   *          the definition to walk
188   */
189  public void walkDefinition(@NonNull IDefinition definition) {
190    walkDefinition(definition, getDefaultData());
191  }
192
193  /**
194   * Will walk the provided model definition.
195   *
196   * @param definition
197   *          the definition to walk
198   * @param data
199   *          additional state information to operate on
200   */
201  public void walkDefinition(@NonNull IDefinition definition, DATA data) {
202    if (definition instanceof IAssemblyDefinition) {
203      walk((IAssemblyDefinition) definition, data);
204    } else if (definition instanceof IFieldDefinition) {
205      walk((IFieldDefinition) definition, data);
206    } else if (definition instanceof IFlagDefinition) {
207      walk((IFlagDefinition) definition, data);
208    }
209  }
210
211  /**
212   * Will walk each of the provided flag instances.
213   *
214   * @param instances
215   *          a collection of flag instances to visit
216   * @param data
217   *          additional state information to operate on
218   */
219  protected void walkFlagInstances(@NonNull Collection<? extends IFlagInstance> instances, DATA data) {
220    for (IFlagInstance instance : instances) {
221      assert instance != null;
222      walk(instance, data);
223    }
224  }
225
226  /**
227   * Will walk each of the provided model instances.
228   *
229   * @param instances
230   *          a collection of model instances to visit
231   * @param data
232   *          additional state information to operate on
233   */
234  protected void walkModelInstances(@NonNull Collection<? extends IModelInstance> instances, DATA data) {
235    for (IModelInstance instance : instances) {
236      assert instance != null;
237      walkModelInstance(instance, data);
238    }
239  }
240
241  /**
242   * Will walk the provided model instance.
243   *
244   * @param instance
245   *          the instance to walk
246   * @param data
247   *          additional state information to operate on
248   */
249  protected void walkModelInstance(@NonNull IModelInstance instance, DATA data) {
250    if (instance instanceof IAssemblyInstance) {
251      walk((IAssemblyInstance) instance, data);
252    } else if (instance instanceof IFieldInstance) {
253      walk((IFieldInstance) instance, data);
254    } else if (instance instanceof IChoiceInstance) {
255      walk((IChoiceInstance) instance, data);
256    }
257  }
258
259  /**
260   * Called when the provided definition is walked. This can be overridden by
261   * child classes to enable processing of the visited definition.
262   *
263   * @param def
264   *          the definition that is visited
265   * @param data
266   *          additional state information to operate on
267   */
268  protected abstract void visit(@NonNull IFlagDefinition def, DATA data);
269
270  /**
271   * Called when the provided definition is walked. This can be overridden by
272   * child classes to enable processing of the visited definition.
273   *
274   * @param def
275   *          the definition that is visited
276   * @param data
277   *          additional state information to operate on
278   * @return {@code true} if child instances are to be walked, or {@code false}
279   *         otherwise
280   */
281  protected boolean visit(@NonNull IFieldDefinition def, DATA data) {
282    return true;
283  }
284
285  /**
286   * Called when the provided definition is walked. This can be overridden by
287   * child classes to enable processing of the visited definition.
288   *
289   * @param def
290   *          the definition that is visited
291   * @param data
292   *          additional state information to operate on
293   * @return {@code true} if child instances are to be walked, or {@code false}
294   *         otherwise
295   */
296  protected boolean visit(@NonNull IAssemblyDefinition def, DATA data) {
297    return true;
298  }
299
300  /**
301   * Called when the provided instance is walked. This can be overridden by child
302   * classes to enable processing of the visited instance.
303   *
304   * @param instance
305   *          the instance that is visited
306   * @param data
307   *          additional state information to operate on
308   * @return {@code true} if the associated definition is to be walked, or
309   *         {@code false} otherwise
310   */
311  protected boolean visit(@NonNull IFlagInstance instance, DATA data) {
312    return true;
313  }
314
315  /**
316   * Called when the provided instance is walked. This can be overridden by child
317   * classes to enable processing of the visited instance.
318   *
319   * @param instance
320   *          the instance that is visited
321   * @param data
322   *          additional state information to operate on
323   * @return {@code true} if the associated definition is to be walked, or
324   *         {@code false} otherwise
325   */
326  protected boolean visit(@NonNull IFieldInstance instance, DATA data) {
327    return true;
328  }
329
330  /**
331   * Called when the provided instance is walked. This can be overridden by child
332   * classes to enable processing of the visited instance.
333   *
334   * @param instance
335   *          the instance that is visited
336   * @param data
337   *          additional state information to operate on
338   * @return {@code true} if the associated definition is to be walked, or
339   *         {@code false} otherwise
340   */
341  protected boolean visit(@NonNull IAssemblyInstance instance, DATA data) {
342    return true;
343  }
344
345  /**
346   * Called when the provided instance is walked. This can be overridden by child
347   * classes to enable processing of the visited instance.
348   *
349   * @param instance
350   *          the instance that is visited
351   * @param data
352   *          additional state information to operate on
353   * @return {@code true} if the child instances are to be walked, or
354   *         {@code false} otherwise
355   */
356  protected boolean visit(@NonNull IChoiceInstance instance, DATA data) {
357    return true;
358  }
359}