View Javadoc
1   /*
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.oscal.lib.profile.resolver.support;
28  
29  import gov.nist.secauto.metaschema.model.common.metapath.item.IDocumentNodeItem;
30  import gov.nist.secauto.metaschema.model.common.metapath.item.IRequiredValueModelNodeItem;
31  import gov.nist.secauto.metaschema.model.common.util.ObjectUtils;
32  
33  import edu.umd.cs.findbugs.annotations.NonNull;
34  
35  /**
36   * Used to visit a catalog containing groups and controls.
37   *
38   * @param <T>
39   *          the type of the state object used to pass calling context
40   *          information
41   * @param <R>
42   *          the type of the result for visiting a collection of groups and/or
43   *          controls
44   */
45  public abstract class AbstractCatalogVisitor<T, R> implements ICatalogVisitor<T, R> {
46  
47    protected abstract R newDefaultResult(T state);
48  
49    protected abstract R aggregateResults(R first, R second, T state);
50  
51    protected R visitCatalog(@NonNull IDocumentNodeItem catalogDocument, T state) {
52      return visitGroupContainer(catalogDocument.getRootAssemblyNodeItem(), newDefaultResult(state), state);
53    }
54  
55    /**
56     * Visit the child groups and controls (in that order) of a given catalog or
57     * group container.
58     *
59     * @param catalogOrGroup
60     *          the catalog or group Metapath item currently being visited
61     * @param initialResult
62     *          the initial result value to use when aggregating child results
63     * @param state
64     *          the current visitor state
65     * @return a meaningful result of the given type
66     */
67    protected R visitGroupContainer(
68        @NonNull IRequiredValueModelNodeItem catalogOrGroup,
69        R initialResult,
70        T state) {
71      R result = catalogOrGroup.getModelItemsByName("group").stream()
72          .map(groupItem -> {
73            return visitGroupItem(ObjectUtils.requireNonNull(groupItem), state);
74          })
75          .reduce(initialResult, (first, second) -> aggregateResults(first, second, state));
76      return visitControlContainer(catalogOrGroup, result, state);
77    }
78  
79    /**
80     * Called when visiting a group.
81     * <p>
82     * This method will first visit the group's children, then the group itself.
83     *
84     * @param item
85     *          the group Metapath item to visit
86     * @param state
87     *          the current visitor state
88     * @return a meaningful result of the given type
89     */
90    protected R visitGroupItem(@NonNull IRequiredValueModelNodeItem item, T state) {
91      R childResult = visitGroupContainer(item, newDefaultResult(state), state);
92      return visitGroupInternal(item, childResult, state);
93    }
94  
95    /**
96     * Called when visiting a group after visiting it's children.
97     *
98     * @param item
99     *          the group Metapath item currently being visited
100    * @param childResult
101    *          the result of visiting the group's children
102    * @param state
103    *          the current visitor state
104    * @return a meaningful result of the given type
105    */
106   protected R visitGroupInternal(
107       @NonNull IRequiredValueModelNodeItem item,
108       R childResult,
109       T state) {
110     return visitGroup(item, childResult, state);
111   }
112 
113   /**
114    * Visit the child controls (in that order) of a given catalog, group, or
115    * control container.
116    *
117    * @param catalogOrGroupOrControl
118    *          the catalog, group, or control Metapath item currently being visited
119    * @param initialResult
120    *          the initial result value to use when aggregating child results
121    * @param state
122    *          the current visitor state
123    * @return a meaningful result of the given type
124    */
125   protected R visitControlContainer(
126       @NonNull IRequiredValueModelNodeItem catalogOrGroupOrControl,
127       R initialResult,
128       T state) {
129     return catalogOrGroupOrControl.getModelItemsByName("control").stream()
130         .map(controlItem -> {
131           return visitControlItem(ObjectUtils.requireNonNull(controlItem), state);
132         })
133         .reduce(initialResult, (first, second) -> aggregateResults(first, second, state));
134   }
135 
136   /**
137    * Called when visiting a control.
138    * <p>
139    * This method will first visit the control's children, then the control itself.
140    *
141    * @param item
142    *          the group Metapath item to visit
143    * @param state
144    *          the current visitor state
145    * @return a meaningful result of the given type
146    */
147   protected R visitControlItem(@NonNull IRequiredValueModelNodeItem item, T state) {
148     R childResult = visitControlContainer(item, newDefaultResult(state), state);
149     return visitControlInternal(item, childResult, state);
150   }
151 
152   /**
153    * Called when visiting a control after visiting it's children.
154    *
155    * @param controlItem
156    *          the Metapath item for the control currently being visited
157    * @param childResult
158    *          the result of visiting the control's children
159    * @param state
160    *          the calling context information
161    * @return a meaningful result of the given type
162    */
163   protected R visitControlInternal(@NonNull IRequiredValueModelNodeItem controlItem, R childResult, T state) {
164     return visitControl(controlItem, childResult, state);
165   }
166 }