/*
* ====================================================================
* Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://svnkit.com/license.html.
* If newer versions of this license are posted there, you may use a
* newer version instead, at your option.
* ====================================================================
*/
package org.tmatesoft.svn.cli;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.internal.util.SVNHashMap;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.util.SVNLogType;
/**
* @version 1.3
* @author TMate Software Ltd.
*/
public class SVNCommandLine {
private static final Map ourOptions = new SVNHashMap();
public static void registerOption(AbstractSVNOption option) {
if (option.getName() != null) {
ourOptions.put("--" + option.getName(), option);
}
if (option.getAlias() != null) {
ourOptions.put("-" + option.getAlias(), option);
}
}
private String myCommand;
private Collection myArguments;
private Collection myOptions;
private boolean myNeedsCommand;
public SVNCommandLine() {
this(true);
}
public SVNCommandLine(boolean needsCommand) {
myArguments = new LinkedList();
myOptions = new LinkedList();
myNeedsCommand = needsCommand;
}
public void init(String[] args) throws SVNException {
myInputArguments = args;
myArgumentPosition = 0;
myArgumentIndex = 0;
myArguments = new LinkedList();
myOptions = new LinkedList();
myCommand = null;
while (true) {
SVNOptionValue value = nextOption();
if (value != null) {
myOptions.add(value);
} else {
return;
}
}
}
private int myArgumentIndex;
private int myArgumentPosition;
private String[] myInputArguments;
private SVNOptionValue nextOption() throws SVNException {
if (myArgumentPosition == 0) {
while (myArgumentIndex < myInputArguments.length && !myInputArguments[myArgumentIndex].startsWith("-")) {
String argument = myInputArguments[myArgumentIndex];
// this is either command name or non-option argument.
if (myNeedsCommand && myCommand == null) {
myCommand = argument;
} else {
myArguments.add(argument);
}
myArgumentIndex++;
}
if (myArgumentIndex >= myInputArguments.length) {
return null;
}
// now we're in the beginning of option. parse option name first.
String argument = myInputArguments[myArgumentIndex];
if (argument.startsWith("--")) {
// it is long option, long option with '=value', or --long value set.
int valueIndex = argument.indexOf('=');
String optionName = valueIndex > 0 ? argument.substring(0, valueIndex) : argument;
AbstractSVNOption option = (AbstractSVNOption) ourOptions.get(optionName);
if (option == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CL_ARG_PARSING_ERROR, "invalid option: {0}", optionName);
SVNErrorManager.error(err, SVNLogType.CLIENT);
}
String value = null;
if (!option.isUnary()) {
if (valueIndex > 0) {
value = argument.substring(valueIndex + 1);
} else {
myArgumentIndex++;
value = myArgumentIndex < myInputArguments.length ? myInputArguments[myArgumentIndex] : null;
}
if (value == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CL_ARG_PARSING_ERROR, "missing argument: {0}", optionName);
SVNErrorManager.error(err, SVNLogType.CLIENT);
}
}
myArgumentIndex++;
return new SVNOptionValue(option, optionName, value);
}
myArgumentPosition = 1;
}
// set of short options or set of short options with '[=]value', or -shortset value
// process each option is set until binary one found. then process value.
String argument = myInputArguments[myArgumentIndex];
String optionName = "-" + argument.charAt(myArgumentPosition++);
AbstractSVNOption option = (AbstractSVNOption) ourOptions.get(optionName);
if (option == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CL_ARG_PARSING_ERROR, "invalid option: {0}", optionName);
SVNErrorManager.error(err, SVNLogType.CLIENT);
}
String value = null;
if (!option.isUnary()) {
if (myArgumentPosition < argument.length()) {
value = argument.substring(myArgumentPosition);
if (value.startsWith("=")) {
value = value.substring(1);
}
} else {
myArgumentIndex++;
value = myArgumentIndex < myInputArguments.length ? myInputArguments[myArgumentIndex] : null;
}
myArgumentPosition = 0;
myArgumentIndex++;
if (value == null) {
SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.CL_ARG_PARSING_ERROR, "missing argument: {0}", optionName);
SVNErrorManager.error(err, SVNLogType.CLIENT);
}
}
if (myArgumentPosition >= argument.length()) {
myArgumentPosition = 0;
myArgumentIndex++;
}
return new SVNOptionValue(option, optionName, value);
}
public Iterator optionValues() {
return myOptions.iterator();
}
public String getCommandName() {
return myCommand;
}
public Collection getArguments() {
return myArguments;
}
}