All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.refcodes.console.impls.ArgsParserImpl Maven / Gradle / Ivy

Go to download

Artifact for console issues regarding a CLI (command line interpreter) frame, CLI commands or CLI interaction and so on.

There is a newer version: 1.0.4
Show newest version
// /////////////////////////////////////////////////////////////////////////////
// REFCODES.ORG
// /////////////////////////////////////////////////////////////////////////////
// This code is copyright (c) by Siegfried Steiner, Munich, Germany and licensed
// under the following (see "http://en.wikipedia.org/wiki/Multi-licensing")
// licenses:
// -----------------------------------------------------------------------------
// GNU General Public License, v3.0 ("http://www.gnu.org/licenses/gpl-3.0.html")
// -----------------------------------------------------------------------------
// Apache License, v2.0 ("http://www.apache.org/licenses/LICENSE-2.0")
// -----------------------------------------------------------------------------
// Please contact the copyright holding author(s) of the software artifacts in
// question for licensing issues not being covered by the above listed licenses,
// also regarding commercial licensing models or regarding the compatibility
// with other open source licenses.
// /////////////////////////////////////////////////////////////////////////////

package org.refcodes.console.impls;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import org.refcodes.console.AmbiguousArgsException;
import org.refcodes.console.ArgsParser;
import org.refcodes.console.Condition;
import org.refcodes.console.ConsoleUtility;
import org.refcodes.console.Operand;
import org.refcodes.console.ParseArgsException;
import org.refcodes.console.SuperfluousArgsException;
import org.refcodes.console.SyntaxNotation;
import org.refcodes.console.UnknownArgsException;
import org.refcodes.data.AsciiColorPaletteConsts;
import org.refcodes.data.LicenseConsts;
import org.refcodes.data.RuntimeConsts;
import org.refcodes.graphical.BoxBorderMode;
import org.refcodes.runtime.SystemUtility;
import org.refcodes.textual.AsciiArtMode;
import org.refcodes.textual.ColumnWidthType;
import org.refcodes.textual.Font;
import org.refcodes.textual.FontStyle;
import org.refcodes.textual.FontType;
import org.refcodes.textual.HorizAlignTextMode;
import org.refcodes.textual.SplitTextMode;
import org.refcodes.textual.TableBuilder;
import org.refcodes.textual.TableStyle;
import org.refcodes.textual.impls.AsciiArtBuilderImpl;
import org.refcodes.textual.impls.FontImpl;
import org.refcodes.textual.impls.HorizAlignTextBuilderImpl;
import org.refcodes.textual.impls.TableBuilderImpl;
import org.refcodes.textual.impls.TextBlockBuilderImpl;
import org.refcodes.textual.impls.TextBorderBuilderImpl;
import org.refcodes.textual.impls.TextLineBuilderImpl;
import org.refcodes.textual.impls.VerboseTextBuilderImpl;

