mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 14:22:05 +01:00
Support for XEP-0122: Data Forms Validation.
Data Forms Validation are a part of Data Fields and implemented as extensions, added to a Datafield. Data validation extensions are validated before adding to the message, using the consistency rules as described in the XEP. Fixes SMACK-621. Minor modifications done by Florian Schmaus <flo@geekplace.eu>
This commit is contained in:
parent
019b9dc5d4
commit
b08dbc1dbc
13 changed files with 943 additions and 66 deletions
|
@ -48,6 +48,7 @@ Smack Extensions and currently supported XEPs by Smack (smack-extensions)
|
||||||
| Stream Initation | [XEP-0095](http://xmpp.org/extensions/xep-0095.html) | Initiating a data stream between any two XMPP entities. |
|
| Stream Initation | [XEP-0095](http://xmpp.org/extensions/xep-0095.html) | Initiating a data stream between any two XMPP entities. |
|
||||||
| [SI File Transfer](filetransfer.html) | [XEP-0096](http://xmpp.org/extensions/xep-0096.html) | Transfer files between two users over XMPP. |
|
| [SI File Transfer](filetransfer.html) | [XEP-0096](http://xmpp.org/extensions/xep-0096.html) | Transfer files between two users over XMPP. |
|
||||||
| [Entity Capabilities](caps.html) | [XEP-0115](http://xmpp.org/extensions/xep-0115.html) | Broadcasting and dynamic discovery of entity capabilities. |
|
| [Entity Capabilities](caps.html) | [XEP-0115](http://xmpp.org/extensions/xep-0115.html) | Broadcasting and dynamic discovery of entity capabilities. |
|
||||||
|
| Data Forms Validation | [XEP-0122](http://xmpp.org/extensions/xep-0122.html) | Enables an application to specify additional validation guidelines . |
|
||||||
| Stream Compression | [XEP-0138](http://xmpp.org/extensions/xep-0138.html) | Support for optional compression of the XMPP stream.
|
| Stream Compression | [XEP-0138](http://xmpp.org/extensions/xep-0138.html) | Support for optional compression of the XMPP stream.
|
||||||
| Data Forms Layout | [XEP-0141](http://xmpp.org/extensions/xep-0141.html) | Enables an application to specify form layouts. |
|
| Data Forms Layout | [XEP-0141](http://xmpp.org/extensions/xep-0141.html) | Enables an application to specify form layouts. |
|
||||||
| Personal Eventing Protocol | [XEP-0163](http://xmpp.org/extensions/xep-0163.html) | Using the XMPP publish-subscribe protocol to broadcast state change events associated with a XMPP account. |
|
| Personal Eventing Protocol | [XEP-0163](http://xmpp.org/extensions/xep-0163.html) | Using the XMPP publish-subscribe protocol to broadcast state change events associated with a XMPP account. |
|
||||||
|
|
|
@ -206,14 +206,14 @@ public class XmlStringBuilder implements Appendable, CharSequence {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the given attribute if value => 0
|
* Add the given attribute if value not null and value => 0.
|
||||||
*
|
*
|
||||||
* @param name
|
* @param name
|
||||||
* @param value
|
* @param value
|
||||||
* @return a reference to this object
|
* @return a reference to this object
|
||||||
*/
|
*/
|
||||||
public XmlStringBuilder optLongAttribute(String name, Long value) {
|
public XmlStringBuilder optLongAttribute(String name, Long value) {
|
||||||
if (value >= 0) {
|
if (value != null && value >= 0) {
|
||||||
attribute(name, Long.toString(value));
|
attribute(name, Long.toString(value));
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
|
|
|
@ -17,12 +17,13 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.xdata;
|
package org.jivesoftware.smackx.xdata;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a field of a form. The field could be used to represent a question to complete,
|
* Represents a field of a form. The field could be used to represent a question to complete,
|
||||||
* a completed question or a data returned from a search. The exact interpretation of the field
|
* a completed question or a data returned from a search. The exact interpretation of the field
|
||||||
|
@ -124,6 +125,7 @@ public class FormField {
|
||||||
private Type type;
|
private Type type;
|
||||||
private final List<Option> options = new ArrayList<Option>();
|
private final List<Option> options = new ArrayList<Option>();
|
||||||
private final List<String> values = new ArrayList<String>();
|
private final List<String> values = new ArrayList<String>();
|
||||||
|
private ValidateElement validateElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new FormField with the variable name that uniquely identifies the field
|
* Creates a new FormField with the variable name that uniquely identifies the field
|
||||||
|
@ -219,6 +221,13 @@ public class FormField {
|
||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the validateElement
|
||||||
|
*/
|
||||||
|
public ValidateElement getValidateElement() {
|
||||||
|
return validateElement;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a description that provides extra clarification about the question. This information
|
* Sets a description that provides extra clarification about the question. This information
|
||||||
* could be presented to the user either in tool-tip, help button, or as a section of text
|
* could be presented to the user either in tool-tip, help button, or as a section of text
|
||||||
|
@ -251,6 +260,14 @@ public class FormField {
|
||||||
this.required = required;
|
this.required = required;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param validateElement the validateElement to set
|
||||||
|
*/
|
||||||
|
public void setValidateElement(ValidateElement validateElement) {
|
||||||
|
validateElement.checkConsistency(this);
|
||||||
|
this.validateElement = validateElement;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an indicative of the format for the data to answer.
|
* Sets an indicative of the format for the data to answer.
|
||||||
*
|
*
|
||||||
|
@ -325,6 +342,7 @@ public class FormField {
|
||||||
for (Option option : getOptions()) {
|
for (Option option : getOptions()) {
|
||||||
buf.append(option.toXML());
|
buf.append(option.toXML());
|
||||||
}
|
}
|
||||||
|
buf.optElement(validateElement);
|
||||||
buf.closeElement(ELEMENT);
|
buf.closeElement(ELEMENT);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ import org.jivesoftware.smackx.xdata.FormField;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout;
|
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout;
|
||||||
import org.jivesoftware.smackx.xdatalayout.provider.DataLayoutProvider;
|
import org.jivesoftware.smackx.xdatalayout.provider.DataLayoutProvider;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.provider.DataValidationProvider;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
@ -102,6 +104,7 @@ public class DataFormProvider extends PacketExtensionProvider<DataForm> {
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case XmlPullParser.START_TAG:
|
case XmlPullParser.START_TAG:
|
||||||
String name = parser.getName();
|
String name = parser.getName();
|
||||||
|
String namespace = parser.getNamespace();
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case "desc":
|
case "desc":
|
||||||
formField.setDescription(parser.nextText());
|
formField.setDescription(parser.nextText());
|
||||||
|
@ -115,6 +118,12 @@ public class DataFormProvider extends PacketExtensionProvider<DataForm> {
|
||||||
case "option":
|
case "option":
|
||||||
formField.addOption(parseOption(parser));
|
formField.addOption(parseOption(parser));
|
||||||
break;
|
break;
|
||||||
|
// See XEP-122 Data Forms Validation
|
||||||
|
case ValidateElement.ELEMENT:
|
||||||
|
if (namespace.equals(ValidateElement.NAMESPACE)) {
|
||||||
|
formField.setValidateElement(DataValidationProvider.parse(parser));
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case XmlPullParser.END_TAG:
|
case XmlPullParser.END_TAG:
|
||||||
if (parser.getDepth() == initialDepth) {
|
if (parser.getDepth() == initialDepth) {
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 Anno van Vliet
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.xdatavalidation;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when {@link ValidateElement} is not consistent with the business rules in XEP=0122.
|
||||||
|
*
|
||||||
|
* @author Anno van Vliet
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ValidationConsistencyException extends IllegalArgumentException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public ValidationConsistencyException(String message) {
|
||||||
|
super( message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 Anno van Vliet
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.xdatavalidation;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPConnectionRegistry;
|
||||||
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
|
||||||
|
public class XDataValidationManager {
|
||||||
|
|
||||||
|
static {
|
||||||
|
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
|
||||||
|
@Override
|
||||||
|
public void connectionCreated(XMPPConnection connection) {
|
||||||
|
ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||||
|
serviceDiscoveryManager.addFeature(ValidateElement.NAMESPACE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,436 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 Anno van Vliet
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.xdatavalidation.packet;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.NamedElement;
|
||||||
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.ValidationConsistencyException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataValidation Extension according to XEP-0122: Data Forms Validation. This specification defines a
|
||||||
|
* backwards-compatible extension to the XMPP Data Forms protocol that enables applications to specify additional
|
||||||
|
* validation guidelines related to a {@link FormField} in a {@link DataForm}, such as validation of standard XML
|
||||||
|
* datatypes, application-specific datatypes, value ranges, and regular expressions.
|
||||||
|
*
|
||||||
|
* @author Anno van Vliet
|
||||||
|
*/
|
||||||
|
public abstract class ValidateElement implements PacketExtension {
|
||||||
|
|
||||||
|
public static final String DATATYPE_XS_STRING = "xs:string";
|
||||||
|
public static final String ELEMENT = "validate";
|
||||||
|
public static final String NAMESPACE = "http://jabber.org/protocol/xdata-validate";
|
||||||
|
|
||||||
|
private final String datatype;
|
||||||
|
|
||||||
|
private ListRange listRange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The 'datatype' attribute specifies the datatype. This attribute is OPTIONAL, and when not specified, defaults to
|
||||||
|
* "xs:string".
|
||||||
|
*
|
||||||
|
* @param datatype the data type of any value contained within the {@link FormField} element.
|
||||||
|
*/
|
||||||
|
private ValidateElement(String datatype) {
|
||||||
|
this.datatype = StringUtils.isNotEmpty(datatype) ? datatype : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the data type of any value contained within the {@link FormField} element. It MUST meet one of the
|
||||||
|
* following conditions:
|
||||||
|
* <ul>
|
||||||
|
* <li>Start with "xs:", and be one of the "built-in" datatypes defined in XML Schema Part 2 <a
|
||||||
|
* href="http://www.xmpp.org/extensions/xep-0122.html#nt-idp1476016">[2]</a></li>
|
||||||
|
* <li>Start with a prefix registered with the XMPP Registrar <a
|
||||||
|
* href="http://www.xmpp.org/extensions/xep-0122.html#nt-idp1478544">[3]</a></li>
|
||||||
|
* <li>Start with "x:", and specify a user-defined datatype <a
|
||||||
|
* href="http://www.xmpp.org/extensions/xep-0122.html#nt-idp1477360">[4]</a></li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @return the datatype
|
||||||
|
*/
|
||||||
|
public String getDatatype() {
|
||||||
|
return datatype != null ? datatype : DATATYPE_XS_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getElementName() {
|
||||||
|
return ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getNamespace() {
|
||||||
|
return NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XmlStringBuilder toXML() {
|
||||||
|
XmlStringBuilder buf = new XmlStringBuilder(this);
|
||||||
|
buf.optAttribute("datatype", datatype);
|
||||||
|
buf.rightAngleBracket();
|
||||||
|
appendXML(buf);
|
||||||
|
buf.optAppend(getListRange());
|
||||||
|
buf.closeElement(this);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param buf
|
||||||
|
*/
|
||||||
|
protected abstract void appendXML(XmlStringBuilder buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param listRange the listRange to set
|
||||||
|
*/
|
||||||
|
public void setListRange(ListRange listRange) {
|
||||||
|
this.listRange = listRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the listRange
|
||||||
|
*/
|
||||||
|
public ListRange getListRange() {
|
||||||
|
return listRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this element is consistent according to the business rules in XEP=0122
|
||||||
|
*
|
||||||
|
* @param formField
|
||||||
|
*/
|
||||||
|
public abstract void checkConsistency(FormField formField);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* This defines the empty validate element that does only specify a 'datatype' attribute.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static class EmptyValidateElement extends ValidateElement {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dataType
|
||||||
|
* @see #getDatatype()
|
||||||
|
*/
|
||||||
|
public EmptyValidateElement(String dataType) {
|
||||||
|
super(dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendXML(XmlStringBuilder buf) {
|
||||||
|
// The empty validate element does not contain any further elements or text, it is empty.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkConsistency(FormField formField) {
|
||||||
|
// Since we can't know all possible datatypes, we can not perform any validation here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation only against the datatype itself. Indicates that the value(s) should simply match the field type and
|
||||||
|
* datatype constraints.
|
||||||
|
*
|
||||||
|
* @see ValidateElement
|
||||||
|
*/
|
||||||
|
public static class BasicValidateElement extends ValidateElement {
|
||||||
|
|
||||||
|
public static final String METHOD = "basic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dataType
|
||||||
|
* @see #getDatatype()
|
||||||
|
*/
|
||||||
|
public BasicValidateElement(String dataType) {
|
||||||
|
super(dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendXML(XmlStringBuilder buf) {
|
||||||
|
buf.emptyElement(METHOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkConsistency(FormField formField) {
|
||||||
|
checkListRangeConsistency(formField);
|
||||||
|
if (formField.getType() != null) {
|
||||||
|
switch (formField.getType()) {
|
||||||
|
case hidden:
|
||||||
|
case jid_multi:
|
||||||
|
case jid_single:
|
||||||
|
throw new ValidationConsistencyException(String.format(
|
||||||
|
"Field type '%1$s' is not consistent with validation method '%2$s'.",
|
||||||
|
formField.getType(), BasicValidateElement.METHOD));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For "list-single" or "list-multi", indicates that the user may enter a custom value (matching the datatype
|
||||||
|
* constraints) or choose from the predefined values.
|
||||||
|
*
|
||||||
|
* @see ValidateElement
|
||||||
|
*/
|
||||||
|
public static class OpenValidateElement extends ValidateElement {
|
||||||
|
|
||||||
|
public static final String METHOD = "open";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dataType
|
||||||
|
* @see #getDatatype()
|
||||||
|
*/
|
||||||
|
public OpenValidateElement(String dataType) {
|
||||||
|
super(dataType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendXML(XmlStringBuilder buf) {
|
||||||
|
buf.emptyElement(METHOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkConsistency(FormField formField) {
|
||||||
|
checkListRangeConsistency(formField);
|
||||||
|
if (formField.getType() != null) {
|
||||||
|
switch (formField.getType()) {
|
||||||
|
case hidden:
|
||||||
|
throw new ValidationConsistencyException(String.format(
|
||||||
|
"Field type '%1$s' is not consistent with validation method '%2$s'.",
|
||||||
|
formField.getType(), OpenValidateElement.METHOD));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the value should fall within a certain range.
|
||||||
|
*
|
||||||
|
* @see ValidateElement
|
||||||
|
*/
|
||||||
|
public static class RangeValidateElement extends ValidateElement {
|
||||||
|
|
||||||
|
public static final String METHOD = "range";
|
||||||
|
private final String min;
|
||||||
|
private final String max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dataType
|
||||||
|
* @param min the minimum allowable value. This attribute is OPTIONAL. The value depends on the datatype in use.
|
||||||
|
* @param max the maximum allowable value. This attribute is OPTIONAL. The value depends on the datatype in use.
|
||||||
|
* @see #getDatatype()
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public RangeValidateElement(String dataType, String min, String max) {
|
||||||
|
super(dataType);
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendXML(XmlStringBuilder buf) {
|
||||||
|
buf.halfOpenElement(METHOD);
|
||||||
|
buf.optAttribute("min", getMin());
|
||||||
|
buf.optAttribute("max", getMax());
|
||||||
|
buf.closeEmptyElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The 'min' attribute specifies the minimum allowable value.
|
||||||
|
*
|
||||||
|
* @return the minimum allowable value. This attribute is OPTIONAL. The value depends on the datatype in use.
|
||||||
|
*/
|
||||||
|
public String getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The 'max' attribute specifies the maximum allowable value.
|
||||||
|
*
|
||||||
|
* @return the maximum allowable value. This attribute is OPTIONAL. The value depends on the datatype in use.
|
||||||
|
*/
|
||||||
|
public String getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkConsistency(FormField formField) {
|
||||||
|
checkNonMultiConsistency(formField, METHOD);
|
||||||
|
if (getDatatype().equals(ValidateElement.DATATYPE_XS_STRING)) {
|
||||||
|
throw new ValidationConsistencyException(String.format(
|
||||||
|
"Field data type '%1$s' is not consistent with validation method '%2$s'.",
|
||||||
|
getDatatype(), RangeValidateElement.METHOD));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the value should be restricted to a regular expression. The regular expression must be that
|
||||||
|
* defined for <a href="http://www.xmpp.org/extensions/xep-0122.html#nt-idp1501344"> POSIX extended regular
|
||||||
|
* expressions </a> including support for <a
|
||||||
|
* href="http://www.xmpp.org/extensions/xep-0122.html#nt-idp1502496">Unicode</a>.
|
||||||
|
*
|
||||||
|
* @see ValidateElement
|
||||||
|
*/
|
||||||
|
public static class RegexValidateElement extends ValidateElement {
|
||||||
|
|
||||||
|
public static final String METHOD = "regex";
|
||||||
|
private final String regex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dataType
|
||||||
|
* @param regex
|
||||||
|
* @see #getDatatype()
|
||||||
|
*/
|
||||||
|
public RegexValidateElement(String dataType, String regex) {
|
||||||
|
super(dataType);
|
||||||
|
this.regex = regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the expression is that defined for POSIX extended regular expressions, including support for Unicode.
|
||||||
|
*
|
||||||
|
* @return the regex
|
||||||
|
*/
|
||||||
|
public String getRegex() {
|
||||||
|
return regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void appendXML(XmlStringBuilder buf) {
|
||||||
|
buf.element("regex", getRegex());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkConsistency(FormField formField) {
|
||||||
|
checkNonMultiConsistency(formField, METHOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This element indicates for "list-multi", that a minimum and maximum number of options should be selected and/or
|
||||||
|
* entered.
|
||||||
|
*/
|
||||||
|
public static class ListRange implements NamedElement {
|
||||||
|
|
||||||
|
public static final String ELEMENT = "list-range";
|
||||||
|
private final Long min;
|
||||||
|
private final Long max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The 'max' attribute specifies the maximum allowable number of selected/entered values. The 'min' attribute
|
||||||
|
* specifies the minimum allowable number of selected/entered values. Both attributes are optional and must be a
|
||||||
|
* positive integer.
|
||||||
|
*
|
||||||
|
* @param min
|
||||||
|
* @param max
|
||||||
|
*/
|
||||||
|
public ListRange(Long min, Long max) {
|
||||||
|
if (min != null && min < 0) {
|
||||||
|
throw new IllegalArgumentException("min must not be negative");
|
||||||
|
}
|
||||||
|
if (max != null && max < 0) {
|
||||||
|
throw new IllegalArgumentException("max must not be negative");
|
||||||
|
}
|
||||||
|
if (max == null && min == null) {
|
||||||
|
throw new IllegalArgumentException("Either min or max must be given");
|
||||||
|
}
|
||||||
|
this.min = min;
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XmlStringBuilder toXML() {
|
||||||
|
XmlStringBuilder buf = new XmlStringBuilder(this);
|
||||||
|
buf.optLongAttribute("min", getMin());
|
||||||
|
buf.optLongAttribute("max", getMax());
|
||||||
|
buf.closeEmptyElement();
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getElementName() {
|
||||||
|
return ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum allowable number of selected/entered values.
|
||||||
|
*
|
||||||
|
* @return a positive integer, can be null
|
||||||
|
*/
|
||||||
|
public Long getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum allowable number of selected/entered values.
|
||||||
|
*
|
||||||
|
* @return a positive integer, can be null
|
||||||
|
*/
|
||||||
|
public Long getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <list-range/> element SHOULD be included only when the <field/> is of type "list-multi" and SHOULD be ignored
|
||||||
|
* otherwise.
|
||||||
|
*
|
||||||
|
* @param formField
|
||||||
|
*/
|
||||||
|
protected void checkListRangeConsistency(FormField formField) {
|
||||||
|
ListRange listRange = getListRange();
|
||||||
|
if (listRange == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long max = listRange.getMax();
|
||||||
|
Long min = listRange.getMin();
|
||||||
|
if ((max != null || min != null) && formField.getType() != FormField.Type.list_multi) {
|
||||||
|
throw new ValidationConsistencyException(
|
||||||
|
"Field type is not of type 'list-multi' while a 'list-range' is defined.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param formField
|
||||||
|
* @param method
|
||||||
|
*/
|
||||||
|
protected void checkNonMultiConsistency(FormField formField, String method) {
|
||||||
|
checkListRangeConsistency(formField);
|
||||||
|
if (formField.getType() != null) {
|
||||||
|
switch (formField.getType()) {
|
||||||
|
case hidden:
|
||||||
|
case jid_multi:
|
||||||
|
case list_multi:
|
||||||
|
case text_multi:
|
||||||
|
throw new ValidationConsistencyException(String.format(
|
||||||
|
"Field type '%1$s' is not consistent with validation method '%2$s'.",
|
||||||
|
formField.getType(), method));
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 Anno van Vliet
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.xdatavalidation.provider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.util.ParserUtils;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.BasicValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.EmptyValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.ListRange;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.OpenValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RangeValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RegexValidateElement;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension Provider for Data validation of forms.
|
||||||
|
*
|
||||||
|
* @author Anno van Vliet
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataValidationProvider {
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(DataValidationProvider.class.getName());
|
||||||
|
|
||||||
|
public static ValidateElement parse(XmlPullParser parser) throws XmlPullParserException, IOException {
|
||||||
|
final int initialDepth = parser.getDepth();
|
||||||
|
final String dataType = parser.getAttributeValue("", "datatype");
|
||||||
|
ValidateElement dataValidation = null;
|
||||||
|
ListRange listRange = null;
|
||||||
|
|
||||||
|
outerloop: while (true) {
|
||||||
|
int eventType = parser.next();
|
||||||
|
switch (eventType) {
|
||||||
|
case XmlPullParser.START_TAG:
|
||||||
|
switch (parser.getName()) {
|
||||||
|
case OpenValidateElement.METHOD:
|
||||||
|
dataValidation = new OpenValidateElement(dataType);
|
||||||
|
break;
|
||||||
|
case BasicValidateElement.METHOD:
|
||||||
|
dataValidation = new BasicValidateElement(dataType);
|
||||||
|
break;
|
||||||
|
case RangeValidateElement.METHOD:
|
||||||
|
dataValidation = new RangeValidateElement(dataType,
|
||||||
|
parser.getAttributeValue("", "min"),
|
||||||
|
parser.getAttributeValue("", "max")
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case RegexValidateElement.METHOD:
|
||||||
|
dataValidation = new RegexValidateElement(dataType,parser.nextText());
|
||||||
|
break;
|
||||||
|
case ListRange.ELEMENT:
|
||||||
|
Long min = ParserUtils.getLongAttribute(parser, "min");
|
||||||
|
Long max = ParserUtils.getLongAttribute(parser, "max");
|
||||||
|
if (min != null || max != null) {
|
||||||
|
listRange = new ListRange(min, max);
|
||||||
|
} else {
|
||||||
|
LOGGER.fine("Ignoring list-range element without min or max attribute");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XmlPullParser.END_TAG:
|
||||||
|
if (parser.getDepth() == initialDepth) {
|
||||||
|
if (dataValidation == null) {
|
||||||
|
dataValidation = new EmptyValidateElement(dataType);
|
||||||
|
}
|
||||||
|
dataValidation.setListRange(listRange);
|
||||||
|
break outerloop;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dataValidation;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,5 +14,6 @@
|
||||||
<className>org.jivesoftware.smackx.vcardtemp.VCardManager</className>
|
<className>org.jivesoftware.smackx.vcardtemp.VCardManager</className>
|
||||||
<className>org.jivesoftware.smackx.xdata.XDataManager</className>
|
<className>org.jivesoftware.smackx.xdata.XDataManager</className>
|
||||||
<className>org.jivesoftware.smackx.xdatalayout.XDataLayoutManager</className>
|
<className>org.jivesoftware.smackx.xdatalayout.XDataLayoutManager</className>
|
||||||
|
<className>org.jivesoftware.smackx.xdatavalidation.XDataValidationManager</className>
|
||||||
</startupClasses>
|
</startupClasses>
|
||||||
</smack>
|
</smack>
|
||||||
|
|
|
@ -20,8 +20,6 @@ import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.packet.Element;
|
import org.jivesoftware.smack.packet.Element;
|
||||||
|
@ -32,6 +30,9 @@ import org.jivesoftware.smackx.xdatalayout.packet.DataLayout;
|
||||||
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout.Fieldref;
|
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout.Fieldref;
|
||||||
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout.Section;
|
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout.Section;
|
||||||
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout.Text;
|
import org.jivesoftware.smackx.xdatalayout.packet.DataLayout.Text;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RangeValidateElement;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
import org.xmlpull.v1.XmlPullParserException;
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
@ -45,11 +46,10 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||||
public class DataFormTest {
|
public class DataFormTest {
|
||||||
private static final String TEST_OUTPUT_1 = "<x xmlns='jabber:x:data' type='SUBMIT'><instructions>InstructionTest1</instructions><field var='testField1'></field></x>";
|
private static final String TEST_OUTPUT_1 = "<x xmlns='jabber:x:data' type='SUBMIT'><instructions>InstructionTest1</instructions><field var='testField1'></field></x>";
|
||||||
private static final String TEST_OUTPUT_2 = "<x xmlns='jabber:x:data' type='SUBMIT'><instructions>InstructionTest1</instructions><field var='testField1'></field><page xmlns='http://jabber.org/protocol/xdata-layout' label='Label'><fieldref var='testField1'/><section label='section Label'><text>SectionText</text></section><text>PageText</text></page></x>";
|
private static final String TEST_OUTPUT_2 = "<x xmlns='jabber:x:data' type='SUBMIT'><instructions>InstructionTest1</instructions><field var='testField1'></field><page xmlns='http://jabber.org/protocol/xdata-layout' label='Label'><fieldref var='testField1'/><section label='section Label'><text>SectionText</text></section><text>PageText</text></page></x>";
|
||||||
private static Logger logger = Logger.getLogger(DataFormTest.class.getName());
|
private static final String TEST_OUTPUT_3 = "<x xmlns='jabber:x:data' type='SUBMIT'><instructions>InstructionTest1</instructions><field var='testField1'><validate xmlns='http://jabber.org/protocol/xdata-validate' datatype='xs:integer'><range min='1111' max='9999'/></validate></field></x>";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() throws XmlPullParserException, IOException, SmackException {
|
public void test() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
//Build a Form
|
//Build a Form
|
||||||
DataForm df = new DataForm("SUBMIT");
|
DataForm df = new DataForm("SUBMIT");
|
||||||
String instruction = "InstructionTest1";
|
String instruction = "InstructionTest1";
|
||||||
|
@ -59,12 +59,11 @@ public class DataFormTest {
|
||||||
|
|
||||||
assertNotNull( df.toXML());
|
assertNotNull( df.toXML());
|
||||||
String output = df.toXML().toString();
|
String output = df.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_1, output);
|
assertEquals(TEST_OUTPUT_1, output);
|
||||||
|
|
||||||
DataFormProvider pr = new DataFormProvider();
|
DataFormProvider pr = new DataFormProvider();
|
||||||
|
|
||||||
XmlPullParser parser = getParser(output);
|
XmlPullParser parser = PacketParserUtils.getParserFor(output);
|
||||||
|
|
||||||
df = pr.parse(parser);
|
df = pr.parse(parser);
|
||||||
|
|
||||||
|
@ -75,15 +74,11 @@ public class DataFormTest {
|
||||||
|
|
||||||
assertNotNull( df.toXML());
|
assertNotNull( df.toXML());
|
||||||
output = df.toXML().toString();
|
output = df.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_1, output);
|
assertEquals(TEST_OUTPUT_1, output);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLayout() throws XmlPullParserException, IOException, SmackException {
|
public void testLayout() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
//Build a Form
|
//Build a Form
|
||||||
DataForm df = new DataForm("SUBMIT");
|
DataForm df = new DataForm("SUBMIT");
|
||||||
String instruction = "InstructionTest1";
|
String instruction = "InstructionTest1";
|
||||||
|
@ -104,12 +99,11 @@ public class DataFormTest {
|
||||||
|
|
||||||
assertNotNull( df.toXML());
|
assertNotNull( df.toXML());
|
||||||
String output = df.toXML().toString();
|
String output = df.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_2, output);
|
assertEquals(TEST_OUTPUT_2, output);
|
||||||
|
|
||||||
DataFormProvider pr = new DataFormProvider();
|
DataFormProvider pr = new DataFormProvider();
|
||||||
|
|
||||||
XmlPullParser parser = getParser(output);
|
XmlPullParser parser = PacketParserUtils.getParserFor(output);
|
||||||
|
|
||||||
df = pr.parse(parser);
|
df = pr.parse(parser);
|
||||||
|
|
||||||
|
@ -124,23 +118,42 @@ public class DataFormTest {
|
||||||
|
|
||||||
assertNotNull( df.toXML());
|
assertNotNull( df.toXML());
|
||||||
output = df.toXML().toString();
|
output = df.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_2, output);
|
assertEquals(TEST_OUTPUT_2, output);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Test
|
||||||
* @param output
|
public void testValidation() throws XmlPullParserException, IOException, SmackException {
|
||||||
* @return
|
//Build a Form
|
||||||
* @throws XmlPullParserException
|
DataForm df = new DataForm("SUBMIT");
|
||||||
* @throws IOException
|
String instruction = "InstructionTest1";
|
||||||
*/
|
df.addInstruction(instruction);
|
||||||
private XmlPullParser getParser(String output) throws XmlPullParserException, IOException {
|
FormField field = new FormField("testField1");
|
||||||
logger.finest("getParser");
|
df.addField(field);
|
||||||
XmlPullParser parser = PacketParserUtils.newXmppParser();
|
|
||||||
parser.setInput(new StringReader(output));
|
ValidateElement dv = new RangeValidateElement("xs:integer","1111", "9999");
|
||||||
parser.next();
|
field.setValidateElement(dv);
|
||||||
return parser;
|
|
||||||
|
assertNotNull( df.toXML());
|
||||||
|
String output = df.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_3, output);
|
||||||
|
|
||||||
|
DataFormProvider pr = new DataFormProvider();
|
||||||
|
|
||||||
|
XmlPullParser parser = PacketParserUtils.getParserFor(output);
|
||||||
|
|
||||||
|
df = pr.parse(parser);
|
||||||
|
|
||||||
|
assertNotNull(df);
|
||||||
|
assertNotNull(df.getFields());
|
||||||
|
assertEquals(1 , df.getFields().size() );
|
||||||
|
Element element = df.getFields().get(0).getValidateElement();
|
||||||
|
assertNotNull(element);
|
||||||
|
dv = (ValidateElement) element;
|
||||||
|
|
||||||
|
assertEquals("xs:integer" , dv.getDatatype());
|
||||||
|
|
||||||
|
assertNotNull( df.toXML());
|
||||||
|
output = df.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_3, output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,6 @@ import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
import org.jivesoftware.smack.util.PacketParserUtils;
|
||||||
|
@ -47,12 +45,9 @@ public class DataLayoutTest {
|
||||||
private static final String TEST_OUTPUT_2 = "<page xmlns='http://jabber.org/protocol/xdata-layout' label='Label'><fieldref var='testField1'/><section label='section Label'><text>SectionText</text></section><text>PageText</text></page>";
|
private static final String TEST_OUTPUT_2 = "<page xmlns='http://jabber.org/protocol/xdata-layout' label='Label'><fieldref var='testField1'/><section label='section Label'><text>SectionText</text></section><text>PageText</text></page>";
|
||||||
private static final String TEST_OUTPUT_SPECIAL = "<page xmlns='http://jabber.org/protocol/xdata-layout' label='Label - & \u00E9 \u00E1 '><fieldref var='testField1'/><section label='section Label - & \u00E9 \u00E1 '><text>SectionText - & \u00E9 \u00E1 </text></section><text>PageText - & \u00E9 \u00E1 </text><section label='<html>Number of Persons by<br/> Nationality and Status</html>'><reportedref/></section><text><html><font color='red'><em>DO NOT DELAY</em></font><br/>supply further information</html></text></page>";
|
private static final String TEST_OUTPUT_SPECIAL = "<page xmlns='http://jabber.org/protocol/xdata-layout' label='Label - & \u00E9 \u00E1 '><fieldref var='testField1'/><section label='section Label - & \u00E9 \u00E1 '><text>SectionText - & \u00E9 \u00E1 </text></section><text>PageText - & \u00E9 \u00E1 </text><section label='<html>Number of Persons by<br/> Nationality and Status</html>'><reportedref/></section><text><html><font color='red'><em>DO NOT DELAY</em></font><br/>supply further information</html></text></page>";
|
||||||
private static final String TEST_INPUT_1 = "xdata-layout-sample.xml";
|
private static final String TEST_INPUT_1 = "xdata-layout-sample.xml";
|
||||||
private static Logger logger = Logger.getLogger(DataLayoutTest.class.getName());
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLayout() throws XmlPullParserException, IOException, SmackException {
|
public void testLayout() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
DataLayout layout = new DataLayout("Label");
|
DataLayout layout = new DataLayout("Label");
|
||||||
Fieldref reffield = new Fieldref("testField1");
|
Fieldref reffield = new Fieldref("testField1");
|
||||||
layout.getPageLayout().add(reffield);
|
layout.getPageLayout().add(reffield);
|
||||||
|
@ -63,10 +58,9 @@ public class DataLayoutTest {
|
||||||
|
|
||||||
assertNotNull( layout.toXML());
|
assertNotNull( layout.toXML());
|
||||||
String output = layout.toXML().toString();
|
String output = layout.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_2, output);
|
assertEquals(TEST_OUTPUT_2, output);
|
||||||
|
|
||||||
XmlPullParser parser = getParser(output);
|
XmlPullParser parser = PacketParserUtils.getParserFor(output);
|
||||||
|
|
||||||
layout = DataLayoutProvider.parse(parser);
|
layout = DataLayoutProvider.parse(parser);
|
||||||
|
|
||||||
|
@ -75,10 +69,7 @@ public class DataLayoutTest {
|
||||||
|
|
||||||
assertNotNull( layout.toXML());
|
assertNotNull( layout.toXML());
|
||||||
output = layout.toXML().toString();
|
output = layout.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_2, output);
|
assertEquals(TEST_OUTPUT_2, output);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -101,10 +92,9 @@ public class DataLayoutTest {
|
||||||
|
|
||||||
assertNotNull( layout.toXML());
|
assertNotNull( layout.toXML());
|
||||||
String output = layout.toXML().toString();
|
String output = layout.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_SPECIAL, output);
|
assertEquals(TEST_OUTPUT_SPECIAL, output);
|
||||||
|
|
||||||
XmlPullParser parser = getParser(output);
|
XmlPullParser parser = PacketParserUtils.getParserFor(output);
|
||||||
|
|
||||||
layout = DataLayoutProvider.parse(parser);
|
layout = DataLayoutProvider.parse(parser);
|
||||||
|
|
||||||
|
@ -122,16 +112,11 @@ public class DataLayoutTest {
|
||||||
|
|
||||||
assertNotNull( layout.toXML());
|
assertNotNull( layout.toXML());
|
||||||
output = layout.toXML().toString();
|
output = layout.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_SPECIAL, output);
|
assertEquals(TEST_OUTPUT_SPECIAL, output);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLayoutFromFile() throws XmlPullParserException, IOException, SmackException {
|
public void testLayoutFromFile() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
|
|
||||||
DataFormProvider pr = new DataFormProvider();
|
DataFormProvider pr = new DataFormProvider();
|
||||||
|
|
||||||
XmlPullParser parser = PacketParserUtils.newXmppParser();
|
XmlPullParser parser = PacketParserUtils.newXmppParser();
|
||||||
|
@ -158,24 +143,6 @@ public class DataLayoutTest {
|
||||||
|
|
||||||
assertNotNull( layout.toXML());
|
assertNotNull( layout.toXML());
|
||||||
String output = layout.toXML().toString();
|
String output = layout.toXML().toString();
|
||||||
logger.finest(output);
|
|
||||||
assertEquals(TEST_OUTPUT_SPECIAL, output);
|
assertEquals(TEST_OUTPUT_SPECIAL, output);
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param output
|
|
||||||
* @return
|
|
||||||
* @throws XmlPullParserException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
private XmlPullParser getParser(String output) throws XmlPullParserException, IOException {
|
|
||||||
logger.finest("getParser");
|
|
||||||
XmlPullParser parser = PacketParserUtils.newXmppParser();
|
|
||||||
parser.setInput(new StringReader(output));
|
|
||||||
parser.next();
|
|
||||||
return parser;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 Anno van Vliet
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.xdatavalidation;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.BasicValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.ListRange;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.OpenValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RangeValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RegexValidateElement;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Anno van Vliet
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataValidationHelperTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckConsistencyFormFieldBasicValidateElement() {
|
||||||
|
FormField field = new FormField("var");
|
||||||
|
field.setType(FormField.Type.jid_single);
|
||||||
|
BasicValidateElement element = new BasicValidateElement(null);
|
||||||
|
try {
|
||||||
|
element.checkConsistency(field);
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
catch (ValidationConsistencyException e) {
|
||||||
|
assertEquals("Field type 'jid-single' is not consistent with validation method 'basic'.", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
new ListRange(-1L, 1L);
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
assertEquals("min must not be negative", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
element.setListRange(new ListRange(10L, 100L));
|
||||||
|
try {
|
||||||
|
element.checkConsistency(field);
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
catch (ValidationConsistencyException e) {
|
||||||
|
assertEquals("Field type is not of type 'list-multi' while a 'list-range' is defined.", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
field.setType(FormField.Type.list_multi);
|
||||||
|
try {
|
||||||
|
element.checkConsistency(field);
|
||||||
|
}
|
||||||
|
catch (ValidationConsistencyException e) {
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckConsistencyFormFieldOpenValidateElement() {
|
||||||
|
FormField field = new FormField("var");
|
||||||
|
field.setType(FormField.Type.hidden);
|
||||||
|
OpenValidateElement element = new OpenValidateElement(null);
|
||||||
|
try {
|
||||||
|
element.checkConsistency(field);
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
catch (ValidationConsistencyException e) {
|
||||||
|
assertEquals("Field type 'hidden' is not consistent with validation method 'open'.", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckConsistencyFormFieldRangeValidateElement() {
|
||||||
|
FormField field = new FormField("var");
|
||||||
|
field.setType(FormField.Type.text_multi);
|
||||||
|
RangeValidateElement element = new RangeValidateElement("xs:integer",null, "99");
|
||||||
|
try {
|
||||||
|
element.checkConsistency(field);
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
catch (ValidationConsistencyException e) {
|
||||||
|
assertEquals("Field type 'text-multi' is not consistent with validation method 'range'.", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckConsistencyFormFieldRegexValidateElement() {
|
||||||
|
FormField field = new FormField("var");
|
||||||
|
field.setType(FormField.Type.list_multi);
|
||||||
|
RegexValidateElement element = new RegexValidateElement(null, ".*");
|
||||||
|
try {
|
||||||
|
element.checkConsistency(field);
|
||||||
|
fail("No correct check on consistency");
|
||||||
|
}
|
||||||
|
catch (ValidationConsistencyException e) {
|
||||||
|
assertEquals("Field type 'list-multi' is not consistent with validation method 'regex'.", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,140 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2014 Anno van Vliet
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.xdatavalidation.provider;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
import org.jivesoftware.smack.test.util.TestUtils;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.EmptyValidateElement;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.ListRange;
|
||||||
|
import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RangeValidateElement;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.xmlpull.v1.XmlPullParser;
|
||||||
|
import org.xmlpull.v1.XmlPullParserException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Anno van Vliet
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataValidationTest {
|
||||||
|
private static final String TEST_OUTPUT_MIN = "<validate xmlns='http://jabber.org/protocol/xdata-validate'></validate>";
|
||||||
|
private static final String TEST_OUTPUT_RANGE = "<validate xmlns='http://jabber.org/protocol/xdata-validate' datatype='xs:string'><range min='min-val' max='max-val'/><list-range min='111' max='999'/></validate>";
|
||||||
|
private static final String TEST_OUTPUT_RANGE2 = "<validate xmlns='http://jabber.org/protocol/xdata-validate'><range/></validate>";
|
||||||
|
private static final String TEST_OUTPUT_FAIL = "<validate xmlns='http://jabber.org/protocol/xdata-validate'><list-range min='1-1-1' max='999'/></validate>";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMin() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
|
ValidateElement dv = new EmptyValidateElement(null);
|
||||||
|
|
||||||
|
assertNotNull( dv.toXML());
|
||||||
|
String output = dv.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_MIN, output);
|
||||||
|
|
||||||
|
XmlPullParser parser = getParser(output);
|
||||||
|
|
||||||
|
dv = DataValidationProvider.parse(parser);
|
||||||
|
|
||||||
|
assertNotNull(dv);
|
||||||
|
assertEquals("xs:string", dv.getDatatype());
|
||||||
|
assertTrue( dv instanceof EmptyValidateElement);
|
||||||
|
|
||||||
|
assertNotNull( dv.toXML());
|
||||||
|
output = dv.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_MIN, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRange() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
|
ValidateElement dv = new RangeValidateElement("xs:string", "min-val", "max-val");
|
||||||
|
|
||||||
|
ListRange listRange = new ListRange(111L, 999L);
|
||||||
|
dv.setListRange(listRange );
|
||||||
|
|
||||||
|
assertNotNull( dv.toXML());
|
||||||
|
String output = dv.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_RANGE, output);
|
||||||
|
|
||||||
|
XmlPullParser parser = getParser(output);
|
||||||
|
|
||||||
|
dv = DataValidationProvider.parse(parser);
|
||||||
|
|
||||||
|
assertNotNull(dv);
|
||||||
|
assertEquals("xs:string", dv.getDatatype());
|
||||||
|
assertTrue(dv instanceof RangeValidateElement );
|
||||||
|
RangeValidateElement rdv = (RangeValidateElement) dv;
|
||||||
|
assertEquals("min-val", rdv.getMin());
|
||||||
|
assertEquals("max-val", rdv.getMax());
|
||||||
|
assertNotNull(rdv.getListRange());
|
||||||
|
assertEquals(new Long(111), rdv.getListRange().getMin());
|
||||||
|
assertEquals(999, rdv.getListRange().getMax().intValue());
|
||||||
|
|
||||||
|
|
||||||
|
assertNotNull( dv.toXML());
|
||||||
|
output = dv.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_RANGE, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRange2() throws XmlPullParserException, IOException, SmackException {
|
||||||
|
|
||||||
|
ValidateElement dv = new RangeValidateElement(null, null, null);
|
||||||
|
|
||||||
|
assertNotNull( dv.toXML());
|
||||||
|
String output = dv.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_RANGE2, output);
|
||||||
|
|
||||||
|
XmlPullParser parser = getParser(output);
|
||||||
|
|
||||||
|
dv = DataValidationProvider.parse(parser);
|
||||||
|
|
||||||
|
assertNotNull(dv);
|
||||||
|
assertEquals("xs:string", dv.getDatatype());
|
||||||
|
assertTrue(dv instanceof RangeValidateElement );
|
||||||
|
RangeValidateElement rdv = (RangeValidateElement) dv;
|
||||||
|
assertEquals(null, rdv.getMin());
|
||||||
|
assertEquals(null, rdv.getMax());
|
||||||
|
|
||||||
|
assertNotNull( rdv.toXML());
|
||||||
|
output = rdv.toXML().toString();
|
||||||
|
assertEquals(TEST_OUTPUT_RANGE2, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=NumberFormatException.class)
|
||||||
|
public void testRangeFailure() throws IOException, SmackException, XmlPullParserException {
|
||||||
|
XmlPullParser parser = getParser(TEST_OUTPUT_FAIL);
|
||||||
|
DataValidationProvider.parse(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param output
|
||||||
|
* @return
|
||||||
|
* @throws XmlPullParserException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private XmlPullParser getParser(String output) throws XmlPullParserException, IOException {
|
||||||
|
return TestUtils.getParser(output, "validate");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue