001/** 002 * 003 * Copyright 2003-2007 Jive Software. 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 */ 017 018package org.jivesoftware.smackx.xdata.provider; 019 020import org.jivesoftware.smack.SmackException; 021import org.jivesoftware.smack.provider.ExtensionElementProvider; 022import org.jivesoftware.smack.roster.packet.RosterPacket; 023import org.jivesoftware.smack.roster.provider.RosterPacketProvider; 024import org.jivesoftware.smackx.xdata.FormField; 025import org.jivesoftware.smackx.xdata.packet.DataForm; 026import org.jivesoftware.smackx.xdatalayout.packet.DataLayout; 027import org.jivesoftware.smackx.xdatalayout.provider.DataLayoutProvider; 028import org.jivesoftware.smackx.xdatavalidation.packet.ValidateElement; 029import org.jivesoftware.smackx.xdatavalidation.provider.DataValidationProvider; 030import org.xmlpull.v1.XmlPullParser; 031import org.xmlpull.v1.XmlPullParserException; 032 033import java.io.IOException; 034import java.util.ArrayList; 035import java.util.List; 036 037/** 038 * The DataFormProvider parses DataForm packets. 039 * 040 * @author Gaston Dombiak 041 */ 042public class DataFormProvider extends ExtensionElementProvider<DataForm> { 043 044 @Override 045 public DataForm parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, 046 SmackException { 047 DataForm.Type dataFormType = DataForm.Type.fromString(parser.getAttributeValue("", "type")); 048 DataForm dataForm = new DataForm(dataFormType); 049 outerloop: while (true) { 050 int eventType = parser.next(); 051 switch (eventType) { 052 case XmlPullParser.START_TAG: 053 String name = parser.getName(); 054 String namespace = parser.getNamespace(); 055 switch (name) { 056 case "instructions": 057 dataForm.addInstruction(parser.nextText()); 058 break; 059 case "title": 060 dataForm.setTitle(parser.nextText()); 061 break; 062 case "field": 063 dataForm.addField(parseField(parser)); 064 break; 065 case "item": 066 dataForm.addItem(parseItem(parser)); 067 break; 068 case "reported": 069 dataForm.setReportedData(parseReported(parser)); 070 break; 071 // See XEP-133 Example 32 for a corner case where the data form contains this extension. 072 case RosterPacket.ELEMENT: 073 if (namespace.equals(RosterPacket.NAMESPACE)) { 074 dataForm.addExtensionElement(RosterPacketProvider.INSTANCE.parse(parser)); 075 } 076 break; 077 // See XEP-141 Data Forms Layout 078 case DataLayout.ELEMENT: 079 if (namespace.equals(DataLayout.NAMESPACE)) { 080 dataForm.addExtensionElement(DataLayoutProvider.parse(parser)); 081 } 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 dataForm; 093 } 094 095 private FormField parseField(XmlPullParser parser) throws XmlPullParserException, IOException { 096 final int initialDepth = parser.getDepth(); 097 final String var = parser.getAttributeValue("", "var"); 098 final FormField.Type type = FormField.Type.fromString(parser.getAttributeValue("", "type")); 099 100 final FormField formField; 101 if (type == FormField.Type.fixed) { 102 formField = new FormField(); 103 } else { 104 formField = new FormField(var); 105 formField.setType(type); 106 } 107 formField.setLabel(parser.getAttributeValue("", "label")); 108 109 outerloop: while (true) { 110 int eventType = parser.next(); 111 switch (eventType) { 112 case XmlPullParser.START_TAG: 113 String name = parser.getName(); 114 String namespace = parser.getNamespace(); 115 switch (name) { 116 case "desc": 117 formField.setDescription(parser.nextText()); 118 break; 119 case "value": 120 formField.addValue(parser.nextText()); 121 break; 122 case "required": 123 formField.setRequired(true); 124 break; 125 case "option": 126 formField.addOption(parseOption(parser)); 127 break; 128 // See XEP-122 Data Forms Validation 129 case ValidateElement.ELEMENT: 130 if (namespace.equals(ValidateElement.NAMESPACE)) { 131 formField.setValidateElement(DataValidationProvider.parse(parser)); 132 } 133 break; 134 } 135 break; 136 case XmlPullParser.END_TAG: 137 if (parser.getDepth() == initialDepth) { 138 break outerloop; 139 } 140 break; 141 } 142 } 143 return formField; 144 } 145 146 private DataForm.Item parseItem(XmlPullParser parser) throws XmlPullParserException, IOException { 147 final int initialDepth = parser.getDepth(); 148 List<FormField> fields = new ArrayList<FormField>(); 149 outerloop: while (true) { 150 int eventType = parser.next(); 151 switch (eventType) { 152 case XmlPullParser.START_TAG: 153 String name = parser.getName(); 154 switch (name) { 155 case "field": 156 fields.add(parseField(parser)); 157 break; 158 } 159 break; 160 case XmlPullParser.END_TAG: 161 if (parser.getDepth() == initialDepth) { 162 break outerloop; 163 } 164 break; 165 } 166 } 167 return new DataForm.Item(fields); 168 } 169 170 private DataForm.ReportedData parseReported(XmlPullParser parser) throws XmlPullParserException, IOException { 171 final int initialDepth = parser.getDepth(); 172 List<FormField> fields = new ArrayList<FormField>(); 173 outerloop: while (true) { 174 int eventType = parser.next(); 175 switch (eventType) { 176 case XmlPullParser.START_TAG: 177 String name = parser.getName(); 178 switch (name) { 179 case "field": 180 fields.add(parseField(parser)); 181 break; 182 } 183 break; 184 case XmlPullParser.END_TAG: 185 if (parser.getDepth() == initialDepth) { 186 break outerloop; 187 } 188 break; 189 } 190 } 191 return new DataForm.ReportedData(fields); 192 } 193 194 private FormField.Option parseOption(XmlPullParser parser) throws XmlPullParserException, IOException { 195 final int initialDepth = parser.getDepth(); 196 FormField.Option option = null; 197 String label = parser.getAttributeValue("", "label"); 198 outerloop: while (true) { 199 int eventType = parser.next(); 200 switch (eventType) { 201 case XmlPullParser.START_TAG: 202 String name = parser.getName(); 203 switch (name) { 204 case "value": 205 option = new FormField.Option(label, parser.nextText()); 206 break; 207 } 208 break; 209 case XmlPullParser.END_TAG: 210 if (parser.getDepth() == initialDepth) { 211 break outerloop; 212 } 213 break; 214 } 215 } 216 return option; 217 } 218}