org.betaconceptframework.astroboa.engine.jcr.io.contenthandler.JsonImportContentHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.betaconceptframework.astroboa.engine.jcr.io.contenthandler.JsonImportContentHandler.java

Source

/*
 * Copyright (C) 2005-2012 BetaCONCEPT Limited
 *
 * This file is part of Astroboa.
 *
 * Astroboa is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Astroboa 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 Astroboa.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.betaconceptframework.astroboa.engine.jcr.io.contenthandler;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.betaconceptframework.astroboa.api.model.RepositoryUser;
import org.betaconceptframework.astroboa.api.model.definition.Localization;
import org.betaconceptframework.astroboa.api.model.exception.CmsException;
import org.betaconceptframework.astroboa.engine.jcr.io.Deserializer;
import org.betaconceptframework.astroboa.engine.jcr.io.IOUtils;
import org.betaconceptframework.astroboa.engine.jcr.io.ImportContext;
import org.betaconceptframework.astroboa.model.impl.item.CmsBuiltInItem;
import org.betaconceptframework.astroboa.util.CmsConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

/**
 * ContentHandler responsible to listen to SAX events during 
 * JSON import.
 * 
 * Its aim is to identify which elements represent attributes
 * in order to feed ImportContentHandler with the correct information
 * 
 *  
 * @author Gregory Chomatas (gchomatas@betaconcept.com)
 * @author Savvas Triantafyllou (striantafyllou@betaconcept.com)
 * 
 */
public class JsonImportContentHandler<T> implements ContentHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private Deque<XMLElement> elementQueue = new ArrayDeque<XMLElement>();

    private ImportContentHandler<T> importContentHandler;

    private StringBuilder elementContent = new StringBuilder();

    private ImportContext importContext;

    public JsonImportContentHandler(Class<T> resultType, Deserializer deserializer) {
        importContext = new ImportContext();
        importContentHandler = new ImportContentHandler<T>(importContext, resultType, deserializer);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {

        elementContent.append(ch, start, length);

    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        XMLElement finishedElement = elementQueue.poll();

        if (finishedElement != null) {

            finishedElement.content = elementContent.toString();

            //Special cases. These built in attributes must be known when creating the actual
            //repository entity which will represent this element
            if (StringUtils.equalsIgnoreCase(CmsBuiltInItem.ContentObjectTypeName.getLocalPart(), localName)
                    || StringUtils.equalsIgnoreCase(CmsBuiltInItem.CmsIdentifier.getLocalPart(), localName)
                    || StringUtils.equalsIgnoreCase(CmsBuiltInItem.Name.getLocalPart(), localName)
                    || StringUtils.equalsIgnoreCase(CmsBuiltInItem.SystemName.getLocalPart(), localName)
                    || StringUtils.equalsIgnoreCase(CmsBuiltInItem.ExternalId.getLocalPart(), localName)) {

                if (elementQueue.isEmpty()) {
                    throw new CmsException("Element " + localName
                            + " represents a built in attribute but no parent element found");
                } else {
                    if (StringUtils.isBlank(finishedElement.content)) {
                        if (!StringUtils.equalsIgnoreCase(CmsBuiltInItem.Name.getLocalPart(), localName)) {
                            throw new CmsException("Element " + localName + " must have a value");
                        }
                    } else {

                        XMLElement parentElement = elementQueue.peek();

                        IOUtils.addAttribute(parentElement.attributes, localName, finishedElement.content.trim());

                        parentElement.childElements.remove(finishedElement);

                    }
                }
            } else {
                //Forward Element to be imported normally
                if (elementQueue.isEmpty()) {
                    importElement(uri, localName, qName, finishedElement);
                }
            }

            logger.debug("Removed element {} from the queue", localName);

        }

        clearElementContent();
    }

    /*
    private void printAttributes(Attributes atts) throws SAXException {
           
       if (atts != null && atts.getLength() >0){
     for (int i=0;i<atts.getLength();i++){
            
        logger.debug(atts.getLocalName(i)+ ":"+ atts.getValue(i));
     }
       }
           
    }*/

    private void importElement(String uri, String localName, String qName, XMLElement element) throws SAXException {

        importContentHandler.startElement(uri, localName, qName, element.attributes);

        if (!element.childElements.isEmpty()) {

            Object entityCurrentlyImported = importContentHandler.getCurrentEntityImported();

            boolean elementContainsTheLabelsOfAnEntity = CmsBuiltInItem.Localization.getLocalPart()
                    .equalsIgnoreCase(localName) && entityCurrentlyImported != null
                    && entityCurrentlyImported instanceof Localization;

            for (XMLElement childElement : element.childElements) {

                entityCurrentlyImported = importContentHandler.getCurrentEntityImported();

                //Check if element represents a built in attribute
                if (elementContainsTheLabelsOfAnEntity
                        && CmsConstants.LOCALIZED_LABEL_ELEMENT_NAME.equalsIgnoreCase(childElement.localName)
                        && CollectionUtils.isNotEmpty(childElement.childElements)) {

                    for (XMLElement childElementOfLabel : childElement.childElements) {
                        ((Localization) entityCurrentlyImported).addLocalizedLabel(childElementOfLabel.localName,
                                childElementOfLabel.content);
                    }
                } else if (childElement.childElements.isEmpty() && importContext
                        .nameCorrespondsToAnAttribute(childElement.localName, entityCurrentlyImported)) {

                    importContentHandler.addAttributeToImportedEntity(childElement.localName, childElement.content);
                } else if (entityCurrentlyImported != null && entityCurrentlyImported instanceof RepositoryUser
                        && CmsConstants.URL_ATTRIBUTE_NAME.equalsIgnoreCase(childElement.localName)) {
                    continue; //Do not import attribute URL for RepositoryUser entity as it is not yet supported
                } else {
                    importElement(uri, childElement.localName, childElement.localName, childElement);
                }
            }
        }

        if (element.content != null) {
            importContentHandler.characters(element.content.toCharArray(), 0, element.content.length());
        }

        importContentHandler.endElement(uri, localName, qName);
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {

        XMLElement element = new XMLElement();
        element.localName = localName;

        if (!elementQueue.isEmpty()) {

            XMLElement parentElement = elementQueue.peek();

            parentElement.childElements.add(element);

        }

        elementQueue.push(element);

        logger.debug("Pushed element {} to queue", localName);

    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException {
        importContentHandler.endPrefixMapping(prefix);

    }

    @Override
    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
        importContentHandler.ignorableWhitespace(ch, start, length);
    }

    @Override
    public void processingInstruction(String target, String data) throws SAXException {
        importContentHandler.processingInstruction(target, data);
    }

    @Override
    public void setDocumentLocator(Locator locator) {
        importContentHandler.setDocumentLocator(locator);
    }

    @Override
    public void skippedEntity(String name) throws SAXException {
        importContentHandler.skippedEntity(name);
    }

    @Override
    public void startDocument() throws SAXException {
        importContentHandler.startDocument();
    }

    @Override
    public void endDocument() throws SAXException {

        elementQueue.clear();

        importContentHandler.endDocument();

    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        importContentHandler.startPrefixMapping(prefix, uri);

    }

    public T getResult() {
        return importContentHandler.getImportResult();
    }

    private class XMLElement {

        private String localName;

        private String content;

        //Built in attribute values
        private AttributesImpl attributes = new AttributesImpl();

        private List<XMLElement> childElements = new ArrayList<XMLElement>();

        public String toString() {
            return localName;
        }
    }

    private void clearElementContent() {
        elementContent.delete(0, elementContent.length());
    }

}