View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets.tag.jstl.core;
20  
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import javax.el.ELException;
27  import javax.faces.FacesException;
28  import javax.faces.application.StateManager;
29  import javax.faces.component.UIComponent;
30  import javax.faces.event.PhaseId;
31  import javax.faces.view.facelets.FaceletContext;
32  import javax.faces.view.facelets.FaceletException;
33  import javax.faces.view.facelets.TagConfig;
34  import javax.faces.view.facelets.TagException;
35  import javax.faces.view.facelets.TagHandler;
36  
37  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
38  import org.apache.myfaces.view.facelets.FaceletCompositionContext;
39  import org.apache.myfaces.view.facelets.tag.ComponentContainerHandler;
40  import org.apache.myfaces.view.facelets.tag.TagHandlerUtils;
41  import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
42  
43  /**
44   * Simple conditional tag that establishes a context for
45   * mutually exclusive conditional operations, marked by
46   * <when> and <otherwise>
47   * 
48   * @author Jacob Hookom
49   * @version $Id: ChooseHandler.java 1306698 2012-03-29 03:13:06Z lu4242 $
50   */
51  @JSFFaceletTag(name="c:choose")
52  public final class ChooseHandler extends TagHandler implements ComponentContainerHandler
53  {
54  
55      private final ChooseOtherwiseHandler otherwise;
56      private final ChooseWhenHandler[] when;
57  
58      public ChooseHandler(TagConfig config)
59      {
60          super(config);
61  
62          List<ChooseWhenHandler> whenList = new ArrayList<ChooseWhenHandler>();
63          for (ChooseWhenHandler handler : TagHandlerUtils.findNextByType(nextHandler, ChooseWhenHandler.class))
64          {
65              whenList.add(handler);
66          }
67          if (whenList.isEmpty())
68          {
69              throw new TagException(this.tag, "Choose Tag must have one or more When Tags");
70          }
71  
72          this.when = (ChooseWhenHandler[]) whenList.toArray(new ChooseWhenHandler[whenList.size()]);
73  
74          Iterator<ChooseOtherwiseHandler> itrOtherwise = 
75              TagHandlerUtils.findNextByType(nextHandler, ChooseOtherwiseHandler.class).iterator();
76          if (itrOtherwise.hasNext())
77          {
78              this.otherwise = itrOtherwise.next();
79          }
80          else
81          {
82              this.otherwise = null;
83          }
84      }
85  
86      public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
87              ELException
88      {
89          FaceletCompositionContext fcc = FaceletCompositionContext.getCurrentInstance(ctx);
90          boolean processed = false;
91          //assign an unique id for this section
92          String uniqueId = fcc.startComponentUniqueIdSection();
93          Integer savedOption = null;
94          
95          Integer restoredSavedOption = getSavedOption(ctx, fcc, parent, uniqueId);
96          
97          if (restoredSavedOption != null)
98          {
99              if (!PhaseId.RESTORE_VIEW.equals(ctx.getFacesContext().getCurrentPhaseId()))
100             {
101                 for (int i = 0; i < this.when.length; i++)
102                 {
103                     //Ensure each option has its unique section
104                     fcc.startComponentUniqueIdSection();
105                     if (!processed)
106                     {
107                         if (this.when[i].isTestTrue(ctx))
108                         {
109                             boolean markInitialState = !restoredSavedOption.equals(i);
110                             boolean oldMarkInitialState = false;
111                             Boolean isBuildingInitialState = null;
112                             try
113                             {
114                                 if (markInitialState)
115                                 {
116                                     //set markInitialState flag
117                                     oldMarkInitialState = fcc.isMarkInitialState();
118                                     fcc.setMarkInitialState(true);
119                                     isBuildingInitialState = (Boolean) ctx.getFacesContext().getAttributes().put(
120                                             "javax.faces.IS_BUILDING_INITIAL_STATE", Boolean.TRUE);
121                                 }
122                                 this.when[i].apply(ctx, parent);
123                             }
124                             finally
125                             {
126                                 if (markInitialState)
127                                 {
128                                     //unset markInitialState flag
129                                     if (isBuildingInitialState == null)
130                                     {
131                                         ctx.getFacesContext().getAttributes().remove(
132                                                 "javax.faces.IS_BUILDING_INITIAL_STATE");
133                                     }
134                                     else
135                                     {
136                                         ctx.getFacesContext().getAttributes().put(
137                                                 "javax.faces.IS_BUILDING_INITIAL_STATE", isBuildingInitialState);
138                                     }
139                                     fcc.setMarkInitialState(oldMarkInitialState);
140                                 }
141                             }
142                             processed = true;
143                             savedOption = i;
144                             //return;
145                         }
146                     }
147                     fcc.endComponentUniqueIdSection();
148                 }
149 
150             }
151             else
152             {
153                 for (int i = 0; i < this.when.length; i++)
154                 {
155                     //Ensure each option has its unique section
156                     fcc.startComponentUniqueIdSection();
157                     if (!processed)
158                     {
159                         if (restoredSavedOption.equals(i))
160                         {
161                             this.when[i].apply(ctx, parent);
162                             processed = true;
163                             savedOption = i;
164                             //return;
165                         }
166                     }
167                     fcc.endComponentUniqueIdSection();
168                 }
169             }
170         }
171         else
172         {
173             for (int i = 0; i < this.when.length; i++)
174             {
175                 //Ensure each option has its unique section
176                 fcc.startComponentUniqueIdSection();
177                 if (!processed)
178                 {
179                     if (this.when[i].isTestTrue(ctx))
180                     {
181                         this.when[i].apply(ctx, parent);
182                         processed = true;
183                         savedOption = i;
184                         //return;
185                     }
186                 }
187                 fcc.endComponentUniqueIdSection();
188             }
189         }
190         if (this.otherwise != null)
191         {
192             fcc.startComponentUniqueIdSection();
193             if (!processed)
194             {
195                 this.otherwise.apply(ctx, parent);
196                 savedOption = -1;
197             }
198             fcc.endComponentUniqueIdSection();
199         }
200         
201         fcc.endComponentUniqueIdSection();
202 
203         ComponentSupport.saveInitialTagState(ctx, fcc, parent, uniqueId, savedOption);
204         if (fcc.isUsingPSSOnThisView() && fcc.isRefreshTransientBuildOnPSS() && !fcc.isRefreshingTransientBuild())
205         {
206             //Mark the parent component to be saved and restored fully.
207             ComponentSupport.markComponentToRestoreFully(ctx.getFacesContext(), parent);
208         }
209     }
210     
211     private Integer getSavedOption(FaceletContext ctx, FaceletCompositionContext fcc,
212                                    UIComponent parent, String uniqueId)
213     {
214         return (Integer) ComponentSupport.restoreInitialTagState(ctx, fcc, parent, uniqueId);
215     }
216 }