Package com.google.sitebricks.rendering.control

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

package com.google.sitebricks.rendering.control;

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

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;

/**
* @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 = bound.getClass();
      }
      else {
        // get the extension subclass above the last
        templateClass = nextExtensionSubclass(previousTemplateClass, bound.getClass());
        if (templateClass == null) {
          throw new IllegalStateException("Could not find subclass of " + previousTemplateClass.getName() + " with @Extension 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();
      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 subclass with an @Extension annotation
  private Class<?> nextExtensionSubclass(Class<?> previousTemplagteClass, Class<?> candidate) {
    if (candidate == previousTemplagteClass) {
      // 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 previsou extension");
    }
    else {
      // check the super class for the result
      Class<?> result = nextExtensionSubclass(previousTemplagteClass, candidate.getSuperclass());
      if (result == null && candidate.isAnnotationPresent(Decorated.class)) {
        // this is the one - retreat!
        return candidate;
      }
      else {
        // we still have not found one
        return null;
      }
    }
  }

  @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.