ControlledString.java
package bjc.everge;
/**
* Represents a string with a set of control flags attached to it.
*
* @author Ben Culkin
*/
public class ControlledString {
/**
* Represents a single control (a key-values pair)
*
* @author Ben Culkin
*/
public static class Control {
/**
* The name of the control.
*/
public String name;
/**
* The arguments to the control.
*/
public String[] args;
/**
* Create a new blank control.
*/
public Control() {
}
/**
* Create a new argless control.
*
* @param nam
* The name of the control.
*/
public Control(String nam) {
name = nam;
}
/**
* Create a new control.
*
* @param nam
* The name of the control.
* @param ars
* The arguments of the control.
*/
public Control(String nam, String... ars) {
name = nam;
args = ars;
}
}
/**
* The string the controls apply to.
*/
public String strang;
/**
* The controls that apply to the string.
*/
public Control[] controls;
/**
* Create a new blank controlled string.
*/
public ControlledString() {
controls = new Control[0];
}
/**
* Create a new controlled string without any controls.
*
* @param strung
* The string to use.
*/
public ControlledString(String strung) {
strang = strung;
controls = new Control[0];
}
/**
* Create a new controlled string.
*
* @param strung
* The string to use.
* @param controls
* The controls that apply to the string.
*/
public ControlledString(String strung, Control... controls) {
strang = strung;
controls = controls;
}
/**
* Check if the string has controls.
*
* @return Whether or not the string has controls.
*/
public boolean hasControls() {
return controls.length > 0;
}
/**
* Parse a controlled string from a regular string.
*
* The controls must be parsed from the beginning of the string, and are indicated by occurances
* of contInd that bracket them from the string. The individual controls are delimited by
* instances of contSep, with arguments to them being separated by occurances of contArg.
*
* Each of those separators (which must be regular strings, not regexes or anything) may be
* escaped by preceeding them with a copy of contEsc.
*
* @param lne
* The string to parse frmo.
* @param contInd
* The indicator for whether or not there are controls.
* @param contSep
* The separator of individual controls.
* @param contArg
* The separator of control arguments.
* @param contEsc
* The escape string for each of the separators/indicators.
*
* @return A parsed control string.
*/
public static ControlledString parse(String lne, String contInd, String contSep,
String contArg, String contEsc) {
if (!lne.startsWith(contInd)) {
return new ControlledString(lne);
}
String tmp = lne.substring(2);
String[] bits = StringUtils.escapeSplit(contEsc, contInd, lne);
if (bits.length < 2) {
String msg = "Did not find control terminator (%s) where it should be";
msg = String.format(msg, contInd);
throw new IllegalArgumentException(msg);
}
ControlledString cs = new ControlledString(bits[0]);
bits = StringUtils.escapeSplit(contEsc, contSep, bits[1]);
cs.controls = new Control[bits.length];
for (int i = 0; i < bits.length; i++) {
String bit = bits[i];
String[] bots = StringUtils.escapeSplit(contEsc, contArg, bit);
Control cont = new Control(bots[0]);
if (cont.name.length() > 1) {
cont.name = cont.name.toUpperCase();
}
if (bots.length > 1) {
cont.args = new String[bots.length - 1];
for (int j = 1; j < bots.length; j++) {
cont.args[j - 1] = bots[j];
}
}
cs.controls[i] = cont;
}
return cs;
}
}