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