2013-04-04 12 views
5

Chciałbym programowo utworzyć instancję komponentów złożonych lub znaczników.Jak programowo utworzyć komponent złożony lub komponent znacznika?

Ta instancja byłaby wykonywana przez niestandardowy komponent, zwykle dodając te komponenty kompozytowe lub znaczniki jako elementy podrzędne.

Najlepszą odpowiedzią znalezioną podczas przeszukiwania forów jest: http://www.java.net/node/701640#comment-791881. Wygląda bardzo podobnie do innej odpowiedzi znalezionej na tym forum: How to programmatically or dynamically create a composite component in JSF 2.

Podczas pracy nad tym pytaniem, w końcu napisałem kod, który działa na złożony instanciation za pomocą MyFaces (przykłady w linku wydają się być specyficzne dla Mojarra). I skopiować go tam zajęło mi trochę czasu, aby ją napisać i mam nadzieję, że to pomoże ktoś inny:

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

Proszę nie zwracać uwagę na brzydkie obsługi wyjątków: to jest tak samo automatycznie generowane przez NetBeans ... ja zapyta twórców MyFaces, czy istnieje sposób na uniknięcie brzydkich hacków refleksyjnych.

Jak mogę zrobić to samo z elementów znaczników, to znaczy elementy zadeklarowane jak:

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

w TagLib.

Z góry dziękuję.

Odpowiedz

0

ok, Znalazłem, jak to zrobić z MyFaces. Wymaga to również trochę brzydkiego refleksji ...

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

Klasa JSFUtilsTagUnit jest:

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"; 
    } 

} 

nadzieję, że pomoże ktoś inny!