Skip to content

Commit 00f8e0a

Browse files
AGNT-536 Add support for formnovalidate, richtextarea and datetime (#398)
* AGNT-536 Add support for formnovalidate, richtextarea and datetime * Fix typo
1 parent b5e8fd9 commit 00f8e0a

37 files changed

+908
-85
lines changed

src/main/java/org/symphonyoss/symphony/messageml/MessageMLParser.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import freemarker.template.TemplateExceptionHandler;
1515
import org.apache.commons.io.input.ReaderInputStream;
1616
import org.apache.commons.lang3.StringUtils;
17-
import org.apache.commons.lang3.tuple.ImmutablePair;
1817
import org.apache.commons.lang3.tuple.Pair;
1918
import org.symphonyoss.symphony.messageml.bi.BiContext;
2019
import org.symphonyoss.symphony.messageml.bi.BiFields;
@@ -40,6 +39,7 @@
4039
import org.symphonyoss.symphony.messageml.elements.ExpandableCard;
4140
import org.symphonyoss.symphony.messageml.elements.ExpandableCardBody;
4241
import org.symphonyoss.symphony.messageml.elements.ExpandableCardHeader;
42+
import org.symphonyoss.symphony.messageml.elements.RichTextArea;
4343
import org.symphonyoss.symphony.messageml.elements.Tag;
4444
import org.symphonyoss.symphony.messageml.elements.Form;
4545
import org.symphonyoss.symphony.messageml.elements.FormElement;
@@ -76,6 +76,7 @@
7676
import org.symphonyoss.symphony.messageml.elements.TableRow;
7777
import org.symphonyoss.symphony.messageml.elements.TextArea;
7878
import org.symphonyoss.symphony.messageml.elements.TextField;
79+
import org.symphonyoss.symphony.messageml.elements.DateTime;
7980
import org.symphonyoss.symphony.messageml.elements.TimePicker;
8081
import org.symphonyoss.symphony.messageml.elements.TimezonePicker;
8182
import org.symphonyoss.symphony.messageml.elements.TooltipableElement;
@@ -85,9 +86,6 @@
8586
import org.symphonyoss.symphony.messageml.util.IDataProvider;
8687
import org.symphonyoss.symphony.messageml.util.NoOpEntityResolver;
8788
import org.symphonyoss.symphony.messageml.util.NullErrorHandler;
88-
import org.symphonyoss.symphony.messageml.util.instrument.resolver.InstrumentKind;
89-
import org.symphonyoss.symphony.messageml.util.instrument.resolver.InstrumentResolution;
90-
import org.symphonyoss.symphony.messageml.util.instrument.resolver.ResolutionResults;
9189
import org.w3c.dom.Document;
9290
import org.w3c.dom.Node;
9391
import org.w3c.dom.NodeList;
@@ -107,7 +105,6 @@
107105
import java.util.Optional;
108106
import java.util.Set;
109107
import java.util.stream.Collectors;
110-
import java.util.stream.IntStream;
111108

112109
import javax.xml.parsers.DocumentBuilder;
113110
import javax.xml.parsers.DocumentBuilderFactory;
@@ -638,6 +635,12 @@ public Element createElement(org.w3c.dom.Element element, Element parent) throws
638635
case Tag.MESSAGEML_TAG:
639636
return new Tag(parent, ++index);
640637

638+
case RichTextArea.MESSAGEML_TAG:
639+
return new RichTextArea(parent, messageFormat);
640+
641+
case DateTime.MESSAGEML_TAG:
642+
return new DateTime(parent, ++index);
643+
641644
default:
642645
throw new InvalidInputException("Invalid MessageML content at element \"" + tag + "\"");
643646
}

