/* * Copyright (c) 2002-2008 "Neo Technology," * Network Engine for Objects in Lund AB [http://neotechnology.com] * * This file is part of Neo4j. * * Neo4j is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.util.shell.apps; import java.rmi.RemoteException; import java.util.Collection; import java.util.Set; import java.util.TreeSet; import java.util.regex.Pattern; import org.neo4j.util.shell.AbstractApp; import org.neo4j.util.shell.AbstractAppServer; import org.neo4j.util.shell.AbstractClient; import org.neo4j.util.shell.App; import org.neo4j.util.shell.AppCommandParser; import org.neo4j.util.shell.AppShellServer; import org.neo4j.util.shell.ClassLister; import org.neo4j.util.shell.OptionValueType; import org.neo4j.util.shell.Output; import org.neo4j.util.shell.Session; import org.neo4j.util.shell.ShellException; import org.neo4j.util.shell.ShellServer; /** * Prints a short manual for an {@link App}. */ public class Man extends AbstractApp { private static Collection<String> availableCommands; public String execute( AppCommandParser parser, Session session, Output out ) throws ShellException { try { if ( parser.arguments().size() == 0 ) { out.println( getHelpString( getServer() ) ); return null; } App app = this.getApp( parser ); out.println( "" ); out.println( this.fixDesciption( app.getDescription() ) ); println( out, "" ); boolean hasOptions = false; for ( String option : app.getAvailableOptions() ) { hasOptions = true; String description = this.fixDesciption( app.getDescription( option ) ); String[] descriptionLines = description.split( Pattern.quote( "\n" ) ); OptionValueType type = app.getOptionValueType( option ); for ( int i = 0; i < descriptionLines.length; i++ ) { String line = ""; if ( i == 0 ) { line = "-" + option; } line += "\t "; line += descriptionLines[ i ]; if ( i == descriptionLines.length - 1 ) { // line += type.getDescription(); } println( out, line ); } } if ( hasOptions ) { println( out, "" ); } } catch ( RemoteException e ) { throw new ShellException( e ); } return null; } private static String getShortUsageString() { return "man <command>"; } private String fixDesciption( String description ) { if ( description == null ) { description = ""; } else if ( !description.endsWith( "." ) ) { description = description + "."; } return description; } private void println( Output out, String string ) throws RemoteException { out.println( " " + string ); } private App getApp( AppCommandParser parser ) throws ShellException { String appName = parser.arguments().get( 0 ); try { App app = this.getServer().findApp( appName ); if ( app == null ) { throw new ShellException( "No manual entry for '" + appName + "'" ); } return app; } catch ( RemoteException e ) { throw new ShellException( e ); } } @Override public String getDescription() { return "Display a manual for a command or a general help message.\n" + "Usage: " + getShortUsageString(); } /** * Utility method for getting a short help string for a server. * Basically it contains an introductory message and also lists all * available apps for the server. * @param server the server to ask for * @return the short introductory help string. */ public static String getHelpString( ShellServer server ) { return "Available commands: " + availableCommandsAsString( server ) + "\n" + "Use " + getShortUsageString() + " for info about each command."; } /** * Uses {@link ClassLister} to list apps available at the server. * @param server the {@link ShellServer}. * @return a list of available commands a client can execute, whre the * server is an {@link AppShellServer}. */ public static synchronized Collection<String> getAvailableCommands( ShellServer server ) { if ( availableCommands == null ) { // TODO Shouldn't trust the server to be an AbstractAppServer Set<String> packages = ( ( AbstractAppServer ) server ).getPackages(); availableCommands = new TreeSet<String>(); for ( Class<? extends App> appClass : ClassLister.listClassesExtendingOrImplementing( App.class, packages ) ) { if ( packages.contains( appClass.getPackage().getName() ) ) { availableCommands.add( appClass.getSimpleName().toLowerCase() ); } } for ( String exitCommand : AbstractClient.getExitCommands() ) { availableCommands.add( exitCommand ); } } return availableCommands; } private static synchronized String availableCommandsAsString( ShellServer server ) { StringBuffer commands = new StringBuffer(); for ( String command : getAvailableCommands( server ) ) { if ( commands.length() > 0 ) { commands.append( " " ); } commands.append( command ); } return commands.toString(); } }