001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.oscal.tools.cli.core.commands; 007 008import org.apache.commons.cli.CommandLine; 009import org.json.JSONObject; 010import org.xml.sax.SAXException; 011 012import java.io.IOException; 013import java.net.URL; 014import java.util.Set; 015 016import dev.metaschema.cli.commands.AbstractValidateContentCommand; 017import dev.metaschema.cli.processor.CallingContext; 018import dev.metaschema.cli.processor.ExitCode; 019import dev.metaschema.cli.processor.command.CommandExecutionException; 020import dev.metaschema.cli.processor.command.ICommandExecutor; 021import dev.metaschema.core.model.IModule; 022import dev.metaschema.core.model.MetaschemaException; 023import dev.metaschema.core.model.constraint.IConstraintSet; 024import dev.metaschema.core.model.validation.JsonSchemaContentValidator; 025import dev.metaschema.core.model.validation.XmlSchemaContentValidator; 026import dev.metaschema.databind.IBindingContext; 027import dev.metaschema.databind.IBindingContext.ISchemaValidationProvider; 028import dev.metaschema.oscal.lib.OscalBindingContext; 029import dev.metaschema.oscal.lib.model.OscalCompleteModule; 030import edu.umd.cs.findbugs.annotations.NonNull; 031 032/** 033 * Used by implementing classes to provide an OSCAL content validation command. 034 */ 035public abstract class AbstractOscalValidationCommand 036 extends AbstractValidateContentCommand { 037 038 /** 039 * Load the OSCAL XML schemas. 040 * 041 * @return the XML schema validator instance 042 * @throws IOException 043 * if an error occurred while parsing the provided XML schemas 044 */ 045 @NonNull 046 protected abstract XmlSchemaContentValidator getOscalXmlSchemas() throws IOException; 047 048 /** 049 * Load the OSCAL JSON schemas. 050 * 051 * @return the XML schema validator instance 052 * @throws IOException 053 * if an error occurred while parsing the provided XML schemas 054 */ 055 @NonNull 056 protected abstract JsonSchemaContentValidator getOscalJsonSchema() throws IOException; 057 058 @Override 059 public abstract ICommandExecutor newExecutor(CallingContext callingContext, CommandLine commandLine); 060 061 /** 062 * Provides OSCAL validation command execution support. 063 */ 064 protected class OscalValidationCommandExecutor 065 extends AbstractValidateContentCommand.AbstractValidationCommandExecutor 066 implements ISchemaValidationProvider { 067 068 /** 069 * Construct a new command executor. 070 * 071 * @param callingContext 072 * the context of the command execution 073 * @param commandLine 074 * the parsed command line details 075 */ 076 protected OscalValidationCommandExecutor( 077 @NonNull CallingContext callingContext, 078 @NonNull CommandLine commandLine) { 079 super(callingContext, commandLine); 080 } 081 082 @Override 083 protected IBindingContext getBindingContext(@NonNull Set<IConstraintSet> constraintSets) { 084 return OscalBindingContext.builder() 085 .constraintSet(constraintSets) 086 .build(); 087 } 088 089 @Override 090 @NonNull 091 public XmlSchemaContentValidator getXmlSchemas(URL targetResource, IBindingContext bindingContext) 092 throws IOException, SAXException { 093 return getOscalXmlSchemas(); 094 } 095 096 @Override 097 @NonNull 098 public JsonSchemaContentValidator getJsonSchema(JSONObject json, IBindingContext bindingContext) 099 throws IOException { 100 return getOscalJsonSchema(); 101 } 102 103 @Override 104 @NonNull 105 protected ISchemaValidationProvider getSchemaValidationProvider( 106 @NonNull IModule module, 107 @NonNull CommandLine commandLine, 108 @NonNull IBindingContext bindingContext) { 109 return this; 110 } 111 112 @Override 113 protected IModule getModule(CommandLine commandLine, IBindingContext bindingContext) 114 throws CommandExecutionException { 115 try { 116 return bindingContext.registerModule(OscalCompleteModule.class); 117 } catch (MetaschemaException ex) { 118 throw new CommandExecutionException(ExitCode.PROCESSING_ERROR, "Failed to register OSCAL module", ex); 119 } 120 } 121 } 122}