All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.zaubersoftware.leviathan.api.engine.impl.DefaultAfterFetchingHandler Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2009-2015 Zauber S.A. 
 *
 * 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 com.zaubersoftware.leviathan.api.engine.impl;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URI;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.stream.StreamSource;

import org.apache.commons.lang.NotImplementedException;
import org.apache.commons.lang.UnhandledException;
import org.apache.commons.lang.Validate;
import org.w3c.dom.Node;

import ar.com.zauber.leviathan.api.URIFetcherResponse;

import com.zaubersoftware.leviathan.api.engine.Action;
import com.zaubersoftware.leviathan.api.engine.ActionAndControlStructureHandler;
import com.zaubersoftware.leviathan.api.engine.ActionAndThenFetch;
import com.zaubersoftware.leviathan.api.engine.ActionHandler;
import com.zaubersoftware.leviathan.api.engine.AfterExceptionCatchDefinition;
import com.zaubersoftware.leviathan.api.engine.AfterFetchingHandler;
import com.zaubersoftware.leviathan.api.engine.AfterForEachHandler;
import com.zaubersoftware.leviathan.api.engine.AfterForEachHandler.EndFor;
import com.zaubersoftware.leviathan.api.engine.AfterForEachHandler.ThenWithContextAwareClosure;
import com.zaubersoftware.leviathan.api.engine.AfterHandleWith;
import com.zaubersoftware.leviathan.api.engine.AfterJavaObjectHandler;
import com.zaubersoftware.leviathan.api.engine.AfterThen;
import com.zaubersoftware.leviathan.api.engine.AfterXMLTransformer;
import com.zaubersoftware.leviathan.api.engine.ContextAwareClosure;
import com.zaubersoftware.leviathan.api.engine.Engine;
import com.zaubersoftware.leviathan.api.engine.ErrorTolerantActionAndControlStructureHandler;
import com.zaubersoftware.leviathan.api.engine.ErrorTolerantAfterThen;
import com.zaubersoftware.leviathan.api.engine.ExceptionHandler;
import com.zaubersoftware.leviathan.api.engine.Pipe;
import com.zaubersoftware.leviathan.api.engine.ProcessingFlow;
import com.zaubersoftware.leviathan.api.engine.impl.pipe.ActionPipe;
import com.zaubersoftware.leviathan.api.engine.impl.pipe.ClosureAdapterPipe;
import com.zaubersoftware.leviathan.api.engine.impl.pipe.ForEachPipe;
import com.zaubersoftware.leviathan.api.engine.impl.pipe.HTMLSanitizerPipe;
import com.zaubersoftware.leviathan.api.engine.impl.pipe.ToJavaObjectPipe;
import com.zaubersoftware.leviathan.api.engine.impl.pipe.XMLPipe;

/**
 * Default implementation of the {@link AfterFetchingHandler} interface that uses a {@link DefaultEngine}
 *
 * @author Martin Silva
 * @since Sep 2, 2011
 */
public final class DefaultAfterFetchingHandler implements AfterFetchingHandler {

    private final DefaultEngine engine;

    private final class DefaultErrorTolerantAfterThen implements ErrorTolerantAfterThen, AfterExceptionCatchDefinition, AfterHandleWith {

        private Class throwableClass;

        @Override
        public ProcessingFlow pack() {
            return DefaultAfterFetchingHandler.this.pack();
        }

        @Override
        public AfterThen onAnyExceptionDo(final ExceptionHandler handler) {
            DefaultAfterFetchingHandler.this.engine.addExceptionHandlerForCurrentPipe(handler);
            return this;
        }

        @Override
        public  AfterExceptionCatchDefinition on(final Class throwableClass) {
            Validate.notNull(throwableClass, "The throwable class canont be null");
            this.throwableClass = throwableClass;
            return this;
        }

        @Override
        public AfterHandleWith handleWith(final ExceptionHandler handler) {
            DefaultAfterFetchingHandler.this
                .engine.addExceptionHandlerForCurrentPipe(this.throwableClass, handler);
            return this;
        }

        @Override
        public AfterThen otherwiseHandleWith(final ExceptionHandler handler) {
            DefaultAfterFetchingHandler.this.engine.addExceptionHandlerForCurrentPipe(handler);
            return this;
        }

    }

    private final class DefaultErrorTolerant implements AfterExceptionCatchDefinition, AfterHandleWith {

        private Class throwableClass;
        private final T ret;

