org.docx4j.model.fields.FieldRef Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of docx4j Show documentation
Show all versions of docx4j Show documentation
docx4j is a library which helps you to work with the Office Open
XML file format as used in docx
documents, pptx presentations, and xlsx spreadsheets.
package org.docx4j.model.fields;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.docx4j.XmlUtils;
import org.docx4j.jaxb.Context;
import org.docx4j.wml.CTFFData;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.FldChar;
import org.docx4j.wml.R;
import org.docx4j.wml.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The objective of this class is to represent a complex field
* (containing nested fields, if any; nested fields are
* represented by FieldRef object of their own).
*
* TODO, consider whether to make this abstract, with
* differing concrete implementations for top level and nested fields.
*
* Background. There are simple fields:
*
4/12/2011
*
* and there are complex fields:
*
REF hi \h
Hello
* A simple field can also take the complex form:
*
DATE
4/12/2011
* A complex field can contain nested fields, in either
* its instruction part, or result part.
*
* we need to represent nest fields in the instructions
* part only (since nested fields in the results part
* get re-generated).
*
* An example of a nested field in the instructions part:
*
IF
4/12/2011
="4/12/2011" "it is 4/12" "not 4/12"
today
* An example of nested fields in the results part:
*
*
TOC \o "1-3" \h \z \ u
one
PAGEREF _Toc310757867 \h
1
oneone
PAGEREF _Toc310757868 \h
1
*
* In general, you can "canonicalise" the field representation
* to be
* (i) instructions, contained within a single run
* (ii) results, immediately following, though not nec just as following siblings
* (iii) the final
*
* Since the purpose of our field support is to update the field
* results, we can delete (ii) and (iii) before adding them in again.
*
* The document is preprocessed to put it into this form.
*
* @author jharrop
*
*/
public class FieldRef {
private static Logger log = LoggerFactory.getLogger(FieldRef.class);
public FieldRef(FldChar fldCharBegin) {
this.fldCharBegin = fldCharBegin;
}
private FldChar fldCharBegin;
protected String fldName = null;
/**
* The name of the (outer most) field, for example DATE, MERGEFIELD.
*
* Assume for now that this is contained in instructions.get(0).
*
* @see field syntax
* @return
*/
public String getFldName() {
Object o = XmlUtils.unwrap(instructions.get(0));
if (o instanceof Text) {
return FormattingSwitchHelper.getFldSimpleName( ((Text)o).getValue() );
} else {
log.error("TODO: extract field name from " + o.getClass().getName() );
if (o instanceof FieldRef) {
// contains a nested field?!
FieldRef nested = (FieldRef)o;
log.error("Nested field " + nested.getFldName() );
} else {
log.error(XmlUtils.marshaltoString(instructions.get(0), true, true) );
}
return null;
}
}
private ContentAccessor parent;
public ContentAccessor getParent() {
return parent;
}
public void setParent(ContentAccessor parent) {
this.parent = parent;
}
/**
* The run
*
*
...
*/
private R beginRun;
public R getBeginRun() {
return beginRun;
}
public void setBeginRun(R beginRun) {
this.beginRun = beginRun;
}
private boolean seenSeparate=false;
public boolean haveSeenSeparate() {
return seenSeparate;
}
public void setSeenSeparate(boolean seenSeparate) {
this.seenSeparate = seenSeparate;
}
private void processFldBegin() {
formFieldProperties = fldCharBegin.getFfData();
customFieldData = fldCharBegin.getFldData();
dirty = fldCharBegin.isDirty();
lock = fldCharBegin.isFldLock();
}
private Boolean mergeFormat;
/**
* @return whether \* MERGEFORMAT is set
*/
public Boolean isMergeFormat() {
if (mergeFormat==null) {
//Work it out. Assume for now that this is contained in instructions.get(0).
mergeFormat = Boolean.FALSE;
Object o = XmlUtils.unwrap(instructions.get(0));
if (o instanceof Text) {
String instr = ((Text)o).getValue();
if (instr.contains("MERGEFORMAT")) {
mergeFormat = Boolean.TRUE;
}
} else {
log.error("TODO: extract field name from " + o.getClass().getName() );
log.error(XmlUtils.marshaltoString(instructions.get(0), true, true) );
}
}
return mergeFormat;
}
private boolean dirty;
/**
* Specifies that this field has been flagged by an application to indicate that its current results
* are invalid (stale) due to other modifications made to the document, and these contents should be
* updated before they are displayed.
* @return whether stale
* @see the spec
*/
public boolean isDirty() {
return dirty;
}
/**
* @param whether stale
* @see the spec
*/
public void setDirty(boolean dirty) {
this.dirty = dirty;
fldCharBegin.setDirty(dirty);
// Note that this doesn't set dirty on any nested fields. TODO: Consider whether it should.
}
private boolean lock;
/**
* @return the lock
* @see the spec
*/
public boolean isLock() {
return lock;
}
/**
* Specifies that the parent complex field shall not have its field result recalculated, even if
* an application attempts to recalculate the results of all fields in the document or a
* recalculation is explicitly requested.
*
* @param lock the lock to set
* @see the spec
*/
public void setLock(boolean lock) {
this.lock = lock;
fldCharBegin.setFldLock(lock);
}
private Text customFieldData;
/**
* application-specific data associated with this field.
*
* @return the customFieldData
* @see the spec
*/
public Text getCustomFieldData() {
return customFieldData;
}
/**
* @param customFieldData the customFieldData to set
* @see the spec
*/
public void setCustomFieldData(Text customFieldData) {
this.customFieldData = customFieldData;
fldCharBegin.setFldData(customFieldData);
}
private CTFFData formFieldProperties;
/**
* Properties specific to FORMCHECKBOX, FORMDROPDOWN, FORMTEXT
*
* @return the formFieldProperties
* @see the spec
*/
public CTFFData getFormFieldProperties() {
return formFieldProperties;
}
/**
* @param formFieldProperties the formFieldProperties to set
* @see the spec
*/
public void setFormFieldProperties(CTFFData formFieldProperties) {
this.formFieldProperties = formFieldProperties;
fldCharBegin.setFfData(formFieldProperties);
}
/**
* The run
*
Store a reference to it so we can delete it.
*/
private R endRun;
public R getEndRun() {
return endRun;
}
public void setEndRun(R endRun) {
this.endRun = endRun;
}
/**
* A list of the content between the outermost w:fldChar begin and separate elements;
* in the simplest case, this will be a single w:instrText object;
* in a more general case it will be a mixture of w:instrText and FieldRef objects
* (and possibly other things such as w:br).
*/
private List