/* * Copyright 2011 cruxframework.org. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package org.cruxframework.crux.tools.parameters; import java.io.PrintStream; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.cruxframework.crux.core.client.utils.StringUtils; /** * @author Thiago da Rosa de Bustamante * */ public class ConsoleParametersProcessor { private Map<String, ConsoleParameter> supportedParameters = new HashMap<String, ConsoleParameter>(); private List<ConsoleParameter> orderedParameters = new ArrayList<ConsoleParameter>(); private Set<String> requiredParameters = new HashSet<String>(); private LinkedList<ConsoleParameter> orderedNoFlagsParameters = new LinkedList<ConsoleParameter>(); private final PrintStream out; private final String programName; private final boolean printErrors; private int maxParameterNameLength = 0; /** * @param programName */ public ConsoleParametersProcessor(String programName) { this(programName, System.out, true); } /** * @param programName */ public ConsoleParametersProcessor(String programName, PrintStream out, boolean printErrors) { this.out = out; this.programName = programName; this.printErrors = printErrors; } /** * @param parameter */ public void addSupportedParameter(ConsoleParameter parameter) { supportedParameters.put(parameter.getName(), parameter); orderedParameters.add(parameter); if (parameter.isRequired()) { requiredParameters.add(parameter.getName()); } if (!parameter.isFlagParameter()) { orderedNoFlagsParameters.add(parameter); } this.maxParameterNameLength = Math.max(parameter.getName().length(), this.maxParameterNameLength); } /** * @param out */ public void showsUsageScreen() { showCommandLineDescription(); out.println("--------------------"); out.println("Program parameters:"); for (ConsoleParameter parameter : orderedParameters) { String name = parameter.getName(); out.println(StringUtils.rpad(name, this.maxParameterNameLength+2, ' ') + "- "+parameter.getDescription()); } } /** * @param commandLineArgs * @return */ public Map<String, ConsoleParameter> processConsoleParameters(String[] commandLineArgs) { Map<String, ConsoleParameter> parameters = new HashMap<String, ConsoleParameter>(); try { Set<String> processedParameters = new HashSet<String>(); if (commandLineArgs != null) { for (int i=0; i < commandLineArgs.length; i++) { String cmd = commandLineArgs[i]; if (!StringUtils.isEmpty(cmd)) { ConsoleParameter parameter; if (supportedParameters.containsKey(cmd)) { parameter = (ConsoleParameter) supportedParameters.get(cmd).clone(); if (parameter.isFlagParameter()) { i = processFlagParameter(commandLineArgs, parameters, processedParameters, i, cmd, parameter); } else { parameter = processNonFlagParameter(processedParameters, cmd); parameters.put(parameter.getName(), parameter); } } else { parameter = processNonFlagParameter(processedParameters, cmd); parameters.put(parameter.getName(), parameter); } } } } checkRequiredParameters(processedParameters); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return parameters; } /** * @param processedParameters */ private void checkRequiredParameters(Set<String> processedParameters) { Iterator<String> requiredParams = requiredParameters.iterator(); while (requiredParams.hasNext()) { String par = requiredParams.next(); if (!processedParameters.contains(par)) { handleProcessingError("Required Parameter <"+par+"> not found."); } } } /** * @param processedParameters * @param cmd * @throws CloneNotSupportedException */ private ConsoleParameter processNonFlagParameter(Set<String> processedParameters, String cmd) throws CloneNotSupportedException { if (orderedNoFlagsParameters.size()>0) { ConsoleParameter parameter = (ConsoleParameter) orderedNoFlagsParameters.removeFirst().clone(); if (parameter == null) { handleProcessingError("Invalid Parameter found: "+cmd+"."); } parameter.setValues(new String[]{cmd}); processedParameters.add(parameter.getName()); return parameter; } else { handleProcessingError("No more parameter expected. Found :"+cmd); return null; } } /** * @param commandLineArgs * @param parameters * @param processedParameters * @param i * @param cmd * @param parameter * @return */ private int processFlagParameter(String[] commandLineArgs, Map<String, ConsoleParameter> parameters, Set<String> processedParameters, int i, String cmd, ConsoleParameter parameter) { if (processedParameters.contains(cmd)) { handleProcessingError("Duplicated Parameter found: "+cmd+"."); } parameters.put(parameter.getName(), parameter); i = processParameterOptions(commandLineArgs, i, parameter); processedParameters.add(cmd); return i; } /** * @param commandLineArgs * @param actualIndex * @param parameter * @return */ private int processParameterOptions(String[] commandLineArgs, int actualIndex, ConsoleParameter parameter) { if (parameter.hasOptions()) { Iterator<ConsoleParameterOption> options = parameter.iterateOptions(); List<String> values = new ArrayList<String>(); while (options.hasNext()) { ConsoleParameterOption option = options.next(); if (actualIndex == commandLineArgs.length -1) { handleProcessingError("Required Parameter option not found: "+option.getName()+"."); } String value = commandLineArgs[++actualIndex]; if (StringUtils.isEmpty(value)) { handleProcessingError("Required Parameter option not found: "+option.getName()+"."); } values.add(value); } parameter.setValues(values.toArray(new String[values.size()])); } return actualIndex; } /** * */ private void showCommandLineDescription() { out.print("Usage: "+programName+ " "); boolean first = true; for (ConsoleParameter parameter : orderedParameters) { if (!first) { out.print(" "); } if (parameter.isRequired()) { out.print(parameter.getName()); if (parameter.hasOptions()) { out.print(" "+getParameterOptionsString(parameter)); } } else { out.print("["+parameter.getName()); if (parameter.hasOptions()) { out.print(" "+getParameterOptionsString(parameter)); } out.print("]"); } first = false; } out.println(); } /** * @param parameter * @return */ private String getParameterOptionsString(ConsoleParameter parameter) { if (!parameter.hasOptions()) { return ""; } StringBuilder builder = new StringBuilder("<"); Iterator<ConsoleParameterOption> options = parameter.iterateOptions(); boolean first = true; while (options.hasNext()) { ConsoleParameterOption option = options.next(); if (!first) { builder.append(","); } builder.append(option.getName()); first = false; } builder.append(">"); return builder.toString(); } /** * @param cmd */ private void handleProcessingError(String message) { if (printErrors) { out.println(message); out.println(); showsUsageScreen(); } throw new ConsoleParametersProcessingException(message); } public static void main(String[] args) { ConsoleParametersProcessor processor = new ConsoleParametersProcessor("meuPrograma"); processor.addSupportedParameter(new ConsoleParameter("par1", "Este é o parâmetro 1 lalala ksdasd eras")); processor.addSupportedParameter(new ConsoleParameter("-par2", "Este é o parâmetro 2 acas", true, true)); processor.addSupportedParameter(new ConsoleParameter("par3", "Este é o parâmetro 3 asdas dsad asd sad sadsadsad", false, false)); ConsoleParameter parameter = new ConsoleParameter("-par4", "Este é o parâmetro 4 s", true, true); parameter.addParameterOption(new ConsoleParameterOption("option1", "Lalalalala asd sad asd ")); parameter.addParameterOption(new ConsoleParameterOption("option2", "Lalalalala")); processor.addSupportedParameter(parameter); processor.showsUsageScreen(); System.out.println(); System.out.println(); String[] params = "-par4 lalala par1 par1 -par3 -par2 ".split(" "); Map<String, ConsoleParameter> parameters = processor.processConsoleParameters(params); for (ConsoleParameter consoleParameter : parameters.values()) { System.out.println("parameter accepted: "+ consoleParameter.getName()); if (consoleParameter.hasOptions()) { Iterator<ConsoleParameterOption> options = consoleParameter.iterateOptions(); int i=0; while (options.hasNext()) { System.out.println(" Parameter Option <"+options.next().getName()+">: " + consoleParameter.getValues()[i++]); } } else if (!consoleParameter.isFlagParameter()) { System.out.println(" Non Flag Parameter Value "+consoleParameter.getValue()); } } } }