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