1 package org.apache.turbine.services.intake.model;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.util.ArrayList;
58 import java.util.HashMap;
59 import java.util.Iterator;
60 import java.util.List;
61 import java.util.Map;
62 import org.apache.turbine.om.Retrievable;
63 import org.apache.turbine.services.intake.TurbineIntake;
64 import org.apache.turbine.services.intake.xmlmodel.XmlField;
65 import org.apache.turbine.services.intake.xmlmodel.XmlGroup;
66 import org.apache.turbine.util.ParameterParser;
67 import org.apache.turbine.util.RunData;
68 import org.apache.turbine.util.TurbineException;
69 import org.apache.turbine.util.pool.Recyclable;
70
71 /***
72 * Holds a group of Fields
73 *
74 * @version $Id: Group.java,v 1.2 2002/07/11 16:53:27 mpoeschl Exp $
75 */
76 public class Group
77 implements Recyclable
78 {
79 public static final String EMPTY = "";
80
81 /*
82 * An id representing a new object.
83 */
84 public static final String NEW = "_0";
85
86 /***
87 * The key used to represent this group in a parameter.
88 * This key is usually a prefix as part of a field key.
89 */
90 protected final String gid;
91
92 /***
93 * The name used in templates and java code to refer to this group.
94 */
95 protected final String name;
96
97 /***
98 * The number of Groups with the same name that will be pooled.
99 */
100 private final int poolCapacity;
101
102 /***
103 * A map of the fields in this group mapped by field name.
104 */
105 protected Map fields;
106
107 /***
108 * Map of the fields by mapToObject
109 */
110 protected Map mapToObjectFields;
111
112 /***
113 * An array of fields in this group.
114 */
115 protected Field[] fieldsArray;
116
117 /***
118 * The object id used to associate this group to a bean
119 * for one request cycle
120 */
121 protected String oid;
122
123 /***
124 * The object containing the request data
125 */
126 protected RunData data;
127
128 /***
129 * A flag to help prevent duplicate hidden fields declaring this group.
130 */
131 protected boolean isDeclared;
132
133 /***
134 * Constructs a new Group based on the xml specification. Groups are
135 * instantiated and pooled by the IntakeService and should not
136 * be instantiated otherwise.
137 *
138 * @param group a <code>XmlGroup</code> value
139 * @exception Exception if an error occurs in other classes
140 */
141 public Group(XmlGroup group)
142 throws Exception
143 {
144 gid = group.getKey();
145 name = group.getName();
146 poolCapacity = Integer.parseInt(group.getPoolCapacity());
147
148 List inputFields = group.getFields();
149 int size = inputFields.size();
150 fields = new HashMap((int)(1.25*size + 1));
151 mapToObjectFields = new HashMap((int)(1.25*size + 1));
152 fieldsArray = new Field[size];
153 for (int i=size-1; i>=0; i--)
154 {
155 XmlField f = (XmlField)inputFields.get(i);
156 Field field = FieldFactory.getInstance(f, this);
157 fieldsArray[i]= field;
158 fields.put(f.getName(), field);
159
160 // map fields by their mapToObject
161 List tmpFields = (List)mapToObjectFields.get(f.getMapToObject());
162 if ( tmpFields == null )
163 {
164 tmpFields = new ArrayList(size);
165 mapToObjectFields.put(f.getMapToObject(), tmpFields);
166 }
167 tmpFields.add(field);
168 }
169
170 // Change the mapToObjectFields values to Field[]
171 Iterator keys = mapToObjectFields.keySet().iterator();
172 while ( keys.hasNext() )
173 {
174 Object key = keys.next();
175 List tmpFields = (List)mapToObjectFields.get(key);
176 mapToObjectFields.put(key,
177 tmpFields.toArray(new Field[tmpFields.size()]));
178 }
179 }
180
181 /***
182 * Initializes the default Group with parameters from RunData.
183 *
184 * @param data a <code>RunData</code> value
185 * @return this Group
186 */
187 public Group init(RunData data) throws TurbineException
188 {
189 return init(NEW, data);
190 }
191
192 /***
193 * Initializes the Group with parameters from RunData
194 * corresponding to key.
195 *
196 * @param data a <code>RunData</code> value
197 * @return this Group
198 */
199 public Group init(String key, RunData data)
200 throws TurbineException
201 {
202 this.oid = key;
203 this.data = data;
204 for (int i=fieldsArray.length-1; i>=0; i--)
205 {
206 fieldsArray[i].init(data);
207 }
208 return this;
209 }
210
211
212 /***
213 * Initializes the group with properties from an object.
214 *
215 * @param obj a <code>Persistent</code> value
216 * @return a <code>Group</code> value
217 */
218 public Group init(Retrievable obj)
219 {
220 this.oid = obj.getQueryKey();
221
222 Class cls = obj.getClass();
223 while ( cls != null )
224 {
225 Field[] flds = (Field[])mapToObjectFields.get(cls.getName());
226 if ( flds != null )
227 {
228 for (int i=flds.length-1; i>=0; i--)
229 {
230 flds[i].init(obj);
231 }
232 }
233
234 cls = cls.getSuperclass();
235 }
236
237 return this;
238 }
239
240
241 /***
242 * Gets a list of the names of the fields stored in this object.
243 *
244 * @return A String array containing the list of names.
245 */
246 public String[] getFieldNames()
247 {
248 String nameList[] = new String[fieldsArray.length];
249 for(int i = 0; i < nameList.length; i++)
250 {
251 nameList[i] = fieldsArray[i].name;
252 }
253 return nameList;
254 }
255
256
257 /***
258 * Return the name given to this group. The long name is to
259 * avoid conflicts with the get(String key) method.
260 *
261 * @return a <code>String</code> value
262 */
263 public String getIntakeGroupName()
264 {
265 return name;
266 }
267
268 /***
269 * Get the number of Group objects that will be pooled.
270 *
271 * @return an <code>int</code> value
272 */
273 public int getPoolCapacity()
274 {
275 return poolCapacity;
276 }
277
278 /***
279 * Get the part of the key used to specify the group.
280 * This is specified in the key attribute in the xml file.
281 *
282 * @return a <code>String</code> value
283 */
284 public String getGID()
285 {
286 return gid;
287 }
288
289 /***
290 * Get the part of the key that distinguishes a group
291 * from others of the same name.
292 *
293 * @return a <code>String</code> value
294 */
295 public String getOID()
296 {
297 return oid;
298 }
299
300 /***
301 * Concatenation of gid and oid.
302 *
303 * @return a <code>String</code> value
304 */
305 public String getObjectKey()
306 {
307 return gid + oid;
308 }
309
310 /***
311 * Describe <code>getObjects</code> method here.
312 *
313 * @param pp a <code>ParameterParser</code> value
314 * @return an <code>ArrayList</code> value
315 * @exception TurbineException if an error occurs
316 */
317 public ArrayList getObjects(RunData data)
318 throws TurbineException
319 {
320 ArrayList objs = null;
321 String[] oids = data.getParameters().getStrings(gid);
322 if (oids != null)
323 {
324 objs = new ArrayList(oids.length);
325 for (int i=oids.length-1; i>=0; i--)
326 {
327 objs.add( TurbineIntake.getGroup(name).init(oids[i], data) );
328 }
329 }
330 return objs;
331 }
332
333 /***
334 * Get the Field .
335 * @return Field.
336 */
337 public Field get(String fieldName)
338 throws TurbineException
339 {
340 if (fields.containsKey(fieldName))
341 {
342 return (Field)fields.get(fieldName);
343 }
344 else
345 {
346 throw new TurbineException ("Intake Field name: " + fieldName +
347 " not found!");
348 }
349 }
350
351 /***
352 * Performs an AND between all the fields in this group.
353 *
354 * @return a <code>boolean</code> value
355 */
356 public boolean isAllValid()
357 {
358 boolean valid = true;
359 for (int i=fieldsArray.length-1; i>=0; i--)
360 {
361 valid &= fieldsArray[i].isValid();
362 }
363 return valid;
364 }
365
366 /***
367 * Calls a setter methods on obj, for fields which have been set.
368 * @exception throws up any exceptions resulting from failure to
369 * check input validity.
370 */
371 public void setProperties(Object obj)
372 throws TurbineException
373 {
374 Class cls = obj.getClass();
375 while ( cls != null )
376 {
377 Field[] flds = (Field[])mapToObjectFields.get(cls.getName());
378 if ( flds != null )
379 {
380 for (int i=flds.length-1; i>=0; i--)
381 {
382 flds[i].setProperty(obj);
383 }
384 }
385
386 cls = cls.getSuperclass();
387 }
388 }
389
390 /***
391 * Calls getter methods on objects that are known to Intake
392 * so that field values in forms can be initialized from
393 * the values contained in the intake tool.
394 */
395 public void getProperties(Object obj)
396 throws Exception
397 {
398 Class cls = obj.getClass();
399 while (cls != null)
400 {
401 Field[] flds = (Field[])mapToObjectFields.get(cls.getName());
402 if( flds != null )
403 {
404 for (int i=flds.length-1; i>=0; i--)
405 {
406 flds[i].getProperty(obj);
407 }
408 }
409
410 cls = cls.getSuperclass();
411 }
412 }
413
414 /***
415 * Removes references to this group and its fields from the
416 * query parameters
417 */
418 public void removeFromRequest()
419 {
420 ParameterParser pp = data.getParameters();
421 String[] groups = pp.getStrings(gid);
422 if ( groups != null )
423 {
424 pp.remove(gid);
425 for (int i=0; i<groups.length; i++)
426 {
427 if ( groups[i] != null && !groups[i].equals(oid) )
428 {
429 pp.add(gid,groups[i]);
430 }
431 }
432 for (int i=fieldsArray.length-1; i>=0; i--)
433 {
434 fieldsArray[i].removeFromRequest();
435 }
436 }
437 }
438
439 /***
440 * To be used in the event this group is used within multiple
441 * forms within the same template.
442 */
443 public void resetDeclared()
444 {
445 isDeclared = false;
446 }
447
448 /***
449 * A xhtml valid hidden input field that notifies intake of the
450 * group's presence.
451 *
452 * @return a <code>String</code> value
453 */
454 public String getHtmlFormInput()
455 {
456 StringBuffer sb = new StringBuffer(64);
457 appendHtmlFormInput(sb);
458 return sb.toString();
459 }
460
461 /***
462 * A xhtml valid hidden input field that notifies intake of the
463 * group's presence.
464 */
465 public void appendHtmlFormInput(StringBuffer sb)
466 {
467 if ( !isDeclared )
468 {
469 isDeclared = true;
470 sb.append("<input type=\"hidden\" name=\"")
471 .append(gid)
472 .append("\" value=\"")
473 .append(oid)
474 .append("\"></input>");
475 }
476 }
477
478 // ****************** Recyclable implementation ************************
479
480 private boolean disposed;
481
482 /***
483 * Recycles the object for a new client. Recycle methods with
484 * parameters must be added to implementing object and they will be
485 * automatically called by pool implementations when the object is
486 * taken from the pool for a new client. The parameters must
487 * correspond to the parameters of the constructors of the object.
488 * For new objects, constructors can call their corresponding recycle
489 * methods whenever applicable.
490 * The recycle methods must call their super.
491 */
492 public void recycle()
493 {
494 disposed = false;
495 }
496
497 /***
498 * Disposes the object after use. The method is called
499 * when the object is returned to its pool.
500 * The dispose method must call its super.
501 */
502 public void dispose()
503 {
504 oid = null;
505 data = null;
506 for (int i=fieldsArray.length-1; i>=0; i--)
507 {
508 fieldsArray[i].dispose();
509 }
510 isDeclared = false;
511
512 disposed = true;
513 }
514
515 /***
516 * Checks whether the recyclable has been disposed.
517 * @return true, if the recyclable is disposed.
518 */
519 public boolean isDisposed()
520 {
521 return disposed;
522 }
523 }
524
525
This page was automatically generated by Maven