Package cz.cuni.mff.inetpaint.svgwb

Source Code of cz.cuni.mff.inetpaint.svgwb.SVGWBExtensionProvider

package cz.cuni.mff.inetpaint.svgwb;

import java.io.ByteArrayInputStream;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;

import org.w3c.dom.*;
import javax.xml.parsers.*;

/**
* Provider parsující {@link SVGWBExtension} z paketů.
*
* @see PacketExtension
* @see PacketExtensionProvider
*
* @author Jindřich Helcl
*/
public class SVGWBExtensionProvider implements PacketExtensionProvider {
    XmlPullParser parser;

    /**
     * Tato metoda jednoduše zahodí všechen text, pokud na něj zrovna parser narazil
     * @throws Exception
     */
    private void ignoreText() throws Exception {
        while(parser.getEventType() == parser.TEXT) {
            parser.next();
        }
    }

    /**
     * Tato metoda zkopíruje právě zpracovávaný XML element do řetězce
     *
     * @param xpp Reference na XmlPullParser, který bude použit při kopírování.
     * @return String obsahující otevírající tag, obsah elementu, a jeho uzavírající tag
     * @throws Exception Pokud XmlPullParser není ve stavu START_TAG a pokud se zjistí invalidita dokumentu
     */
    private String copyXMLElement(XmlPullParser xpp) throws Exception {
        StringBuilder sb = new StringBuilder("");

        // Pokud nejsem na START_TAG, vyhodim vyjimku
        if(xpp.getEventType() != xpp.START_TAG) throw new Exception("xpp is not on START_TAG");

        //jsem START TAG, zkopiruju se na vystup a pak zkopiruju svuj obsah
        sb.append(xpp.getText());

        // nejsem-li prázdný, zkopíruju svůj obsah
        if(!xpp.isEmptyElementTag()) {
            // pokud je pristim eventem TEXT, zkopiruju text
            int event = xpp.next();
            if(event == xpp.TEXT) {
                sb.append(xpp.getText());
                event = xpp.next();
            }

            //dokud neni pristi element END_TAG, kopiruju tagy a přidávám je do StringBufferu.
            while(event != xpp.END_TAG) {
                // je-li to text, zkopiruju
                if(event == xpp.TEXT) {
                    // zkopiruju text a posunu rafičku
                    sb.append(xpp.getText());
                    event = xpp.next();
                    continue;
                }

                if(event == xpp.START_TAG) {
                    // pripojim zkopirovany vnoreny element
                    sb.append(copyXMLElement(xpp));
                    // rafička je teď zase buď na TEXT, START TAG nebo END TAG
                    // pokud je na END TAG, je to na mě a je konec
                    event = xpp.getEventType();
                    continue;
                }
            }

            // ted je na rade koncovy tag. jediny problem je v tom, ze
            // kdyz dam gettext, bude tam s lomitkem na druhe strane..

            sb.append(xpp.getText());

        }
        // byl-li jsem na empty tagu, rafička bude hned ted na END_TAG
        else {
            xpp.next();
        }

        // ted jsem na END_TAG, takze posunu parser
        xpp.next();

        return sb.toString();
    }

