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  
20  package org.apache.myfaces.tobago.internal.component;
21  
22  import org.apache.myfaces.tobago.component.Attributes;
23  import org.apache.myfaces.tobago.component.Visual;
24  import org.apache.myfaces.tobago.model.ExpandedState;
25  import org.apache.myfaces.tobago.model.ScrollPosition;
26  import org.apache.myfaces.tobago.model.SelectedState;
27  import org.apache.myfaces.tobago.model.TreeState;
28  
29  import javax.el.ELContext;
30  import javax.el.ValueExpression;
31  import javax.faces.component.NamingContainer;
32  import javax.faces.component.UIComponent;
33  import javax.faces.context.FacesContext;
34  
35  public abstract class AbstractUITree extends AbstractUIData implements NamingContainer, Visual {
36  
37    public static final String MESSAGE_NOT_LEAF = "tobago.tree.MESSAGE_NOT_LEAF";
38  
39    /**
40     * @deprecated since 2.0.0
41     */
42    @Deprecated
43    public static final String SEP = "-";
44  
45    /**
46     * @deprecated since 2.0.0
47     */
48    @Deprecated
49    public static final String SELECT_STATE = SEP + "selectState";
50  
51    /**
52     * @deprecated since 2.0.0
53     */
54    @Deprecated
55    public static final String MARKED = "marked";
56  
57    private TreeState state;
58  
59    @Override
60    public void processValidators(final FacesContext facesContext) {
61      final int last = hasRows() ? getFirst() + getRows() : Integer.MAX_VALUE;
62      for (int rowIndex = getFirst(); rowIndex < last; rowIndex++) {
63        setRowIndex(rowIndex);
64        if (!isRowAvailable()) {
65          break;
66        }
67        for (final UIComponent child : getChildren()) {
68          child.processValidators(facesContext);
69        }
70      }
71      setRowIndex(-1);
72    }
73  
74    @Override
75    public void processUpdates(final FacesContext facesContext) {
76      final int last = hasRows() ? getFirst() + getRows() : Integer.MAX_VALUE;
77      for (int rowIndex = getFirst(); rowIndex < last; rowIndex++) {
78        setRowIndex(rowIndex);
79        if (!isRowAvailable()) {
80          break;
81        }
82        for (final UIComponent child : getChildren()) {
83          child.processUpdates(facesContext);
84        }
85      }
86      setRowIndex(-1);
87    }
88  
89    /**
90     * @deprecated since 2.0.0
91     */
92    @Deprecated
93    public UIComponent getRoot() {
94      // find the UITreeNode in the children.
95      for (final UIComponent child : getChildren()) {
96        if (child instanceof AbstractUITreeNodeBase) {
97          return child;
98        }
99      }
100     return null;
101   }
102 
103   @Override
104   public boolean getRendersChildren() {
105     return true;
106   }
107 
108   @Override
109   public void processDecodes(final FacesContext facesContext) {
110 
111     if (!isRendered()) {
112       return;
113     }
114 
115     final int last = hasRows() ? getFirst() + getRows() : Integer.MAX_VALUE;
116     for (int rowIndex = getFirst(); rowIndex < last; rowIndex++) {
117       setRowIndex(rowIndex);
118       if (!isRowAvailable()) {
119         break;
120       }
121       for (final UIComponent child : getChildren()) {
122         child.processDecodes(facesContext);
123       }
124     }
125     setRowIndex(-1);
126 
127     decode(facesContext);
128   }
129 
130 /* XXX
131   @Override
132   public void validate(FacesContext context) {
133 */
134 
135   // todo: validate must be written new, without TreeState
136 /*
137     if (isRequired() && getState().getSelection().size() == 0) {
138       setValid(false);
139       FacesMessage facesMessage = MessageUtils.createFacesMessage(context,
140           UISelectOne.MESSAGE_VALUE_REQUIRED, FacesMessage.SEVERITY_ERROR);
141       context.addMessage(getClientId(context), facesMessage);
142     }
143 
144     String selectable = ComponentUtils.getStringAttribute(this, selectable);
145     if (selectable != null && selectable.endsWith("LeafOnly")) {
146 
147       Set<DefaultMutableTreeNode> selection = getState().getSelection();
148 
149       for (DefaultMutableTreeNode node : selection) {
150         if (!node.isLeaf()) {
151           FacesMessage facesMessage = MessageUtils.createFacesMessage(
152               context, MESSAGE_NOT_LEAF, FacesMessage.SEVERITY_ERROR);
153           context.addMessage(getClientId(context), facesMessage);
154           break; // don't continue iteration, no dublicate messages needed
155         }
156       }
157     }
158 */
159 //  call all validators
160 /*
161     if (getValidators() != null) {
162       for (Validator validator : getValidators()) {
163         try {
164           validator.validate(context, this, null);
165         } catch (ValidatorException ve) {
166           // If the validator throws an exception, we're
167           // invalid, and we need to add a message
168           setValid(false);
169           FacesMessage message = ve.getFacesMessage();
170           if (message != null) {
171             message.setSeverity(FacesMessage.SEVERITY_ERROR);
172             context.addMessage(getClientId(context), message);
173           }
174         }
175       }
176     }
177   }
178 
179   @Override
180   public void updateModel(FacesContext facesContext) {
181     // nothing to update for tree's
182     // TODO: updating the model here and *NOT* in the decode phase
183   }
184 */
185   public void setState(final TreeState state) {
186     this.state = state;
187   }
188 
189   public TreeState getState() {
190     if (state != null) {
191       return state;
192     }
193 
194     final ELContext elContext = FacesContext.getCurrentInstance().getELContext();
195     final ValueExpression expression = getValueExpression(Attributes.state.getName());
196 
197     if (expression != null) {
198       TreeState state = (TreeState) expression.getValue(elContext);
199       if (state == null) {
200         state = new TreeState(new ExpandedState(2), new SelectedState(), new ScrollPosition());
201         expression.setValue(elContext, state);
202       }
203       return state;
204     }
205 
206     state = new TreeState(new ExpandedState(2), new SelectedState(), new ScrollPosition());
207     return state;
208   }
209 
210   @Override
211   public SelectedState getSelectedState() {
212     return getState().getSelectedState();
213   }
214 
215   @Override
216   public ExpandedState getExpandedState() {
217     return getState().getExpandedState();
218   }
219 
220   @Override
221   public void restoreState(final FacesContext context, final Object componentState) {
222     final Object[] values = (Object[]) componentState;
223     super.restoreState(context, values[0]);
224     state = (TreeState) values[1];
225   }
226 
227   @Override
228   public Object saveState(final FacesContext context) {
229     final Object[] values = new Object[2];
230     values[0] = super.saveState(context);
231     values[1] = state;
232     return values;
233   }
234 }