getopt + other tool classes

This commit is contained in:
overflowerror 2018-09-12 21:51:48 +02:00
parent 490daa2726
commit 0a9877b2a6
19 changed files with 607 additions and 0 deletions

View 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;
}
}

View 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();
}
}

View 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();
}
}

View file

@ -0,0 +1,7 @@
package net.persei.tools.exceptions;
public class WhatTheFuckException extends RuntimeException {
private static final long serialVersionUID = 8501185517458311794L;
}

View file

@ -0,0 +1,5 @@
package net.persei.tools.getopt;
public enum ArgumentType {
NONE, OPTIONAL, NECESSARY
}

View 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;
}
}

View 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();
}
}

View 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;
}

View 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);
}
}

View file

@ -0,0 +1,5 @@
package net.persei.tools.getopt;
public enum OptionType {
OPTIONAL, NECESSARY
}

View file

@ -0,0 +1,5 @@
package net.persei.tools.getopt;
public enum UnknownOptionBehaviour {
END, ERROR, IGNORE
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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;
}

View 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;
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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;
}
}

View file

@ -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);
}
}