mirror of
https://github.com/sigmasternchen/ServiceOracle
synced 2025-03-15 07:58:59 +00:00
getopt + other tool classes
This commit is contained in:
parent
490daa2726
commit
0a9877b2a6
19 changed files with 607 additions and 0 deletions
10
src/net/persei/tools/ArrayHelper.java
Normal file
10
src/net/persei/tools/ArrayHelper.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package net.persei.tools;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ArrayHelper {
|
||||
public static <E> E[] fillArray(E[] array, E value) {
|
||||
Arrays.fill(array, value);
|
||||
return array;
|
||||
}
|
||||
}
|
54
src/net/persei/tools/Base62.java
Normal file
54
src/net/persei/tools/Base62.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
package net.persei.tools;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Base62 {
|
||||
|
||||
private static final BigInteger SIXTY_TWO = BigInteger.valueOf(62);
|
||||
|
||||
private static char toChar(byte value) {
|
||||
if (value < 0)
|
||||
throw new IllegalArgumentException("< 0");
|
||||
if (value < 10)
|
||||
return (char) ('0' + value);
|
||||
if (value < 36)
|
||||
return (char) ('A' + value - 10);
|
||||
if (value < 62)
|
||||
return (char) ('a' + value - 36);
|
||||
throw new IllegalArgumentException("> 61");
|
||||
}
|
||||
|
||||
private static byte toByte(char value) {
|
||||
if (value >= '0' && value <= '9')
|
||||
return (byte) (value - '0');
|
||||
if (value >= 'A' && value <= 'Z')
|
||||
return (byte) (value - 'A' + 10);
|
||||
if (value >= 'a' && value <= 'z')
|
||||
return (byte) (value - 'a' + 36);
|
||||
throw new IllegalArgumentException("not a valid base62 char");
|
||||
}
|
||||
|
||||
public static byte[] decode(String key) {
|
||||
BigInteger value = BigInteger.ZERO;
|
||||
|
||||
for (int i = 0; i < key.length(); i++) {
|
||||
value = value.multiply(SIXTY_TWO);
|
||||
value = value.add(BigInteger.valueOf(toByte(key.charAt(i))));
|
||||
}
|
||||
|
||||
return value.toByteArray();
|
||||
}
|
||||
|
||||
public static String encode(byte key[]) {
|
||||
BigInteger i = new BigInteger(key);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
while (i.compareTo(BigInteger.ZERO) > 0) {
|
||||
builder.append(toChar(i.mod(SIXTY_TWO).byteValue()));
|
||||
i = i.divide(SIXTY_TWO);
|
||||
}
|
||||
|
||||
return builder.reverse().toString();
|
||||
}
|
||||
}
|
11
src/net/persei/tools/StringHelper.java
Normal file
11
src/net/persei/tools/StringHelper.java
Normal file
|
@ -0,0 +1,11 @@
|
|||
package net.persei.tools;
|
||||
|
||||
public class StringHelper {
|
||||
public static String repeat(int length, String string) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
builder.append(string);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package net.persei.tools.exceptions;
|
||||
|
||||
public class WhatTheFuckException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 8501185517458311794L;
|
||||
|
||||
}
|
5
src/net/persei/tools/getopt/ArgumentType.java
Normal file
5
src/net/persei/tools/getopt/ArgumentType.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
public enum ArgumentType {
|
||||
NONE, OPTIONAL, NECESSARY
|
||||
}
|
80
src/net/persei/tools/getopt/HelpHandler.java
Normal file
80
src/net/persei/tools/getopt/HelpHandler.java
Normal file
|
@ -0,0 +1,80 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.persei.tools.getopt.exceptions.OptionException;
|
||||
import net.persei.tools.getopt.exceptions.SilentShutdownException;
|
||||
|
||||
public class HelpHandler implements OptionHandler {
|
||||
|
||||
private List<Option> options;
|
||||
private String applicationName;
|
||||
private String version;
|
||||
private String copyright;
|
||||
private String licence;
|
||||
private String helpText;
|
||||
private String appendex;
|
||||
private String executeableName;
|
||||
|
||||
public HelpHandler(List<Option> options, String applicationName, String version, String copyright, String licence, String helpText, String appendex) {
|
||||
this.options = options.stream().filter(o -> o.hasSynopsis()).collect(Collectors.toList());
|
||||
this.applicationName = applicationName;
|
||||
this.version = version;
|
||||
this.copyright = copyright;
|
||||
this.licence = licence;
|
||||
this.helpText = helpText;
|
||||
this.appendex = appendex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(String argument) throws OptionException {
|
||||
if (executeableName == null)
|
||||
executeableName = "";
|
||||
|
||||
if (applicationName != null) {
|
||||
System.out.print(applicationName);
|
||||
if (version != null)
|
||||
System.out.print(" " + version);
|
||||
|
||||
if (copyright != null)
|
||||
System.out.print(" - (C) by " + copyright);
|
||||
|
||||
System.out.println();
|
||||
|
||||
if (licence != null) {
|
||||
System.out.println(licence);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
System.out.print("SYNOPSIS: " + executeableName + " [OPTIONS] ");
|
||||
|
||||
if (appendex != null)
|
||||
System.out.print(appendex);
|
||||
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
|
||||
if (helpText != null) {
|
||||
System.out.println(helpText);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
if (options != null && options.size() > 0) {
|
||||
System.out.println("OPTIONS:");
|
||||
|
||||
for (Option option : options) {
|
||||
System.out.println(option.getSynopsis());
|
||||
}
|
||||
}
|
||||
|
||||
throw new SilentShutdownException(0);
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.executeableName = name;
|
||||
}
|
||||
|
||||
}
|
180
src/net/persei/tools/getopt/Option.java
Normal file
180
src/net/persei/tools/getopt/Option.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
import java.awt.datatransfer.StringSelection;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sun.org.apache.bcel.internal.generic.NEW;
|
||||
import com.sun.xml.internal.ws.message.StringHeader;
|
||||
|
||||
import net.persei.tools.StringHelper;
|
||||
import net.persei.tools.getopt.exceptions.NecessaryOptionMissingException;
|
||||
import net.persei.tools.getopt.exceptions.OptionAlreadyGivenException;
|
||||
import net.persei.tools.getopt.exceptions.OptionDoesNotHaveArgumentException;
|
||||
import net.persei.tools.getopt.exceptions.OptionException;
|
||||
import net.persei.tools.getopt.exceptions.OptionNeedsArgumentException;
|
||||
|
||||
public class Option {
|
||||
|
||||
private static final int LONG_OPTION_MAX_LENGTH = 10;
|
||||
private static final int MAX_LINE_LENGTH = 80;
|
||||
|
||||
private Character shortOption;
|
||||
private String longOption;
|
||||
private ArgumentType argumentType = ArgumentType.NONE;
|
||||
private OptionType optionType = OptionType.OPTIONAL;
|
||||
private String synopsis = null;
|
||||
private boolean isSingleton = false;
|
||||
private boolean wasHandled = false;
|
||||
private OptionHandler handler;
|
||||
|
||||
public Option() {
|
||||
}
|
||||
|
||||
public Option(char option, OptionHandler handler) {
|
||||
this.shortOption = Character.valueOf(option);
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public Option(String option, OptionHandler handler) {
|
||||
this.longOption = option;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public Option setSynopsis(String synopsis) {
|
||||
this.synopsis = synopsis;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option setShortOption(char option) {
|
||||
this.shortOption = Character.valueOf(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option setLongOption(String option) {
|
||||
this.longOption = option;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option setArgumentType(ArgumentType type) {
|
||||
this.argumentType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option setOptionType(OptionType type) {
|
||||
this.optionType = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option setHandler(OptionHandler handler) {
|
||||
this.handler = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option setSingleton(boolean singleton) {
|
||||
this.isSingleton = singleton;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return ((shortOption != null || longOption != null)
|
||||
&& argumentType != null
|
||||
&& optionType != null
|
||||
&& handler != null);
|
||||
}
|
||||
|
||||
public OptionType getOptionType() {
|
||||
return optionType;
|
||||
}
|
||||
|
||||
public void handlingWasOkay() throws OptionException {
|
||||
if (!wasHandled && optionType == OptionType.NECESSARY)
|
||||
throw new NecessaryOptionMissingException(toString());
|
||||
}
|
||||
|
||||
public boolean check(boolean isShort, String option, String argument) throws OptionException {
|
||||
if (isShort) {
|
||||
if (shortOption == null)
|
||||
return false;
|
||||
if (!option.equals(String.valueOf(shortOption)))
|
||||
return false;
|
||||
if (argument == null && argumentType == ArgumentType.NECESSARY)
|
||||
throw new OptionNeedsArgumentException("-" + option);
|
||||
if (argument != null && argumentType == ArgumentType.NONE)
|
||||
throw new OptionDoesNotHaveArgumentException("-" + option);
|
||||
} else {
|
||||
if (longOption == null)
|
||||
return false;
|
||||
if (!option.equals(longOption))
|
||||
return false;
|
||||
if (argument == null && argumentType == ArgumentType.NECESSARY)
|
||||
throw new OptionNeedsArgumentException("--" + option);
|
||||
if (argument != null && argumentType == ArgumentType.NONE)
|
||||
throw new OptionDoesNotHaveArgumentException("--" + option);
|
||||
}
|
||||
|
||||
if (isSingleton && wasHandled) {
|
||||
throw new OptionAlreadyGivenException((isShort ? "-" : "--") + option);
|
||||
}
|
||||
wasHandled = true;
|
||||
handler.handle(argument);
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (shortOption != null)
|
||||
return "-" + shortOption;
|
||||
if (longOption != null)
|
||||
return "--" + longOption;
|
||||
return "[no option set]";
|
||||
}
|
||||
|
||||
public boolean hasSynopsis() {
|
||||
return synopsis != null;
|
||||
}
|
||||
|
||||
public String getSynopsis() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append(" ");
|
||||
|
||||
if (shortOption == null)
|
||||
builder.append(" ");
|
||||
else
|
||||
builder.append("-").append(shortOption);
|
||||
|
||||
builder.append(" ");
|
||||
|
||||
int tmp = 0;
|
||||
|
||||
if (longOption == null)
|
||||
tmp = LONG_OPTION_MAX_LENGTH + 2;
|
||||
else {
|
||||
builder.append("--").append(longOption);
|
||||
tmp = LONG_OPTION_MAX_LENGTH - longOption.length();
|
||||
}
|
||||
|
||||
builder.append(StringHelper.repeat(tmp, " "));
|
||||
|
||||
builder.append(" ");
|
||||
|
||||
int offset = 1 + 2 + 2 + 2 + LONG_OPTION_MAX_LENGTH + 2;
|
||||
|
||||
String syn = synopsis;
|
||||
|
||||
boolean first = true;
|
||||
while(syn != null && syn.length() > 0) {
|
||||
if (!first)
|
||||
builder.append("\n").append(StringHelper.repeat(offset, " "));
|
||||
first = false;
|
||||
if (syn.length() > MAX_LINE_LENGTH - offset) {
|
||||
builder.append(syn.substring(0, MAX_LINE_LENGTH - offset));
|
||||
syn = syn.substring(MAX_LINE_LENGTH - offset);
|
||||
} else {
|
||||
builder.append(syn);
|
||||
syn = null;
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
10
src/net/persei/tools/getopt/OptionHandler.java
Normal file
10
src/net/persei/tools/getopt/OptionHandler.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
import net.persei.tools.getopt.exceptions.OptionException;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface OptionHandler {
|
||||
|
||||
void handle(String argument) throws OptionException;
|
||||
|
||||
}
|
145
src/net/persei/tools/getopt/OptionParser.java
Normal file
145
src/net/persei/tools/getopt/OptionParser.java
Normal file
|
@ -0,0 +1,145 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.persei.tools.exceptions.WhatTheFuckException;
|
||||
import net.persei.tools.getopt.exceptions.OptionDoesNotHaveArgumentException;
|
||||
import net.persei.tools.getopt.exceptions.OptionException;
|
||||
import net.persei.tools.getopt.exceptions.OptionNotValidException;
|
||||
import net.persei.tools.getopt.exceptions.UnknownOptionException;
|
||||
|
||||
public class OptionParser {
|
||||
|
||||
private UnknownOptionBehaviour unknownOptionBehaviour = UnknownOptionBehaviour.ERROR;
|
||||
|
||||
private List<Option> options;
|
||||
|
||||
private HelpHandler helpHandler;
|
||||
|
||||
public OptionParser() {
|
||||
this.options = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void addOption(Option option) throws OptionException {
|
||||
if (!option.isValid())
|
||||
throw new OptionNotValidException(option.toString());
|
||||
options.add(option);
|
||||
}
|
||||
|
||||
public void setUnknownOptionBehaviour(UnknownOptionBehaviour b) {
|
||||
this.unknownOptionBehaviour = b;
|
||||
}
|
||||
|
||||
public String[] parse(String[] args) throws OptionException {
|
||||
if (helpHandler != null && args.length > 0)
|
||||
helpHandler.setName(args[0]);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
|
||||
if (arg.startsWith("--")) {
|
||||
arg = arg.substring(2);
|
||||
if (arg.length() == 0)
|
||||
break;
|
||||
String argument = null;
|
||||
String optionString = null;
|
||||
int equals = arg.indexOf("=");
|
||||
if (equals >= 0) {
|
||||
optionString = arg.substring(0, equals);
|
||||
if (arg.length() > equals + 1)
|
||||
argument = arg.substring(equals + 1);
|
||||
} else {
|
||||
optionString = arg;
|
||||
}
|
||||
boolean okay = false;
|
||||
for (Option option : options) {
|
||||
if (option.check(false, optionString, argument)) {
|
||||
okay = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!okay) {
|
||||
boolean end = false;
|
||||
switch (unknownOptionBehaviour) {
|
||||
case END:
|
||||
end = true;
|
||||
break;
|
||||
case ERROR:
|
||||
throw new UnknownOptionException("--" + optionString);
|
||||
case IGNORE:
|
||||
break;
|
||||
default:
|
||||
throw new WhatTheFuckException();
|
||||
}
|
||||
|
||||
if (end)
|
||||
break;
|
||||
}
|
||||
} else if (arg.startsWith("-")) {
|
||||
arg = arg.substring(1);
|
||||
if (arg.length() == 0)
|
||||
break;
|
||||
String argument = null;
|
||||
if (args.length > i + 1)
|
||||
argument = args[i + 1];
|
||||
for(int j = 0; j < arg.length(); j++) {
|
||||
String optionString = arg.substring(j, j + 1);
|
||||
boolean okay = false;
|
||||
for (Option option : options) {
|
||||
try {
|
||||
if (arg.length() == j + 1 && argument != null) {
|
||||
okay = option.check(true, optionString, argument);
|
||||
i++;
|
||||
} else {
|
||||
okay = option.check(true, optionString, null);
|
||||
}
|
||||
} catch (OptionDoesNotHaveArgumentException e) {
|
||||
okay = option.check(true, optionString, null);
|
||||
} catch (OptionException e) {
|
||||
throw e;
|
||||
}
|
||||
if (okay)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!okay) {
|
||||
boolean end = false;
|
||||
switch (unknownOptionBehaviour) {
|
||||
case END:
|
||||
end = true;
|
||||
break;
|
||||
case ERROR:
|
||||
throw new UnknownOptionException("-" + optionString);
|
||||
case IGNORE:
|
||||
break;
|
||||
default:
|
||||
throw new WhatTheFuckException();
|
||||
}
|
||||
|
||||
if (end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == args.length + 1)
|
||||
return new String[0];
|
||||
|
||||
return Arrays.asList(args).subList(i, args.length).toArray(new String[args.length - i]);
|
||||
}
|
||||
|
||||
public void setHelp(Option option, String applicationName, String version, String copyright, String licence, String helpText, String appendex) throws OptionException {
|
||||
helpHandler = new HelpHandler(options, applicationName, version, copyright, licence, helpText, appendex);
|
||||
option.setHandler(helpHandler);
|
||||
|
||||
addOption(option);
|
||||
}
|
||||
|
||||
}
|
5
src/net/persei/tools/getopt/OptionType.java
Normal file
5
src/net/persei/tools/getopt/OptionType.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
public enum OptionType {
|
||||
OPTIONAL, NECESSARY
|
||||
}
|
5
src/net/persei/tools/getopt/UnknownOptionBehaviour.java
Normal file
5
src/net/persei/tools/getopt/UnknownOptionBehaviour.java
Normal file
|
@ -0,0 +1,5 @@
|
|||
package net.persei.tools.getopt;
|
||||
|
||||
public enum UnknownOptionBehaviour {
|
||||
END, ERROR, IGNORE
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class NecessaryOptionMissingException extends OptionException {
|
||||
private static final long serialVersionUID = 8987159468839724409L;
|
||||
|
||||
public NecessaryOptionMissingException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class OptionAlreadyGivenException extends OptionException {
|
||||
private static final long serialVersionUID = 4569388876043615748L;
|
||||
|
||||
public OptionAlreadyGivenException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class OptionDoesNotHaveArgumentException extends OptionException {
|
||||
|
||||
public OptionDoesNotHaveArgumentException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 8676936026575565663L;
|
||||
|
||||
}
|
14
src/net/persei/tools/getopt/exceptions/OptionException.java
Normal file
14
src/net/persei/tools/getopt/exceptions/OptionException.java
Normal file
|
@ -0,0 +1,14 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class OptionException extends Exception {
|
||||
public OptionException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
public OptionException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -2759943457136830835L;
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class OptionNeedsArgumentException extends OptionException {
|
||||
public OptionNeedsArgumentException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 8065562591269139444L;
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class OptionNotValidException extends OptionException {
|
||||
private static final long serialVersionUID = 5443326801299785361L;
|
||||
|
||||
public OptionNotValidException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class SilentShutdownException extends OptionException {
|
||||
|
||||
private static final long serialVersionUID = -8807171464602371333L;
|
||||
|
||||
private int errorCode;
|
||||
|
||||
public SilentShutdownException(int errorCode) {
|
||||
super(String.valueOf(errorCode));
|
||||
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package net.persei.tools.getopt.exceptions;
|
||||
|
||||
public class UnknownOptionException extends OptionException {
|
||||
|
||||
private static final long serialVersionUID = -6800015913092083730L;
|
||||
|
||||
public UnknownOptionException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue