📄 formfields.java
字号:
* <ul>
* <li>
* Add a single column:
* <table class="CompactDL">
* <tr><td>{@linkplain #getColumnLabels() Label}:<td>the {@linkplain FormField#getName() name} of the form field in original case
* <tr><td>Value:<td>the single value mapped to this field in the specified <a href="#FieldDataSet">field data set</a>,
* which in the case of a set of radio buttons should be the {@linkplain FormControl#getPredefinedValue() predefined value}
* of the {@linkplain FormControl#isChecked() checked} radio button.
* </table>
* </ul>
* </ul>
* <li>
* Otherwise, if the form field has {@linkplain FormField#getPredefinedValues() predefined values}
* and {@linkplain FormField#allowsMultipleValues() allows multiple values},
* such as a set of {@linkplain FormControlType#CHECKBOX checkboxes}, then:
* <ul>
* <li>
* For each {@linkplain FormField#getPredefinedValues() predefined value} in the form field:
* <ul>
* <li>
* Add a boolean column:
* <table class="CompactDL">
* <tr><td>{@linkplain #getColumnLabels() Label}:<td>"<code><i>FieldName</i>.<i>PredefinedValue</i></code>",
* where <code><i>FieldName</i></code> is the {@linkplain FormField#getName() name} of the form field in original case,
* and <code><i>PredefinedValue</i></code> is the {@linkplain FormField#getPredefinedValues() predefined value}.
* <tr><td>Value:<td>the currently configured string representation for <i>{@linkplain Config#ColumnValueTrue true}</i>
* if a value mapped to this field in the specified <a href="#FieldDataSet">field data set</a> matches the
* {@linkplain FormField#getPredefinedValues() predefined value}, otherwise <i>{@linkplain Config#ColumnValueFalse false}</i>
* </table>
* </ul>
* <li>
* In addition, if the form field can also contain user values ({@link FormField#getUserValueCount()}<code>>0</code>), then:
* <ul>
* <li>
* Add another column:
* <table class="CompactDL">
* <tr><td>{@linkplain #getColumnLabels() Label}:<td>the {@linkplain FormField#getName() name} of the form field in original case
* <tr><td>Value:<td>all values mapped to this field in the specified <a href="#FieldDataSet">field data set</a>
* that do not match any of the {@linkplain FormField#getPredefinedValues() predefined values},
* separated by the text defined in the static {@link Config#ColumnMultipleValueSeparator} property.
* </table>
* </ul>
* </ul>
* </ul>
* </ul>
* <p>
* The sample program FormFieldCSVOutput demonstrates the use of this method and its output.
*
* @param dataSet a <a href="#FieldDataSet">field data set</a> containing the data to convert.
* @return the data values in the specified <a href="#FieldDataSet">field data set</a> in the form of a simple string array.
* @see Util#outputCSVLine(Writer,String[])
* @see #getColumnLabels()
* @see #getColumnValues()
*/
public String[] getColumnValues(final Map<String,String[]> dataSet) {
initColumns();
final String[] columnValues=new String[columns.length];
if (Config.ColumnValueFalse!=null) {
// initialise all boolean columns with false string
for (int i=0; i<columns.length; i++)
if (columns[i].isBoolean) columnValues[i]=Config.ColumnValueFalse;
}
for (Map.Entry<String,String[]> entry : dataSet.entrySet()) {
final String fieldName=entry.getKey();
final FormField formField=get(fieldName);
if (formField!=null) {
final int columnIndex=formField.columnIndex;
for (String value : entry.getValue()) {
for (int ci=columnIndex; ci<columns.length; ci++) {
final Column column=columns[ci];
if (column.formField!=formField) break;
if (column.predefinedValue!=null) {
if (!column.predefinedValue.equals(value)) continue;
columnValues[ci]=Config.ColumnValueTrue;
} else {
if (column.isBoolean) {
if (value!=null) columnValues[ci]=Config.ColumnValueTrue;
} else if (columnValues[ci]==null) {
columnValues[ci]=value;
} else {
columnValues[ci]=columnValues[ci]+Config.ColumnMultipleValueSeparator+value;
}
}
break;
}
}
}
}
return columnValues;
}
/**
* Converts all the {@linkplain FormField#getValues() form submission values} of the constituent form fields into a simple string array,
* suitable for storage in a tabular format such as a database table or <code>.CSV</code> file.
* <p>
* This is equivalent to {@link #getColumnValues(Map) getColumnValues}<code>(</code>{@link #getDataSet()}<code>)</code>.
*
* @return all the {@linkplain FormField#getValues() form submission values} of the constituent form fields in the form of a simple string array.
*/
public String[] getColumnValues() {
return getColumnValues(getDataSet());
}
private void initColumns() {
if (columns!=null) return;
final ArrayList<Column> columnList=new ArrayList<Column>();
for (FormField formField : this) {
formField.columnIndex=columnList.size();
if (!formField.allowsMultipleValues() || formField.getPredefinedValues().isEmpty()) {
columnList.add(new Column(formField,formField.getPredefinedValues().size()==1,null));
} else {
// add a column for every predefined value
for (String predefinedValue : formField.getPredefinedValues())
columnList.add(new Column(formField,true,predefinedValue));
if (formField.getUserValueCount()>0) columnList.add(new Column(formField,false,null)); // add a column for user values, must come after predefined values for algorithm in getColumnValues to work
}
}
columns=columnList.toArray(new Column[columnList.size()]);
}
private Column[] columns=null;
private static class Column {
public FormField formField;
public boolean isBoolean;
public String predefinedValue;
public Column(final FormField formField, final boolean isBoolean, final String predefinedValue) {
this.formField=formField;
this.isBoolean=isBoolean;
this.predefinedValue=predefinedValue;
}
}
/**
* Returns a list of all the {@linkplain FormField#getFormControls() constituent form controls} from all the {@linkplain FormField form fields} in this collection.
* @return a list of all the {@linkplain FormField#getFormControls() constituent form controls} from all the {@linkplain FormField form fields} in this collection.
*/
public List getFormControls() {
return formControls;
}
/**
* Merges the specified <code>FormFields</code> into this <code>FormFields</code> collection.
* This is useful if a full collection of possible form fields is required from multiple {@linkplain Source source} documents.
* <p>
* If both collections contain a <code>FormField</code> with the same {@linkplain FormField#getName() name},
* the resulting <code>FormField</code> has the following properties:
* <ul>
* <li>{@link FormField#getUserValueCount() getUserValueCount()} : the maximum user value count from both form fields</li>
* <li>{@link FormField#allowsMultipleValues() allowsMultipleValues()} : <code>true</code> if either form field allows multiple values</li>
* <li>{@link FormField#getPredefinedValues() getPredefinedValues()} : the union of predefined values in both form fields</li>
* <li>{@link FormField#getFormControls() getFormControls()} : the union of {@linkplain FormControl form controls} from both form fields</li>
* </ul>
* <p>
* NOTE: Some underlying data structures may end up being shared between the two merged <code>FormFields</code> collections.
*/
public void merge(final FormFields formFields) {
for (FormField formField : formFields) {
final String fieldName=formField.getName();
final FormField existingFormField=get(fieldName);
if (existingFormField==null)
map.put(formField.getName(),formField);
else
existingFormField.merge(formField);
}
}
/**
* Returns a string representation of this object useful for debugging purposes.
* @return a string representation of this object useful for debugging purposes.
*/
public String getDebugInfo() {
final StringBuilder sb=new StringBuilder();
for (FormField formField : this) sb.append(formField);
return sb.toString();
}
/**
* Returns a string representation of this object useful for debugging purposes.
* <p>
* This is equivalent to {@link #getDebugInfo()}.
*
* @return a string representation of this object useful for debugging purposes.
*/
public String toString() {
return getDebugInfo();
}
void add(final FormControl formControl) {
add(formControl,formControl.getPredefinedValue());
}
void add(final FormControl formControl, final String predefinedValue) {
add(formControl,predefinedValue,formControl.name);
}
void addName(final FormControl formControl, final String fieldName) {
add(formControl,null,fieldName);
}
void add(final FormControl formControl, final String predefinedValue, String fieldName) {
if (Config.CurrentCompatibilityMode.isFormFieldNameCaseInsensitive()) fieldName=fieldName.toLowerCase();
FormField formField=(FormField)map.get(fieldName);
if (formField==null) {
formField=new FormField(fieldName);
map.put(formField.getName(),formField);
}
formField.addFormControl(formControl,predefinedValue);
}
void replaceInOutputDocument(final OutputDocument outputDocument) {
for (FormControl formControl : formControls) outputDocument.replace(formControl);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -