001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.oscal.tools.cli.core.commands;
007
008import gov.nist.secauto.metaschema.cli.commands.AbstractConvertSubcommand;
009import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext;
010import gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor;
011import gov.nist.secauto.metaschema.core.model.IBoundObject;
012import gov.nist.secauto.metaschema.databind.IBindingContext;
013import gov.nist.secauto.metaschema.databind.io.Format;
014import gov.nist.secauto.metaschema.databind.io.FormatDetector;
015import gov.nist.secauto.metaschema.databind.io.IBoundLoader;
016import gov.nist.secauto.metaschema.databind.io.ISerializer;
017import gov.nist.secauto.metaschema.databind.io.ModelDetector;
018import gov.nist.secauto.oscal.lib.OscalBindingContext;
019
020import org.apache.commons.cli.CommandLine;
021
022import java.io.FileNotFoundException;
023import java.io.IOException;
024import java.io.InputStream;
025import java.io.Writer;
026import java.net.URI;
027
028import edu.umd.cs.findbugs.annotations.NonNull;
029
030public class ConvertCommand
031    extends AbstractConvertSubcommand {
032  @Override
033  public String getDescription() {
034    return "Check that the specified OSCAL instance is well-formed and valid to an OSCAL model.";
035  }
036
037  @Override
038  public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine commandLine) {
039    return new OscalCommandExecutor(callingContext, commandLine);
040  }
041
042  private static final class OscalCommandExecutor
043      extends AbstractConversionCommandExecutor {
044
045    private OscalCommandExecutor(
046        @NonNull CallingContext callingContext,
047        @NonNull CommandLine commandLine) {
048      super(callingContext, commandLine);
049    }
050
051    @Override
052    protected IBindingContext getBindingContext() {
053      return OscalBindingContext.instance();
054    }
055
056    @Override
057    protected void handleConversion(URI source, Format toFormat, Writer writer, IBoundLoader loader)
058        throws FileNotFoundException, IOException {
059
060      Class<? extends IBoundObject> boundClass;
061      IBoundObject object;
062      try (InputStream is = source.toURL().openStream()) {
063        FormatDetector.Result formatResult = loader.detectFormat(is);
064        Format sourceformat = formatResult.getFormat();
065        try (InputStream fis = formatResult.getDataStream()) {
066          try (ModelDetector.Result modelResult = loader.detectModel(fis, sourceformat)) {
067            boundClass = modelResult.getBoundClass();
068            try (InputStream mis = modelResult.getDataStream()) {
069              object = loader.load(boundClass, sourceformat, mis, source);
070            }
071          }
072        }
073      }
074      ISerializer<?> serializer = getBindingContext().newSerializer(toFormat, boundClass);
075      serializer.serialize(object, writer);
076    }
077  }
078}