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