src/main/java/org/symphonyoss/symphony/messageml/bi/BiFields.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ public enum BiFields {
1010
FORM("form", BiEventType.MESSAGEML_ELEMENT_SENT),
1111
BUTTON("button", BiEventType.MESSAGEML_ELEMENT_SENT),
1212
TEXT_AREA("textarea", BiEventType.MESSAGEML_ELEMENT_SENT),
13+
RICH_TEXT_AREA("richtextarea", BiEventType.MESSAGEML_MESSAGE_SENT),
1314
TEXT_FIELD("textfield", BiEventType.MESSAGEML_ELEMENT_SENT),
1415
CHECKBOX("checkbox", BiEventType.MESSAGEML_ELEMENT_SENT),
1516
RADIO("radio", BiEventType.MESSAGEML_ELEMENT_SENT),
@@ -79,7 +80,8 @@ public enum BiFields {
7980
POPUPS("popups", BiEventType.MESSAGEML_MESSAGE_SENT, "0"),
8081
OPENIM("uiactions_openim", BiEventType.MESSAGEML_MESSAGE_SENT, "0"),
8182
OPENDIALOG("uiactions_opendialog", BiEventType.MESSAGEML_MESSAGE_SENT, "0"),
82-
COUNT("count", BiEventType.NONE, "0");
83+
COUNT("count", BiEventType.NONE, "0"),
84+
DATE_TIME("datetime", BiEventType.MESSAGEML_MESSAGE_SENT, "0");
8385

8486
private final String value;
8587
private final BiEventType type;

src/main/java/org/symphonyoss/symphony/messageml/elements/Button.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.util.Map;
2222
import java.util.Set;
2323

24+
import static org.symphonyoss.symphony.messageml.elements.FormElement.FORMNOVALIDATE_ATTR;
25+
import static org.symphonyoss.symphony.messageml.elements.FormElement.FORMNOVALIDATE_PML_ATTR;
2426
import static org.symphonyoss.symphony.messageml.elements.FormElement.NAME_ATTR;
2527
import static org.symphonyoss.symphony.messageml.elements.FormElement.TYPE_ATTR;
2628

@@ -88,6 +90,18 @@ public void buildAttribute(MessageMLParser parser, Node item) throws InvalidInpu
8890
}
8991
setAttribute(TooltipableElement.DATA_TITLE, getStringAttribute(item));
9092
break;
93+
case FORMNOVALIDATE_ATTR:
94+
if (format != FormatEnum.MESSAGEML) {
95+
throwInvalidInputException(item);
96+
}
97+
setAttribute(FORMNOVALIDATE_ATTR, getStringAttribute(item));
98+
break;
99+
case FORMNOVALIDATE_PML_ATTR:
100+
if (format != FormatEnum.PRESENTATIONML) {
101+
throwInvalidInputException(item);
102+
}
103+
setAttribute(FORMNOVALIDATE_PML_ATTR, getStringAttribute(item));
104+
break;
91105
default:
92106
throwInvalidInputException(item);
93107
}
@@ -103,14 +117,18 @@ void asPresentationML(XmlPrintStream out, MessageMLContext context) {
103117
}
104118

