package org.jivesoftware.smack.util;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.compress.packet.Compress;
import org.jivesoftware.smack.packet.DefaultExtensionElement;
import org.jivesoftware.smack.packet.EmptyResultIQ;
import org.jivesoftware.smack.packet.ErrorIQ;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Session;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StartTls;
import org.jivesoftware.smack.packet.StreamError;
import org.jivesoftware.smack.packet.UnparsedIQ;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smack.provider.ExtensionElementProvider;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jivesoftware.smack.sasl.packet.SaslStreamElements;
import org.jxmpp.jid.Jid;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

public class PacketParserUtils {
   private static final Logger LOGGER = Logger.getLogger(PacketParserUtils.class.getName());
   public static final String FEATURE_XML_ROUNDTRIP = "http://xmlpull.org/v1/doc/features.html#xml-roundtrip";
   private static final XmlPullParserFactory XML_PULL_PARSER_FACTORY;
   public static final boolean XML_PULL_PARSER_SUPPORTS_ROUNDTRIP;

   public static XmlPullParser getParserFor(String stanza) throws XmlPullParserException, IOException {
      return getParserFor((Reader)(new StringReader(stanza)));
   }

   public static XmlPullParser getParserFor(Reader reader) throws XmlPullParserException, IOException {
      XmlPullParser parser = newXmppParser(reader);

      for(int event = parser.getEventType(); event != 2; event = parser.next()) {
         if (event == 1) {
            throw new IllegalArgumentException("Document contains no start tag");
         }
      }

      return parser;
   }

   public static XmlPullParser getParserFor(String stanza, String startTag) throws XmlPullParserException, IOException {
      XmlPullParser parser = getParserFor(stanza);

      while(true) {
         int event = parser.getEventType();
         String name = parser.getName();
         if (event == 2 && name.equals(startTag)) {
            return parser;
         }

         if (event == 1) {
            throw new IllegalArgumentException("Could not find start tag '" + startTag + "' in stanza: " + stanza);
         }

         parser.next();
      }
   }

   public static Stanza parseStanza(String stanza) throws XmlPullParserException, IOException, SmackException {
      return parseStanza(getParserFor(stanza));
   }

   public static Stanza parseStanza(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      ParserUtils.assertAtStartTag(parser);
      String name = parser.getName();
      byte var3 = -1;
      switch(name.hashCode()) {
      case -1276666629:
         if (name.equals("presence")) {
            var3 = 2;
         }
         break;
      case 3368:
         if (name.equals("iq")) {
            var3 = 1;
         }
         break;
      case 954925063:
         if (name.equals("message")) {
            var3 = 0;
         }
      }

      switch(var3) {
      case 0:
         return parseMessage(parser);
      case 1:
         return parseIQ(parser);
      case 2:
         return parsePresence(parser);
      default:
         throw new IllegalArgumentException("Can only parse message, iq or presence, not " + name);
      }
   }

   public static XmlPullParser newXmppParser() throws XmlPullParserException {
      XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
      parser.setFeature("http://xmlpull.org/v1/doc/features.html#process-namespaces", true);
      if (XML_PULL_PARSER_SUPPORTS_ROUNDTRIP) {
         try {
            parser.setFeature("http://xmlpull.org/v1/doc/features.html#xml-roundtrip", true);
         } catch (XmlPullParserException var2) {
            LOGGER.log(Level.SEVERE, "XmlPullParser does not support XML_ROUNDTRIP, although it was first determined to be supported", var2);
         }
      }

      return parser;
   }

   public static XmlPullParser newXmppParser(Reader reader) throws XmlPullParserException {
      XmlPullParser parser = newXmppParser();
      parser.setInput(reader);
      return parser;
   }

   public static Message parseMessage(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      ParserUtils.assertAtStartTag(parser);

      assert parser.getName().equals("message");

      int initialDepth = parser.getDepth();
      Message message = new Message();
      message.setStanzaId(parser.getAttributeValue("", "id"));
      message.setTo(ParserUtils.getJidAttribute(parser, "to"));
      message.setFrom(ParserUtils.getJidAttribute(parser, "from"));
      String typeString = parser.getAttributeValue("", "type");
      if (typeString != null) {
         message.setType(Message.Type.fromString(typeString));
      }

      String language = getLanguageAttribute(parser);
      String defaultLanguage = null;
      if (language != null && !"".equals(language.trim())) {
         message.setLanguage(language);
         defaultLanguage = language;
      } else {
         defaultLanguage = Stanza.getDefaultLanguage();
      }

      String thread = null;

      label69:
      do {
         while(true) {
            int eventType = parser.next();
            switch(eventType) {
            case 2:
               String elementName = parser.getName();
               String namespace = parser.getNamespace();
               byte var11 = -1;
               switch(elementName.hashCode()) {
               case -1867885268:
                  if (elementName.equals("subject")) {
                     var11 = 0;
                  }
                  break;
               case -874443254:
                  if (elementName.equals("thread")) {
                     var11 = 2;
                  }
                  break;
               case 3029410:
                  if (elementName.equals("body")) {
                     var11 = 1;
                  }
                  break;
               case 96784904:
                  if (elementName.equals("error")) {
                     var11 = 3;
                  }
               }

               switch(var11) {
               case 0:
                  String xmlLangSubject = getLanguageAttribute(parser);
                  if (xmlLangSubject == null) {
                     xmlLangSubject = defaultLanguage;
                  }

                  String subject = parseElementText(parser);
                  if (message.getSubject(xmlLangSubject) == null) {
                     message.addSubject(xmlLangSubject, subject);
                  }
                  continue;
               case 1:
                  String xmlLang = getLanguageAttribute(parser);
                  if (xmlLang == null) {
                     xmlLang = defaultLanguage;
                  }

                  String body = parseElementText(parser);
                  if (message.getBody(xmlLang) == null) {
                     message.addBody(xmlLang, body);
                  }
                  continue;
               case 2:
                  if (thread == null) {
                     thread = parser.nextText();
                  }
                  continue;
               case 3:
                  message.setError(parseError(parser));
                  continue;
               default:
                  addExtensionElement((Stanza)message, parser, elementName, namespace);
                  continue;
               }
            case 3:
               continue label69;
            }
         }
      } while(parser.getDepth() != initialDepth);

      message.setThread(thread);
      return message;
   }

   public static String parseElementText(XmlPullParser parser) throws XmlPullParserException, IOException {
      assert parser.getEventType() == 2;

      String res;
      if (parser.isEmptyElementTag()) {
         res = "";
      } else {
         int event = parser.next();
         if (event != 4) {
            if (event == 3) {
               return "";
            }

            throw new XmlPullParserException("Non-empty element tag not followed by text, while Mixed Content (XML 3.2.2) is disallowed");
         }

         res = parser.getText();
         event = parser.next();
         if (event != 3) {
            throw new XmlPullParserException("Non-empty element tag contains child-elements, while Mixed Content (XML 3.2.2) is disallowed");
         }
      }

      return res;
   }

   public static CharSequence parseElement(XmlPullParser parser) throws XmlPullParserException, IOException {
      return parseElement(parser, false);
   }

   public static CharSequence parseElement(XmlPullParser parser, boolean fullNamespaces) throws XmlPullParserException, IOException {
      assert parser.getEventType() == 2;

      return parseContentDepth(parser, parser.getDepth(), fullNamespaces);
   }

   public static CharSequence parseContent(XmlPullParser parser) throws XmlPullParserException, IOException {
      assert parser.getEventType() == 2;

      if (parser.isEmptyElementTag()) {
         return "";
      } else {
         parser.next();
         return parseContentDepth(parser, parser.getDepth(), false);
      }
   }

   public static CharSequence parseContentDepth(XmlPullParser parser, int depth) throws XmlPullParserException, IOException {
      return parseContentDepth(parser, depth, false);
   }

   public static CharSequence parseContentDepth(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
      return parser.getFeature("http://xmlpull.org/v1/doc/features.html#xml-roundtrip") ? parseContentDepthWithRoundtrip(parser, depth, fullNamespaces) : parseContentDepthWithoutRoundtrip(parser, depth, fullNamespaces);
   }

   private static CharSequence parseContentDepthWithoutRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
      XmlStringBuilder xml = new XmlStringBuilder();
      int event = parser.getEventType();
      boolean isEmptyElement = false;
      String namespaceElement = null;

