instanceof vérifier dans EL langage d'expression

y a-t-il un moyen d'effectuer un contrôle EL instanceof ?

E. G.

<h:link rendered="#{model instanceof ClassA}">      
    #{errorMessage1}
</h:link>
<h:link rendered="#{model instanceof ClassB}">      
    #{errorMessage2}
</h:link>
30
demandé sur BalusC 2012-04-25 14:55:47

7 réponses

vous pourriez comparer Class#getName() ou, peut-être mieux, Class#getSimpleName() à un String .

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

noter l'importance de spécifier Object#getClass() avec la notation brace ['class'] parce que class est un Java littéral réservé qui autrement lancerait une exception EL dans EL 2.2+.

l'alternative type sûre est d'ajouter quelques public enum Type { A, B } avec public abstract Type getType() à la classe de base commune du modèle.

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

toute valeur non valide lancerait ici une exception EL pendant L'exécution dans EL 2.2+.

dans le cas où vous utilisez OmniFaces , depuis la version 3.0 vous pouvez utiliser #{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>
47
répondu BalusC 2018-06-01 11:39:23

ça ne marche pas dans EL . Utilisez le support pour ceci:

public class MyBean {

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


}

et ensuite faire le contrôle en appelant la fève de soutien:

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

7
répondu flash 2012-04-25 11:01:52

cela fonctionne:

rendered="#{node.getClass().getSimpleName() == 'Logt_anno'}"
4
répondu user2362075 2014-01-21 16:05:36

définit une fonction statique comme:

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

définit une fonction EL personnalisée pour elle, et utilise cela. Nous pourrions aussi passer un nom de chaîne et faire un forName() à l'intérieur de la méthode.

3
répondu manojm 2015-11-18 14:35:37

Il y a un moyen, voir

JSF EL: instanceof réservé, mais n'est pas encore implémentée?

cependant, l'opérateur instanceof n'est toujours pas mis en œuvre, du moins en Mojarra 2.1. S'il vous plaît voter pour le bug ici:

http://java.net/jira/browse/JSP_SPEC_PUBLIC-113

la meilleure solution actuellement est probablement de stocker le nom de la classe dans un support getter au lieu de créer une méthode d'essai booléenne pour chaque classe:

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

donc ce serait un mélange de solutions de BalusC et de flash. Il serait cependant beaucoup plus lisible dans JSF que celui de BalusC et ressemble plutôt au futur instanceof operator use:

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

il n'en résultera pas une méthode par classe d'essai sur la fève de soutien, comme le suggère flash. Ça pourrait être plus lent que flash.

2
répondu Kawu 2017-05-23 10:31:37

pas très élégant car il mélange JSP EL et le plus ancien syntaxe d'expression , mais ne nécessite pas de Java code:

<%@ 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>
1
répondu Bass 2017-05-31 14:31:05

vous pourriez utiliser un haricot auxiliaire pour cela:

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

Utilisation:

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

cela a l'avantage que l'héritage est pris en compte et vous pouvez tester pour les classes que vous ne pouvez pas modifier (les deux inconvénients des solutions de BalusC).

si vous aimez utiliser le nom de classe simple (et ne craignez pas les conflits de nom), vous pouvez utiliser une carte de recherche que vous remplissez à la main ou avec un scanner de chemin de classe comme org.réflexions :

@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);
  }
}

vous pourriez même déplacer la fonction helper à 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 ...
}

Utilisation:

<h:link rendered="#{model.isInstanceOf('package.ClassA')}">
  #{errorMessage1}
</h:link>
0
répondu Tobias Liefke 2018-06-01 09:40:24