2015-07-09 5 views
3

Могу ли я получить доступ к строке выражения ValueExpression, переданной как значение атрибута в мой компонент taglib?Доступ к необработанному выражению атрибута ValueExpression компоненту taglib

Моя цель - программно вывести из нее отсутствующие значения атрибутов. В этом случае я стараюсь не повторять атрибут как литерал.

Сейчас:

<a:columnText title="name" value="#{entity.name}" sortBy="entity.name" /> 

желательно:

<a:columnText title="name" value="#{entity.name}" /> 

-taglib.xml

<tag> 
    <tag-name>columnText</tag-name> 
    <source>column-text.xhtml</source> 
    <attribute> 
     <name>value</name> 
     <required>true</required> 
    </attribute> 
    <attribute> 
     <name>title</name> 
     <required>false</required> 
    </attribute> 
    <attribute> 
     <name>sortBy</name> 
     <required>false</required> 
    </attribute> 
</tag> 

колонного text.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" 
       xmlns:p="http://primefaces.org/ui" xmlns:h="http://java.sun.com/jsf/html" 
       xmlns:a="http://www.kwa.nl/jsf/app-legacy" xmlns:c="http://java.sun.com/jstl/core"> 

    <c:if test="#{empty sortBy}"> 
     <a:expressionAsLiteral var="#{sortBy}" value="#{value}" /> 
    </c:if> 

    <p:column headerText="#{title}" sortable="true" sortBy="#{sortBy}"> 
     <h:outputText value="#{value}"/> 
     <a:sortByUnwrapper/> 
    </p:column> 
</ui:composition> 

<a:expressionAsLiteral /> предназначен для разворачивания ValueExpression '# {value}' до '# {entity.name}' и установки '# {sortBy}' в литерал 'entity.name'. В этом примере для подачи столбца sort sort.

public class ExpressionAsLiteral extends TagHandler { 

    private final TagAttribute var; 
    private final TagAttribute value; 

    public ExpressionAsLiteral(TagConfig config) { 
     super(config); 
     var = getRequiredAttribute("var"); 
     value = getRequiredAttribute("value"); 
    }  

    @Override 
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException { 
     // abstracted for example. 
     setAsLiteral(ctx, var, unwrapFaceletAttributeValue(ctx,value)); 
    } 
} 

Мой отладчик говорит мне информацию, необходимую спрятана в ValueExpressionImpl-значения private VariableMapper varMapper. Моя проблема заключается в распаковке возвращаемого ValueExpressionImpl, не прибегая к запахам кода.

My google-fu не дает мне возможности. Я чувствую, что мой подход не прав, какие-то советы?

EDIT # 1: Попытался следующее. Результаты в #{value} вместо желаемого значения атрибута #{iRow.title}.

valueExpressionString = value.getValueExpression(ctx, Object.class).getExpressionString(); 

Variables in trace

+0

Какую версию PF вы используете? В PF 5.2 оба 'sortBy =" # {entity.name} "' в клиенте шаблона и 'sortBy =" # {value} "в теге body работают просто отлично для меня. – BalusC

+0

Primefaces 5.2.0 изначально, я попробую еще раз, с учетом возможных исправлений. :) Мне все еще интересно узнать, как разворачивать, не прибегая к отражению тэгов TagValueExpression.orig.varMapper. –

ответ

2

Что касается конкретного вопроса, вы можете получить доступ к ValueExpression, представляющее значение атрибута тега, как это определено в клиенте шаблона с помощью FaceletContext#getVariableMapper(), а затем VariableMapper#resolveVariable() передавая тег имя атрибута. Затем вы можете получить буквальную строку выражения через ValueExpression#getExpressionString().

<my:expressionAsLiteral tagAttributeName="value" /> 
String tagAttributeName = getRequiredAttribute("tagAttributeName").getValue(); 
ValueExpression ve = context.getVariableMapper().resolveVariable(tagAttributeName); 
String expression = ve.getExpressionString(); // #{entity.name} 
String literal = expression.substring(2, expression.length() - 1); // entity.name 

Однако, после этого, это не возможно поставить его в рамки EL с помощью некоторых «вар», потому что PF 4.x в конечном итоге интерпретировать значение sortBy="#{sortBy}" буквально #{sortBy}, не как entity.name. Вам лучше вложить его в <p:column> и обработчик тега явно установить его.

<p:column> 
    <my:expressionAsLiteral tagAttributeName="value" componentAttributeName="sortBy" /> 
    #{value} 
</p:column> 
String componentAttributeName = getRequiredAttribute("componentAttributeName").getValue(); 
parent.getAttributes().put(componentAttributeName, literal); 

Что касается функциональной задачи вы на самом деле пытаетесь решить следующие работы просто отлично для меня на PF 5.2. Исходя из исходного кода, они зафиксировали его в 5.0 и улучшили в 5.1.

/WEB-INF/tags/column.xhtml:

<ui:composition 
    xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:f="http://xmlns.jcp.org/jsf/core" 
    xmlns:h="http://xmlns.jcp.org/jsf/html" 
    xmlns:ui="http://xmlns.jcp.org/jsf/facelets" 
    xmlns:p="http://primefaces.org/ui" 
> 
    <p:column sortBy="#{empty sortBy ? value : sortBy}">#{value}</p:column> 
</ui:composition> 

Шаблон клиента:

<p:dataTable value="#{bean.items}" var="item"> 
    <my:column value="#{item.id}" /> 
    <my:column value="#{item.name}" sortBy="#{item.value}" /> 
    <my:column value="#{item.value}" /> 
</p:dataTable>