net.tirasa.hct.cocoon.sax.HippoRepositoryTransformer.java Source code

Java tutorial

Introduction

Here is the source code for net.tirasa.hct.cocoon.sax.HippoRepositoryTransformer.java

Source

/*
 * Copyright (C) 2012 Tirasa
 *
 * 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.tirasa.hct.cocoon.sax;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import javax.jcr.RepositoryException;
import net.tirasa.hct.cocoon.cache.AvailabilityLocaleCacheKey;
import net.tirasa.hct.cocoon.sax.Constants.Attribute;
import net.tirasa.hct.cocoon.sax.Constants.Availability;
import net.tirasa.hct.cocoon.sax.Constants.Element;
import net.tirasa.hct.cocoon.sax.Constants.StartEndDocumentFilter;
import net.tirasa.hct.cocoon.sax.Constants.State;
import net.tirasa.hct.hstbeans.HCTTaxonomyCategoryBean;
import net.tirasa.hct.hstbeans.HippoCompoundDocument;
import net.tirasa.hct.hstbeans.HippoDate;
import net.tirasa.hct.hstbeans.RelatedDocs;
import net.tirasa.hct.repository.HCTConnManager;
import net.tirasa.hct.repository.HCTDocument;
import net.tirasa.hct.repository.HCTQuery;
import net.tirasa.hct.repository.HCTQueryResult;
import net.tirasa.hct.repository.HCTTraversal;
import net.tirasa.hct.util.ObjectUtils;
import net.tirasa.hct.util.TaxonomyUtils;
import org.apache.cocoon.configuration.Settings;
import org.apache.cocoon.pipeline.ProcessingException;
import org.apache.cocoon.pipeline.caching.CacheKey;
import org.apache.cocoon.pipeline.component.CachingPipelineComponent;
import org.apache.cocoon.sax.AbstractSAXTransformer;
import org.apache.cocoon.sax.util.XMLUtils;
import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.hippoecm.hst.content.beans.ObjectBeanManagerException;
import org.hippoecm.hst.content.beans.standard.HippoAsset;
import org.hippoecm.hst.content.beans.standard.HippoBean;
import org.hippoecm.hst.content.beans.standard.HippoDocument;
import org.hippoecm.hst.content.beans.standard.HippoFacetSelect;
import org.hippoecm.hst.content.beans.standard.HippoFolder;
import org.hippoecm.hst.content.beans.standard.HippoGalleryImageSet;
import org.hippoecm.hst.content.beans.standard.HippoHtml;
import org.hippoecm.hst.content.beans.standard.HippoItem;
import org.hippoecm.hst.content.beans.standard.HippoMirror;
import org.hippoecm.repository.api.HippoNodeType;
import org.onehippo.forge.ecmtagging.TaggingNodeType;
import org.onehippo.forge.ecmtagging.providers.AllTagsProvider;
import org.onehippo.taxonomy.api.TaxonomyNodeTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

public class HippoRepositoryTransformer extends AbstractSAXTransformer implements CachingPipelineComponent {

    private static final Logger LOG = LoggerFactory.getLogger(HippoRepositoryTransformer.class);

    private static final String PARAM_LOCALE = "locale";

    private static final String PARAM_AVAILABILITY = "availability";

    private Locale locale;

    private Availability availability;

    private State state;

    private transient HCTDocument hctDocument;

    private transient HCTTraversal hctTraversal;

    private transient HCTQuery hctQuery;

    @Override
    @SuppressWarnings("unchecked")
    public void setConfiguration(final Map<String, ? extends Object> configuration) {
        this.setup((Map<String, Object>) configuration);
    }

    @Override
    public void setup(final Map<String, Object> parameters) {
        if (parameters == null) {
            return;
        }

        if (parameters.containsKey(PARAM_AVAILABILITY)) {
            try {
                availability = Availability.valueOf((String) parameters.get(PARAM_AVAILABILITY));
            } catch (IllegalArgumentException e) {
                availability = Availability.live;

                LOG.warn("Invalid availability specified, reverting to " + availability, e);
            }
        } else {
            availability = Availability.live;

            LOG.warn("No availability specified, reverting to " + availability);
        }

        Locale defaultLocale;
        if (parameters.containsKey(Settings.ROLE)) {
            final Settings settings = (Settings) parameters.get(Settings.ROLE);
            final String localeString = settings.getProperty("net.tirasa.hct.defaultLocale",
                    Locale.getDefault().getLanguage());
            try {
                defaultLocale = LocaleUtils.toLocale(localeString);
            } catch (IllegalArgumentException e) {
                defaultLocale = Locale.getDefault();

                LOG.error("Could not parse provided '{}' as default Locale", localeString, e);
            }
        } else {
            defaultLocale = Locale.getDefault();
        }

        if (parameters.containsKey(PARAM_LOCALE)) {
            try {
                locale = LocaleUtils.toLocale((String) parameters.get(PARAM_LOCALE));
            } catch (IllegalArgumentException e) {
                locale = defaultLocale;

                LOG.error("Could not parse provided '{}' as Locale", parameters.get(PARAM_LOCALE), e);
            }
        } else {
            locale = defaultLocale;

            LOG.warn("No locale specified, reverting to " + locale);
        }

        state = State.OUTSIDE;
    }

    @Override
    public void finish() {
        state = null;

        super.finish();
    }

    @Override
    public CacheKey constructCacheKey() {
        return new AvailabilityLocaleCacheKey(availability, locale);
    }

    private void findAndDumpImagesAndAssets(final HCTConnManager connManager, final HippoDocument doc,
            final HippoItemXMLDumper dumper) throws ObjectBeanManagerException, SAXException {

        final List<HippoGalleryImageSet> images = new ArrayList<HippoGalleryImageSet>();
        final List<HippoAsset> assets = new ArrayList<HippoAsset>();
        for (HippoMirror mirror : doc.getChildBeans(HippoMirror.class)) {
            final HippoBean bean = mirror.getReferencedBean();
            if (bean != null) {
                if (bean instanceof HippoGalleryImageSet) {
                    final HippoItem subElement = ObjectUtils.getHippoItemByUuid(connManager,
                            (String) ((HippoFacetSelect) mirror).getProperty(HippoNodeType.HIPPO_DOCBASE));
                    if (subElement instanceof HippoGalleryImageSet) {
                        images.add((HippoGalleryImageSet) subElement);
                    }
                }
                if (bean instanceof HippoAsset) {
                    assets.add((HippoAsset) bean);
                }
            }
        }
        dumper.dumpImages(images, Element.IMAGE.getName(), true);
        dumper.dumpAssets(assets, Element.ASSET.getName(), true, hctDocument.getDateFormat(), locale);
    }

    private void compounds(final HCTConnManager connManager, final HippoDocument container,
            final HippoItemXMLDumper dumper, final XMLReader xmlReader)
            throws SAXException, RepositoryException, ObjectBeanManagerException, IOException {

        dumper.startHippoCompounds();
        for (HippoDocument compound : container.getChildBeans(HippoCompoundDocument.class)) {
            dumper.startHippoCompound(compound);

            // 1 Compound properties
            for (Entry<String, Object> entry : compound.getProperties().entrySet()) {
                dumper.dumpField(entry, hctDocument.getDateFormat(), locale);
            }

            // 2 Compound date fields
            for (HippoDate date : compound.getChildBeans(HippoDate.class)) {
                dumper.dumpDate(date.getName(), date.getCalendar(), hctDocument.getDateFormat(), locale);
            }

            // 3 Compound HTML fields
            for (HippoHtml rtf : compound.getChildBeans(HippoHtml.class)) {
                dumper.dumpHtml(connManager, rtf, xmlReader, hctDocument.getDateFormat(), locale);
            }

            // 4 Compound images and assets
            findAndDumpImagesAndAssets(connManager, compound, dumper);

            compounds(connManager, compound, dumper, xmlReader);

            dumper.endHippoCompound(compound);
        }
        dumper.endHippoCompounds();
    }

    private void document(final HCTConnManager connManager)
            throws ObjectBeanManagerException, SAXException, IOException, RepositoryException {

        final HippoDocument doc = hctDocument.getHippoDocument(connManager, locale, availability);

        final HippoItemXMLDumper dumper = new HippoItemXMLDumper(this.getSAXConsumer());

        // 1. document
        dumper.startHippoItem(doc, doc.getPath());

        // 2. properties
        for (Entry<String, Object> entry : doc.getProperties().entrySet()) {
            if (TaggingNodeType.PROP_TAGS.equals(entry.getKey())) {
                dumper.dumpTags((String[]) entry.getValue());
            } else if (TaxonomyNodeTypes.HIPPOTAXONOMY_KEYS.equals(entry.getKey())) {
                dumper.dumpTaxonomies(TaxonomyUtils.getTaxonomies(connManager, (String[]) entry.getValue()),
                        locale);
            } else {
                dumper.dumpField(entry, hctDocument.getDateFormat(), locale);
            }
        }

        // 3. Date fields
        for (HippoDate date : doc.getChildBeans(HippoDate.class)) {
            dumper.dumpDate(date.getName(), date.getCalendar(), hctDocument.getDateFormat(), locale);
        }

        // 4. HTML fields
        final XMLReader xmlReader = new StartEndDocumentFilter(XMLUtils.createXMLReader(this.getSAXConsumer()));
        xmlReader.setContentHandler(this.getSAXConsumer());
        for (HippoHtml rtf : doc.getChildBeans(HippoHtml.class)) {
            dumper.dumpHtml(connManager, rtf, xmlReader, hctDocument.getDateFormat(), locale);
        }

        // 5. Images and Assets
        findAndDumpImagesAndAssets(connManager, doc, dumper);

        // 6. Compounds
        compounds(connManager, doc, dumper, xmlReader);

        // 7. Related documents
        final List<HippoDocument> relDocs = new ArrayList<HippoDocument>();
        for (RelatedDocs docs : doc.getChildBeans(RelatedDocs.class)) {
            for (String relDocUuid : docs.getRelatedDocsUuids()) {
                HippoDocument docByUuid = ObjectUtils.getHippoItemByUuid(connManager, relDocUuid,
                        HippoDocument.class);
                if (docByUuid != null) {
                    relDocs.add(doc);
                }
            }
        }
        dumper.dumpRelatedDocs(relDocs, Element.DOCUMENT.getName(), true);

        dumper.endHippoItem(doc);
    }

    private void tags(final HCTConnManager connManager) throws RepositoryException, SAXException {
        final HippoItemXMLDumper dumper = new HippoItemXMLDumper(this.getSAXConsumer());

        dumper.dumpTags(AllTagsProvider.getTags(connManager.getSession(), "tags"));
    }

    private <T extends HippoItem> void recursiveTraversal(final HippoItem item, final Class<T> traversalType,
            final int depth, final HippoItemXMLDumper dumper) throws SAXException, RepositoryException {

        dumper.startHippoItem(item, item.getPath());
        if (depth > 0) {
            final List<T> children = item.getChildBeans(traversalType);
            if (!children.isEmpty()) {
                for (T child : children) {
                    recursiveTraversal(child, traversalType, depth - 1, dumper);
                }
            }
        }
        dumper.endHippoItem(item);
    }

    private void traverse(final HCTConnManager connManager)
            throws ObjectBeanManagerException, SAXException, RepositoryException {

        if (hctTraversal == null) {
            throw new IllegalArgumentException("HCTTraversal is null");
        }
        final HippoItem base = ObjectUtils.getHippoItem(connManager, hctTraversal.getBase());
        if (base == null) {
            throw new IllegalArgumentException("base is null");
        }

        final Class<? extends HippoItem> traversalType = hctTraversal.getBase().startsWith("/content/taxonomies")
                ? HCTTaxonomyCategoryBean.class
                : HippoFolder.class;
        final HippoItemXMLDumper dumper = new HippoItemXMLDumper(this.getSAXConsumer());

        recursiveTraversal(base, traversalType, hctTraversal.getDepth(), dumper);
    }

    private void query(final HCTConnManager connManager)
            throws SAXException, RepositoryException, IOException, ObjectBeanManagerException {

        if (hctQuery == null) {
            throw new IllegalArgumentException("HCTQuery is null");
        }
        hctQuery.setSession(connManager.getSession());

        final HCTQueryResult queryResult = hctQuery.execute(locale, availability);
        LOG.debug("Query is {}", hctQuery.getSQLQuery());

        final HippoItemXMLDumper dumper = new HippoItemXMLDumper(this.getSAXConsumer());

        final HippoItem base = ObjectUtils.getHippoItem(connManager, hctQuery.getBase());
        dumper.startQueryResult(queryResult, base);

        if (hctQuery.isIncludeFolders()) {
            // 1. group matching documents by folder / taxonomy
            final Map<HippoItem, List<HippoItem>> resultByFolder = new HashMap<HippoItem, List<HippoItem>>();
            for (String uuid : queryResult.getUuids()) {
                final HippoItem item = ObjectUtils.getHippoItemByUuid(connManager, uuid);
                if (item != null) {
                    if (hctQuery.getType() == HCTQuery.Type.TAXONOMY_DOCS) {
                        final String[] keys = item.getProperty(TaxonomyNodeTypes.HIPPOTAXONOMY_KEYS);
                        for (int i = 0; keys != null && i < keys.length; i++) {
                            if (hctQuery.getTaxonomies().keySet().contains(keys[i])) {
                                final HCTTaxonomyCategoryBean taxonomy = ObjectUtils.getHippoItem(connManager,
                                        hctQuery.getTaxonomies().get(keys[i]), HCTTaxonomyCategoryBean.class);
                                if (taxonomy != null) {
                                    if (!resultByFolder.containsKey(taxonomy)) {
                                        resultByFolder.put(taxonomy, new ArrayList<HippoItem>());
                                    }
                                    resultByFolder.get(taxonomy).add(item);
                                }
                            }
                        }
                    } else {
                        final HippoFolder folder = (HippoFolder) item.getParentBean();
                        if (!resultByFolder.containsKey(folder)) {
                            resultByFolder.put(folder, new ArrayList<HippoItem>());
                        }
                        resultByFolder.get(folder).add(item);
                    }
                }
            }

            // 2. output results by folder / taxonomy
            for (Map.Entry<HippoItem, List<HippoItem>> entry : resultByFolder.entrySet()) {
                if (hctQuery.getType() == HCTQuery.Type.TAXONOMY_DOCS) {
                    dumper.startTaxonomy((HCTTaxonomyCategoryBean) entry.getKey(), locale);
                    for (HippoItem item : entry.getValue()) {
                        dumper.dumpHippoItem(connManager, item,
                                TaxonomyUtils.buildPathInTaxonomy(entry.getKey().getPath(), item.getName()),
                                hctQuery, locale);
                    }
                    dumper.endTaxonomy();
                } else {
                    dumper.startHippoItem(entry.getKey(), entry.getKey().getPath());
                    for (HippoItem item : entry.getValue()) {
                        dumper.dumpHippoItem(connManager, item, item.getPath(), hctQuery, locale);
                    }
                    dumper.endHippoItem(entry.getKey());
                }
            }
        } else {
            for (String uuid : queryResult.getUuids()) {
                final HippoItem item = ObjectUtils.getHippoItemByUuid(connManager, uuid);
                if (item != null) {
                    switch (hctQuery.getType()) {
                    case TAXONOMY_DOCS:
                        final String[] keys = item.getProperty(TaxonomyNodeTypes.HIPPOTAXONOMY_KEYS);
                        for (int i = 0; keys != null && i < keys.length; i++) {
                            if (hctQuery.getTaxonomies().keySet().contains(keys[i])) {
                                dumper.dumpHippoItem(connManager, item, TaxonomyUtils.buildPathInTaxonomy(
                                        hctQuery.getTaxonomies().get(keys[i]), item.getName()), hctQuery, locale);
                            }
                        }
                        break;

                    case FOLDER_DOCS:
                    default:
                        dumper.dumpHippoItem(connManager, item, item.getPath(), hctQuery, locale);
                    }
                }
            }
        }

        dumper.endQueryResult();
    }

    private String parseDateFormat(final Attributes atts) {
        String dateFormat = atts.getValue(Attribute.DATE_FORMAT.getName());
        if (StringUtils.isBlank(dateFormat)) {
            dateFormat = Constants.DEFAULT_DATE_FORMAT;
        }

        return dateFormat;
    }

    private int parseDepth(final Attributes atts) {
        int depth = 0;
        if (StringUtils.isNotBlank(atts.getValue(Attribute.DEPTH.getName()))) {
            try {
                depth = Integer.parseInt(atts.getValue(Attribute.DEPTH.getName()));
            } catch (NumberFormatException e) {
                LOG.error("Invalid depth specified, reverting to default (0)", e);
            }
        }

        return depth;
    }

    private long parseSize(final Attributes atts) {
        long size = 5;
        if (StringUtils.isNotBlank(atts.getValue(Attribute.SIZE.getName()))) {
            try {
                size = Long.parseLong(atts.getValue(Attribute.SIZE.getName()));
            } catch (NumberFormatException e) {
                LOG.error("Invalid size specified, reverting to default (5)", e);
            }
        }

        return size;
    }

    private long parsePage(final Attributes atts) {
        long page = 0L;
        if (StringUtils.isNotBlank(atts.getValue(Attribute.PAGE.getName()))) {
            try {
                page = Long.parseLong(atts.getValue(Attribute.PAGE.getName()));
            } catch (NumberFormatException e) {
                LOG.error("Invalid page specified, assuming not paginated result", e);
            }
        }

        return page;
    }

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

        if (!Constants.NS_HCT.equals(uri)) {
            super.startElement(uri, localName, name, atts);
            return;
        }

        Element element;
        try {
            element = Element.fromName(localName);
        } catch (IllegalArgumentException e) {
            throw new SAXException("Invalid element found", e);
        }

        if (element == Element.DOCUMENT) {
            if (state != State.OUTSIDE) {
                throw new InvalidHCTRequestException(localName, state);
            }

            hctDocument = new HCTDocument();
            hctDocument.setPath(atts.getValue(Attribute.PATH.getName()));
            hctDocument.setUuid(atts.getValue(Attribute.UUID.getName()));
            hctDocument.setDateFormat(parseDateFormat(atts));
        }

        if (element == Element.FOLDERS) {
            if (state != State.OUTSIDE) {
                throw new InvalidHCTRequestException(localName, state);
            }

            hctTraversal = new HCTTraversal();
            hctTraversal.setBase(atts.getValue(Attribute.BASE.getName()) == null ? "/"
                    : atts.getValue(Attribute.BASE.getName()));
            hctTraversal.setDepth(parseDepth(atts));
            hctTraversal.setSize(parseSize(atts));
        }

        if (element == Element.QUERY) {
            if (state != State.OUTSIDE) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_QUERY;

            hctQuery = new HCTQuery();
            hctQuery.setBase(atts.getValue(Attribute.BASE.getName()) == null ? "/"
                    : atts.getValue(Attribute.BASE.getName()));
            hctQuery.setReturnType(atts.getValue(Attribute.TYPE.getName()) == null ? "nt:base"
                    : atts.getValue(Attribute.TYPE.getName()));
            hctQuery.setDateFormat(parseDateFormat(atts));
            hctQuery.setDepth(parseDepth(atts));
            hctQuery.setSize(parseSize(atts));
            hctQuery.setPage(parsePage(atts));

            hctQuery.setIncludeFolders("true".equalsIgnoreCase(atts.getValue(Attribute.INCLUDE_FOLDERS.getName())));
        }

        if (element == Element.FILTER) {
            if (state != State.INSIDE_QUERY) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_FILTER;
        }

        if (element == Element.AND || element == Element.OR) {
            if (state != State.INSIDE_FILTER) {
                throw new InvalidHCTRequestException(localName, state);
            }

            if (element == Element.AND) {
                state = State.INSIDE_FILTER_AND;
            }
            if (element == Element.OR) {
                state = State.INSIDE_FILTER_OR;
            }
        }

        if (Constants.FILTER_ELEMENTS.contains(element)) {
            if (state != State.INSIDE_FILTER_AND && state != State.INSIDE_FILTER_OR) {
                throw new InvalidHCTRequestException(localName, state);
            }

            if (!Constants.Element.CONTAINS.getName().equals(localName)
                    && StringUtils.isBlank(atts.getValue(Attribute.FIELD.getName()))) {

                throw new InvalidHCTRequestException(
                        Attribute.FIELD.getName() + " must be specified for " + localName);
            }
            try {
                hctQuery.getFilter().addCond(state, element, atts);
            } catch (RepositoryException e) {
                throw new SAXException(e);
            }
        }

        if (element == Element.ORDERBY) {
            if (state != State.INSIDE_QUERY) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_ORDERBY;
        }

        if (element == Element.DESCENDING || element == Element.ASCENDING) {
            if (state != State.INSIDE_ORDERBY) {
                throw new InvalidHCTRequestException(localName, state);
            }

            if (StringUtils.isBlank(atts.getValue(Attribute.FIELD.getName()))) {
                throw new InvalidHCTRequestException(
                        Attribute.FIELD.getName() + " must be specified for " + localName);
            }

            if (element == Element.DESCENDING) {
                hctQuery.addOrderByDescending(atts.getValue(Attribute.FIELD.getName()));
            }
            if (element == Element.ASCENDING) {
                hctQuery.addOrderByAscending(atts.getValue(Attribute.FIELD.getName()));
            }
        }

        if (element == Element.RETURN) {
            if (state != State.INSIDE_QUERY) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_RETURN;
        }

        if (element == Element.FIELD) {
            if (state != State.INSIDE_RETURN) {
                throw new InvalidHCTRequestException(localName, state);
            }

            if (StringUtils.isBlank(atts.getValue(Attribute.NAME.getName()))) {
                throw new InvalidHCTRequestException(
                        Attribute.NAME.getName() + " must be specified for " + localName);
            }

            hctQuery.addReturnField(atts.getValue(Attribute.NAME.getName()));
        }

        if (element == Element.TAGS) {
            if (state == State.INSIDE_RETURN) {
                hctQuery.setReturnTags(true);
            } else if (state == State.OUTSIDE) {
                LOG.debug("Requiring tags, no processing needed here");
            } else {
                throw new InvalidHCTRequestException(localName, state);
            }
        }

        if (element == Element.TAXONOMIES) {
            if (state != State.INSIDE_RETURN) {
                throw new InvalidHCTRequestException(localName, state);
            }

            hctQuery.setReturnTaxonomies(true);
        }

        if (element == Element.IMAGES) {
            if (state != State.INSIDE_RETURN) {
                throw new InvalidHCTRequestException(localName, state);
            }

            hctQuery.setReturnImages(true);
        }

        if (element == Element.RELATED_DOCS) {
            if (state != State.INSIDE_RETURN) {
                throw new InvalidHCTRequestException(localName, state);
            }

            hctQuery.setReturnRelatedDocs(true);
        }
    }

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

        if (!Constants.NS_HCT.equals(uri)) {
            super.endElement(uri, localName, name);
            return;
        }

        Element element;
        try {
            element = Element.fromName(localName);
        } catch (IllegalArgumentException e) {
            throw new SAXException("Invalid element found", e);
        }

        if (element == Element.RETURN) {
            if (state != State.INSIDE_RETURN) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_QUERY;

            LOG.debug("Fields to be returned: {}; images: {}; relatedDocs: {}", new Object[] {
                    hctQuery.getReturnFields(), hctQuery.isReturnImages(), hctQuery.isReturnRelatedDocs() });
        }

        if (element == Element.ORDERBY) {
            if (state != State.INSIDE_ORDERBY) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_QUERY;
        }

        if ((element == Element.AND || element == Element.OR)) {
            if (state != State.INSIDE_FILTER_AND && state != State.INSIDE_FILTER_OR) {
                throw new InvalidHCTRequestException(localName, state);
            }

            state = State.INSIDE_FILTER;
        }

        if (element == Element.FILTER) {
            if (state != State.INSIDE_FILTER) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.INSIDE_QUERY;
        }

        if (element == Element.QUERY) {
            if (state != State.INSIDE_QUERY) {
                throw new InvalidHCTRequestException(localName, state);
            }
            state = State.OUTSIDE;

            final HCTConnManager connManager = HCTConnManager.getContentInstance();
            try {
                query(connManager);
            } catch (Exception e) {
                throw new ProcessingException("While performing query " + hctQuery.getSQLQuery(), e);
            } finally {
                connManager.logout();
            }
        }

        if (element == Element.FOLDERS) {
            if (state != State.OUTSIDE) {
                throw new InvalidHCTRequestException(localName, state);
            }

            final HCTConnManager connManager = HCTConnManager.getContentInstance();
            try {
                traverse(connManager);
            } catch (Exception e) {
                throw new ProcessingException("While performing traversal " + hctTraversal, e);
            } finally {
                connManager.logout();
            }

        }

        if (element == Element.TAGS) {
            if (state != State.OUTSIDE) {
                throw new InvalidHCTRequestException(localName, state);
            }

            final HCTConnManager connManager = HCTConnManager.getContentInstance();
            try {
                tags(connManager);
            } catch (Exception e) {
                throw new ProcessingException("While fetching tags", e);
            } finally {
                connManager.logout();
            }
        }

        if (element == Element.DOCUMENT) {
            if (state != State.OUTSIDE) {
                throw new InvalidHCTRequestException(localName, state);
            }

            final HCTConnManager connManager = HCTConnManager.getContentInstance();
            try {
                document(connManager);
            } catch (Exception e) {
                throw new ProcessingException("While fetching document", e);
            } finally {
                connManager.logout();
            }
        }
    }
}