2013-04-04 9 views
5

Vorrei creare un'istanza di componenti compositi o di tag in modo programmatico.Come creare un'istanza di un componente composito o di un componente di tag in modo programmatico?

Questa istanziazione verrà eseguita da un componente personalizzato, in genere aggiungendo quei componenti compositi o di tag come bambini.

La risposta migliore che ho trovato durante la scansione dei forum è: http://www.java.net/node/701640#comment-791881. Sembra molto simile a un'altra risposta che ho trovato su questo forum: How to programmatically or dynamically create a composite component in JSF 2.

Mentre lavoravo a questa domanda, ho finalmente scritto il codice che funziona per composito instanciation usando MyFaces (gli esempi nel collegamento sembrano essere specifici di Mojarra). Copio lì come mi c'è voluto del tempo per scrivere e spero che aiutare qualcun altro:

public UIComponent instantiateComposite(String namespace, String componentName) { 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    Resource resource = ctx.getApplication().getResourceHandler().createResource(componentName + ".xhtml", namespace); 
    UIComponent cc = ctx.getApplication().createComponent(ctx, resource); 
    UIPanel panel = (UIPanel) ctx.getApplication().createComponent(UIPanel.COMPONENT_TYPE); 

    // set the facelet's parent 
    cc.getFacets().put(UIComponent.COMPOSITE_FACET_NAME, panel); 

    FaceletFactory ff = (DefaultFaceletFactory) DefaultFaceletFactory.getInstance(); 
    if(ff == null) { 
     FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(ctx); 

     Method createCompiler = null; 
     Method createFaceletFactory = null; 
     try { 
      createCompiler = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createCompiler",FacesContext.class); 
      createFaceletFactory = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createFaceletFactory",FacesContext.class,org.apache.myfaces.view.facelets.compiler.Compiler.class); 
      createCompiler.setAccessible(true); 
      createFaceletFactory.setAccessible(true); 
      org.apache.myfaces.view.facelets.compiler.Compiler compiler = (org.apache.myfaces.view.facelets.compiler.Compiler) createCompiler.invoke(vdl, ctx); 
      ff = (FaceletFactory) createFaceletFactory.invoke(vdl, ctx, compiler); 
     } catch (IllegalAccessException ex) { 
      Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IllegalArgumentException ex) { 
      Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (InvocationTargetException ex) { 
      Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (NoSuchMethodException ex) { 
      Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (SecurityException ex) { 
      Logger.getLogger(SenatDataTableEntryDetail.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 

    try { 
     Facelet facelet = ff.getFacelet(resource.getURL()); 
     facelet.apply(ctx, panel); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return cc; 
} 

Si prega di non prestare attenzione alla gestione delle eccezioni brutto: è proprio generato come automaticamente da NetBeans ... I chiederò agli sviluppatori di MyFaces se c'è un modo per evitare gli attacchi di brutti riflessi.

Come posso fare lo stesso con i componenti di tag, voglio dire i componenti dichiarati come:

<tag> 
    <description>blah blah</description> 
    <tag-name>myWonderfulTag</tag-name> 
    <source>tags/mwl/myWonderfulTag.xhtml</source> 
<!-- attributes --> 
</tag> 

in taglib.

Grazie in anticipo.

risposta

0

ok, ho trovato come farlo con MyFaces. Si richiede anche un po 'di brutto riflessione ...

public static UIComponent instantiateTagComponent(Location loc, String namespace, String localPrefix, String componentName, TagComponentParam params[]) { 
    final String ERROR_MESSAGE = "Erreur lors de l'instanciation d'un tag component"; 
    FacesContext ctx = FacesContext.getCurrentInstance(); 
    AbstractFaceletContext fctx = (AbstractFaceletContext) ctx.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY); 
    fctx.pushPageContext(new PageContextImpl()); 

    FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(ctx); 

    UIPanel panel = (UIPanel) ctx.getApplication().createComponent(UIPanel.COMPONENT_TYPE); 

    try { 
     Method createCompiler = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createCompiler",FacesContext.class); 
     Method createFaceletFactory = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createFaceletFactory",FacesContext.class,org.apache.myfaces.view.facelets.compiler.Compiler.class); 
     createCompiler.setAccessible(true); 
     createFaceletFactory.setAccessible(true); 
     org.apache.myfaces.view.facelets.compiler.Compiler compiler = (org.apache.myfaces.view.facelets.compiler.Compiler) createCompiler.invoke(vdl, ctx); 
     FaceletFactory ff = (FaceletFactory) createFaceletFactory.invoke(vdl, ctx, compiler); 
     TagLibrary tl = compiler.createTagLibrary(); 
     TagConfig tc = new JSFUtilsTagUnit(tl, namespace, localPrefix, componentName,params,loc); 
     TagHandler th = tl.createTagHandler(namespace, componentName, tc); 
     Field declaredField = FaceletCompositionContext.class.getDeclaredField("FACELET_COMPOSITION_CONTEXT_KEY"); 
     declaredField.setAccessible(true); 
     FaceletCompositionContextImpl faceletCompositionContextImpl = new FaceletCompositionContextImpl(ff,ctx); 
     Class<?> dfcClass = Class.forName("org.apache.myfaces.view.facelets.impl.DefaultFaceletContext"); 
     Field fMCTX = dfcClass.getDeclaredField("_mctx"); 
     fMCTX.setAccessible(true); 
     fMCTX.set(fctx, faceletCompositionContextImpl); 
     FacesContext.getCurrentInstance().getAttributes().put((String)declaredField.get(null),faceletCompositionContextImpl); 
     FaceletCompositionContext mctx = (FaceletCompositionContext) FaceletCompositionContext.getCurrentInstance(fctx); 
     mctx.startComponentUniqueIdSection(); 
     th.apply(fctx, panel); 
    } catch (IOException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (InvocationTargetException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (NoSuchMethodException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (NoSuchFieldException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (SecurityException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (ClassNotFoundException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (IllegalArgumentException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } catch (IllegalAccessException ex) { 
     log.error(ERROR_MESSAGE, ex); 
    } 
    finally { 
     fctx.popPageContext(); 
    } 
    return panel; 
} 

La classe JSFUtilsTagUnit è:

static class JSFUtilsTagUnit implements TagConfig { 

    private final TagLibrary library; 
    private final String namespace; 
    private final String name; 
    private Tag tag; 

    public JSFUtilsTagUnit(TagLibrary library, String namespace, String localPrefix, String name, TagComponentParam params[], Location loc) { 
     this.library = library; 
     this.namespace = namespace; 
     this.name = name; 
     if(loc == null) { 
      loc = new Location("virtual", -1, -1); 
     } 
     TagAttribute[] tas; 
     if((params != null) && (params.length > 0)) { 
      tas = new TagAttribute[params.length]; 
      int iCurrent = 0; 
      for(TagComponentParam tcpCur : params) { 
       tas[iCurrent] = new TagAttributeImpl(loc,"",tcpCur.getName(), tcpCur.getName(), tcpCur.getValue()); 
       iCurrent++; 
      } 
     } else { 
      tas = new TagAttribute[0]; 
     } 
     TagAttributes tattrs = new TagAttributesImpl(tas); 
     tag = new Tag(loc, namespace, name, localPrefix+":"+name, tattrs); 
    } 

    public FaceletHandler getNextHandler() { 
     return new FaceletHandler() { 

      public void apply(FaceletContext ctx, UIComponent parent) throws IOException { 
      } 
     }; 
    } 

    public Tag getTag() { 
     return tag; 
    } 

    public String getTagId() { 
     return "-1"; 
    } 

} 

Spero che vi aiuterà a qualcun altro!