001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.oscal.lib;
007
008import java.io.File;
009import java.io.IOException;
010import java.net.URISyntaxException;
011import java.net.URL;
012import java.nio.file.Path;
013
014import dev.metaschema.core.metapath.StaticContext;
015import dev.metaschema.core.model.MetaschemaException;
016import dev.metaschema.core.util.ObjectUtils;
017import dev.metaschema.databind.DefaultBindingContext;
018import dev.metaschema.databind.IBindingContext;
019import dev.metaschema.databind.SimpleModuleLoaderStrategy;
020import dev.metaschema.oscal.lib.model.AssessmentPlan;
021import dev.metaschema.oscal.lib.model.AssessmentResults;
022import dev.metaschema.oscal.lib.model.Catalog;
023import dev.metaschema.oscal.lib.model.ComponentDefinition;
024import dev.metaschema.oscal.lib.model.OscalCompleteModule;
025import dev.metaschema.oscal.lib.model.PlanOfActionAndMilestones;
026import dev.metaschema.oscal.lib.model.Profile;
027import dev.metaschema.oscal.lib.model.SystemSecurityPlan;
028import edu.umd.cs.findbugs.annotations.NonNull;
029import nl.talsmasoftware.lazy4j.Lazy;
030
031public class OscalBindingContext
032    extends DefaultBindingContext {
033
034  @NonNull
035  public static final StaticContext OSCAL_STATIC_METAPATH_CONTEXT = StaticContext.builder()
036      .defaultModelNamespace(OscalModelConstants.NS_OSCAL)
037      .build();
038  private static final Lazy<OscalBindingContext> SINGLETON = Lazy.of(OscalBindingContext::new);
039
040  @NonNull
041  public static OscalBindingContext instance() {
042    return ObjectUtils.notNull(SINGLETON.get());
043  }
044
045  /**
046   * Get a new builder that can produce a new, configured OSCAL-flavored binding
047   * context.
048   *
049   * @return the builder
050   * @since 2.0.0
051   */
052  public static IBindingContext.BindingContextBuilder builder() {
053    return new IBindingContext.BindingContextBuilder(OscalBindingContext::new);
054  }
055
056  /**
057   * Get a new OSCAL-flavored {@link IBindingContext} instance, which can be used
058   * to load information that binds a model to a set of Java classes.
059   *
060   * @return a new binding context
061   * @since 2.0.0
062   */
063  @NonNull
064  public static OscalBindingContext newInstance() {
065    return new OscalBindingContext();
066  }
067
068  /**
069   * Get a new OSCAL-flavored {@link IBindingContext} instance, which can be used
070   * to load information that binds a model to a set of Java classes.
071   *
072   * @param strategy
073   *          the loader strategy to use when loading Metaschema modules
074   * @return a new binding context
075   * @since 2.0.0
076   */
077  @NonNull
078  public static OscalBindingContext newInstance(@NonNull IBindingContext.IModuleLoaderStrategy strategy) {
079    return new OscalBindingContext(strategy);
080  }
081
082  /**
083   * Construct a new OSCAL-flavored binding context.
084   */
085  protected OscalBindingContext() {
086    this(new SimpleModuleLoaderStrategy());
087  }
088
089  /**
090   * Construct a new OSCAL-flavored binding context.
091   *
092   * @param strategy
093   *          the behavior class to use for loading Metaschema modules
094   * @since 2.0.0
095   */
096  @SuppressWarnings("PMD.ConstructorCallsOverridableMethod") // false positive
097  public OscalBindingContext(@NonNull IBindingContext.IModuleLoaderStrategy strategy) {
098    super(strategy);
099    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}