        /**
         * Creates the DefaultErrorTolerant.
         *
         * @param throwableClass
         * @param ret
         */
        public DefaultErrorTolerant(final Class throwableClass, final T ret) {
            Validate.notNull(throwableClass, "The throwableClass cannot be null");
            Validate.notNull(ret, "The return object cannot be null");
            this.throwableClass = throwableClass;
            this.ret = ret;
        }

        @Override
        public  AfterExceptionCatchDefinition on(final Class throwableClass) {
            Validate.notNull(throwableClass, "The throwable class canont be null");
            this.throwableClass = throwableClass;
            return this;
        }

        @Override
        public AfterHandleWith handleWith(final ExceptionHandler handler) {
            DefaultAfterFetchingHandler.this.engine.addExceptionHandlerForCurrentPipe(this.throwableClass, handler);
            return this;
        }

        @Override
        public T otherwiseHandleWith(final ExceptionHandler handler) {
            DefaultAfterFetchingHandler.this.engine.addExceptionHandlerForCurrentPipe(handler);
            return this.ret;
        }

    }

    private final class DefaultActionAndControlStructureHandler implements ErrorTolerantActionAndControlStructureHandler, AfterJavaObjectHandler {

        @Override
        public  ActionAndControlStructureHandler then(final Action action) {
            Validate.notNull(action, "The action cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(new ActionPipe(action));
            return new DefaultActionAndControlStructureHandler();
        }
        @Override
        public AfterFetchingHandler then(final ActionAndThenFetch object) {
            throw new NotImplementedException();
        }

        @Override
        public ErrorTolerantAfterThen then(final ContextAwareClosure closure) {
            Validate.notNull(closure, "The closure cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(new ClosureAdapterPipe(closure));
            return new DefaultErrorTolerantAfterThen();
        }

        @Override
        public AfterFetchingHandler thenFetch(final String uriTemplate) {
            throw new NotImplementedException();
        }

        @Override
        public AfterFetchingHandler thenFetch(final URI uri) {
            throw new NotImplementedException();
        }

        @Override
        public Engine thenDoNothing() {
            pack();
            return DefaultAfterFetchingHandler.this.engine;
        }

        @Override
        public ProcessingFlow pack() {
            return DefaultAfterFetchingHandler.this.pack();
        }

        @Override
        public ErrorTolerantActionAndControlStructureHandler onAnyExceptionDo(final ExceptionHandler handler) {
            DefaultAfterFetchingHandler.this.engine.addExceptionHandlerForCurrentPipe(handler);
            return this;
        }

        @Override
        public  AfterExceptionCatchDefinition> on(
                final Class throwableClass) {
            return new DefaultErrorTolerant>(throwableClass, this);
        }

        @Override
        public  AfterForEachHandler forEach(final Class elementClass) {
            return new DefaultAfterForEachHandler();
        }

    }

    public final class DefaultAfterForEachHandler 
            implements AfterForEachHandler, ThenWithContextAwareClosure, EndFor {

        private String propertyName;
        private ContextAwareClosure closure;

        @Override
        public ThenWithContextAwareClosure in(
                final String propertyName) {
            this.propertyName = propertyName;
            return this;
        }

        @Override
        public EndFor then(
                final ContextAwareClosure closure) {
            this.closure = closure;
            return this;
        }

        @Override
        public ErrorTolerantActionAndControlStructureHandler endFor() {
            DefaultAfterFetchingHandler.this.engine.appendPipe(new ForEachPipe(
                    this.propertyName, new ClosureAdapterPipe(this.closure)));
            return new DefaultActionAndControlStructureHandler();
        }

    }

    private final class DefaultAfterXMLTransformer implements AfterXMLTransformer {

        @Override
        public  AfterJavaObjectHandler toJavaObject(final Class aClass) {
            Validate.notNull(aClass, "The class cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(new ToJavaObjectPipe(aClass));
            return new DefaultActionAndControlStructureHandler();
        }
        @Override
        public  AfterJavaObjectHandler toJavaObject(final Pipe pipe) {
            Validate.notNull(pipe, "pipe cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(pipe);
            return new DefaultActionAndControlStructureHandler();
        }
        
        @Override
        public AfterXMLTransformer transformXML(final String xsl) {
            Validate.notNull(xsl, "The XSLT path cannot be null");
            try {
                DefaultAfterFetchingHandler.this.engine.appendPipe(
                        new XMLPipe(new StreamSource(new FileInputStream(xsl))));
            } catch (final FileNotFoundException e) {
                throw new UnhandledException(e);
            }
            return this;
        }

        @Override
        public AfterXMLTransformer transformXML(final Source xsl) {
            Validate.notNull(xsl, "The XSLT source cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(new XMLPipe(xsl));
            return this;
        }

        @Override
        public AfterXMLTransformer transformXML(final Templates xsl) {
            Validate.notNull(xsl, "The XSLT transformer cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(new XMLPipe(xsl));
            return this;
        }
        @Override
        public AfterXMLTransformer transformXML(Pipe pipe) {
            Validate.notNull(pipe, "The pipe cannot be null");
            DefaultAfterFetchingHandler.this.engine.appendPipe(pipe);
            return this;
        }
    }

    /**
     * Creates the DefaultAfterFetchingHandler.
     *
     * @param engine
     */
    public DefaultAfterFetchingHandler(final DefaultEngine engine) {
        Validate.notNull(engine, "The engine cannot be null");
        this.engine = engine;
    }

    @Override
    public AfterXMLTransformer transformXML(final String xsl) {
        Validate.notNull(xsl, "The XSLT source cannot be null");
        try {
            this.engine.appendPipe(new XMLPipe(new StreamSource(new FileInputStream(xsl))));
        } catch (final FileNotFoundException e) {
            throw new UnhandledException(e);
        }
        return this;
    }

    @Override
    public AfterXMLTransformer transformXML(final Source xsl) {
        Validate.notNull(xsl, "The XSLT transformer cannot be null");
        this.engine.appendPipe(new XMLPipe(xsl));
        return this;
    }

    @Override
    public AfterXMLTransformer transformXML(final Templates xsl) {
        Validate.notNull(xsl, "The XSLT transformer cannot be null");
        this.engine.appendPipe(new XMLPipe(xsl));
        return this;
    }

    @Override
    public AfterXMLTransformer transformXML(final Pipe pipe) {
        this.engine.appendPipe(pipe);
        return this;
    }
    
    @Override
    public  AfterJavaObjectHandler toJavaObject(final Class aClass) {
        Validate.notNull(aClass, "The class cannot be null");
        this.engine.appendPipe(new ToJavaObjectPipe(aClass));
        return new DefaultActionAndControlStructureHandler();
    }

    @Override
    public  AfterJavaObjectHandler toJavaObject(final Pipe pipe) {
        Validate.notNull(pipe, "pipe cannot be null");
        this.engine.appendPipe(pipe);
        return new DefaultActionAndControlStructureHandler();
    }
    
    @Override
    public ActionHandler onAnyExceptionDo(final ExceptionHandler handler) {
        Validate.notNull(handler, "The handler cannot be null");
        this.engine.onAnyExceptionDo(handler);
        return new DefaultActionAndControlStructureHandler();
    }

    @Override
    public  ActionAndControlStructureHandler then(final Action object) {
        Validate.notNull(object, "The action cannot be null");
        this.engine.appendPipe(new ActionPipe(object));
        return new DefaultActionAndControlStructureHandler();
    }

    @Override
    public AfterFetchingHandler then(final ActionAndThenFetch object) {
        throw new NotImplementedException();
    }

    @Override
    public ErrorTolerantAfterThen then(final ContextAwareClosure closure) {
        this.engine.appendPipe(new ClosureAdapterPipe(closure));
        return new DefaultErrorTolerantAfterThen();
    }

    @Override
    public AfterFetchingHandler thenFetch(final String uriTemplate) {
        throw new NotImplementedException();
    }

    @Override
    public AfterFetchingHandler thenFetch(final URI uri) {
        throw new NotImplementedException();
    }

    @Override
    public Engine thenDoNothing() {
        return this.engine;
    }

    @Override
    public AfterXMLTransformer sanitizeHTML() {
        this.engine.appendPipe(new HTMLSanitizerPipe());
        return new DefaultAfterXMLTransformer();
    }
    {
    }
    @Override
    public AfterXMLTransformer isXML() {
        this.engine.appendPipe(new Pipe() {
            @Override
            public Node execute(final URIFetcherResponse input) {
                final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                try {
                    final DocumentBuilder db = dbf.newDocumentBuilder();
                    return db.parse(input.getHttpResponse().getRawContent());
                } catch(Exception e) {
                    throw new UnhandledException(e);
                }
            }
        });
        return new DefaultAfterXMLTransformer();
    }
    
    @Override
    public ProcessingFlow pack() {
        return this.engine.packCurrentFlow();
    }

    @Override
    public  AfterExceptionCatchDefinition> on(
            final Class throwableClass) {
        throw new NotImplementedException("This should handle exeception that occur while fetching "
            + "(POST or GET). They should be treated as engine exceptions");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy