package com.idega.facelets.ui;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELException;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.UIParameter;
import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;
import com.sun.facelets.FaceletFactory;
import com.sun.facelets.FaceletHandler;
import com.sun.facelets.FaceletViewHandler;
import com.sun.facelets.compiler.Compiler;
import com.sun.facelets.el.VariableMapperWrapper;
import com.sun.facelets.impl.DefaultFaceletFactory;
import com.sun.facelets.impl.ResourceResolver;
import com.sun.facelets.tag.CompositeFaceletHandler;
import com.sun.facelets.tag.Location;
import com.sun.facelets.tag.Tag;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.TagAttributes;
import com.sun.facelets.tag.TagConfig;
import com.sun.facelets.tag.TagHandler;
import com.sun.facelets.tag.ui.ParamHandler;
/**
*
* @author <a href="civilis@idega.com">Vytautas Čivilis</a>
* @version $Revision: 1.2 $
*
* Last modified: $Date: 2007/11/22 16:41:39 $ by $Author: civilis $
*
*/
public class FaceletFactoryFactory {
private Compiler compiler;
private ResourceResolver resourceResolver;
private FaceletFactory faceletFactory;
/**
* Method should be called only, when current FacesContext is available
* @return FaceletFactory
*/
public synchronized FaceletFactory createFaceletFactory() {
if(faceletFactory == null) {
long refreshPeriod = FaceletViewHandler.DEFAULT_REFRESH_PERIOD;
faceletFactory = new DefaultFaceletFactory(getCompiler(), getResourceResolver(), refreshPeriod);
}
return faceletFactory;
}
/**
* Method should be called only, when current FacesContext is available
* @return FaceletFactory, new each time, contrary to when not passing any parameters
*/
public synchronized FaceletFactory createFaceletFactory(List<UIParameter> params) {
if(params == null || params.size()<1){
return createFaceletFactory();
} else {
long refreshPeriod = FaceletViewHandler.DEFAULT_REFRESH_PERIOD;
faceletFactory = new DefaultFaceletFactory(new IWCompiler(getCompiler(), params), getResourceResolver(), refreshPeriod);
return faceletFactory;
}
}
public Compiler getCompiler() {
return compiler;
}
public void setCompiler(Compiler compiler) {
this.compiler = compiler;
}
public ResourceResolver getResourceResolver() {
return resourceResolver;
}
public void setResourceResolver(ResourceResolver resourceResolver) {
this.resourceResolver = resourceResolver;
}
public class IWCompiler extends Compiler {
Compiler compiler;
List<UIParameter> params;
public IWCompiler(Compiler compiler, List<UIParameter> params){
this.compiler = compiler;
this.params = params;
}
@Override
protected FaceletHandler doCompile(URL src, String alias)
throws IOException, FaceletException, ELException,
FacesException {
// final FaceletHandler nextHandler = compiler.compile(src, alias);
final FaceletHandler leaf = new FaceletHandler() {
public void apply(FaceletContext ctx, UIComponent parent)
throws IOException {
}
public String toString() {
return "FaceletHandler Tail";
}
};
ArrayList<FaceletHandler> paramHandlersList = new ArrayList<FaceletHandler>();
for(UIParameter p : params){
ValueExpression nameExp = p.getValueExpression("name");
String name = null;
if(nameExp != null){
name = nameExp.getExpressionString();
} else{
name = p.getName();
}
ValueExpression valueExp = p.getValueExpression("value");
String value = null;
if(valueExp != null){
value = valueExp.getExpressionString();
} else{
try {
value = (String)p.getValue();
} catch (ClassCastException e) {
getLogger().log(Level.WARNING, "A non-String value can only be passed as an expression to an included facelet.", e);
}
}
ParamConfig conf = new ParamConfig(leaf,name,value);
paramHandlersList.add(new ParamHandler(conf));
}
final CompositeFaceletHandler paramHandlers = new CompositeFaceletHandler((FaceletHandler[])paramHandlersList.toArray(new FaceletHandler[paramHandlersList.size()]));
final FaceletHandler wrapper = new IWIncludeHandler(src, alias, paramHandlers);
return wrapper;
}
}
private class ParamConfig implements TagConfig {
private final String tagId = "_" + UUID.randomUUID().toString();
private FaceletHandler nextHandler;
private Tag theTag;
private Location location = new Location("iwInclude", -1, -1);
private String ns = ""; //"http://java.sun.com/jsf/facelets";
public ParamConfig(FaceletHandler nextHandler,String name, String value) {
this.nextHandler = nextHandler;
TagAttribute attributes[] = new TagAttribute[2];
attributes[0] = new TagAttribute(location,ns,"name","name",name);
attributes[1] = new TagAttribute(location,ns,"value","value",value);
theTag = new Tag(location, ns, "param", "ui:param", new TagAttributes(attributes));
}
@Override
public FaceletHandler getNextHandler() {
return this.nextHandler;
}
@Override
public Tag getTag() {
return theTag;
}
@Override
public String getTagId() {
return tagId;
}
}
private class FakeTagConfig implements TagConfig {
private final String tagId = "_" + UUID.randomUUID().toString();
private FaceletHandler nextHandler;
private Tag theTag = new Tag(new Location("iwInclude", -1, -1), "", "include", "iw:include", new TagAttributes(new TagAttribute[0]));
public FakeTagConfig(FaceletHandler nextHandler) {
this.nextHandler = nextHandler;
}
@Override
public FaceletHandler getNextHandler() {
return this.nextHandler;
}
@Override
public Tag getTag() {
return theTag;
}
@Override
public String getTagId() {
return tagId;
}
}
public class IWIncludeHandler extends TagHandler {
private String alias;
private URL src;
public IWIncludeHandler(URL src, String alias, FaceletHandler paramHandlers ){
super(new FakeTagConfig(paramHandlers));
this.alias=alias;
this.src = src;
}
public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, ELException {
VariableMapper orig = ctx.getVariableMapper();
ctx.setVariableMapper(new VariableMapperWrapper(orig));
try {
//apply ui:param
this.nextHandler.apply(ctx, null);
//include facelet
FaceletHandler root = getCompiler().compile(src, alias);
root.apply(ctx, parent);
// ctx.includeFacelet(parent, alias);
} finally {
ctx.setVariableMapper(orig);
}
}
}
protected Logger getLogger(){
return Logger.getLogger(getClass().getName());
}
}