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