    /**
     * Metoda vrátí objektovou reprezentaci SVGWB element <new> a posune parser za jeho koncový tag
     * @return Instance objektu SVGWBNewElement
     * @throws Exception Pokud není dokument validní, nebo pokud nezačínám na začátku tagu <new>
     */
    private SVGWBNewElement parseNewElement() throws Exception{
        String id = parser.getAttributeValue(null, "id");
        String indexStr = parser.getAttributeValue(null, "index");

        float index = Float.parseFloat(indexStr);

        String versionStr = parser.getAttributeValue(null, "version");
        String parent = parser.getAttributeValue(null, "parent");

        SVGWBNewElement el = new SVGWBNewElement(id, index);

        if(versionStr != null)
            el.setVersion(Integer.parseInt(versionStr));

        if(parent != null)
            el.setParent(parent);

        parser.next();
        // ted jsem za zacatecnim tagem <new>. nasleduje bud TEXT, nebo START TAG..
        ignoreText();
       
        //ted musi byt START.
        if(parser.getEventType() != parser.START_TAG) throw new Exception("invalid");
        // zacal vnitrni tag. ten musi byt presne jeden, takze vezmu vsecko co je
        // na tehle urovni.

        String svgContent = copyXMLElement(parser);
       
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

        factory.setNamespaceAware(true);
        DocumentBuilder builder = factory.newDocumentBuilder();

        Document doc = builder.parse(new ByteArrayInputStream(svgContent.getBytes()));
        el.setSVGContent((Element)doc.getDocumentElement().cloneNode(true));

        //ted jsme za koncovym tagem SVG obsahu. bud je TEXT, ktery zahodim, anebo je END_TAG
        ignoreText();

        //ted musi prijit end tag tagu <new/>
        if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");

        // jsem na konci tagu new. zahodim ho.
        parser.next();

        return el;
    }
    
    /**
     * Metoda vrátí objektovou reprezentaci elementu editace atributu a posune parser za jeho koncový tag
     * @return Instance objektu AttributeElementEdit
     * @throws Exception Pokud není dokument validní, nebo pokud nezačínám na příslušném otevírajícím tagu
     */
    private SVGWBConfigureElement.AttributeElementEdit parseAttributeElementEdit() throws Exception {
        //jsem na startu elementu attribute.
        String name = parser.getAttributeValue(null, "name");
        String fromStr = parser.getAttributeValue(null, "from");
        String toStr = parser.getAttributeValue(null, "to");

        //obsah elementu: je-li prázdný, content nastavím na prázdný řetězec
        String content;

        if(parser.isEmptyElementTag()) {
            content = "";

            //posunu parser na pozici END_TAG:
            parser.next();
        }
        else {
            //element není degenerovaný
            int event = parser.next();
            StringBuilder sb = new StringBuilder("");

            while(event == parser.TEXT) {
                sb.append(parser.getText());
                event = parser.next();
            }

            content = sb.toString();
            //ted jsem na pozici END_TAG, nebo START TAG. Pokud je START TAG, je to invalidní
            if(event == parser.START_TAG) throw new Exception("invalid - tag v elementu attribute");

            //ted jsem na pozici END_TAG
        }

        // posunu parser za END_TAG a nastavim hodnoty do objektu
        parser.next();

        SVGWBConfigureElement.AttributeElementEdit el = new SVGWBConfigureElement.AttributeElementEdit(name, content);

        if(fromStr != null) {
            int from = Integer.parseInt(fromStr);
            el.setFrom(from);
        }

        if(toStr != null) {
            int to = Integer.parseInt(toStr);
            el.setTo(to);
        }

        return el;
    }

    /**
     * Metoda vrátí objektovou reprezentaci elementu editace obsahu a posune parser za jeho koncový tag
     * @return Instance objektu ContentElementEdit
     * @throws Exception Pokud není dokument validní, nebo pokud nezačínám na příslušném otevírajícím tagu
     */
    private SVGWBConfigureElement.ContentElementEdit parseContentElementEdit() throws Exception {
        //content nema zadne atributy, zajima nas jen obsah..
        String content;

        if(parser.isEmptyElementTag()) {
            content = "";
            parser.next();
        }

        else {
           StringBuilder sb = new StringBuilder("");

           int event = parser.next();

           while(event == parser.TEXT) {
               sb.append(parser.getText());
               event = parser.next();
           }

           content = sb.toString();
           if(event == parser.START_TAG) throw new Exception("invalid - another element found inside a content element");
        }

        parser.next();

        SVGWBConfigureElement.ContentElementEdit el = new SVGWBConfigureElement.ContentElementEdit(content);
        return el;
    }

