/** * Copyright (c) 2013, Redsolution LTD. All rights reserved. * * This file is part of Xabber project; you can redistribute it and/or * modify it under the terms of the GNU General Public License, Version 3. * * Xabber is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License, * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.xabber.xmpp; import org.xmlpull.v1.XmlPullParser; /** * Provides common interface to parse extensions. * * @param <Extension> * @author alexander.ivanov */ public abstract class AbstractExtensionProvider<Extension extends PacketExtension> extends org.jivesoftware.smack.provider.ExtensionElementProvider<Extension> { /** * Creates an instance. * <p/> * Parser position mustn't be changed. * * @param parser * @return */ abstract protected Extension createInstance(XmlPullParser parser); /** * Parse XML tag and create instance. * * @param parser an XML parser. * @return new instance. * @throws Exception if an error occurs while parsing. */ public Extension provideInstance(XmlPullParser parser) throws Exception { Extension instance = createInstance(parser); return parseTag(parser, instance); } /** * Parse XML tag and populate element instance. At the beginning of the * method call, the XML parser will be positioned on the opening tag. At the * end of the method call, the parser <b>must</b> be positioned on the end * of processed tag. * * @param parser an XML parser. * @param instance instance to be updated. * @return updated or replaced instance. * @throws Exception if an error occurs parsing the XML. */ public Extension parseTag(XmlPullParser parser, Extension instance) throws Exception { String name = parser.getName(); instance = preProcess(parser, instance); while (true) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG) { if (!parseInner(parser, instance)) ProviderUtils.skipTag(parser); } else if (eventType == XmlPullParser.END_TAG) { if (name.equals(parser.getName())) break; else throw new IllegalStateException(); } else if (eventType == XmlPullParser.END_DOCUMENT) break; } return postProcess(instance); } /** * Updates instance from tag name or attributes. * <p/> * Parser position mustn't be changed. * * @param instance * @param parser * @return modified instance. */ protected Extension preProcess(XmlPullParser parser, Extension instance) { return instance; } /** * Called when packet have been fully parsed. * <p/> * Parser position mustn't be changed. * * @param instance * @return modified instance. */ protected Extension postProcess(Extension instance) { return instance; } /** * Parses inner tag. * <p/> * Parser position either <b>must</b> be move to the end of processed tag, * either <b>mustn't</b> be changed at all. * * @param parser * @param instance * @return Whether parser position have been changed. * @throws Exception */ protected boolean parseInner(XmlPullParser parser, Extension instance) throws Exception { return false; } @Override public Extension parse(XmlPullParser parser, int initialDepth) throws Exception { return provideInstance(parser); } }