/*
* Copyright (c) 2013-2014 the original author or authors
*
* 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 io.werval.runtime.filters;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import io.werval.api.Application;
import io.werval.api.Global;
import io.werval.api.context.Context;
import io.werval.api.exceptions.WervalException;
import io.werval.api.filters.Filter;
import io.werval.api.filters.FilterChain;
import io.werval.api.outcomes.Outcome;
import io.werval.util.Couple;
/**
* Instance of FilterChain.
*/
/* package */ class FilterChainInstance
implements FilterChain
{
/**
* End of the FilterChain, this is the Controller Method Invocation.
*/
/* package */ static class FilterChainControllerTail
implements FilterChain
{
private final Application app;
private final Global global;
/* package */ FilterChainControllerTail( Application app, Global global )
{
this.app = app;
this.global = global;
}
@Override
public CompletableFuture<Outcome> next( Context context )
{
Object controller = global.getControllerInstance( app, context.route().controllerType() );
Object result = global.invokeControllerMethod( context, controller );
if( CompletableFuture.class.isAssignableFrom( result.getClass() ) )
{
try
{
return (CompletableFuture<Outcome>) result;
}
catch( ClassCastException ex )
{
throw new WervalException(
context.route().controllerMethod()
+ " returned a CompletableFuture of something else than Outcome. Check your code.",
ex
);
}
}
if( Outcome.class.isAssignableFrom( result.getClass() ) )
{
return CompletableFuture.completedFuture( (Outcome) result );
}
throw new WervalException(
context.route().controllerMethod()
+ " did not return an Outcome nor a CompletableFuture<Outcome> but a "
+ result.getClass()
+ ". Check your code."
);
}
}
private final Application app;
private final Global global;
private final Couple<Class<? extends Filter>, Annotation> filterInfo;
private final FilterChain next;
/* package */ FilterChainInstance(
Application app, Global global, Couple<Class<? extends Filter>, Annotation> filterInfo, FilterChain next
)
{
this.app = app;
this.global = global;
this.filterInfo = filterInfo;
this.next = next;
}
@Override
public CompletableFuture<Outcome> next( Context context )
{
Filter filter = global.getFilterInstance( app, filterInfo.left() );
return filter.filter( next, context, Optional.ofNullable( filterInfo.right() ) );
}
}