001/*
002 *
003 * Copyright 2014 Anno van Vliet
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.xdatavalidation.provider;
018
019import java.io.IOException;
020import java.util.logging.Logger;
021
022import javax.xml.namespace.QName;
023
024import org.jivesoftware.smack.datatypes.UInt32;
025import org.jivesoftware.smack.packet.XmlEnvironment;
026import org.jivesoftware.smack.util.ParserUtils;
027import org.jivesoftware.smack.xml.XmlPullParser;
028import org.jivesoftware.smack.xml.XmlPullParserException;
029
030import org.jivesoftware.smackx.xdata.provider.FormFieldChildElementProvider;
031import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement;
032import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.BasicValidateElement;
033import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.ListRange;
034import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.OpenValidateElement;
035import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RangeValidateElement;
036import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement.RegexValidateElement;
037
038import org.jxmpp.JxmppContext;
039
040/**
041 * Extension Provider for Data validation of forms.
042 *
043 * @author Anno van Vliet
044 *
045 */
046public class DataValidationProvider extends FormFieldChildElementProvider<ValidateElement> {
047    private static final Logger LOGGER = Logger.getLogger(DataValidationProvider.class.getName());
048
049    @Override
050    public ValidateElement parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext)
051                    throws XmlPullParserException, IOException {
052        final String dataType = parser.getAttributeValue("", "datatype");
053        ValidateElement dataValidation = null;
054        ListRange listRange = null;
055
056        outerloop: while (true) {
057            XmlPullParser.Event eventType = parser.next();
058            switch (eventType) {
059            case START_ELEMENT:
060                String name = parser.getName();
061                switch (name) {
062                case OpenValidateElement.METHOD:
063                    dataValidation = new OpenValidateElement(dataType);
064                    break;
065                case BasicValidateElement.METHOD:
066                    dataValidation = new BasicValidateElement(dataType);
067                    break;
068                case RangeValidateElement.METHOD:
069                    dataValidation = new RangeValidateElement(dataType,
070                                    parser.getAttributeValue("", "min"),
071                                    parser.getAttributeValue("", "max")
072                                    );
073                    break;
074                case RegexValidateElement.METHOD:
075                    dataValidation = new RegexValidateElement(dataType, parser.nextText());
076                    break;
077                case ListRange.ELEMENT:
078                    UInt32 min = ParserUtils.getUInt32Attribute(parser, "min");
079                    UInt32 max = ParserUtils.getUInt32Attribute(parser, "max");
080                    if (min != null || max != null) {
081                        listRange = new ListRange(min, max);
082                    } else {
083                        LOGGER.fine("Ignoring list-range element without min or max attribute");
084                    }
085                    break;
086                default:
087                    break;
088                }
089                break;
090            case END_ELEMENT:
091                if (parser.getDepth() == initialDepth) {
092                    if (dataValidation == null) {
093                        // XEP-122 ยง 3.2 states that "If no validation method is specified,
094                        // form processors MUST assume <basic/> validation."
095                        dataValidation = new BasicValidateElement(dataType);
096                    }
097                    dataValidation.setListRange(listRange);
098                    break outerloop;
099                }
100                break;
101            default:
102                // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
103                break;
104            }
105        }
106        return dataValidation;
107    }
108
109    @Override
110    public QName getQName() {
111        return ValidateElement.QNAME;
112    }
113
114}