![JAR search and dependency download from the Maven repository](/logo.png)
com.codetaco.cli.impl.parser.NamespaceParser Maven / Gradle / Ivy
Show all versions of cli Show documentation
package com.codetaco.cli.impl.parser;
import com.codetaco.cli.impl.input.AbstractInputParser;
import com.codetaco.cli.impl.input.NodeOc;
import com.codetaco.cli.impl.input.Token;
import com.codetaco.cli.impl.type.ICmdLineArg;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* Properties can be used to represent command line args using a modified
* namespace encoding. "."s break the name up into group levels and the final
* node is the specific arg name. On the RHS of the = is the value associated
* with the arg.
*
* Each of the nodes in the arg name can be suffixed with an index in order to
* handle multi valued args. These are specified with brackets. [0] for
* instance.
*
* @author Chris DeGreef [email protected]
*/
public final class NamespaceParser extends AbstractInputParser implements IParserInput {
static public IParserInput getInstance(final File file) throws IOException {
final List args = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String aConfigLine;
while ((aConfigLine = reader.readLine()) != null) {
if (aConfigLine.length() > 0 && aConfigLine.charAt(0) != '#') {
args.add(aConfigLine);
}
}
}
final NamespaceParser parser = new NamespaceParser();
parser.args = args.toArray(new String[0]);
return parser;
}
static public IParserInput getInstance(final String... args) {
final NamespaceParser parser = new NamespaceParser();
parser.args = args;
return parser;
}
static private String parseNamespaceLine(final String arg,
final List line) {
/*
* Scanning for the equal sign rather than simply splitting on it allows
* for equal signs in the value portion without effecting the logic of
* this method.
*/
final int indexOfSeparator = arg.indexOf('=');
final String[] keyValue = new String[2];
if (indexOfSeparator <= 0) {
keyValue[0] = "";
} else {
keyValue[0] = arg.substring(0, indexOfSeparator).trim();
}
if (indexOfSeparator == arg.length() - 1) {
keyValue[1] = "";
} else {
keyValue[1] = arg.substring(indexOfSeparator + 1).trim();
}
/*
* "a.b.c." represents a positional (unnamed) final level. If the split
* does not see a space after the last node then it will only count 3.
* It needs to count 4. The [0] seems to indicate a multiple item But
* the 0 element is the same as a direct reference in cli.
*/
String value = keyValue[0];
if (value.length() > 0) {
if (value.charAt(value.length() - 1) == '.') {
value = keyValue[0] + "[0]";
}
}
final String[] nodes = value.split("\\.");
line.clear();
Arrays.stream(nodes).forEach(node -> {
final int start = node.indexOf("[");
final NodeOc newNode = new NodeOc();
if (start > -1) {
final int end = node.indexOf("]");
newNode.key = node.substring(0, start);
newNode.occurrance = Integer.parseInt(node.substring(start + 1, end));
} else {
newNode.key = node;
newNode.occurrance = -1;
}
line.add(newNode);
});
return keyValue[1];
}
static public String unparseTokens(final List> args) {
final StringBuilder out = new StringBuilder();
unparseTokens("", args, out);
return out.toString();
}
static public void unparseTokens(final String prefix,
final List> args,
final StringBuilder out) {
args.stream()
.filter(ICmdLineArg::isParsed)
.forEach(arg -> arg.exportNamespace(prefix, out));
}
protected String[] args;
private final char commandPrefix = '-';
private NamespaceParser() {
super();
}
@Override
public Token[] parseTokens() {
final List out = new ArrayList<>();
final List depth = new ArrayList<>();
final List line = new ArrayList<>();
Arrays.stream(args)
.sorted()
.forEach(arg -> buildTokens(commandPrefix,
out,
depth,
line,
parseNamespaceLine(arg, line)));
for (int d = 1; d < depth.size(); d++) {
out.add(new Token(commandPrefix,
CLOSE_GROUP,
0,
0,
false));
}
return out.toArray(new Token[0]);
}
@Override
public String substring(final int inclusiveStart, final int exclusiveEnd) {
return "";
}
}