    /**
     * Metoda vrátí objektovou reprezentaci elementu editace rodiče a posune parser za jeho koncový tag
     * @return Instance objektu ParentElementEdit
     * @throws Exception Pokud není dokument validní, nebo pokud nezačínám na příslušném otevírajícím tagu
     */
    private SVGWBConfigureElement.ParentElementEdit parseParentElementEdit() throws Exception {
        //parent nema zadne atributy, zajima nas jen obsah..
        String content;

        if(parser.isEmptyElementTag()) {
            content = "";
            parser.next();
        }

        else {
           StringBuilder sb = new StringBuilder("");

           int event = parser.next();

           while(event == parser.TEXT) {
               sb.append(parser.getText());
               event = parser.next();
           }

           content = sb.toString();
           if(event == parser.START_TAG) throw new Exception("invalid - another element found inside a parent element");
        }

        parser.next();

        SVGWBConfigureElement.ParentElementEdit el = new SVGWBConfigureElement.ParentElementEdit(content);
        return el;
    }

    /**
    *  Metoda vrátí objektovou reprezentaci SVGWB element &lt;configure&gt; a posune parser za jeho koncový tag
    *  @return Instance objektu SVGWBConfigureElement
    *  @throws Exception Pokud není dokument validní, nebo pokud nezačínám na začátku tagu &lt;configure&gt;
    */
    private SVGWBConfigureElement parseConfigureElement() throws Exception {
        String target = parser.getAttributeValue(null, "target");
        String verStr = parser.getAttributeValue(null, "version");

        int version = Integer.parseInt(verStr);

        SVGWBConfigureElement el = new SVGWBConfigureElement(target, version);

        // jsem na zacatku configure tagu. pokud je prázdný, přejdu za jeho konec a vrátím ho.
        if(parser.isEmptyElementTag()) {
            parser.next(); // posunul jsem se na END TAG configure
            parser.next(); // posunul jsem se za tag configure
            return el;
        }

        //element configure tedy není prázdný (ve smyslu nepárového tagu). Text mohu zahodit, není potřeba
        parser.next();
        ignoreText();
       
        //teď bude následovat buď END_TAG, anebo START TAG některé z editací.
        //pokud bude START TAG, editaci zpracuji a zahodím text za ní.
        while(parser.getEventType() != parser.END_TAG) {
            //teď musím být na START_TAGu.

            // jsou tři typu elementů, na které zde mohu narazit. attribute, parent nebo content
            String name = parser.getName();
            if(name.equals("attribute")) {
                el.addEdit(parseAttributeElementEdit());
            }

            if(name.equals("parent")) {
                el.addEdit(parseParentElementEdit());
            }

            if(name.equals("content")) {
                el.addEdit(parseContentElementEdit());
            }

            ignoreText();
        }

        //ted jsem na konci tagu configure. prejdu za nej a vrátím vytvořený objekt.
        parser.next();
   
        return el;
    }

    private SVGWBRemoveElement parseRemoveElement() throws Exception {
        String target = parser.getAttributeValue(null, "target");

        //remove element musí být prázdný, tj, další musí být end_tag.
        parser.next();
        ignoreText();

        if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");

        //posunu za konec remove elementu
        parser.next();

        return new SVGWBRemoveElement(target);
    }

    private SVGWBMoveElement parseMoveElement() throws Exception {
        String target = parser.getAttributeValue(null, "target");
        String diStr = parser.getAttributeValue(null, "di");

        float di = Float.parseFloat(diStr);

        parser.next();
        ignoreText();

        //move element musí být prázdný, tj, další musí být end_tag.
        if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");

        // posunu parser za konec elementu
        parser.next();

        return new SVGWBMoveElement(target, di);
    }

    private SVGWBProtocolElement.EmptyProtocolElement parseEmptyProtocolElement(
            SVGWBProtocolElement.EmptyProtocolElement.Type type) throws Exception {
        //tento element je prazdny. jsem na start tagu
        parser.next();
        ignoreText();
        //ted jsem urcite na end_tagu. kdyz ne, je to spatne
        if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid - empty element is not empty");
        //posunu se za konec
        parser.next();
        return new SVGWBProtocolElement.EmptyProtocolElement(type);
    }

