1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.oscal.lib;
7   
8   import java.io.File;
9   import java.io.IOException;
10  import java.net.URISyntaxException;
11  import java.net.URL;
12  import java.nio.file.Path;
13  
14  import dev.metaschema.core.metapath.StaticContext;
15  import dev.metaschema.core.model.MetaschemaException;
16  import dev.metaschema.core.util.ObjectUtils;
17  import dev.metaschema.databind.DefaultBindingContext;
18  import dev.metaschema.databind.IBindingContext;
19  import dev.metaschema.databind.SimpleModuleLoaderStrategy;
20  import dev.metaschema.oscal.lib.model.AssessmentPlan;
21  import dev.metaschema.oscal.lib.model.AssessmentResults;
22  import dev.metaschema.oscal.lib.model.Catalog;
23  import dev.metaschema.oscal.lib.model.ComponentDefinition;
24  import dev.metaschema.oscal.lib.model.OscalCompleteModule;
25  import dev.metaschema.oscal.lib.model.PlanOfActionAndMilestones;
26  import dev.metaschema.oscal.lib.model.Profile;
27  import dev.metaschema.oscal.lib.model.SystemSecurityPlan;
28  import edu.umd.cs.findbugs.annotations.NonNull;
29  import nl.talsmasoftware.lazy4j.Lazy;
30  
31  public class OscalBindingContext
32      extends DefaultBindingContext {
33  
34    @NonNull
35    public static final StaticContext OSCAL_STATIC_METAPATH_CONTEXT = StaticContext.builder()
36        .defaultModelNamespace(OscalModelConstants.NS_OSCAL)
37        .build();
38    private static final Lazy<OscalBindingContext> SINGLETON = Lazy.of(OscalBindingContext::new);
39  
40    @NonNull
41    public static OscalBindingContext instance() {
42      return ObjectUtils.notNull(SINGLETON.get());
43    }
44  
45    /**
46     * Get a new builder that can produce a new, configured OSCAL-flavored binding
47     * context.
48     *
49     * @return the builder
50     * @since 2.0.0
51     */
52    public static IBindingContext.BindingContextBuilder builder() {
53      return new IBindingContext.BindingContextBuilder(OscalBindingContext::new);
54    }
55  
56    /**
57     * Get a new OSCAL-flavored {@link IBindingContext} instance, which can be used
58     * to load information that binds a model to a set of Java classes.
59     *
60     * @return a new binding context
61     * @since 2.0.0
62     */
63    @NonNull
64    public static OscalBindingContext newInstance() {
65      return new OscalBindingContext();
66    }
67  
68    /**
69     * Get a new OSCAL-flavored {@link IBindingContext} instance, which can be used
70     * to load information that binds a model to a set of Java classes.
71     *
72     * @param strategy
73     *          the loader strategy to use when loading Metaschema modules
74     * @return a new binding context
75     * @since 2.0.0
76     */
77    @NonNull
78    public static OscalBindingContext newInstance(@NonNull IBindingContext.IModuleLoaderStrategy strategy) {
79      return new OscalBindingContext(strategy);
80    }
81  
82    /**
83     * Construct a new OSCAL-flavored binding context.
84     */
85    protected OscalBindingContext() {
86      this(new SimpleModuleLoaderStrategy());
87    }
88  
89    /**
90     * Construct a new OSCAL-flavored binding context.
91     *
92     * @param strategy
93     *          the behavior class to use for loading Metaschema modules
94     * @since 2.0.0
95     */
96    @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") // false positive
97    public OscalBindingContext(@NonNull IBindingContext.IModuleLoaderStrategy strategy) {
98      super(strategy);
99      try {
100       registerModule(OscalCompleteModule.class);
101     } catch (MetaschemaException ex) {
102       throw new IllegalStateException("Failed to register OSCAL module", ex);
103     }
104   }
105 
106   @NonNull
107   public Catalog loadCatalog(@NonNull URL url) throws IOException, URISyntaxException {
108     return newBoundLoader().load(Catalog.class, url);
109   }
110 
111   @NonNull
112   public Catalog loadCatalog(@NonNull Path path) throws IOException {
113     return newBoundLoader().load(Catalog.class, path);
114   }
115 
116   @NonNull
117   public Catalog loadCatalog(@NonNull File file) throws IOException {
118     return newBoundLoader().load(Catalog.class, file);
119   }
120 
121   @NonNull
122   public Profile loadProfile(@NonNull URL url) throws IOException, URISyntaxException {
123     return newBoundLoader().load(Profile.class, url);
124   }
125 
126   @NonNull
127   public Profile loadProfile(@NonNull Path path) throws IOException {
128     return newBoundLoader().load(Profile.class, path);
129   }
130 
131   @NonNull
132   public Profile loadProfile(@NonNull File file) throws IOException {
133     return newBoundLoader().load(Profile.class, file);
134   }
135 
136   @NonNull
137   public SystemSecurityPlan loadSystemSecurityPlan(@NonNull URL url) throws IOException, URISyntaxException {
138     return newBoundLoader().load(SystemSecurityPlan.class, url);
139   }
140 
141   @NonNull
142   public SystemSecurityPlan loadSystemSecurityPlan(@NonNull Path path) throws IOException {
143     return newBoundLoader().load(SystemSecurityPlan.class, path);
144   }
145 
146   @NonNull
147   public SystemSecurityPlan loadSystemSecurityPlan(@NonNull File file) throws IOException {
148     return newBoundLoader().load(SystemSecurityPlan.class, file);
149   }
150 
151   @NonNull
152   public ComponentDefinition loadComponentDefinition(@NonNull URL url) throws IOException, URISyntaxException {
153     return newBoundLoader().load(ComponentDefinition.class, url);
154   }
155 
156   @NonNull
157   public ComponentDefinition loadComponentDefinition(@NonNull Path path) throws IOException {
158     return newBoundLoader().load(ComponentDefinition.class, path);
159   }
160 
161   @NonNull
162   public ComponentDefinition loadComponentDefinition(@NonNull File file) throws IOException {
163     return newBoundLoader().load(ComponentDefinition.class, file);
164   }
165 
166   @NonNull
167   public AssessmentPlan loadAssessmentPlan(@NonNull URL url) throws IOException, URISyntaxException {
168     return newBoundLoader().load(AssessmentPlan.class, url);
169   }
170 
171   @NonNull
172   public AssessmentPlan loadAssessmentPlan(@NonNull Path path) throws IOException {
173     return newBoundLoader().load(AssessmentPlan.class, path);
174   }
175 
176   @NonNull
177   public AssessmentPlan loadAssessmentPlan(@NonNull File file) throws IOException {
178     return newBoundLoader().load(AssessmentPlan.class, file);
179   }
180 
181   @NonNull
182   public AssessmentResults loadAssessmentResults(@NonNull URL url) throws IOException, URISyntaxException {
183     return newBoundLoader().load(AssessmentResults.class, url);
184   }
185 
186   @NonNull
187   public AssessmentResults loadAssessmentResults(@NonNull Path path) throws IOException {
188     return newBoundLoader().load(AssessmentResults.class, path);
189   }
190 
191   @NonNull
192   public AssessmentResults loadAssessmentResults(@NonNull File file) throws IOException {
193     return newBoundLoader().load(AssessmentResults.class, file);
194   }
195 
196   @NonNull
197   public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull URL url)
198       throws IOException, URISyntaxException {
199     return newBoundLoader().load(PlanOfActionAndMilestones.class, url);
200   }
201 
202   @NonNull
203   public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull Path path) throws IOException {
204     return newBoundLoader().load(PlanOfActionAndMilestones.class, path);
205   }
206 
207   @NonNull
208   public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull File file) throws IOException {
209     return newBoundLoader().load(PlanOfActionAndMilestones.class, file);
210   }
211 }