Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FormField#getDisplayType (fixes #393) #394

Merged
merged 1 commit into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ public interface FormField {
public enum Kind {
COMPUTED, COMPUTEDFORDISPLAY, COMPUTEDWHENCOMPOSED, EDITABLE
}

public enum Type {
TEXT, DATETIME, NUMBER, DIALOGLIST, CHECKBOX, RADIOBUTTON, LISTBOX, COMBOBOX,
RICHTEXT, AUTHORS, NAMES, READERS, PASSWORD, FORMULA, TIMEZONE, RICHTEXTLITE,
COLOR
}

/**
* Returns the field data type
Expand Down Expand Up @@ -159,4 +165,12 @@ public enum Kind {
* @since 1.27.0
*/
Kind getKind();

/**
* Determines the display type of the field.
*
* @return a {@link Type} value for the field
* @since 1.27.0
*/
Type getDisplayType();
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,15 @@ public Short getValue() {

@StructureGetter("Flags1")
Set<Flag> getFlags1();

@StructureGetter("Flags1")
int getFlags1Raw();

@StructureGetter("Flags2")
Set<Flag2> getFlags2();

@StructureGetter("Flags2")
int getFlags2Raw();

@StructureGetter("Header")
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public List<FormField> getFields() {
} else if (record instanceof CDIDName) {
fieldStructs.add(record);
} else if (record instanceof CDColor) {
// Don't close fields on COLOR
fieldStructs.add(record);
} else if (record instanceof CDDataFlags) {
if (foundFieldBegin.get()) {
fieldStructs.add(record);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import java.util.stream.Collectors;
import com.hcl.domino.data.ItemDataType;
import com.hcl.domino.design.format.FieldListDelimiter;
import com.hcl.domino.design.format.FieldListDisplayDelimiter;
import com.hcl.domino.richtext.FormField;
import com.hcl.domino.richtext.records.CDColor;
import com.hcl.domino.richtext.records.CDDataFlags;
import com.hcl.domino.richtext.records.CDExtField;
import com.hcl.domino.richtext.records.CDIDName;
import com.hcl.domino.richtext.records.ICDField;
import com.hcl.domino.richtext.records.RichTextRecord;
Expand Down Expand Up @@ -223,4 +226,92 @@ public Kind getKind() {
})
.orElseThrow(() -> new IllegalStateException("Unable to find kind in field structs"));
}

@Override
public Type getDisplayType() {
Optional<ItemDataType> dataType = getDataType();
if(dataType.isPresent()) {
switch(dataType.get()) {
case TYPE_TIME:
case TYPE_TIME_RANGE:
return Type.DATETIME;
case TYPE_NUMBER:
case TYPE_NUMBER_RANGE:
return Type.NUMBER;
case TYPE_COMPOSITE:
// In this case, look for record of type 62 for Rich Text Lite
List<CDDataFlags> dataFlags = this.structs.stream()
.filter(s -> s instanceof CDDataFlags)
.map(CDDataFlags.class::cast)
.collect(Collectors.toList());
for(CDDataFlags dataFlag : dataFlags) {
Optional<CDDataFlags.ElementType> elemType = dataFlag.getElementType();
if(elemType.isPresent() && elemType.get().equals(CDDataFlags.ElementType.FIELDLIMIT)) {
return Type.RICHTEXTLITE;
}
}
return Type.RICHTEXT;
case TYPE_FORMULA:
return Type.FORMULA;
case TYPE_USERID:
return Type.AUTHORS;
default:
// Continue below for text UI types
break;
}
}

Set<ICDField.Flag> flags = this.structs.stream()
.filter(s -> s instanceof ICDField)
.map(ICDField.class::cast)
.findFirst()
.map(ICDField::getFlags)
.orElseThrow(() -> new IllegalStateException("Unable to find flags in field structs"));
Optional<CDExtField> extField = this.structs.stream()
.filter(s -> s instanceof CDExtField)
.findFirst()
.map(CDExtField.class::cast);

if(flags.contains(ICDField.Flag.KEYWORDS)) {
if(flags.contains(ICDField.Flag.KEYWORDS_UI_CHECKBOX)) {
return Type.CHECKBOX;
} else if(flags.contains(ICDField.Flag.KEYWORDS_UI_RADIOBUTTON)) {
return Type.RADIOBUTTON;
}

if(extField.isPresent()) {
Set<CDExtField.Flag> extFlags = extField.get().getFlags1();
if(extFlags.contains(CDExtField.Flag.KEYWORDS_UI_COMBO)) {
return Type.COMBOBOX;
} else if(extFlags.contains(CDExtField.Flag.KEYWORDS_UI_LIST)) {
return Type.LISTBOX;
}
}

return Type.DIALOGLIST;
}

if(flags.contains(ICDField.Flag.READERS)) {
return Type.READERS;
} else if(flags.contains(ICDField.Flag.READWRITERS)) {
return Type.AUTHORS;
} else if(flags.contains(ICDField.Flag.NAMES)) {
return Type.NAMES;
}

if(extField.isPresent()) {
Set<CDExtField.Flag2> extFlags2 = extField.get().getFlags2();
if(extFlags2.contains(CDExtField.Flag2.PASSWORD)) {
return Type.PASSWORD;
} else if(extFlags2.contains(CDExtField.Flag2.TIMEZONE)) {
return Type.TIMEZONE;
}
}

if(this.structs.stream().anyMatch(CDColor.class::isInstance)) {
return Type.COLOR;
}

return Type.TEXT;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1839,41 +1839,118 @@ public void testDbDesignComputedFields() throws Exception {
List<FormField> fields = form.getFields();

{
FormField field = fields.stream()
.filter(f -> "NormalField".equals(f.getName()))
.findFirst()
.get();
FormField field = getField(fields, "NormalField");
assertEquals(FormField.Kind.EDITABLE, field.getKind());
}
{
FormField field = fields.stream()
.filter(f -> "ComputedWhenComposed".equals(f.getName()))
.findFirst()
.get();
FormField field = getField(fields, "ComputedWhenComposed");
assertEquals(FormField.Kind.COMPUTEDWHENCOMPOSED, field.getKind());
}
{
FormField field = fields.stream()
.filter(f -> "ComputedForDisplay".equals(f.getName()))
.findFirst()
.get();
FormField field = getField(fields, "ComputedForDisplay");
assertEquals(FormField.Kind.COMPUTEDFORDISPLAY, field.getKind());
}
{
FormField field = fields.stream()
.filter(f -> "Computed".equals(f.getName()))
.findFirst()
.get();
FormField field = getField(fields, "Computed");
assertEquals(FormField.Kind.COMPUTED, field.getKind());
}
});
}

@Test
public void testFieldTypes() throws Exception {
withResourceDxl("/dxl/testDbDesignForms", database -> {
Form form = database.getDesign().getForm("Field Types Form").get();

List<FormField> fields = form.getFields();

{
FormField field = getField(fields, "Text");
assertEquals(FormField.Type.TEXT, field.getDisplayType());
}
{
FormField field = getField(fields, "DateTime");
assertEquals(FormField.Type.DATETIME, field.getDisplayType());
}
{
FormField field = getField(fields, "Number");
assertEquals(FormField.Type.NUMBER, field.getDisplayType());
}
{
FormField field = getField(fields, "DialogList");
assertEquals(FormField.Type.DIALOGLIST, field.getDisplayType());
}
{
FormField field = getField(fields, "Checkbox");
assertEquals(FormField.Type.CHECKBOX, field.getDisplayType());
}
{
FormField field = getField(fields, "RadioButton");
assertEquals(FormField.Type.RADIOBUTTON, field.getDisplayType());
}
{
FormField field = getField(fields, "ListBox");
assertEquals(FormField.Type.LISTBOX, field.getDisplayType());
}
{
FormField field = getField(fields, "ComboBox");
assertEquals(FormField.Type.COMBOBOX, field.getDisplayType());
}
{
FormField field = getField(fields, "RichText");
assertEquals(FormField.Type.RICHTEXT, field.getDisplayType());
}
{
FormField field = getField(fields, "Authors");
assertEquals(FormField.Type.AUTHORS, field.getDisplayType());
}
{
FormField field = getField(fields, "AuthorsMulti");
assertEquals(FormField.Type.AUTHORS, field.getDisplayType());
}
{
FormField field = getField(fields, "Names");
assertEquals(FormField.Type.NAMES, field.getDisplayType());
}
{
FormField field = getField(fields, "Readers");
assertEquals(FormField.Type.READERS, field.getDisplayType());
}
{
FormField field = getField(fields, "Password");
assertEquals(FormField.Type.PASSWORD, field.getDisplayType());
}
{
FormField field = getField(fields, "Formula");
assertEquals(FormField.Type.FORMULA, field.getDisplayType());
}
{
FormField field = getField(fields, "TimeZone");
assertEquals(FormField.Type.TIMEZONE, field.getDisplayType());
}
{
FormField field = getField(fields, "RichTextLite");
assertEquals(FormField.Type.RICHTEXTLITE, field.getDisplayType());
}
{
FormField field = getField(fields, "Color");
assertEquals(FormField.Type.COLOR, field.getDisplayType());
}
});
}

// *******************************************************************************
// * Internal utility methods
// *******************************************************************************

private List<?> extractOle(List<?> body, int index) {
return extract(body, index, CDOLEBegin.class, CDOLEEnd.class);
}

private FormField getField(List<FormField> fields, String fieldName) {
return fields.stream()
.filter(f -> fieldName.equals(f.getName()))
.findFirst()
.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version='1.0' encoding='utf-8'?>
<form name='Field Types Form' xmlns='http://www.lotus.com/dxl' version='12.0'
publicaccess='false' designerversion='8.5.3' renderpassthrough='true'>
<body><richtext>
<pardef id='1'/>
<par def='1'><field type='text' kind='editable' name='Text'/><compositedata
type='98' prevtype='65418' nexttype='222' afterparcount='7' containertype='65418'
aftercontainercount='1' afterbegincount='3'>
Yg4BAIQAAAAAAAAAAAA=
</compositedata></par>
<par def='1'><field type='datetime' kind='editable' name='DateTime'><datetimeformat
show='date' date='yearmonthday' fourdigityearfor21stcentury='true' zone='never'
dateformat='weekdaymonthdayyear' dayformat='twodigitday' monthformat='twodigitmonth'
yearformat='fourdigityear' weekdayformat='shortname' dateseparator1=' ' dateseparator2='/'
dateseparator3='/' timeseparator=':' preference='usersetting'/></field></par>
<par def='1'><field type='number' kind='editable' name='Number'><numberformat
format='general' digits='2' punctuated='false' parens='false' percent='false'
bytes='false'/></field></par>
<par def='1'><field type='keyword' kind='editable' name='DialogList'><keywords
ui='dialoglist'/></field></par>
<par def='1'><field borderstyle='inset' lookupeachchar='false' lookupaddressonrefresh='false'
type='keyword' allowmultivalues='true' kind='editable' name='Checkbox' listinputseparators='comma'
listdisplayseparator='comma'><keywords helperbutton='false' columns='1' ui='checkbox'/></field></par>
<par def='1'><field borderstyle='inset' lookupeachchar='false' lookupaddressonrefresh='false'
type='keyword' kind='editable' name='RadioButton'><keywords helperbutton='false'
columns='1' ui='radiobutton'/></field></par>
<par def='1'><field usenotesstyle='false' height='0.2500in' width='1in' multiline='true'
borderstyle='single' lookupeachchar='false' lookupaddressonrefresh='false'
type='keyword' kind='editable' name='ListBox'><keywords helperbutton='false'
columns='1' ui='listbox'/></field></par>
<par def='1'><field usenotesstyle='false' height='0.2500in' width='1in' multiline='true'
borderstyle='inset' lookupeachchar='false' lookupaddressonrefresh='false'
type='keyword' kind='editable' name='ComboBox'><keywords helperbutton='false'
columns='1' ui='combobox'/></field></par>
<par def='1'><field type='richtext' kind='editable' name='RichText'/><compositedata
type='98' prevtype='65418' nexttype='222' afterparcount='6' containertype='65418'
aftercontainercount='1' afterbegincount='3'>
Yg4BAIQAAAAAAAEAAAA=
</compositedata></par>
<par def='1'><field type='authors' kind='editable' name='Authors'/></par>
<par def='1'><field type='authors' allowmultivalues='true' kind='editable'
name='AuthorsMulti' listinputseparators='comma' listdisplayseparator='comma'/></par>
<par def='1'><field type='names' kind='editable' name='Names'/></par>
<par def='1'><field type='readers' kind='editable' name='Readers'/></par>
<par def='1'><field type='password' kind='editable' seal='true' name='Password'/></par>
<par def='1'><field literalize='true' type='formula' name='Formula' listdisplayseparator='semicolon'><code
event='defaultvalue'><formula>""</formula></code></field></par>
<par def='1'><field type='timezone' usenotesstyle='false' height='0.2500in'
width='1in' multiline='true' borderstyle='single' kind='editable' name='TimeZone'/></par>
<par def='1'><field type='richtextlite' kind='editable' name='RichTextLite'
onlyallow='picture sharedimage attachment graphicsignature view datepicker sharedapplet text object calendar inbox help clear graphic link'
firstdisplay='text'/><compositedata type='98' prevtype='65418' nexttype='98'
afterparcount='7' containertype='65418' aftercontainercount='1' afterbegincount='4'>
Yg4BAIQAAAAAAAEAAAA=
</compositedata></par>
<par def='1'><field type='color' usenotesstyle='false' height='0.2500in' width='1in'
multiline='true' borderstyle='single' kind='editable' name='Color'/></par></richtext></body>
<item name='$$ScriptName' summary='false' sign='true'><text>Field Types Form</text></item>
<item name='Number' summary='false'><number>0</number></item></form>
Loading