    private SVGWBProtocolElement.ProtocolAbortNegotiationElement parseAbortNegotiationElement() throws Exception {
        // start tagu abort negotiation - zadne atributy, jen podelementy, nepovinne
        parser.next();
        ignoreText();
       
        // ted muzu byt bud na konci anebo na nejakem z duvodu.
        SVGWBProtocolElement.ProtocolAbortNegotiationElement el = new SVGWBProtocolElement.ProtocolAbortNegotiationElement();
       
        if(parser.getEventType() == parser.START_TAG) {
            if(parser.getName().equals("supported-features")) {
                // jsem na zacatku tagu supported features. ten nema atributy a obsahuje
                // jen tagy feature
                el.setFeaturesUnsupported(true);
               
                parser.next();
                ignoreText();
                               
                while(parser.getEventType() == parser.START_TAG) {
                    // jsem na zacatku tagu feature
                    if(!parser.getName().equals("feature")) throw new Exception("invalid");
                   
                    parser.next();
                   
                    //ted nasleduje nazev featury
                    if(parser.getEventType() != parser.TEXT) throw new Exception("invalid");
                    String text = parser.getText().trim();
                    if(text.isEmpty()) throw new Exception("invalid");
                   
                    el.addFeature(text);
                   
                    //konec tagu feature
                    if(parser.next() != parser.END_TAG) throw new Exception("invalid");
                   
                    //posunu za konec
                    parser.next();
                    //preskocim text k dalsimu elementu feature nebo na konec tagu supported features
                    ignoreText();
                }    
               
                // jsem na end_tagu. posunu se za nej
                parser.next();               
            }
           
            else if(parser.getName().equals("peer-already-in-session")) {
                el.setAlreadyLogged(true);
               
                // jsem na zacatku elementu
                parser.next();
               
                if(parser.getEventType() == parser.TEXT) {
                    String text = parser.getText().trim();
                    // muze obsahovat session id. kdyz ho neobsahuje, nic nedelam
                   
                    if(!text.isEmpty())
                        el.setSessionID(text);
                   
                    parser.next();                   
                }
               
                // ted musim byt na konci elementu
                if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");
               
                //posunu za konec
                parser.next();               
            }
          
            else throw new Exception("invalid - unknown reason-tag");
           
        }
        // jsem za tagem s duvodama
        ignoreText();
        if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");

        parser.next();

        return el;
    }

    private SVGWBProtocolElement.ProtocolDocumentEndElement parseDocumentEndElement() throws Exception {
        // document end musi obsahovat element last-wb. sam nema zadne atributy, ale last-wb
        // musi mit atributy sender a hash.

        parser.next();
        ignoreText();

        if(parser.getEventType() != parser.START_TAG) throw new Exception("invalid");
        if(!parser.getName().equals("last-wb")) throw new Exception("invalid");

        String sender = parser.getAttributeValue(null, "sender");
        String hash = parser.getAttributeValue(null, "hash");

        if(sender == null || sender.isEmpty() || hash == null || hash.isEmpty()) throw new Exception("invalid");

        SVGWBProtocolElement.ProtocolDocumentEndElement el = new SVGWBProtocolElement.ProtocolDocumentEndElement(sender, hash);

        parser.next();
        ignoreText();

        if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");

        //posunu se za konec
        parser.next();

        return el;
    }


    private SVGWBProtocolElement.ProtocolElementWithFeatures parseElementWithFeatures(
            SVGWBProtocolElement.ProtocolElementWithFeatures.Type type) throws Exception {

        // jsem na zacatku elementu s featurama. tyhle elementy nemaji zadne atributy,
        // jen podelementy feature, jez maji textovy obsah, ktery nas zajima.

        SVGWBProtocolElement.ProtocolElementWithFeatures el = new SVGWBProtocolElement.ProtocolElementWithFeatures(type);

        //posunu za start
        parser.next();
        ignoreText();

        while(parser.getEventType() == parser.START_TAG) {
            if(!parser.getName().equals("feature")) throw new Exception("invalid");

            // ted jsme na zacatku tagu feature.
            parser.next();

            if(parser.getEventType() != parser.TEXT) throw new Exception("invalid");

            String text = parser.getText().trim();
            if(text.isEmpty()) throw new Exception("invalid - empty feature");
            el.addFeature(text);

            parser.next();
            if(parser.getEventType() != parser.END_TAG) throw new Exception("invalid");

            // jsme na konci tagu, posunu se dal
            parser.next();
            ignoreText();
        }

        //jsem na konci tagu, posunu se dal
        parser.next();
        return el;
    }


