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