1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.lib.model.control.catalog;
7   
8   import gov.nist.secauto.metaschema.core.util.CollectionUtil;
9   import gov.nist.secauto.metaschema.core.util.ObjectUtils;
10  import gov.nist.secauto.oscal.lib.model.Catalog;
11  import gov.nist.secauto.oscal.lib.model.CatalogGroup;
12  import gov.nist.secauto.oscal.lib.model.Control;
13  import gov.nist.secauto.oscal.lib.model.Parameter;
14  
15  import java.util.Objects;
16  
17  import edu.umd.cs.findbugs.annotations.NonNull;
18  
19  public abstract class AbstractCatalogVisitor<RESULT, CONTEXT> implements ICatalogVisitor<RESULT, CONTEXT> {
20  
21    /**
22     * Get a new initial/default result for the visitor.
23     *
24     * @return the result
25     */
26    protected abstract RESULT defaultResult();
27  
28    /**
29     * Aggregate two results into one.
30     *
31     * @param previous
32     *          the first result
33     * @param current
34     *          the next result
35     * @return the result produced by combining the two results
36     */
37    protected RESULT aggregateResult(RESULT previous, RESULT current) {
38      return current;
39    }
40  
41    @Override
42    public RESULT visitCatalog(Catalog catalog, CONTEXT context) {
43      RESULT result = CollectionUtil.listOrEmpty(catalog.getGroups()).stream()
44          .filter(Objects::nonNull)
45          .map(childGroup -> visitGroup(ObjectUtils.notNull(childGroup), context))
46          .reduce(defaultResult(), this::aggregateResult);
47      result = CollectionUtil.listOrEmpty(catalog.getControls()).stream()
48          .filter(Objects::nonNull)
49          .map(childControl -> visitControl(ObjectUtils.notNull(childControl), context))
50          .reduce(result, this::aggregateResult);
51      return CollectionUtil.listOrEmpty(catalog.getParams()).stream()
52          .filter(Objects::nonNull)
53          .map(childParameter -> visitParameter(ObjectUtils.notNull(childParameter), context))
54          .reduce(result, this::aggregateResult);
55    }
56  
57    @Override
58    public RESULT visitGroup(@NonNull CatalogGroup group, CONTEXT context) {
59      RESULT result = CollectionUtil.listOrEmpty(group.getGroups()).stream()
60          .filter(Objects::nonNull)
61          .map(childGroup -> visitGroup(ObjectUtils.notNull(childGroup), context))
62          .reduce(defaultResult(), this::aggregateResult);
63      result = CollectionUtil.listOrEmpty(group.getControls()).stream()
64          .filter(Objects::nonNull)
65          .map(childControl -> visitControl(ObjectUtils.notNull(childControl), context))
66          .reduce(result, this::aggregateResult);
67      return CollectionUtil.listOrEmpty(group.getParams()).stream()
68          .filter(Objects::nonNull)
69          .map(childParameter -> visitParameter(ObjectUtils.notNull(childParameter), context))
70          .reduce(result, this::aggregateResult);
71    }
72  
73    @Override
74    public RESULT visitControl(Control control, CONTEXT context) {
75      RESULT result = CollectionUtil.listOrEmpty(control.getControls()).stream()
76          .filter(Objects::nonNull)
77          .map(childControl -> visitControl(ObjectUtils.notNull(childControl), context))
78          .reduce(defaultResult(), this::aggregateResult);
79      return CollectionUtil.listOrEmpty(control.getParams()).stream()
80          .filter(Objects::nonNull)
81          .map(childParameter -> visitParameter(ObjectUtils.notNull(childParameter), context))
82          .reduce(result, this::aggregateResult);
83    }
84  
85    @Override
86    public RESULT visitParameter(Parameter parameter, CONTEXT context) {
87      return defaultResult();
88    }
89  
90  }