[ 
https://issues.apache.org/jira/browse/DELTASPIKE-877?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Gerhard Petracek resolved DELTASPIKE-877.
-----------------------------------------
    Resolution: Fixed

> allow to inherit dynamically changed metadata 
> ----------------------------------------------
>
>                 Key: DELTASPIKE-877
>                 URL: https://issues.apache.org/jira/browse/DELTASPIKE-877
>             Project: DeltaSpike
>          Issue Type: New Feature
>          Components: JSF-Module
>    Affects Versions: 1.3.0
>            Reporter: Gerhard Petracek
>            Assignee: Gerhard Petracek
>             Fix For: 1.3.1
>
>
> currently a ConfigPreProcessor can manipulate custom metadata.
> such a changed annotation-instance will be used instead of the found one.
> however, those changes are currently limited to the current node and they 
> aren't visible to child nodes. that can lead to redundant implementations 
> (depending on the concrete use-case).
> changing metadata in a "mixed" tree (inheritance and nesting) can get 
> complex, however, if we allow child nodes to see just the changes done by 
> ancestor-nodes, it won't increase the complexity for users and it's possible 
> to support nice uses-cases like:
> {code}
> @View(navigation = REDIRECT)
> public interface Pages extends ViewConfig {
>     //...
>     @Wizard //all wizard-steps inherit this meta-data and Step1 is known as 
> entry-point (for all wizard-steps)
>     interface MyWizard extends Pages {
>         @EntryPoint
>         class Step1 implements MyWizard {}
>         class Step2 implements MyWizard {} //protected wizard-step (see 
> EntryPointHandler)
>         class Summary implements MyWizard {} //protected wizard-step (see 
> EntryPointHandler)
>     }
> }
> //...
> @ViewMetaData
> public @interface EntryPoint {
> }
> //...
> @ViewMetaData(preProcessor = Wizard.EntryPointProcessor.class)
> public @interface Wizard {
>     Class<? extends ViewConfig> entryPoint() default ViewConfig.class;
>     class EntryPointProcessor implements ConfigPreProcessor<Wizard> {
>         @Override
>         public Wizard beforeAddToConfig(Wizard wizard, ViewConfigNode 
> viewConfigNode) {
>             if (!ViewConfig.class.equals(wizard.entryPoint()) /*explicitly 
> defined entry-point*/) {
>                 return wizard;
>             }
>             for (ViewConfigNode childNode : viewConfigNode.getChildren()) {
>                 for (Annotation childMetaData : childNode.getMetaData()) {
>                     if 
> (EntryPoint.class.equals(childMetaData.annotationType())) {
>                         Map<String, Object> values = new HashMap<String, 
> Object>();
>                         values.put("entryPoint", childNode.getSource());
>                         return AnnotationInstanceProvider.of(Wizard.class, 
> values);
>                     }
>                 }
>             }
>             return wizard;
>         }
>     }
> }
> @WindowScoped
> public class EntryPointHandler implements Serializable {
>     private Class<? extends ViewConfig> previousEntryPoint;
>     @Inject
>     private ViewConfigResolver viewConfigResolver;
>     @Inject
>     private ViewNavigationHandler viewNavigationHandler;
>     protected void checkEntryPointsAndWizardSteps(@Observes 
> @BeforePhase(JsfPhaseId.RENDER_RESPONSE) PhaseEvent phaseEvent) {
>         UIViewRoot viewRoot = phaseEvent.getFacesContext().getViewRoot();
>         if (viewRoot == null) {
>             return;
>         }
>         String viewIdToRender = viewRoot.getViewId();
>         ViewConfigDescriptor viewConfigDescriptor = 
> viewConfigResolver.getViewConfigDescriptor(viewIdToRender);
>         if (viewConfigDescriptor == null) {
>             return;
>         }
>         if (!viewConfigDescriptor.getMetaData(EntryPoint.class).isEmpty()) {
>             this.previousEntryPoint = viewConfigDescriptor.getConfigClass();
>             //additional entry-point logic - like close open conversation, 
> fire an event,...
>         } else if (!viewConfigDescriptor.getMetaData(Wizard.class).isEmpty()) 
> {
>             Wizard wizard = 
> viewConfigDescriptor.getMetaData(Wizard.class).iterator().next();
>             Class<? extends ViewConfig> entryPointOfWizard = 
> wizard.entryPoint();
>             if (!entryPointOfWizard.equals(this.previousEntryPoint)) {
>                 this.viewNavigationHandler.navigateTo(entryPointOfWizard);
>             }
>         }
>     }
> }
> {code}
> that are less than 100 loc for a simple but generic entry-point logic and 
> protection of wizard steps (including redirection to the start/entry-point of 
> the corresponding wizard) which replace features like @ConversationRequired 
> and it's way nicer than what's needed currently:
> {code}
> @View(navigation = REDIRECT)
> public interface Pages extends ViewConfig {
>     //...
>     interface OutdatedWizard extends Pages {
>         @EntryPoint
>         class Step1 implements MyWizard {}
>         @Wizard(EntryPoint = Pages.MyWizard.Step1.class)
>         class Step2 implements MyWizard {}
>         @Wizard(EntryPoint = Pages.MyWizard.Step1.class)
>         class Summary implements PromotionWizard {}
>     }
> }
> //...
> {code}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to