105119
private Map<String, String> getPresentationMLAttributes() {
106-
Map<String, String> attributes = getAttributes();
107-
if (format == FormatEnum.MESSAGEML && attributes.containsKey(TooltipableElement.TITLE)) {
108-
Map<String, String> presentationAttributes = new LinkedHashMap<>(attributes);
109-
presentationAttributes.put(TooltipableElement.DATA_TITLE, attributes.get(TooltipableElement.TITLE));
110-
presentationAttributes.remove(TooltipableElement.TITLE);
111-
return presentationAttributes;
120+
Map<String, String> presentationAttributes = new LinkedHashMap<>(getAttributes());
121+
if (format == FormatEnum.MESSAGEML) {
122+
if (presentationAttributes.containsKey(TooltipableElement.TITLE)) {
123+
presentationAttributes.put(TooltipableElement.DATA_TITLE, presentationAttributes.get(TooltipableElement.TITLE));
124+
presentationAttributes.remove(TooltipableElement.TITLE);
125+
}
126+
if (presentationAttributes.containsKey(FORMNOVALIDATE_ATTR)) {
127+
presentationAttributes.put(FORMNOVALIDATE_PML_ATTR, presentationAttributes.get(FORMNOVALIDATE_ATTR));
128+
presentationAttributes.remove(FORMNOVALIDATE_ATTR);
129+
}
112130
}
113-
return attributes;
131+
return presentationAttributes;
114132
}
115133

116134
@Override

src/main/java/org/symphonyoss/symphony/messageml/elements/Checkbox.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ protected void buildAttribute(MessageMLParser parser,
6666
case LABEL:
6767
case DISABLED_ATTR:
6868
case READONLY_ATTR:
69+
case FORMNOVALIDATE_ATTR:
70+
setAttribute(item.getNodeName(), getStringAttribute(item));
71+
break;
72+
case FORMNOVALIDATE_PML_ATTR:
73+
if(this.format != FormatEnum.PRESENTATIONML){
74+
throwInvalidInputException(item);
75+
}
6976
setAttribute(item.getNodeName(), getStringAttribute(item));
7077
break;
7178
case ID_ATTR:

src/main/java/org/symphonyoss/symphony/messageml/elements/DatePicker.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ protected void buildAttribute(MessageMLParser parser, Node item) throws InvalidI
7272
case DISABLED_DATE_ATTR:
7373
case HIGHLIGHTED_DATE_ATTR:
7474
case FORMAT_ATTR:
75+
case FORMNOVALIDATE_ATTR:
7576
if (this.format != FormatEnum.MESSAGEML) {
7677
throwInvalidInputException(item);
7778
}
@@ -82,6 +83,7 @@ protected void buildAttribute(MessageMLParser parser, Node item) throws InvalidI
8283
case PRESENTATIONML_DISABLED_DATE_ATTR:
8384
case PRESENTATIONML_HIGHLIGHTED_DATE_ATTR:
8485
case PRESENTATIONML_FORMAT_ATTR:
86+
case FORMNOVALIDATE_PML_ATTR:
8587
if (this.format != FormatEnum.PRESENTATIONML) {
8688
throwInvalidInputException(item);
8789
}
@@ -203,6 +205,12 @@ private Map<String, Object> buildDataPickerInputAttributes() {
203205
if (getAttribute(PRESENTATIONML_FORMAT_ATTR) != null) {
204206
presentationAttrs.put(PRESENTATIONML_FORMAT_ATTR, getAttribute(PRESENTATIONML_FORMAT_ATTR));
205207
}
208+
if (getAttribute(FORMNOVALIDATE_ATTR) != null) {
209+
presentationAttrs.put(FORMNOVALIDATE_PML_ATTR, getAttribute(FORMNOVALIDATE_ATTR));
210+
}
211+
if(getAttribute(FORMNOVALIDATE_PML_ATTR) != null) {
212+
presentationAttrs.put(FORMNOVALIDATE_PML_ATTR, getAttribute(FORMNOVALIDATE_ATTR));
213+
}
206214
return presentationAttrs;
207215
}
208216

src/main/java/org/symphonyoss/symphony/messageml/elements/DateSelector.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ protected void buildAttribute(MessageMLParser parser,
9595
case REQUIRED_ATTR:
9696
setAttribute(REQUIRED_ATTR, getStringAttribute(item));
9797
break;
98+
case FORMNOVALIDATE_ATTR:
99+
setAttribute(FORMNOVALIDATE_ATTR, getStringAttribute(item));
100+
break;
98101
default:
99102
throwInvalidInputException(item);
100103
}
@@ -131,6 +134,10 @@ private Map<String, String> buildDateSelectorInputAttributes() {
131134
presentationAttrs.put(PRESENTATIONML_REQUIRED_ATTR, getAttribute(REQUIRED_ATTR));
132135
}
133136

137+
if(getAttribute(FORMNOVALIDATE_ATTR) != null) {
138+
presentationAttrs.put(FORMNOVALIDATE_PML_ATTR, getAttribute(FORMNOVALIDATE_ATTR));
139+
}
140+
134141
return presentationAttrs;
135142
}
136143

@@ -149,6 +156,11 @@ void buildElementFromDiv(MessageMLParser parser, org.w3c.dom.Element element) th
149156
element.removeAttribute(PRESENTATIONML_REQUIRED_ATTR);
150157
}
151158

