/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions;
import java.util.logging.*;
import net.java.sip.communicator.service.protocol.jabber.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import org.xmlpull.v1.*;
/**
* A provider that parses incoming packet extensions into instances of the
* {@link Class} that it has been instantiated for.
*
* @param <C> Class that the packets we will be parsing belong to
* @author Emil Ivov
*/
public class DefaultPacketExtensionProvider<C extends AbstractPacketExtension>
implements PacketExtensionProvider
{
/**
* The <tt>Logger</tt> used by the <tt>DefaultPacketExtensionProvider</tt>
* class and its instances for logging output.
*/
private static final Logger logger = Logger
.getLogger(DefaultPacketExtensionProvider.class.getName());
/**
* The <tt>AbstractSmackInteroperabilityLayer</tt> instance implementing
* necessary methods
*/
private AbstractSmackInteroperabilityLayer smackInteroperabilityLayer =
AbstractSmackInteroperabilityLayer.getInstance();
/**
* The {@link Class} that the packets we will be parsing here belong to.
*/
private final Class<C> packetClass;
/**
* Creates a new packet provider for the specified packet extensions.
*
* @param c the {@link Class} that the packets we will be parsing belong to.
*/
public DefaultPacketExtensionProvider(Class<C> c)
{
this.packetClass = c;
}
/**
* Parse an extension sub-packet and create a <tt>C</tt> instance. At
* the beginning of the method call, the xml parser will be positioned on
* the opening element of the packet extension and at the end of the method
* call it will be on the closing element of the packet extension.
*
* @param parser an XML parser positioned at the packet's starting element.
*
* @return a new packet extension instance.
*
* @throws java.lang.Exception if an error occurs parsing the XML.
*/
public C parseExtension(XmlPullParser parser) throws Exception
{
C packetExtension = packetClass.newInstance();
//first, set all attributes
int attrCount = parser.getAttributeCount();
for (int i = 0; i < attrCount; i++)
{
packetExtension.setAttribute(
parser.getAttributeName(i),
parser.getAttributeValue(i));
}
//now parse the sub elements
boolean done = false;
int eventType;
String elementName;
String namespace;
while (!done)
{
eventType = parser.next();
elementName = parser.getName();
namespace = parser.getNamespace();
if (logger.isLoggable(Level.FINEST))
logger.finest("Will parse " + elementName
+ " ns=" + namespace
+ " class=" + packetExtension.getClass().getSimpleName());
if (eventType == XmlPullParser.START_TAG)
{
PacketExtensionProvider provider = smackInteroperabilityLayer
.getExtensionProvider( elementName, namespace );
if(provider == null)
{
//we don't know how to handle this kind of extensions.
logger.fine("Could not add a provider for element "
+ elementName + " from namespace " + namespace);
}
else
{
PacketExtension childExtension
= provider.parseExtension(parser);
if(namespace != null)
{
if(childExtension instanceof AbstractPacketExtension)
{
((AbstractPacketExtension)childExtension).
setNamespace(namespace);
}
}
packetExtension.addChildExtension(childExtension);
}
}
if (eventType == XmlPullParser.END_TAG)
{
if (parser.getName().equals(packetExtension.getElementName()))
{
done = true;
}
}
if (eventType == XmlPullParser.TEXT)
{
String text = parser.getText();
packetExtension.setText(text);
}
if (logger.isLoggable(Level.FINEST))
logger.finest("Done parsing " + elementName);
}
return packetExtension;
}
}