operadores language jsf el instanceof

operadores - jsf expression language operators



instancia de verificación en el lenguaje de expresión EL (7)

Defina una función estática como:

public boolean isInstanceOf( Object obj, Class targetClass) { return targetClass.isInstance(obj); }

Defina una función EL personalizada para él, y úselo. También podríamos pasar un nombre de cadena y hacer un forName() dentro del método.

¿Hay alguna manera de realizar una instanceof verificación en EL?

P.ej

<h:link rendered="#{model instanceof ClassA}"> #{errorMessage1} </h:link> <h:link rendered="#{model instanceof ClassB}"> #{errorMessage2} </h:link>


Eso no funciona en EL . Usa el bean de respaldo para esto:

public class MyBean { public boolean getIsClassA() { if(model instanceof ClassA) { return true; } return false; } }

Y luego haga el control llamando al bean de respaldo:

<h:link outcome="#{PageNameA}?faces-redirect=true&amp;" rendered="#{myBean.isClassA}"> #{errorMessage} </h:link>


Hay una manera, ver

JSF EL: ¿instancia de reserva pero aún no implementada?

Sin embargo, el operador instanceof aún no está implementado, al menos en Mojarra 2.1. Por favor vote por el error aquí:

java.net/jira/browse/JSP_SPEC_PUBLIC-113

La mejor solución actualmente es, probablemente, almacenar el nombre de clase en un getter de bean de respaldo en lugar de crear un método de prueba booleano para cada clase:

public String getSelectedNodeClassName() { return selectedNode.getClass().getSimpleName(); }

Entonces sería una mezcla de las soluciones de BalusC y flash. Sin embargo, sería mucho más legible en JSF que BalusC''s plus, más o menos se asemeja a la instanceof futura de uso del operador:

rendered="#{nodeManager.selectedNodeClassName eq ''ChapterNode''}"

Esto no producirá un método por prueba de clase en el bean de respaldo como se sugiere flash. Sin embargo, esto podría ser más lento que flash.


No es muy elegante ya que mezcla JSP EL y la sintaxis de expresión anterior, pero no requiere ningún código Java adicional:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <c:set var="interfaceClass" value="<%=com.example.ClassA.class%>"/> <c:set var="implementationClass" value="${model[''class'']}"/> <c:if test="${interfaceClass.isAssignableFrom(implementationClass)}"> <%-- Your logic here. --%> </c:if>


Podría comparar la Class#getName() o, mejor aún, la Class#getSimpleName() a una String .

<h:link rendered="#{model[''class''].simpleName eq ''ClassA''}"> #{errorMessage1} </h:link> <h:link rendered="#{model[''class''].simpleName eq ''ClassB''}"> #{errorMessage2} </h:link>

Tenga en cuenta la importancia de especificar el Object#getClass() con la notación de paréntesis [''class''] porque la class es un literal reservado de Java que arrojaría una excepción EL en EL 2.2+.

La alternativa de tipo seguro es agregar alguna public enum Type { A, B } junto con public abstract Type getType() a la clase base común del modelo.

<h:link rendered="#{model.type eq ''A''}"> #{errorMessage1} </h:link> <h:link rendered="#{model.type eq ''B''}"> #{errorMessage2} </h:link>

Cualquier valor inválido arrojaría aquí una excepción EL durante el tiempo de ejecución en EL 2.2+.

En caso de que esté usando OmniFaces , desde la versión 3.0 podría usar #{of:isInstance()} .

<h:link rendered="#{of:isInstance(''com.example.ClassA'', model)}"> #{errorMessage1} </h:link> <h:link rendered="#{of:isInstance(''com.example.ClassB'', model)}"> #{errorMessage2} </h:link>


Podría usar un bean auxiliar para eso:

@ManagedBean public class Helper { public boolean isInstance(Object bean, String fullyQualifiedClassName) { return Class.forName(fullyQualifiedClassName).isInstance(bean); } }

Uso:

<h:link rendered="#{helper.isInstance(model, ''package.ClassA'')}"> #{errorMessage1} </h:link>

Esto tiene la ventaja de que se tiene en cuenta la herencia y puede probar las clases que no puede modificar (ambas desventajas de las soluciones de BalusC).

Si te gusta usar el nombre de clase simple (y no temas los conflictos de nombres), puedes usar un mapa de búsqueda que llenes a mano o con un escáner de ruta de clase como org.reflections :

@ManagedBean @ApplicationScoped public class Helper { private Map<String, Class<? extends MyBaseClass>> classes = new Reflections("myrootpackage").getSubTypesOf(MyBaseClass.class).stream() .collect(Collectors.toMap(Class::getSimpleName, Function.identity())); public boolean isInstance(Object bean, String simpleClassName) { final Class<? extends MyBaseClass> c = this.classes.get(simpleClassName); return c != null && c.isInstance(bean); } }

Incluso podría mover la función auxiliar a un ELResolver:

public class InstanceOfELResolver extends ELResolver { public Object invoke(final ELContext context, final Object base, final Object method, final Class<?>[] paramTypes, final Object[] params) { if ("isInstanceOf".equals(method) && params.length == 1) { context.setPropertyResolved(true); try { return params[0] != null && Class.forName(params[0].toString()).isInstance(base); } catch (final ClassNotFoundException e) { return false; } } return null; } // ... All other methods with default implementation ... }

Uso:

<h:link rendered="#{model.isInstanceOf(''package.ClassA'')}"> #{errorMessage1} </h:link>


funciona:

rendered="#{node.getClass().getSimpleName() == ''Logt_anno''}"