/** * Copyright (c) 2007-2011, JAGaToo Project Group all rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.jagatoo.commandline; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jagatoo.util.strings.SimpleStringTokenizer; /** * Holds a distinct set of all known and valid arguments of a command line. * * @author Marvin Froehlich (aka Qudus) */ public class ArgumentsRegistry { private static final Comparator<Argument> ARGUMENT_COMPARATOR = new Comparator<Argument>() { /** * {@inheritDoc} */ @Override public int compare( Argument a1, Argument a2 ) { int result = 0; if ( a1.getLongName() == null ) { if ( a2.getLongName() != null ) return ( -1 ); } else if ( a2.getLongName() == null ) { return ( +1 ); } result = a1.getLongName().compareTo( a2.getLongName() ); if ( result != 0 ) return ( result ); if ( a1.getShortName() < a2.getShortName() ) return ( -1 ); if ( a1.getShortName() > a2.getShortName() ) return ( +1 ); return ( 0 ); } }; private final String headLine; private final String name; private final Map<Character, Argument> arguments_by_short_name = new HashMap<Character, Argument>(); private final Map<String, Argument> arguments_by_long_name = new HashMap<String, Argument>(); private final List<Argument> arguments = new ArrayList<Argument>(); /** * Gets this registry's name. * * @return the name. */ public final String getName() { return ( name ); } /** * Adds a new argument. * * @param arg */ public void addArgument( Argument arg ) { if ( arg.getShortName() != '\0' ) { if ( arguments_by_short_name.containsKey( arg.getShortName() ) ) throw new Error( "duplicate Argument " + arg ); } if ( arg.getLongName() != null ) { if ( arguments_by_long_name.containsKey( arg.getLongName() ) ) throw new Error( "duplicate Argument " + arg ); } if ( arg.getShortName() != '\0' ) arguments_by_short_name.put( arg.getShortName(), arg ); if ( arg.getLongName() != null ) arguments_by_long_name.put( arg.getLongName(), arg ); arguments.add( arg ); } /** * Removes an argument. * * @param arg */ public void removeArgument( Argument arg ) { if ( arg.getShortName() != '\0' ) arguments_by_short_name.remove( arg.getShortName() ); if ( arg.getLongName() != null ) arguments_by_long_name.remove( arg.getLongName() ); arguments.remove( arg ); } /** * Checks whether an argument exists with the given short-name. * * @param shortName * * @return true, if it exists. */ public final boolean contains( char shortName ) { return ( arguments_by_short_name.containsKey( shortName ) ); } /** * Checks whether an argument exists with the given long-name. * * @param longName * * @return true, if it exists. */ public final boolean contains( String longName ) { return ( arguments_by_long_name.containsKey( longName ) ); } /** * Gets the argument corresponding to the given short-name. * * @param shortName * * @return the corresponding argument. */ public final Argument getArgument( char shortName ) { return ( arguments_by_short_name.get( shortName ) ); } /** * Gets the argument corresponding to the given long-name. * * @param longName * * @return the corresponding argument. */ public final Argument getArgument( String longName ) { return ( arguments_by_long_name.get( longName ) ); } /** * Dumps all registered arguments. * * @param maxLineWidth * @param out */ public void dump( int maxLineWidth, java.io.PrintStream out ) { if ( headLine == null ) out.println( "Argument list for " + getName() ); else out.println( headLine ); Collections.sort( arguments, ARGUMENT_COMPARATOR ); int indent = 0; for ( Argument arg : arguments ) { // -a, --an-argument int length = 0; if ( arg.getShortName() != '\0' ) { length += 2; if ( arg.getLongName() != null ) { length += 4 + arg.getLongName().length(); } } else if ( arg.getLongName() != null ) { length += 2 + arg.getLongName().length(); } length += 2; if ( length > indent ) indent = length; } int descWidth = maxLineWidth - indent; for ( Argument arg : arguments ) { out.println(); int length = 0; if ( arg.getShortName() != '\0' ) { length += 2; out.print( '-' ); out.print( arg.getShortName() ); if ( arg.getLongName() != null ) { length += 4 + arg.getLongName().length(); out.print( ", --" ); out.print( arg.getLongName() ); } } else if ( arg.getLongName() != null ) { length += 2 + arg.getLongName().length(); out.print( "--" ); out.print( arg.getLongName() ); } length += 2; for ( int i = indent - length + 1; i >= 0; i-- ) out.print( ' ' ); String desc = arg.getDecription(); if ( desc != null ) { String[] descParts = desc.split( "\n" ); int j = 0; for ( String part : descParts ) { if ( j++ > 0 ) { for ( int i = 0; i < indent; i++ ) out.print( ' ' ); } if ( part.length() > 0 ) { int offset = 0; int nextOffset = 0; while ( offset < part.length() ) { int end = Math.min( offset + descWidth, part.length() ); if ( end < part.length() ) { if ( !SimpleStringTokenizer.isWhitespace( part.charAt( end ) ) ) { while ( !SimpleStringTokenizer.isWhitespace( part.charAt( end ) ) ) { end--; } } } nextOffset = end; if ( offset > 0 ) { for ( int i = 0; i < indent; i++ ) out.print( ' ' ); } while ( SimpleStringTokenizer.isWhitespace( part.charAt( offset ) ) ) { offset++; } while ( SimpleStringTokenizer.isWhitespace( part.charAt( end - 1 ) ) ) { end--; } out.println( part.substring( offset, end ) ); offset = nextOffset; } } else { out.println(); } } } else { out.println( "(No description available)" ); } } } /** * Dumps all registered arguments to stdout. * * @param maxLineWidth */ public final void dump( int maxLineWidth ) { dump( maxLineWidth, System.out ); } /** * Dumps all registered arguments with a maximum line width of 80. * * @param out */ public final void dump( java.io.PrintStream out ) { dump( 80, out ); } /** * Dumps all registered arguments to stdout with a maximum line width of 80. */ public final void dump() { dump( 80, System.out ); } /** * Creates a new ArgumentsRegistry. * * @param name the name (used in the {@link #dump()} method. * @param headLine if not null, the name is ignored in the {@link #dump()} method and this String is dumped first. */ public ArgumentsRegistry( String name, String headLine ) { this.name = name; this.headLine = headLine; } /** * Creates a new ArgumentsRegistry. * * @param name the name (used in the {@link #dump()} method. */ public ArgumentsRegistry( String name ) { this( name, null ); } }