    private SVGWBProtocolElement parseProtocolElement() throws Exception {
        //element protocol nema zadne atributy.
        //protocol ma prave jeden podelement urcujici typ zpravy.

        parser.next();
        ignoreText();

        if(parser.getEventType() != parser.START_TAG) throw new Exception("invalid protocol element");
        //jsem na zacatku tagu

        String name = parser.getName();

        SVGWBProtocolElement el;

        if(name.equals("history-offer")) el = parseElementWithFeatures(SVGWBProtocolElement.ProtocolElementWithFeatures.Type.history_offer) ;
        else if(name.equals("abort-negotiation")) el = parseAbortNegotiationElement();
        else if(name.equals("invitation")) el = parseElementWithFeatures(SVGWBProtocolElement.ProtocolElementWithFeatures.Type.invitation);
        else if(name.equals("connect-request")) el = parseEmptyProtocolElement(SVGWBProtocolElement.EmptyProtocolElement.Type.connect_request);
        else if(name.equals("accept-invitation")) el = parseEmptyProtocolElement(SVGWBProtocolElement.EmptyProtocolElement.Type.accept_invitation) ;
        else if(name.equals("accept-history")) el =  parseEmptyProtocolElement(SVGWBProtocolElement.EmptyProtocolElement.Type.accept_history);
        else if(name.equals("document-begin")) el =  parseEmptyProtocolElement(SVGWBProtocolElement.EmptyProtocolElement.Type.document_begin);
        else if(name.equals("document-end")) el = parseDocumentEndElement();
        else throw new Exception("unknown protocol tag");

        // ted jsem za koncem vnitrniho elementu
        ignoreText();

        //ted musi byt end tag
        if(parser.getEventType() != parser.END_TAG) throw new Exception("more than one elements in protocol element");

        //jdu za end tag
        parser.next();
        return el;
    }

    private SVGWBExtension parseRootElement() throws Exception {
        String session = parser.getAttributeValue(null, "sesion");
        String hash = parser.getAttributeValue(null, "hash");

        SVGWBExtension ext = new SVGWBExtension(session, hash);

        parser.next();
        //ted jsem za zacatkem korenoveho elementu.
        //dokud zacinaji nove elementy, tak je zpracovavam.

        ignoreText();

        while(parser.getEventType() == parser.START_TAG) {
            String name = parser.getName();

            if(name.equals("protocol"))
                ext.addElement(parseProtocolElement());

            else if(name.equals("move"))
                ext.addElement(parseMoveElement());

            else if(name.equals("remove"))
                ext.addElement(parseRemoveElement());

            else if(name.equals("new"))
                ext.addElement(parseNewElement());

            else if(name.equals("configure"))
                ext.addElement(parseConfigureElement());

            else throw new Exception("unknown element");

            //přeskočím text k dalšímu elementu
            ignoreText();
        }

        // ted je end_tag korenoveho elementu
       
        //ted uz jsem na konci dokumentu
        //if(parser.getEventType() != parser.END_DOCUMENT) throw new Exception("eof expected");
        return ext;
    }

    @Override
    public PacketExtension parseExtension(XmlPullParser xppp) throws Exception {
        parser = xppp;

        if(parser.getEventType() != parser.START_TAG) throw new Exception();
       
        //zpracovat prvni element. musi to byt wb. ale mam to validovat? to prece ne
        // spoleham na to, ze je to validni..
        PacketExtension ext = parseRootElement();
       
        return ext;
    }
}
TOP

Related Classes of cz.cuni.mff.inetpaint.svgwb.SVGWBExtensionProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.