001/**
002 *
003 * Copyright © 2016 Florian Schmaus
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.iot.data.provider;
018
019import java.io.IOException;
020import java.text.ParseException;
021import java.util.ArrayList;
022import java.util.Date;
023import java.util.List;
024import java.util.logging.Logger;
025
026import org.jivesoftware.smack.provider.ExtensionElementProvider;
027import org.jivesoftware.smack.util.ParserUtils;
028import org.jivesoftware.smackx.iot.data.element.IoTDataField;
029import org.jivesoftware.smackx.iot.data.element.IoTFieldsExtension;
030import org.jivesoftware.smackx.iot.data.element.NodeElement;
031import org.jivesoftware.smackx.iot.data.element.TimestampElement;
032import org.jivesoftware.smackx.iot.element.NodeInfo;
033import org.jivesoftware.smackx.iot.parser.NodeInfoParser;
034import org.jxmpp.util.XmppDateTime;
035import org.xmlpull.v1.XmlPullParser;
036import org.xmlpull.v1.XmlPullParserException;
037
038public class IoTFieldsExtensionProvider extends ExtensionElementProvider<IoTFieldsExtension> {
039
040    private static final Logger LOGGER = Logger.getLogger(IoTFieldsExtensionProvider.class.getName());
041
042    @Override
043    public IoTFieldsExtension parse(XmlPullParser parser, int initialDepth) throws Exception {
044        int seqNr = ParserUtils.getIntegerAttributeOrThrow(parser, "seqnr", "IoT data request <accepted/> without sequence number");
045        boolean done = ParserUtils.getBooleanAttribute(parser, "done", false);
046        List<NodeElement> nodes = new ArrayList<>();
047        outerloop: while (true) {
048            final int eventType = parser.next();
049            final String name = parser.getName();
050            switch (eventType) {
051            case XmlPullParser.START_TAG:
052                switch (name) {
053                case NodeElement.ELEMENT:
054                    NodeElement node = parseNode(parser);
055                    nodes.add(node);
056                    break;
057                }
058                break;
059            case XmlPullParser.END_TAG:
060                if (parser.getDepth() == initialDepth) {
061                    break outerloop;
062                }
063                break;
064            }
065        }
066        return new IoTFieldsExtension(seqNr, done, nodes);
067    }
068
069    public NodeElement parseNode(XmlPullParser parser) throws XmlPullParserException, IOException, ParseException {
070        final int initialDepth = parser.getDepth();
071        final NodeInfo nodeInfo = NodeInfoParser.parse(parser);
072        List<TimestampElement> timestampElements = new ArrayList<>();
073        outerloop: while (true) {
074            final int eventType = parser.next();
075            final String name = parser.getName();
076            switch (eventType) {
077            case XmlPullParser.START_TAG:
078                switch (name){
079                case TimestampElement.ELEMENT:
080                    TimestampElement timestampElement = parseTimestampElement(parser);
081                    timestampElements.add(timestampElement);
082                    break;
083                }
084                break;
085            case XmlPullParser.END_TAG:
086                if (parser.getDepth() == initialDepth) {
087                    break outerloop;
088                }
089                break;
090            }
091        }
092        return new NodeElement(nodeInfo, timestampElements);
093    }
094
095    public TimestampElement parseTimestampElement(XmlPullParser parser) throws ParseException, XmlPullParserException, IOException {
096        final int initialDepth = parser.getDepth();
097        final String dateString = parser.getAttributeValue(null, "value");
098        final Date date = XmppDateTime.parseDate(dateString);
099        List<IoTDataField> fields = new ArrayList<>();
100        outerloop: while (true) {
101            final int eventType = parser.next();
102            final String name = parser.getName();
103            switch (eventType) {
104            case XmlPullParser.START_TAG:
105                IoTDataField field = null;
106                final String fieldName = parser.getAttributeValue(null, "name");
107                final String fieldValue = parser.getAttributeValue(null, "value");
108                switch (name) {
109                case "int": {
110                    int value = Integer.parseInt(fieldValue);
111                    field = new IoTDataField.IntField(fieldName, value);
112                    }
113                    break;
114                case "boolean": {
115                    boolean value = Boolean.parseBoolean(fieldValue);
116                    field = new IoTDataField.BooleanField(fieldName, value);
117                    }
118                    break;
119                default:
120                    LOGGER.warning("IoT Data field type '" + name + "' not implement yet. Ignoring.");
121                    break;
122                }
123                if (field != null) {
124                    fields.add(field);
125                }
126                break;
127            case XmlPullParser.END_TAG:
128                if (parser.getDepth() == initialDepth) {
129                    break outerloop;
130                }
131                break;
132            }
133        }
134        return new TimestampElement(date, fields);
135    }
136}