ratpack.render.internal.DefaultRenderController Maven / Gradle / Ivy
/*
* Copyright 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 ratpack.render.internal;
import com.google.common.collect.Iterables;
import com.google.common.reflect.TypeToken;
import ratpack.exec.Promise;
import ratpack.handling.Context;
import ratpack.render.*;
import ratpack.util.Types;
import java.util.Iterator;
public class DefaultRenderController implements RenderController {
private static final TypeToken> RENDERER_TYPE = Types.intern(new TypeToken>() {});
private static final TypeToken> RENDERABLE_DECORATOR_TYPE = Types.intern(new TypeToken>() {});
@Override
public void render(final Object toRender, final Context context) throws Exception {
if (toRender == null) {
context.clientError(404);
return;
}
doRender(toRender, context);
}
private void doRender(T toRender, Context context) throws Exception {
Class type = Types.cast(toRender.getClass());
Iterator extends RenderableDecorator>> decorators = Iterables.filter(
context.getAll(RENDERABLE_DECORATOR_TYPE),
d -> d.getType().isAssignableFrom(type)
).iterator();
if (decorators.hasNext()) {
Promise promise = Promise.value(toRender);
while (decorators.hasNext()) {
RenderableDecorator cast = Types.cast(decorators.next());
promise = promise.flatMap(r -> cast.decorate(context, r));
}
promise.then(r -> doRender(context, type, r));
} else {
doRender(context, type, toRender);
}
}
private void doRender(Context context, Class type, T decorated) {
Iterable extends Renderer>> renderers = context.getAll(RENDERER_TYPE);
for (Renderer> renderer : renderers) {
if (renderer.getType().isAssignableFrom(type)) {
Renderer cast = Types.cast(renderer);
try {
cast.render(context, decorated);
return;
} catch (RenderException e) {
throw e;
} catch (Exception e) {
throw new RendererException(renderer, decorated, e);
}
}
}
throw new NoSuchRendererException(decorated);
}
}