1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.cli.commands;
7   
8   import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext;
9   import gov.nist.secauto.metaschema.cli.processor.command.CommandExecutionException;
10  import gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor;
11  import gov.nist.secauto.metaschema.core.model.IModule;
12  import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
13  import gov.nist.secauto.metaschema.core.model.util.JsonUtil;
14  import gov.nist.secauto.metaschema.core.model.validation.JsonSchemaContentValidator;
15  import gov.nist.secauto.metaschema.core.model.validation.XmlSchemaContentValidator;
16  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
17  import gov.nist.secauto.metaschema.databind.IBindingContext;
18  import gov.nist.secauto.metaschema.databind.IBindingContext.ISchemaValidationProvider;
19  import gov.nist.secauto.metaschema.databind.model.metaschema.binding.MetaschemaModelModule;
20  
21  import org.apache.commons.cli.CommandLine;
22  import org.json.JSONObject;
23  import org.xml.sax.SAXException;
24  
25  import java.io.BufferedReader;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.io.InputStreamReader;
29  import java.net.URL;
30  import java.nio.charset.StandardCharsets;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.Set;
34  
35  import javax.xml.transform.Source;
36  import javax.xml.transform.stream.StreamSource;
37  
38  import edu.umd.cs.findbugs.annotations.NonNull;
39  import nl.talsmasoftware.lazy4j.Lazy;
40  
41  /**
42   * This command implementation supports validation a Metaschema module.
43   */
44  class ValidateModuleCommand
45      extends AbstractValidateContentCommand {
46    @NonNull
47    private static final String COMMAND = "validate";
48  
49    @Override
50    public String getName() {
51      return COMMAND;
52    }
53  
54    @Override
55    public String getDescription() {
56      return "Validate that the specified Module is well-formed and valid to the Module model";
57    }
58  
59    @Override
60    public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine commandLine) {
61      return new CommandExecutor(callingContext, commandLine);
62    }
63  
64    private final class CommandExecutor
65        extends AbstractValidationCommandExecutor {
66      private final Lazy<ValidationProvider> validationProvider = Lazy.lazy(ValidationProvider::new);
67  
68      private CommandExecutor(
69          @NonNull CallingContext callingContext,
70          @NonNull CommandLine commandLine) {
71        super(callingContext, commandLine);
72      }
73  
74      @Override
75      protected IBindingContext getBindingContext(Set<IConstraintSet> constraintSets)
76          throws CommandExecutionException {
77        return MetaschemaCommands.newBindingContextWithDynamicCompilation(constraintSets);
78      }
79  
80      @Override
81      protected IModule getModule(CommandLine commandLine, IBindingContext bindingContext) {
82        return bindingContext.registerModule(MetaschemaModelModule.class);
83      }
84  
85      @Override
86      protected ISchemaValidationProvider getSchemaValidationProvider(
87          IModule module,
88          CommandLine commandLine,
89          IBindingContext bindingContext) {
90        // ignore the arguments and return the pre-generated schema provider
91        return ObjectUtils.notNull(validationProvider.get());
92      }
93    }
94  
95    private static final class ValidationProvider implements ISchemaValidationProvider {
96      @SuppressWarnings("resource")
97      @Override
98      public XmlSchemaContentValidator getXmlSchemas(
99          @NonNull URL targetResource,
100         @NonNull IBindingContext bindingContext) throws IOException, SAXException {
101       try (InputStream is = this.getClass().getResourceAsStream("/schema/xml/metaschema-model_schema.xsd")) {
102         List<Source> sources = new LinkedList<>();
103         sources.add(new StreamSource(
104             ObjectUtils.requireNonNull(is,
105                 "Unable to load '/schema/xml/metaschema.xsd' on the classpath")));
106         return new XmlSchemaContentValidator(sources);
107       }
108     }
109 
110     @Override
111     public JsonSchemaContentValidator getJsonSchema(
112         @NonNull JSONObject json,
113         @NonNull IBindingContext bindingContext) throws IOException {
114       try (BufferedReader reader = new BufferedReader(
115           new InputStreamReader(
116               this.getClass().getResourceAsStream("/schema/json/metaschema-model_schema.json"),
117               StandardCharsets.UTF_8))) {
118         return new JsonSchemaContentValidator(JsonUtil.toJsonObject(reader));
119       }
120     }
121   }
122 }