159+
if (element.hasAttribute(FORMNOVALIDATE_PML_ATTR)) {
160+
element.setAttribute(FORMNOVALIDATE_ATTR, element.getAttribute(FORMNOVALIDATE_PML_ATTR));
161+
element.removeAttribute(FORMNOVALIDATE_PML_ATTR);
162+
}
163+
152164
NamedNodeMap attributes = element.getAttributes();
153165

154166
for (int i = 0; i < attributes.getLength(); i++) {
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
package org.symphonyoss.symphony.messageml.elements;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
5+
import com.fasterxml.jackson.databind.node.ObjectNode;
6+
import org.commonmark.node.Node;
7+
import org.symphonyoss.symphony.messageml.MessageMLContext;
8+
import org.symphonyoss.symphony.messageml.MessageMLParser;
9+
import org.symphonyoss.symphony.messageml.bi.BiContext;
10+
import org.symphonyoss.symphony.messageml.bi.BiFields;
11+
import org.symphonyoss.symphony.messageml.bi.BiItem;
12+
import org.symphonyoss.symphony.messageml.exceptions.InvalidInputException;
13+
import org.symphonyoss.symphony.messageml.markdown.nodes.DateTimeNode;
14+
import org.symphonyoss.symphony.messageml.util.XmlPrintStream;
15+
16+
import java.time.format.DateTimeFormatter;
17+
import java.util.Arrays;
18+
import java.util.Collections;
19+
import java.util.HashMap;
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
/**
24+
* MessageML entity that allows to display a time following local time zone and user preference
25+
* Fields:
26+
* * value : time value according to ISO 8601 with date, time and timezone
27+
* * example: 2024-12-31T09:29:47Z
28+
* * format: which format to use to display the date
29+
* * available values: date, time, date_time, time_secs
30+
*/
31+
public class DateTime extends Entity {
32+
public static final String MESSAGEML_TAG = "dateTime";
33+
private static final String PRESENTATIONML_TAG = "time";
34+
35+
private static final String ENTITY_TYPE = "org.symphonyoss";
36+
private static final String ENTITY_SUBTYPE = "org.symphonyoss.datetime";
37+
private static final String ENTITY_VERSION = "1.0";
38+
private static final String ENTITY_ID_PREFIX = "datetime";
39+
40+
private static final String ATTR_VALUE = "value";
41+
private static final String ATTR_FORMAT = "format";
42+
43+
private static final String ATTR_PML_FORMAT = "data-format";
44+
private static final String ATTR_PML_VALUE = "datetime";
45+
46+
private static final String DATA_NODE = "data";
47+
48+
private static List<String> VALID_DATE_FORMATS = Arrays.asList("date_time", "date", "time", "time_secs");
49+
50+
private String value;
51+
private String dateFormat;
52+
53+
54+
public DateTime(Element parent, int entityIndex) {
55+
super(parent, MESSAGEML_TAG, PRESENTATIONML_TAG, FormatEnum.MESSAGEML);
56+
this.entityId = getEntityId(entityIndex);
57+
}
58+
59+
@Override
60+
protected String getEntityValue() {
61+
return value;
62+
}
63+
64+
@Override
65+
protected String getEntitySubType() {
66+
return ENTITY_SUBTYPE;
67+
}
68+
69+
@Override
70+
protected String getEntityVersion() {
71+
return ENTITY_VERSION;
72+
}
73+
74+
@Override
75+
protected String getEntityType() {
76+
return ENTITY_TYPE;
77+
}
78+
79+
@Override
80+
protected String getEntityIdPrefix() {
81+
return ENTITY_ID_PREFIX;
82+
}
83+
84+
@Override
85+
public void validate() throws InvalidInputException {
86+
super.validate();
87+
88+
assertAttributeNotBlank(ATTR_VALUE);
89+
assertDateFormat(ATTR_VALUE, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
90+
91+
if (getAttribute(ATTR_FORMAT) != null) {
92+
assertAttributeValue(ATTR_FORMAT, VALID_DATE_FORMATS);
93+
}
94+
95+
}
96+
97+
@Override
98+
protected void buildAttribute(MessageMLParser parser,
99+
org.w3c.dom.Node item) throws InvalidInputException {
100+
switch (item.getNodeName()) {
101+
case ATTR_VALUE:
102+
this.value = getStringAttribute(item);
103+
setAttribute(ATTR_VALUE, this.value);
104+
break;
105+
case ATTR_FORMAT:
106+
this.dateFormat = getStringAttribute(item);
107+
setAttribute(ATTR_FORMAT, dateFormat);
108+
break;
109+
default:
110+
throw new InvalidInputException( "Attribute \"" + item.getNodeName() + "\" is not allowed in \"" + getMessageMLTag() + "\"");
111+
}
112+
}
113+
114+
115+
@Override
116+
public void asPresentationML(XmlPrintStream out, MessageMLContext context) {
117+
Map<String, String> attributes = new HashMap<>();
118+
attributes.put(ENTITY_ID_ATTR, entityId);
119+
120+
if (getAttribute(ATTR_FORMAT) != null) {
121+
attributes.put(ATTR_PML_FORMAT, getAttribute(ATTR_FORMAT));
122+
}
123+
attributes.put(ATTR_PML_VALUE, getAttribute(ATTR_VALUE));
124+
out.printElement(PRESENTATIONML_TAG, value, attributes);
125+
}
126+
127+
@Override
128+
Node asMarkdown() throws InvalidInputException {
129+
return new DateTimeNode(entityId, value, dateFormat);
130+
}
131+
132+
@Override
133+
public ObjectNode asEntityJson(ObjectNode parent) {
134+
JsonNode entityNode = parent.path(entityId);
135+
136+
if (entityNode.isMissingNode()) {
137+
ObjectNode node = new ObjectNode(JsonNodeFactory.instance);
138+
node.put(Entity.TYPE_FIELD, getEntityType());
139+
node.put(Entity.VERSION_FIELD, getEntityVersion());
140+
141+
ObjectNode dataNode = new ObjectNode(JsonNodeFactory.instance);
142+
dataNode.put(Entity.VALUE_FIELD, value);
143+
dataNode.put(Entity.TYPE_FIELD, getEntitySubType());
144+
dataNode.put(ATTR_FORMAT, dateFormat);
145+
146+
node.set(DATA_NODE, dataNode);
147+
148+
parent.set(entityId, node);
149+
150+
return node;
151+
152+
} else {
153+
//For preexisting data-entity-id the node type has already been validated by MessageMLParser
154+
return (ObjectNode) entityNode;
155+
}
156+
}
157+
158+
@Override
159+
public void updateBiContext(BiContext context) {
160+
super.updateBiContext(context);
161+
context.updateItemCount(BiFields.DATE_TIME.getValue());
162+
context.addItem(new BiItem(BiFields.ENTITY.getValue(),
163+
Collections.singletonMap(BiFields.ENTITY_TYPE.getValue(), this.getEntitySubType())));
164+
}
165+
}

src/main/java/org/symphonyoss/symphony/messageml/elements/FormElement.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,16 @@
22

33
import org.symphonyoss.symphony.messageml.exceptions.InvalidInputException;
44

5+
import java.util.Arrays;
56
import java.util.Collections;
7+
import java.util.List;
68

79
public class FormElement extends Element {
810
public static final String INPUT_TAG = "input";
911
public static final String TYPE_ATTR = "type";
12+
public static final String FORMNOVALIDATE_ATTR = "formnovalidate";
13+
public static final String FORMNOVALIDATE_PML_ATTR = "data-formnovalidate";
14+
1015

1116
protected static final String NAME_ATTR = "name";
1217

@@ -21,6 +26,12 @@ public FormElement(Element parent, String messageMLTag, FormatEnum format) {
2126
@Override
2227
public void validate() throws InvalidInputException {
2328
super.validate();
29+
if (getAttribute(FORMNOVALIDATE_ATTR) != null) {
30+
assertAttributeIsBoolean(FORMNOVALIDATE_ATTR);
31+
}
32+
if (getAttribute(FORMNOVALIDATE_PML_ATTR) != null) {
33+
assertAttributeIsBoolean(FORMNOVALIDATE_PML_ATTR);
34+
}
2435
assertParentAtAnyLevel(Collections.singleton(Form.class));
2536
}
2637
}

0 commit comments

Comments
 (0)