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 extends Throwable> 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 extends Throwable> throwableClass;
private final T ret;
/**
* Creates the DefaultErrorTolerant.
*
* @param throwableClass
* @param ret
*/
public DefaultErrorTolerant(final Class extends Throwable> 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");
}
}