001/** 002 * 003 * Copyright 2015-2019 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.smack.parsing; 018 019import java.io.IOException; 020import java.util.LinkedHashMap; 021import java.util.Map; 022 023import org.jivesoftware.smack.packet.StandardExtensionElement; 024import org.jivesoftware.smack.packet.XmlEnvironment; 025import org.jivesoftware.smack.provider.ExtensionElementProvider; 026import org.jivesoftware.smack.util.ParserUtils; 027import org.jivesoftware.smack.util.StringUtils; 028import org.jivesoftware.smack.xml.XmlPullParser; 029import org.jivesoftware.smack.xml.XmlPullParserException; 030 031/** 032 * The parser for {@link StandardExtensionElement}s. 033 * 034 * @author Florian Schmaus 035 * 036 */ 037public class StandardExtensionElementProvider extends ExtensionElementProvider<StandardExtensionElement> { 038 039 public static StandardExtensionElementProvider INSTANCE = new StandardExtensionElementProvider(); 040 041 @Override 042 public StandardExtensionElement parse(final XmlPullParser parser, final int initialDepth, XmlEnvironment xmlEnvironment) 043 throws XmlPullParserException, IOException { 044 // Unlike most (all?) other providers, we don't know the name and namespace of the element 045 // we are parsing here. 046 String name = parser.getName(); 047 String namespace = parser.getNamespace(); 048 StandardExtensionElement.Builder builder = StandardExtensionElement.builder(name, namespace); 049 final int namespaceCount = parser.getNamespaceCount(); 050 final int attributeCount = parser.getAttributeCount(); 051 final Map<String, String> attributes = new LinkedHashMap<>(namespaceCount + attributeCount); 052 for (int i = 0; i < namespaceCount; i++) { 053 String nsprefix = parser.getNamespacePrefix(i); 054 if (nsprefix == null) { 055 // Skip the default namespace. 056 continue; 057 } 058 // XmlPullParser must either return null or a non-empty String. 059 assert StringUtils.isNotEmpty(nsprefix); 060 String nsuri = parser.getNamespaceUri(i); 061 attributes.put("xmlns:" + nsprefix, nsuri); 062 } 063 for (int i = 0; i < attributeCount; i++) { 064 String attributePrefix = parser.getAttributePrefix(i); 065 String attributeName = parser.getAttributeName(i); 066 String attributeValue = parser.getAttributeValue(i); 067 String attributeKey; 068 if (StringUtils.isNullOrEmpty(attributePrefix)) { 069 attributeKey = attributeName; 070 } 071 else { 072 attributeKey = attributePrefix + ':' + attributeName; 073 } 074 attributes.put(attributeKey, attributeValue); 075 } 076 builder.addAttributes(attributes); 077 078 outerloop: while (true) { 079 XmlPullParser.Event event = parser.next(); 080 switch (event) { 081 case START_ELEMENT: 082 builder.addElement(parse(parser, parser.getDepth(), xmlEnvironment)); 083 break; 084 case TEXT_CHARACTERS: 085 builder.setText(parser.getText()); 086 break; 087 case END_ELEMENT: 088 if (initialDepth == parser.getDepth()) { 089 break outerloop; 090 } 091 break; 092 default: 093 // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement. 094 break; 095 } 096 } 097 098 ParserUtils.assertAtEndTag(parser); 099 return builder.build(); 100 } 101}