Package com.google.sitebricks.rendering.control

Source Code of com.google.sitebricks.rendering.control.DecorateWidget

package com.google.sitebricks.rendering.control;

import com.google.inject.Inject;
import com.google.sitebricks.Evaluator;
import com.google.sitebricks.Renderable;
import com.google.sitebricks.Respond;
import com.google.sitebricks.StringBuilderRespond;
import com.google.sitebricks.rendering.Decorated;
import com.google.sitebricks.routing.PageBook;

import java.util.Collections;
import java.util.Set;

/**
* @author John Patterson (jdpatterson@gmail.com)
*/
public class DecorateWidget implements Renderable {

  @Inject
  private PageBook book;

  private ThreadLocal<Class<?>> templateClassLocal = new ThreadLocal<Class<?>>();

  public static String embedNameFor(Class<?> pageClass) {
    return pageClass.getName().toLowerCase() + "-extend";
  }

  public DecorateWidget(WidgetChain chain, String expression, Evaluator evaluator) {
    // do not need any of the compulsory constructor args
  }

  @Override
  public void render(Object bound, Respond respond) {

    Class<?> templateClass;
    Class<?> previousTemplateClass = templateClassLocal.get();
    try {
      if (previousTemplateClass == null) {
        templateClass = nextDecoratedClassInHierarchy(null, bound.getClass());
      } else {
        // get the extension subclass above the last
        templateClass = nextDecoratedClassInHierarchy(previousTemplateClass, bound.getClass());
        if (templateClass == null) {
          throw new IllegalStateException(
              "Could not find subclass of " + previousTemplateClass.getName() +
                  " with @Decorated annotation.");
        }
      }
      templateClassLocal.set(templateClass);

      // get the extension page by name
      PageBook.Page page = book.forName(DecorateWidget.embedNameFor(templateClass));

      // create a dummy respond to collect the output of the embedded page
      StringBuilderRespond sbrespond = new StringBuilderRespond(bound);
      EmbeddedRespond embedded = new EmbeddedRespond(null, sbrespond);
      page.widget().render(bound, embedded);

      // write the head and content to the real respond
      respond.writeToHead(embedded.toHeadString());
      respond.write(embedded.toString());

      // free some memory
      embedded.clear();
    } finally {
      // we are finished with this extension
      if (previousTemplateClass == null) {
        templateClassLocal.set(null);
      }
    }
  }

  // recursively find the next superclass with an @Decorated annotation
  private Class<?> nextDecoratedClassInHierarchy(Class<?> previousTemplateClass,
                                                 Class<?> candidate) {
    if (candidate == previousTemplateClass) {
      // terminate the recursion
      return null;
    } else if (candidate == Object.class) {
      // this should never happen - we should terminate recursion first
      throw new IllegalStateException("Did not find previous extension");
    } else {
      boolean isDecorated = candidate.isAnnotationPresent(Decorated.class);

      if (isDecorated)
        return candidate;
      else
        return nextDecoratedClassInHierarchy(previousTemplateClass, candidate.getSuperclass());
    }
  }

  @Override
  public <T extends Renderable> Set<T> collect(Class<T> clazz) {
    return Collections.emptySet();
  }
}
TOP

Related Classes of com.google.sitebricks.rendering.control.DecorateWidget

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.