      while(true) {
         switch(event) {
         case 2:
            xml.halfOpenElement(parser.getName());
            if (namespaceElement == null || fullNamespaces) {
               String namespace = parser.getNamespace();
               if (StringUtils.isNotEmpty(namespace)) {
                  xml.attribute("xmlns", namespace);
                  namespaceElement = parser.getName();
               }
            }

            for(int i = 0; i < parser.getAttributeCount(); ++i) {
               xml.attribute(parser.getAttributeName(i), parser.getAttributeValue(i));
            }

            if (parser.isEmptyElementTag()) {
               xml.closeEmptyElement();
               isEmptyElement = true;
            } else {
               xml.rightAngleBracket();
            }
            break;
         case 3:
            if (isEmptyElement) {
               isEmptyElement = false;
            } else {
               xml.closeElement(parser.getName());
            }

            if (namespaceElement != null && namespaceElement.equals(parser.getName())) {
               namespaceElement = null;
            }

            if (parser.getDepth() <= depth) {
               return xml;
            }
            break;
         case 4:
            xml.append((CharSequence)parser.getText());
         }

         event = parser.next();
      }
   }

   private static CharSequence parseContentDepthWithRoundtrip(XmlPullParser parser, int depth, boolean fullNamespaces) throws XmlPullParserException, IOException {
      StringBuilder sb = new StringBuilder();
      int event = parser.getEventType();

      while(true) {
         if (event != 2 || !parser.isEmptyElementTag()) {
            sb.append(parser.getText());
         }

         if (event == 3 && parser.getDepth() <= depth) {
            return sb;
         }

         event = parser.next();
      }
   }

   public static Presence parsePresence(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      ParserUtils.assertAtStartTag(parser);
      int initialDepth = parser.getDepth();
      Presence.Type type = Presence.Type.available;
      String typeString = parser.getAttributeValue("", "type");
      if (typeString != null && !typeString.equals("")) {
         type = Presence.Type.fromString(typeString);
      }

      Presence presence = new Presence(type);
      presence.setTo(ParserUtils.getJidAttribute(parser, "to"));
      presence.setFrom(ParserUtils.getJidAttribute(parser, "from"));
      presence.setStanzaId(parser.getAttributeValue("", "id"));
      String language = getLanguageAttribute(parser);
      if (language != null && !"".equals(language.trim())) {
         presence.setLanguage(language);
      }

      label61:
      do {
         while(true) {
            int eventType = parser.next();
            switch(eventType) {
            case 2:
               String elementName = parser.getName();
               String namespace = parser.getNamespace();
               byte var10 = -1;
               switch(elementName.hashCode()) {
               case -1165461084:
                  if (elementName.equals("priority")) {
                     var10 = 1;
                  }
                  break;
               case -892481550:
                  if (elementName.equals("status")) {
                     var10 = 0;
                  }
                  break;
               case 3529469:
                  if (elementName.equals("show")) {
                     var10 = 2;
                  }
                  break;
               case 96784904:
                  if (elementName.equals("error")) {
                     var10 = 3;
                  }
               }

               switch(var10) {
               case 0:
                  presence.setStatus(parser.nextText());
                  continue label61;
               case 1:
                  int priority = Integer.parseInt(parser.nextText());
                  presence.setPriority(priority);
                  continue label61;
               case 2:
                  String modeText = parser.nextText();
                  if (StringUtils.isNotEmpty(modeText)) {
                     presence.setMode(Presence.Mode.fromString(modeText));
                  } else {
                     LOGGER.warning("Empty or null mode text in presence show element form " + presence.getFrom() + " with id '" + presence.getStanzaId() + "' which is invalid according to RFC6121 4.7.2.1");
                  }
                  continue label61;
               case 3:
                  presence.setError(parseError(parser));
                  continue label61;
               default:
                  try {
                     addExtensionElement((Stanza)presence, parser, elementName, namespace);
                  } catch (Exception var14) {
                     LOGGER.log(Level.WARNING, "Failed to parse extension packet in Presence packet.", var14);
                  }
               }
            case 3:
               continue label61;
            }
         }
      } while(parser.getDepth() != initialDepth);

      return presence;
   }

   public static IQ parseIQ(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      ParserUtils.assertAtStartTag(parser);
      int initialDepth = parser.getDepth();
      IQ iqPacket = null;
      XMPPError error = null;
      String id = parser.getAttributeValue("", "id");
      Jid to = ParserUtils.getJidAttribute(parser, "to");
      Jid from = ParserUtils.getJidAttribute(parser, "from");
      IQ.Type type = IQ.Type.fromString(parser.getAttributeValue("", "type"));

      label41:
      do {
         while(true) {
            int eventType = parser.next();
            switch(eventType) {
            case 2:
               String elementName = parser.getName();
               String namespace = parser.getNamespace();
               byte var12 = -1;
               switch(elementName.hashCode()) {
               case 96784904:
                  if (elementName.equals("error")) {
                     var12 = 0;
                  }
               default:
                  switch(var12) {
                  case 0:
                     error = parseError(parser);
                     continue;
                  default:
                     IQProvider<IQ> provider = ProviderManager.getIQProvider(elementName, namespace);
                     if (provider != null) {
                        iqPacket = (IQ)provider.parse(parser);
                     } else {
                        iqPacket = new UnparsedIQ(elementName, namespace, parseElement(parser));
                     }
                     continue;
                  }
               }
            case 3:
               continue label41;
            }
         }
      } while(parser.getDepth() != initialDepth);

      if (iqPacket == null) {
         switch(type) {
         case error:
            iqPacket = new ErrorIQ(error);
            break;
         case result:
            iqPacket = new EmptyResultIQ();
         }
      }

      ((IQ)iqPacket).setStanzaId(id);
      ((IQ)iqPacket).setTo(to);
      ((IQ)iqPacket).setFrom(from);
      ((IQ)iqPacket).setType(type);
      ((IQ)iqPacket).setError(error);
      return (IQ)iqPacket;
   }

   public static Collection<String> parseMechanisms(XmlPullParser parser) throws XmlPullParserException, IOException {
      List<String> mechanisms = new ArrayList();
      boolean done = false;

      while(!done) {
         int eventType = parser.next();
         if (eventType == 2) {
            String elementName = parser.getName();
            if (elementName.equals("mechanism")) {
               mechanisms.add(parser.nextText());
            }
         } else if (eventType == 3 && parser.getName().equals("mechanisms")) {
            done = true;
         }
      }

      return mechanisms;
   }

   public static Compress.Feature parseCompressionFeature(XmlPullParser parser) throws IOException, XmlPullParserException {
      assert parser.getEventType() == 2;

      int initialDepth = parser.getDepth();
      LinkedList methods = new LinkedList();

      while(true) {
         while(true) {
            int eventType = parser.next();
            String name;
            byte var6;
            switch(eventType) {
            case 2:
               name = parser.getName();
               var6 = -1;
               switch(name.hashCode()) {
               case -1077554975:
                  if (name.equals("method")) {
                     var6 = 0;
                  }
               default:
                  switch(var6) {
                  case 0:
                     methods.add(parser.nextText());
                  default:
                     continue;
                  }
               }
            case 3:
               name = parser.getName();
               var6 = -1;
               switch(name.hashCode()) {
               case 1431984486:
                  if (name.equals("compression")) {
                     var6 = 0;
                  }
               }

               switch(var6) {
               case 0:
                  if (parser.getDepth() == initialDepth) {
                     assert parser.getEventType() == 3;

                     assert parser.getDepth() == initialDepth;

                     return new Compress.Feature(methods);
                  }
               }
            }
         }
      }
   }

   public static Map<String, String> parseDescriptiveTexts(XmlPullParser parser, Map<String, String> descriptiveTexts) throws XmlPullParserException, IOException {
      if (descriptiveTexts == null) {
         descriptiveTexts = new HashMap();
      }

      String xmllang = getLanguageAttribute(parser);
      String text = parser.nextText();
      String previousValue = (String)((Map)descriptiveTexts).put(xmllang, text);

      assert previousValue == null;

      return (Map)descriptiveTexts;
   }

   public static SaslStreamElements.SASLFailure parseSASLFailure(XmlPullParser parser) throws XmlPullParserException, IOException {
      int initialDepth = parser.getDepth();
      String condition = null;
      Map descriptiveTexts = null;

      label29:
      do {
         while(true) {
            int eventType = parser.next();
            switch(eventType) {
            case 2:
               String name = parser.getName();
               if (name.equals("text")) {
                  descriptiveTexts = parseDescriptiveTexts(parser, descriptiveTexts);
               } else {
                  assert condition == null;

                  condition = parser.getName();
               }
               break;
            case 3:
               continue label29;
            }
         }
      } while(parser.getDepth() != initialDepth);

      return new SaslStreamElements.SASLFailure(condition, descriptiveTexts);
   }

   public static StreamError parseStreamError(XmlPullParser parser) throws IOException, XmlPullParserException, SmackException {
      int initialDepth = parser.getDepth();
      List<ExtensionElement> extensions = new ArrayList();
      Map<String, String> descriptiveTexts = null;
      StreamError.Condition condition = null;
      String conditionText = null;

      label40:
      do {
         while(true) {
            int eventType = parser.next();
            switch(eventType) {
            case 2:
               String name = parser.getName();
               String namespace = parser.getNamespace();
               byte var10 = -1;
               switch(namespace.hashCode()) {
               case 904188284:
                  if (namespace.equals("urn:ietf:params:xml:ns:xmpp-streams")) {
                     var10 = 0;
                  }
               default:
                  switch(var10) {
                  case 0:
                     byte var12 = -1;
                     switch(name.hashCode()) {
                     case 3556653:
                        if (name.equals("text")) {
                           var12 = 0;
                        }
                     default:
                        switch(var12) {
                        case 0:
                           descriptiveTexts = parseDescriptiveTexts(parser, descriptiveTexts);
                           continue;
                        default:
                           condition = StreamError.Condition.fromString(name);
                           if (!parser.isEmptyElementTag()) {
                              conditionText = parser.nextText();
                           }
                           continue;
                        }
                     }
                  default:
                     addExtensionElement((Collection)extensions, parser, name, namespace);
                     continue;
                  }
               }
            case 3:
               continue label40;
            }
         }
      } while(parser.getDepth() != initialDepth);

      return new StreamError(condition, conditionText, descriptiveTexts, extensions);
   }

   public static XMPPError parseError(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      int initialDepth = parser.getDepth();
      Map<String, String> descriptiveTexts = null;
      XMPPError.Condition condition = null;
      String conditionText = null;
      List<ExtensionElement> extensions = new ArrayList();
      XMPPError.Type errorType = XMPPError.Type.fromString(parser.getAttributeValue("", "type"));
      String errorGenerator = parser.getAttributeValue("", "by");

      label40:
      do {
         while(true) {
            int eventType = parser.next();
            switch(eventType) {
            case 2:
               String name = parser.getName();
               String namespace = parser.getNamespace();
               byte var12 = -1;
               switch(namespace.hashCode()) {
               case 888780199:
                  if (namespace.equals("urn:ietf:params:xml:ns:xmpp-stanzas")) {
                     var12 = 0;
                  }
               default:
                  switch(var12) {
                  case 0:
                     byte var14 = -1;
                     switch(name.hashCode()) {
                     case 3556653:
                        if (name.equals("text")) {
                           var14 = 0;
                        }
                     default:
                        switch(var14) {
                        case 0:
                           descriptiveTexts = parseDescriptiveTexts(parser, descriptiveTexts);
                           continue;
                        default:
                           condition = XMPPError.Condition.fromString(name);
                           if (!parser.isEmptyElementTag()) {
                              conditionText = parser.nextText();
                           }
                           continue;
                        }
                     }
                  default:
                     addExtensionElement((Collection)extensions, parser, name, namespace);
                     continue;
                  }
               }
            case 3:
               continue label40;
            }
         }
      } while(parser.getDepth() != initialDepth);

      return new XMPPError(condition, conditionText, errorGenerator, errorType, descriptiveTexts, extensions);
   }

   /** @deprecated */
   @Deprecated
   public static ExtensionElement parsePacketExtension(String elementName, String namespace, XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      return parseExtensionElement(elementName, namespace, parser);
   }

   public static ExtensionElement parseExtensionElement(String elementName, String namespace, XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      ParserUtils.assertAtStartTag(parser);
      ExtensionElementProvider<ExtensionElement> provider = ProviderManager.getExtensionProvider(elementName, namespace);
      if (provider != null) {
         return (ExtensionElement)provider.parse(parser);
      } else {
         int initialDepth = parser.getDepth();
         DefaultExtensionElement extension = new DefaultExtensionElement(elementName, namespace);

         label29:
         do {
            while(true) {
               int eventType = parser.next();
               switch(eventType) {
               case 2:
                  String name = parser.getName();
                  if (parser.isEmptyElementTag()) {
                     extension.setValue(name, "");
                  } else {
                     eventType = parser.next();
                     if (eventType == 4) {
                        String value = parser.getText();
                        extension.setValue(name, value);
                     }
                  }
                  break;
               case 3:
                  continue label29;
               }
            }
         } while(parser.getDepth() != initialDepth);

         return extension;
      }
   }

   public static StartTls parseStartTlsFeature(XmlPullParser parser) throws XmlPullParserException, IOException {
      assert parser.getEventType() == 2;

      assert parser.getNamespace().equals("urn:ietf:params:xml:ns:xmpp-tls");

      int initalDepth = parser.getDepth();
      boolean required = false;

      label48:
      do {
         while(true) {
            int event = parser.next();
            switch(event) {
            case 2:
               String name = parser.getName();
               byte var6 = -1;
               switch(name.hashCode()) {
               case -393139297:
                  if (name.equals("required")) {
                     var6 = 0;
                  }
               default:
                  switch(var6) {
                  case 0:
                     required = true;
                  default:
                     continue;
                  }
               }
            case 3:
               continue label48;
            }
         }
      } while(parser.getDepth() != initalDepth);

      assert parser.getEventType() == 3;

      return new StartTls(required);
   }

   public static Session.Feature parseSessionFeature(XmlPullParser parser) throws XmlPullParserException, IOException {
      ParserUtils.assertAtStartTag(parser);
      int initialDepth = parser.getDepth();
      boolean optional = false;
      if (!parser.isEmptyElementTag()) {
         while(true) {
            while(true) {
               int event = parser.next();
               switch(event) {
               case 2:
                  String name = parser.getName();
                  byte var6 = -1;
                  switch(name.hashCode()) {
                  case -79017120:
                     if (name.equals("optional")) {
                        var6 = 0;
                     }
                  default:
                     switch(var6) {
                     case 0:
                        optional = true;
                        continue;
                     }
                  }
               case 3:
                  if (parser.getDepth() == initialDepth) {
                     return new Session.Feature(optional);
                  }
               }
            }
         }
      } else {
         return new Session.Feature(optional);
      }
   }

   private static String getLanguageAttribute(XmlPullParser parser) {
      for(int i = 0; i < parser.getAttributeCount(); ++i) {
         String attributeName = parser.getAttributeName(i);
         if ("xml:lang".equals(attributeName) || "lang".equals(attributeName) && "xml".equals(parser.getAttributePrefix(i))) {
            return parser.getAttributeValue(i);
         }
      }

      return null;
   }

   /** @deprecated */
   @Deprecated
   public static void addPacketExtension(Stanza packet, XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      addExtensionElement(packet, parser);
   }

   /** @deprecated */
   @Deprecated
   public static void addPacketExtension(Stanza packet, XmlPullParser parser, String elementName, String namespace) throws XmlPullParserException, IOException, SmackException {
      addExtensionElement(packet, parser, elementName, namespace);
   }

   /** @deprecated */
   @Deprecated
   public static void addPacketExtension(Collection<ExtensionElement> collection, XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      addExtensionElement(collection, parser, parser.getName(), parser.getNamespace());
   }

   /** @deprecated */
   @Deprecated
   public static void addPacketExtension(Collection<ExtensionElement> collection, XmlPullParser parser, String elementName, String namespace) throws XmlPullParserException, IOException, SmackException {
      addExtensionElement(collection, parser, elementName, namespace);
   }

   public static void addExtensionElement(Stanza packet, XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      ParserUtils.assertAtStartTag(parser);
      addExtensionElement(packet, parser, parser.getName(), parser.getNamespace());
   }

   public static void addExtensionElement(Stanza packet, XmlPullParser parser, String elementName, String namespace) throws XmlPullParserException, IOException, SmackException {
      ExtensionElement packetExtension = parseExtensionElement(elementName, namespace, parser);
      packet.addExtension(packetExtension);
   }

   public static void addExtensionElement(Collection<ExtensionElement> collection, XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
      addExtensionElement(collection, parser, parser.getName(), parser.getNamespace());
   }

   public static void addExtensionElement(Collection<ExtensionElement> collection, XmlPullParser parser, String elementName, String namespace) throws XmlPullParserException, IOException, SmackException {
      ExtensionElement packetExtension = parseExtensionElement(elementName, namespace, parser);
      collection.add(packetExtension);
   }

   static {
      boolean roundtrip = false;

      try {
         XML_PULL_PARSER_FACTORY = XmlPullParserFactory.newInstance();
         XmlPullParser xmlPullParser = XML_PULL_PARSER_FACTORY.newPullParser();

         try {
            xmlPullParser.setFeature("http://xmlpull.org/v1/doc/features.html#xml-roundtrip", true);
            roundtrip = true;
         } catch (XmlPullParserException var3) {
            LOGGER.log(Level.FINEST, "XmlPullParser does not support XML_ROUNDTRIP", var3);
         }
      } catch (XmlPullParserException var4) {
         throw new AssertionError(var4);
      }

      XML_PULL_PARSER_SUPPORTS_ROUNDTRIP = roundtrip;
   }
}
