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