/**
 * A straightforward implementation of the {@link ArgsParser} interface. The
 * constructor only provides means to set the required attributes as the
 * attributes to be adjusted optionally are already sufficiently pre-configured.
 * For adjusting them, a flavor of the builder pattern is provided with which
 * you can easily chain the configuration of this instance; as them methods
 * return the instance of this class being configured. This helps to prevent the
 * telescoping constructor anti-pattern.
 * 

* The {@link SyntaxNotation} is pre-set with the * {@link SyntaxNotation#REFCODES} notation. *

* The console width id pre-configured with the console's width as determined by * the {@link SystemUtility#getConsoleWidth()}. *

* The standard out {@link PrintStream} is pre-configured with the * {@link System#out} {@link PrintStream}. *

* The newline characters to be used for line breaks is "\r\n" on Windows * machines and "\"n" on all other machines as of the * {@link SystemUtility#getLineBreak()}. * * @see "http://en.wikipedia.org/wiki/Builder_pattern" * */ public class ArgsParserImpl implements ArgsParser { // ///////////////////////////////////////////////////////////////////////// // STATIC: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // CONSTANTS: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // VARIABLES: // ///////////////////////////////////////////////////////////////////////// private Font _bannerFont = new FontImpl( FontType.DIALOG, FontStyle.PLAIN, 12 ); private char[] _bannerFontPalette = AsciiColorPaletteConsts.HALFTONE_GRAY; private char _separatorChar = '-'; private Condition _rootCondition; private SyntaxNotation _syntaxNotation = SyntaxNotation.REFCODES; private PrintStream _standardOut = System.out; private int _consoleWidth; private int _maxConsoleWidth = -1; private String _lineBreak = SystemUtility.getLineBreak(); private String _title = null; private String _name = "foobar"; private String _description = "See the syntax declaration for usage, see the descriptions for the short- and the long-options. Option arguments are noted in angle brackets."; private String _usageLabel = "Usage"; private String _licenseNote = LicenseConsts.LICENSE_NOTE; private String _copyrightNote = LicenseConsts.COPYRIGHT_NOTE; private PrintStream _errorOut = System.err;; // ///////////////////////////////////////////////////////////////////////// // CONSTRUCTORS: // ///////////////////////////////////////////////////////////////////////// /** * Constructs the {@link ArgsParser} instance with the given root * {@link Condition} and the default {@link SyntaxNotation#REFCODES}. * * The constructor only provides means to set the required attributes as the * attributes to be adjusted optionally are already sufficiently * pre-configured. For adjusting them, a flavor of the builder pattern is * provided with which you can easily chain the configuration of this * instance; as them methods return the instance of this class being * configured. * * @param aRootCondition The root condition being the node from which * parsing the command line arguments starts. */ public ArgsParserImpl( Condition aRootCondition ) { _rootCondition = aRootCondition; setConsoleWidth( SystemUtility.getConsoleWidth() ); } @Override public void setSyntaxNotation( SyntaxNotation aSyntaxNotation ) { _syntaxNotation = aSyntaxNotation; } @Override public void setStandardOut( PrintStream aStandardOut ) { _standardOut = aStandardOut; } @Override public void setErrorOut( PrintStream aErrorOut ) { _errorOut = aErrorOut; } @Override public void setConsoleWidth( int aConsoleWidth ) { if ( aConsoleWidth == -1 ) { aConsoleWidth = SystemUtility.getConsoleWidth(); if ( aConsoleWidth < RuntimeConsts.NORM_CONSOLE_WIDTH ) { aConsoleWidth = RuntimeConsts.NORM_CONSOLE_WIDTH; } } _consoleWidth = _maxConsoleWidth != -1 ? (_maxConsoleWidth < aConsoleWidth ? _maxConsoleWidth : aConsoleWidth) : aConsoleWidth; } @Override public void setLineBreak( String aLineBreak ) { if ( aLineBreak == null ) { aLineBreak = SystemUtility.getLineBreak(); } _lineBreak = aLineBreak; } @Override public void setDescription( String aDescription ) { _description = aDescription; } @Override public void setName( String aName ) { _name = aName; } @Override public void setLicenseNote( String aLicenseNote ) { _licenseNote = aLicenseNote; } @Override public void setUsageLabel( String aUsageLabel ) { _usageLabel = aUsageLabel; } @Override public void setCopyrightNote( String aCopyrightNote ) { _copyrightNote = aCopyrightNote; } @Override public void setSeparatorChar( char aSeparatorChar ) { _separatorChar = aSeparatorChar; } @Override public void setBannerFont( Font aBannerFont ) { _bannerFont = aBannerFont; } @Override public void setBannerFontPalette( char[] aColorPalette ) { _bannerFontPalette = aColorPalette; } @Override public void setTitle( String aTitle ) { _title = aTitle; } @Override public void setMaxConsoleWidth( int aMaxConsoleWidth ) { _maxConsoleWidth = aMaxConsoleWidth; _consoleWidth = _maxConsoleWidth != -1 ? (_maxConsoleWidth < _consoleWidth ? _maxConsoleWidth : _consoleWidth) : _consoleWidth; } // ///////////////////////////////////////////////////////////////////////// // METHODS: // ///////////////////////////////////////////////////////////////////////// @Override public void printLicenseNote() { String[] theLines = new TextBlockBuilderImpl().withText( _licenseNote ).withColumnWidth( _consoleWidth ).withSplitTextMode( SplitTextMode.AT_SPACE ).toStrings(); theLines = new HorizAlignTextBuilderImpl().withHorizAlignTextMode( HorizAlignTextMode.CENTER ).withText( theLines ).withColumnWidth( _consoleWidth ).withFillChar( ' ' ).toStrings(); _standardOut.println( fromTextBlock( theLines, _lineBreak ) ); } @Override public void printCopyrightNote() { String[] theLines = new TextBlockBuilderImpl().withText( _copyrightNote ).withColumnWidth( _consoleWidth ).withSplitTextMode( SplitTextMode.AT_SPACE ).toStrings(); theLines = new HorizAlignTextBuilderImpl().withHorizAlignTextMode( HorizAlignTextMode.CENTER ).withText( theLines ).withColumnWidth( _consoleWidth ).withFillChar( ' ' ).toStrings(); _standardOut.println( fromTextBlock( theLines, _lineBreak ) ); } @Override public List> evalArgs( String[] aArgs ) throws UnknownArgsException, AmbiguousArgsException, SuperfluousArgsException, ParseArgsException { List> theOperands = _rootCondition.parseArgs( aArgs ); String[] theSuperflousArgs = ConsoleUtility.toDiff( aArgs, theOperands ); if ( theSuperflousArgs != null && theSuperflousArgs.length > 0 ) { throw new SuperfluousArgsException( theSuperflousArgs, "Superflous command arguments " + new VerboseTextBuilderImpl().withElements( theSuperflousArgs ).toString() + " were provided but not evaluatable (supported)." ); } return theOperands; } @Override public void printHelp() { printBanner(); printLicenseNote(); printSeparatorLn(); printUsage(); printSeparatorLn(); printDescription(); printSeparatorLn(); printOptions(); printSeparatorLn(); printCopyrightNote(); printSeparatorLn(); } @Override public void printUsage() { // @formatter:off // String theLine = _usageLabel + ": "; // String[] theLines = toTextBlock( _name + " " + _rootCondition.parseSyntax( _syntaxNotation ), _consoleWidth - theLine.length(), TextSplitMode.AT_SPACE ); // theLines[0] = theLine + theLines[0]; // if ( theLines.length > 0 ) { // theLine = DrawTextUtility.toLine( theLine.length(), ' ' ); // for ( int i = 1; i < theLines.length; i++ ) { // theLines[i] = theLine + theLines[i]; // } // } // String theSyntax = fromTextBlock( theLines, _lineBreak ); // @formatter:on String theSyntax = _usageLabel + ": " + _name + " " + _rootCondition.parseSyntax( _syntaxNotation ); _standardOut.println( theSyntax ); } @Override public void printDescription() { String[] theLines = new TextBlockBuilderImpl().withText( _description ).withColumnWidth( _consoleWidth ).withSplitTextMode( SplitTextMode.AT_SPACE ).toStrings(); _standardOut.println( fromTextBlock( theLines, _lineBreak ) ); } @Override public void printLn( String aLine ) { String[] theLines = new TextBlockBuilderImpl().withText( aLine ).withColumnWidth( _consoleWidth ).withSplitTextMode( SplitTextMode.AT_SPACE ).toStrings(); _standardOut.println( fromTextBlock( theLines, _lineBreak ) ); } @Override public void errorLn( String aLine ) { String[] theLines = new TextBlockBuilderImpl().withText( aLine ).withColumnWidth( _consoleWidth ).withSplitTextMode( SplitTextMode.AT_SPACE ).toStrings(); _errorOut.println( fromTextBlock( theLines, _lineBreak ) ); } @Override public void printLn() { _standardOut.println(); } @Override public void printSeparatorLn() { _standardOut.println( new TextLineBuilderImpl().withColumnWidth( _consoleWidth ).withLineChar( _separatorChar ).toString() ); } @Override public void printBanner() { int theBannerWidth = _consoleWidth - 4; String[] theCanvas = new AsciiArtBuilderImpl().withText( _title != null ? _title : _name ).withFont( _bannerFont ).withAsciiColors( _bannerFontPalette ).withColumnWidth( theBannerWidth ).withAsciiArtMode( AsciiArtMode.NORMAL ).toStrings(); theCanvas = new HorizAlignTextBuilderImpl().withHorizAlignTextMode( HorizAlignTextMode.CENTER ).withText( theCanvas ).withColumnWidth( theBannerWidth ).withFillChar( ' ' ).toStrings(); theCanvas = new TextBorderBuilderImpl().withBoxBorderMode( BoxBorderMode.ALL ).withText( theCanvas ).withBorderWidth( 1 ).withBorderChar( ' ' ).toStrings(); theCanvas = new TextBorderBuilderImpl().withText( theCanvas ).withTableStyle( TableStyle.DOUBLE ).withBoxBorderMode( BoxBorderMode.ALL ).toStrings(); String theBanner = fromTextBlock( theCanvas, _lineBreak ); _standardOut.println( theBanner ); } @Override public void printOptions() { // @formatter:off // List> theOperands = _rootCondition.toOperands(); // List theOptionStrs = new ArrayList(); // for ( Operand eOperand : theOperands ) { // theOptionStrs.add( new String[] { // ConsoleUtility.toSpec( eOperand ), eOperand.getDescription() // } ); // } // int theMaxLength = 0; // for ( String[] eOptionStrs : theOptionStrs ) { // if ( eOptionStrs[0].length() > theMaxLength ) { // theMaxLength = eOptionStrs[0].length(); // } // } // String theColon = ": "; // theMaxLength += theColon.length(); // String eLine; // String[] eLines; // for ( String[] eOptionStrs : theOptionStrs ) { // // eLine = AlignTextUtility.toAlignRight( eOptionStrs[0], theMaxLength, ' ' ) + theColon; // eLines = toTextBlock( eOptionStrs[1], (_consoleWidth - theMaxLength) - theColon.length(), TextAlignMode.LEFT, TextSplitMode.AT_SPACE ); // eLines[0] = eLine + eLines[0]; // if ( eLines.length > 0 ) { // eLine = DrawTextUtility.toLine( eLine.length(), ' ' ); // for ( int i = 1; i < eLines.length; i++ ) { // eLines[i] = eLine + eLines[i]; // } // } // TextOutputUtility.printLines( eLines, _standardOut ); // } // @formatter:on List> theOperands = _rootCondition.toOperands(); List theOptArgs = new ArrayList(); int theMaxLength = 0; String eOpt; for ( Operand eOperand : theOperands ) { eOpt = ConsoleUtility.toSpec( eOperand ) + ":"; theOptArgs.add( new String[] { eOpt, eOperand.getDescription() } ); if ( eOpt.length() > theMaxLength ) theMaxLength = eOpt.length(); } TableBuilder theOptTable = new TableBuilderImpl().withTableStyle( TableStyle.BLANK ).withRowWidth( _consoleWidth ).withPrintStream( _standardOut ); theOptTable.addColumn().withColumnHorizAlignTextMode( HorizAlignTextMode.RIGHT ).withColumnWidth( theMaxLength, ColumnWidthType.ABSOLUTE ).withLeftBorder( false ).withRightBorder( false ); theOptTable.addColumn().withColumnHorizAlignTextMode( HorizAlignTextMode.LEFT ).withLeftBorder( false ).withRightBorder( false ).withColumnSplitTextMode( SplitTextMode.AT_SPACE ); for ( String[] eOptArg : theOptArgs ) { theOptTable.printRowContinue( eOptArg ); } } @Override public Condition getRootCondition() { return _rootCondition; } @Override public void reset() { if ( _rootCondition != null ) { _rootCondition.reset(); } } // ///////////////////////////////////////////////////////////////////////// // HOOKS: // ///////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////// // HELPER: // ///////////////////////////////////////////////////////////////////////// private static String fromTextBlock( String[] aTextBlock, String aDelimeter ) { StringBuilder theBuilder = new StringBuilder(); for ( String eString : aTextBlock ) { if ( aDelimeter != null && aDelimeter.length() != 0 ) { if ( theBuilder.length() > 0 ) { theBuilder.append( aDelimeter ); } } theBuilder.append( eString ); } return theBuilder.toString(); } // ///////////////////////////////////////////////////////////////////////// // INNER CLASSES: // ///////////////////////////////////////////////////////////////////////// }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy