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.trinidad.component;
20  
21  import java.util.ArrayList;
22  import java.util.List;
23  
24  import javax.el.MethodExpression;
25  
26  import javax.faces.component.UIComponent;
27  import javax.faces.context.FacesContext;
28  import javax.faces.event.AbortProcessingException;
29  import javax.faces.event.FacesEvent;
30  import javax.faces.event.PhaseId;
31  
32  import org.apache.myfaces.trinidad.event.RowDisclosureEvent;
33  import org.apache.myfaces.trinidad.model.RowKeySet;
34  
35  
36  /**
37   * utility methods for dealing with tree structures that do disclosure.
38   */
39  public final class HierarchyUtils
40  {
41    static void __handleBroadcast(
42      UIXHierarchy  comp,
43      FacesEvent    event,
44      RowKeySet     state,
45      MethodExpression method) throws AbortProcessingException
46    {
47      // Notify the specified disclosure listener method (if any)
48      if (event instanceof RowDisclosureEvent)
49      {
50        RowDisclosureEvent dEvent = (RowDisclosureEvent) event;
51        state.removeAll(dEvent.getRemovedSet());
52        state.addAll(dEvent.getAddedSet());
53        //pu: Implicitly record a Change for 'disclosedRowKeys' attribute
54        comp.addAttributeChange("disclosedRowKeys", state);
55        comp.broadcastToMethodExpression(event, method);
56      }
57    }
58  
59  
60    static void __handleEncodeBegin(
61      UIXHierarchy comp,
62      RowKeySet    set
63      )
64    {
65      if (comp.__isFirstRender())
66      {
67        // @todo - the focusPath in tree is an attr, the focusPath in
68        // navigationTree comes off the model, okay???
69        Object focusRowKey = comp.getFocusRowKey();
70        if ( focusRowKey != null)
71        {
72          List<Object> focusPath =
73            new ArrayList<Object>(comp.getAllAncestorContainerRowKeys(focusRowKey));
74          focusPath.add(focusRowKey);
75          int size = focusPath.size();
76          for ( int i = 0 ; i < size; i++)
77          {
78            Object subkey = focusPath.get(i);
79            set.add(subkey);
80          }
81        }
82      }
83    }
84  
85  
86    static void __processLevel(
87      FacesContext context,
88      PhaseId      phaseId,
89      UIXHierarchy comp
90      )
91    {
92      if (comp.getRowCount() != 0)
93      {
94        UIComponent nodeStamp = comp.getFacet("nodeStamp");
95  
96        if ( nodeStamp != null)
97        {
98          Object oldRowKey = comp.getRowKey();
99          try
100         {
101           int startIndex = comp.getFirst();
102           int endIndex = TableUtils.getLast(comp, startIndex);
103 
104           for (int i = startIndex; i <= endIndex; i++)
105           {
106             comp.setRowIndex(i);
107             comp.processComponent(context, nodeStamp, phaseId);
108           }
109         }
110         finally
111         {
112           comp.setRowKey(oldRowKey);
113         }
114       }
115     }
116   }
117 
118   static void __iterateOverTree(
119     FacesContext context,
120     PhaseId      phaseId,
121     UIXHierarchy comp,
122     RowKeySet    state,
123     boolean      processChildrenAsStamps
124     )
125   {
126     UIComponent nodeStamp = comp.getFacet("nodeStamp");
127     int oldRow = comp.getRowIndex();
128 
129     try
130     {
131       int first = comp.getFirst();
132       int last = TableUtils.getLast(comp, first);
133       for(int i=first; i<=last; i++)
134       {
135         comp.setRowIndex(i);
136         if (processChildrenAsStamps)
137           TableUtils.processStampedChildren(context, comp, phaseId);
138         comp.processComponent(context, nodeStamp, phaseId);
139         if (comp.isContainer() && (state.isContained()))
140         {
141           comp.enterContainer();
142 
143           try
144           {
145             __iterateOverTree( context,
146                                phaseId,
147                                comp,
148                                state,
149                                processChildrenAsStamps);
150           }
151           finally
152           {
153             comp.exitContainer();
154           }
155         }
156       }
157     }
158     finally
159     {
160       comp.setRowIndex(oldRow);
161     }
162   }
163 
164   // sets the currency to the row or container that we want to start rendering
165   // from:
166   static boolean __setStartDepthPath(
167     UIXHierarchy component,
168     int          startDepth)
169   {
170     boolean isNewPath = false;
171     Object focusKey = component.getFocusRowKey();
172 
173     if (focusKey != null )
174     {
175       List<Object> focusPath = component.getAllAncestorContainerRowKeys(focusKey);
176       focusPath = new ArrayList<Object>(focusPath);
177       focusPath.add(focusKey);
178       int focusSize =  focusPath.size();
179       if ( focusSize > startDepth )
180       {
181         isNewPath = true;
182         component.setRowKey(focusPath.get(startDepth));
183       }
184       else if ( focusSize == startDepth )
185       {
186         isNewPath = true;
187         component.setRowKey(focusKey);
188         component.enterContainer();
189       }
190     }
191     else
192     {
193       if (startDepth  == 0)
194       {
195         isNewPath = true;
196         component.setRowKey(null);
197       }
198     }
199 
200     return isNewPath;
201   }
202 
203   private HierarchyUtils()
204   {
205   }
206 }