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.orchestra.dynaForm.jsf.guiBuilder;
20  
21  import org.apache.myfaces.orchestra.dynaForm.metadata.FieldRepresentation;
22  import org.apache.myfaces.orchestra.dynaForm.metadata.MetaField;
23  import org.apache.myfaces.orchestra.dynaForm.metadata.RelationType;
24  import org.apache.myfaces.orchestra.dynaForm.metadata.utils.TypeInfos;
25  import org.apache.myfaces.orchestra.lib.OrchestraException;
26  
27  import javax.faces.component.UIComponent;
28  import java.util.Date;
29  import java.util.Map;
30  
31  /**
32   * A factory for creating gui-framework-specific representations of
33   * data to be displayed to a user.
34   * <p>
35   * A concrete subclass of this type is needed for each specific
36   * UI framework. Component-based frameworks (such as JSF) may create
37   * component objects and add them to a "component tree", while other
38   * frameworks may simply write data to the current response stream.
39   * <p>
40   * This base class defines the abstract factory methods, and also
41   * provides a number of utility classes for the concrete subclasses
42   * to use. 
43   */
44  public abstract class GuiBuilder
45  {
46      private UIComponent destCmp;
47  
48      private boolean idAsDisplayOnly;
49      private boolean displayOnly;
50      private Map<String, String> labelBundle;
51  
52      public void setDestCmp(UIComponent destCmp)
53      {
54          this.destCmp = destCmp;
55      }
56  
57      public UIComponent getDestCmp()
58      {
59          return destCmp;
60      }
61  
62      /**
63       * Returns true if this field should be rendered display only.
64       */
65      public boolean isFieldDisplayOnly(MetaField field)
66      {
67          return displayOnly || (isIdAsDisplayOnly() && field.isId());
68      }
69  
70      /**
71       * Set to true if the guiBuilder should build a read-only form only.
72       */
73      public void setFormDisplayOnly(boolean displayOnly)
74      {
75          this.displayOnly = displayOnly;
76      }
77  
78      /**
79       * @see #setIdAsDisplayOnly(boolean)
80       */
81      public boolean isIdAsDisplayOnly()
82      {
83          return idAsDisplayOnly;
84      }
85  
86      /**
87       * set if the guiBuilder should build all id fields display only
88       */
89      public void setIdAsDisplayOnly(boolean idAsDisplayOnly)
90      {
91          this.idAsDisplayOnly = idAsDisplayOnly;
92      }
93  
94      /**
95       * @see #setLabelBundle(Map)
96       */
97      public Map<String, String> getLabelBundle()
98      {
99          return labelBundle;
100     }
101 
102     /**
103      * The resource bundle to be used when translating field names into
104      * text labels.
105      * <p>
106      * A labelBundle is optional; if not specified then the field name will
107      * be used as the label. In addition, if a field-name is not defined in
108      * the resource bundle then the raw field-name will also be used.
109      */
110     public void setLabelBundle(Map<String, String> labelBundle)
111     {
112         this.labelBundle = labelBundle;
113     }
114 
115     /**
116      * Output text using the field as value provider.
117      */
118     public abstract void createOutputText(MetaField field);
119 
120     /**
121      * input field
122      */
123     public abstract void createInputText(MetaField field);
124 
125     /**
126      * input date
127      */
128     public abstract void createInputDate(MetaField field);
129 
130     /**
131      * select one menu
132      */
133     public abstract void createSelectOneMenu(MetaField field);
134 
135     /**
136      * enter a number
137      */
138     public abstract void createInputNumber(MetaField field);
139 
140     /**
141      * select a boolean
142      */
143     public abstract void createInputBoolean(MetaField field);
144 
145     /**
146      * search for component
147      */
148     public abstract void createSearchFor(MetaField field);
149 
150     /**
151      * search for component
152      */
153     public abstract void createSearchForSelectMenu(MetaField field);
154 
155     // public abstract void createSearchForSelectMenu(MetaField field);
156 
157     /**
158      * this is when the user passed in a component to use for the this field
159      */
160     public abstract void createNative(MetaField field);
161 
162     /**
163      * actuallly build the fields gui component
164      */
165     protected boolean buildField(MetaField field)
166     {
167         Class<?> fieldType = field.getType();
168 
169         if (field.getWantedComponent() != null)
170         {
171             createNative(field);
172             return true;
173         }
174 
175         if (!field.getWantedComponentType().equals(FieldRepresentation.Automatic))
176         {
177             switch (field.getWantedComponentType())
178             {
179                 case OutputText:
180                     createOutputText(field);
181                     return true;
182 
183                 case InputText:
184                     createInputText(field);
185                     return true;
186 
187                 case InputDate:
188                     createInputDate(field);
189                     return true;
190 
191                 case SelectOneMenu:
192                     if (RelationType.MANY_TO_ONE.equals(field.getRelationType()))
193                     {
194                         createSearchForSelectMenu(field);
195                     }
196                     else
197                     {
198                         // TODO: will not work now
199                         createSelectOneMenu(field);
200                     }
201                     return true;
202 
203                     /*
204                  case SelectSearchMenu:
205                      createSearchForSelectMenu(field);
206                      return true;
207                  */
208 
209                 case InputNumber:
210                     createInputNumber(field);
211                     return true;
212 
213                 case InputBoolean:
214                     createInputBoolean(field);
215                     return true;
216                     
217                 default:
218                     throw new OrchestraException("Unhandled wantedComponentType");
219                         
220             }
221         }
222 
223         if (Boolean.TRUE.equals(field.getDisplayOnly()))
224         {
225             createOutputText(field);
226             return true;
227         }
228 
229         if (field.getAllowedSelections() != null)
230         {
231             createSelectOneMenu(field);
232             return true;
233         }
234 
235         if (RelationType.MANY_TO_ONE.equals(field.getRelationType()))
236         {
237             createSearchFor(field);
238             return true;
239         }
240 
241         if (fieldType == null)
242         {
243             throw new IllegalArgumentException("No type for field '" + field.getName() + "' detected.");
244         }
245 
246         if (Date.class.isAssignableFrom(fieldType))
247         {
248             createInputDate(field);
249             return true;
250         }
251 
252         TypeInfos.Info typeInfo = TypeInfos.getInfo(fieldType);
253         if (typeInfo != null && typeInfo.isNumber())
254         {
255             createInputNumber(field);
256             return true;
257         }
258 
259         if (String.class.isAssignableFrom(fieldType))
260         {
261             createInputText(field);
262             return true;
263         }
264 
265         if (Boolean.class.isAssignableFrom(fieldType) || boolean.class.equals(fieldType))
266         {
267             createInputBoolean(field);
268             return true;
269         }
270 
271         return false;
272     }
273 
274     /**
275      * Localise a text string using the resource-bundle specified for the dynaform.
276      * <p>
277      * If the key is null, or there is no resource-bundle, or there is no entry in
278      * the resource bundle for the specified key, then return the dflt string. 
279      */
280     protected String translateText(String key, String dflt)
281     {
282         if (key == null)
283         {
284             return dflt;
285         }
286 
287         Map<String, String> bundle = getLabelBundle();
288         if (bundle == null)
289         {
290             return dflt;
291         }
292         
293         Object val = bundle.get(key);
294         if (val != null)
295         {
296             return val.toString();
297         }
298         
299         return dflt;
300     }
301 }