001/*
002 * Portions of this software was developed by employees of the National Institute
003 * of Standards and Technology (NIST), an agency of the Federal Government and is
004 * being made available as a public service. Pursuant to title 17 United States
005 * Code Section 105, works of NIST employees are not subject to copyright
006 * protection in the United States. This software may be subject to foreign
007 * copyright. Permission in the United States and in foreign countries, to the
008 * extent that NIST may hold copyright, to use, copy, modify, create derivative
009 * works, and distribute this software and its documentation without fee is hereby
010 * granted on a non-exclusive basis, provided that this notice and disclaimer
011 * of warranty appears in all copies.
012 *
013 * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
014 * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
015 * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
016 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
017 * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
018 * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
019 * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
020 * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
021 * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
022 * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
023 * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
024 * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
025 */
026
027package gov.nist.secauto.oscal.lib;
028
029import gov.nist.secauto.metaschema.binding.DefaultBindingContext;
030import gov.nist.secauto.metaschema.binding.IBindingMatcher;
031import gov.nist.secauto.metaschema.model.common.constraint.IConstraintSet;
032import gov.nist.secauto.oscal.lib.model.AssessmentPlan;
033import gov.nist.secauto.oscal.lib.model.AssessmentResults;
034import gov.nist.secauto.oscal.lib.model.Catalog;
035import gov.nist.secauto.oscal.lib.model.ComponentDefinition;
036import gov.nist.secauto.oscal.lib.model.PlanOfActionAndMilestones;
037import gov.nist.secauto.oscal.lib.model.Profile;
038import gov.nist.secauto.oscal.lib.model.SystemSecurityPlan;
039
040import java.io.File;
041import java.io.IOException;
042import java.net.URISyntaxException;
043import java.net.URL;
044import java.nio.file.Path;
045import java.util.Set;
046
047import javax.xml.namespace.QName;
048
049import edu.umd.cs.findbugs.annotations.NonNull;
050
051public class OscalBindingContext
052    extends DefaultBindingContext {
053  @NonNull
054  private static final OscalBindingContext SINGLETON = new OscalBindingContext();
055
056  @NonNull
057  public static OscalBindingContext instance() {
058    return SINGLETON;
059  }
060
061  /**
062   * Construct a new OSCAL-flavored binding context with custom constraints.
063   *
064   * @param constraintSets
065   *          a set of additional constraints to apply
066   */
067  public OscalBindingContext(@NonNull Set<IConstraintSet> constraintSets) {
068    super(constraintSets);
069    registerBindingMatcher(new Matcher());
070  }
071
072  /**
073   * Construct a new OSCAL-flavored binding context.
074   */
075  protected OscalBindingContext() {
076    registerBindingMatcher(new Matcher());
077  }
078
079  @NonNull
080  public Catalog loadCatalog(@NonNull URL url) throws IOException, URISyntaxException {
081    return newBoundLoader().load(Catalog.class, url);
082  }
083
084  @NonNull
085  public Catalog loadCatalog(@NonNull Path path) throws IOException {
086    return newBoundLoader().load(Catalog.class, path);
087  }
088
089  @NonNull
090  public Catalog loadCatalog(@NonNull File file) throws IOException {
091    return newBoundLoader().load(Catalog.class, file);
092  }
093
094  @NonNull
095  public Profile loadProfile(@NonNull URL url) throws IOException, URISyntaxException {
096    return newBoundLoader().load(Profile.class, url);
097  }
098
099  @NonNull
100  public Profile loadProfile(@NonNull Path path) throws IOException {
101    return newBoundLoader().load(Profile.class, path);
102  }
103
104  @NonNull
105  public Profile loadProfile(@NonNull File file) throws IOException {
106    return newBoundLoader().load(Profile.class, file);
107  }
108
109  @NonNull
110  public SystemSecurityPlan loadSystemSecurityPlan(@NonNull URL url) throws IOException, URISyntaxException {
111    return newBoundLoader().load(SystemSecurityPlan.class, url);
112  }
113
114  @NonNull
115  public SystemSecurityPlan loadSystemSecurityPlan(@NonNull Path path) throws IOException {
116    return newBoundLoader().load(SystemSecurityPlan.class, path);
117  }
118
119  @NonNull
120  public SystemSecurityPlan loadSystemSecurityPlan(@NonNull File file) throws IOException {
121    return newBoundLoader().load(SystemSecurityPlan.class, file);
122  }
123
124  @NonNull
125  public ComponentDefinition loadComponentDefinition(@NonNull URL url) throws IOException, URISyntaxException {
126    return newBoundLoader().load(ComponentDefinition.class, url);
127  }
128
129  @NonNull
130  public ComponentDefinition loadComponentDefinition(@NonNull Path path) throws IOException {
131    return newBoundLoader().load(ComponentDefinition.class, path);
132  }
133
134  @NonNull
135  public ComponentDefinition loadComponentDefinition(@NonNull File file) throws IOException {
136    return newBoundLoader().load(ComponentDefinition.class, file);
137  }
138
139  @NonNull
140  public AssessmentPlan loadAssessmentPlan(@NonNull URL url) throws IOException, URISyntaxException {
141    return newBoundLoader().load(AssessmentPlan.class, url);
142  }
143
144  @NonNull
145  public AssessmentPlan loadAssessmentPlan(@NonNull Path path) throws IOException {
146    return newBoundLoader().load(AssessmentPlan.class, path);
147  }
148
149  @NonNull
150  public AssessmentPlan loadAssessmentPlan(@NonNull File file) throws IOException {
151    return newBoundLoader().load(AssessmentPlan.class, file);
152  }
153
154  @NonNull
155  public AssessmentResults loadAssessmentResults(@NonNull URL url) throws IOException, URISyntaxException {
156    return newBoundLoader().load(AssessmentResults.class, url);
157  }
158
159  @NonNull
160  public AssessmentResults loadAssessmentResults(@NonNull Path path) throws IOException {
161    return newBoundLoader().load(AssessmentResults.class, path);
162  }
163
164  @NonNull
165  public AssessmentResults loadAssessmentResults(@NonNull File file) throws IOException {
166    return newBoundLoader().load(AssessmentResults.class, file);
167  }
168
169  @NonNull
170  public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull URL url)
171      throws IOException, URISyntaxException {
172    return newBoundLoader().load(PlanOfActionAndMilestones.class, url);
173  }
174
175  @NonNull
176  public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull Path path) throws IOException {
177    return newBoundLoader().load(PlanOfActionAndMilestones.class, path);
178  }
179
180  @NonNull
181  public PlanOfActionAndMilestones loadPlanOfActionAndMilestones(@NonNull File file) throws IOException {
182    return newBoundLoader().load(PlanOfActionAndMilestones.class, file);
183  }
184
185  private static final class Matcher implements IBindingMatcher {
186    @Override
187    public Class<?> getBoundClassForXmlQName(QName startElementQName) {
188      Class<?> clazz = null;
189      if ("http://csrc.nist.gov/ns/oscal/1.0".equals(startElementQName.getNamespaceURI())) {
190        switch (startElementQName.getLocalPart()) {
191        case "catalog":
192          clazz = Catalog.class;
193          break;
194        case "profile":
195          clazz = Profile.class;
196          break;
197        case "system-security-plan":
198          clazz = SystemSecurityPlan.class;
199          break;
200        case "component-definition":
201          clazz = ComponentDefinition.class;
202          break;
203        case "assessment-plan":
204          clazz = AssessmentPlan.class;
205          break;
206        case "assessment-results":
207          clazz = AssessmentResults.class;
208          break;
209        case "plan-of-action-and-milestones":
210          clazz = PlanOfActionAndMilestones.class;
211          break;
212        default:
213          throw new UnsupportedOperationException("Unrecognized element name: " + startElementQName.toString());
214        }
215      }
216      return clazz;
217    }
218
219    @Override
220    public Class<?> getBoundClassForJsonName(String name) {
221      Class<?> retval;
222      switch (name) {
223      case "catalog":
224        retval = Catalog.class;
225        break;
226      case "profile":
227        retval = Profile.class;
228        break;
229      case "system-security-plan":
230        retval = SystemSecurityPlan.class;
231        break;
232      case "component-definition":
233        retval = ComponentDefinition.class;
234        break;
235      case "assessment-plan":
236        retval = AssessmentPlan.class;
237        break;
238      case "assessment-results":
239        retval = AssessmentResults.class;
240        break;
241      case "plan-of-action-and-milestones":
242        retval = PlanOfActionAndMilestones.class;
243        break;
244      default:
245        throw new UnsupportedOperationException("Unrecognized field name: " + name);
246      }
247      return retval;
248    }
249
250  }
251}