package org.docx4j.model.fields;
import org.docx4j.XmlUtils;
import org.docx4j.wml.CTSimpleField;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import javax.xml.transform.TransformerException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** Just a basic model for w:fldSimple that gets used in the
* FldSimpleModelConverter for the conversion to pdf/html
*
* @see <a href="http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/XML.html">the spec</a>
*
*/
public class FldSimpleModel {
private static Logger log = LoggerFactory.getLogger(FldSimpleModel.class);
protected CTSimpleField fldSimple = null;
protected Node content = null;
protected String fldName = null;
protected String fldParameterString = null;
protected List<String> fldParameters = null;
public void build(CTSimpleField fldSimple, Node content) throws TransformerException {
this.fldSimple = fldSimple;
if(log.isDebugEnabled()) {
log.debug("\n" + XmlUtils.marshaltoString(fldSimple, true, true));
}
this.content = content;
setupNameParameterString(fldSimple.getInstr());
}
public void build(String inStr) throws TransformerException {
reset();
setupNameParameterString(inStr);
}
protected void setupNameParameterString(String text) {
int nameStart = 0;
int nameEnd = 0;
if ((text != null) && (text.length() > 0)) {
while ((nameStart < text.length()) && (text.charAt(nameStart) == ' '))
nameStart++;
if (nameStart < text.length()) {
nameEnd = nameStart + 1;
if (text.charAt(nameStart) == '=') {
// Special case =nn
// NB, we can't process this field unless it is just a number (as opposed to a calculation)
} else {
while ((nameEnd < text.length()) && (text.charAt(nameEnd) != ' '))
nameEnd++;
}
}
if (nameStart < nameEnd) {
fldName = text.substring(nameStart, nameEnd);
log.debug("fldName: " + fldName);
if (nameEnd < text.length()) {
fldParameterString = text.substring(nameEnd).trim();
log.debug("fldParameterString: " + fldParameterString);
}
}
}
if (fldName != null) fldName = fldName.toUpperCase();
}
public static List<String> splitParameters(String text) {
log.debug("splitParameters: " + text);
List<String> ret = Collections.EMPTY_LIST;
int valStart = -1;
boolean inLiteral = false;
char ch = '\0';
if ((text != null) && (text.length() > 0)) {
ret = new ArrayList<String>(4);
for (int chidx = 0; chidx<text.length(); chidx++) {
ch = text.charAt(chidx);
if (ch == '"') {
if (inLiteral) {
//add literals with the enclosing "
appendParameter(ret, text.substring(valStart, chidx + 1));
inLiteral = false;
valStart = -1;
}
else {
valStart = chidx;
inLiteral = true;
}
}
else if (ch == ' ') {
if ((valStart > -1) && (!inLiteral)) {
appendParameter(ret, text.substring(valStart, chidx));
valStart = -1;
}
}
else if (valStart == -1) {
valStart = chidx;
}
}
if (valStart > -1) {
appendParameter(ret, text.substring(valStart));
valStart = -1;
}
}
return ret;
}
public static void appendParameter(List<String> parameters, String value) {
log.debug("parameter: " + value);
parameters.add(value);
}
/**
* The name of the field, for example DATE, MERGEFIELD
* @see <a href="http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/file_2.html">field syntax</a>
* @return
*/
public String getFldName() {
return fldName;
}
public String getFldArgument() {
return getFldParameters().get(0);
}
/**
* For example, "caContractId \* UPPER"
*/
public String getFldParameterString() {
return fldParameterString;
}
public List<String> getFldParameters() {
if (fldParameters == null) {
fldParameters = splitParameters(fldParameterString );
}
return fldParameters;
}
public CTSimpleField getFldSimple() {
return fldSimple;
}
public Node getContent() {
return content;
}
protected void reset() {
fldSimple = null;
content = null;
fldName = null;
fldParameterString = null;
fldParameters = null;
}
}