KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > taglib > nested > NestedPropertyHelper


1 /*
2  * $Id: NestedPropertyHelper.java 54929 2004-10-16 16:38:42Z germuska $
3  *
4  * Copyright 1999-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * 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, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18 package org.apache.struts.taglib.nested;
19
20 import java.util.*;
21 import javax.servlet.http.HttpServletRequest JavaDoc;
22 import javax.servlet.jsp.tagext.Tag JavaDoc;
23
24 import org.apache.struts.taglib.html.Constants;
25 import org.apache.struts.taglib.html.FormTag;
26
27 /**
28  * <p>A simple helper class that does everything that needs to be done to get
29  * the nested tag extension to work. The tags will pass in their relative
30  * properties and this class will leverage the accessibility of the request
31  * object to calculate the nested references and manage them from a central
32  * place.</p>
33  *
34  * <p>The helper method {@link #setNestedProperties} takes a reference to the
35  * tag itself so all the simpler tags can have their references managed from a
36  * central location. From here, the reference to a provided name is also
37  * preserved for use.</p>
38  *
39  * <p>With all tags keeping track of themselves, we only have to seek to the
40  * next level, or parent tag, were a tag will append a dot and it's own
41  * property.</p>
42  *
43  * @since Struts 1.1
44  * @version $Rev: 54929 $ $Date: 2004-10-16 17:38:42 +0100 (Sat, 16 Oct 2004) $
45  */

46 public class NestedPropertyHelper {
47
48   /* key that the tags can rely on to set the details against */
49   public static final String JavaDoc NESTED_INCLUDES_KEY = "<nested-includes-key/>";
50
51
52   /**
53    * Returns the current nesting property from the request object.
54    * @param request object to fetch the property reference from
55    * @return String of the bean name to nest against
56    */

57   public static final String JavaDoc getCurrentProperty(HttpServletRequest JavaDoc request) {
58     // get the old one if any
59
NestedReference nr = (NestedReference) request.getAttribute(NESTED_INCLUDES_KEY);
60     // return null or the property
61
return (nr == null) ? null : nr.getNestedProperty();
62   }
63
64
65   /**
66    * <p>Returns the bean name from the request object that the properties are
67    * nesting against.</p>
68    *
69    * <p>The requirement of the tag itself could be removed in the future, but is
70    * required if support for the <html:form> tag is maintained.</p>
71    * @param request object to fetch the bean reference from
72    * @param nested tag from which to start the search from
73    * @return the string of the bean name to be nesting against
74    */

75   public static final String JavaDoc getCurrentName(HttpServletRequest JavaDoc request,
76                                             NestedNameSupport nested) {
77     // get the old one if any
78
NestedReference nr = (NestedReference) request.getAttribute(NESTED_INCLUDES_KEY);
79     // return null or the property
80
if (nr != null) {
81       return nr.getBeanName();
82
83     } else {
84       // need to look for a form tag...
85
Tag JavaDoc tag = (Tag JavaDoc) nested;
86       Tag JavaDoc formTag = null;
87
88       // loop all parent tags until we get one that can be nested against
89
do {
90         tag = tag.getParent();
91         if (tag != null && tag instanceof FormTag) {
92           formTag = tag;
93         }
94       } while (formTag == null && tag != null);
95
96       if (formTag == null) {
97         return "";
98       }
99       // return the form's name
100
return ((FormTag) formTag).getBeanName();
101     }
102   }
103
104   /**
105    * Get the adjusted property.
106    * Apply the provided property, to the property already stored
107    * in the request object.
108    * @param request to pull the reference from
109    * @param property to retrieve the evaluated nested property with
110    * @return String of the final nested property reference.
111    */

112   public static final String JavaDoc getAdjustedProperty(HttpServletRequest JavaDoc request,
113                                                  String JavaDoc property) {
114     // get the old one if any
115
String JavaDoc parent = getCurrentProperty(request);
116     return calculateRelativeProperty(property, parent);
117   }
118
119   /**
120    * Sets the provided property into the request object for reference by the
121    * other nested tags.
122    * @param request object to set the new property into
123    * @param property String to set the property to
124    */

125   public static final void setProperty(HttpServletRequest JavaDoc request,
126                                        String JavaDoc property) {
127     // get the old one if any
128
NestedReference nr = referenceInstance(request);
129     nr.setNestedProperty(property);
130   }
131
132   /**
133    * Sets the provided name into the request object for reference by the
134    * other nested tags.
135    * @param request object to set the new name into
136    * @param name String to set the name to
137    */

138   public static final void setName(HttpServletRequest JavaDoc request, String JavaDoc name) {
139     // get the old one if any
140
NestedReference nr = referenceInstance(request);
141     nr.setBeanName(name);
142   }
143
144   /**
145    * Deletes the nested reference from the request object.
146    * @param request object to remove the reference from
147    */

148   public static final void deleteReference(HttpServletRequest JavaDoc request) {
149     // delete the reference
150
request.removeAttribute(NESTED_INCLUDES_KEY);
151   }
152
153   /**
154    * Helper method that will set all the relevant nesting properties for the
155    * provided tag reference depending on the implementation.
156    * @param request object to pull references from
157    * @param tag to set the nesting values into
158    */

159   public static void setNestedProperties(HttpServletRequest JavaDoc request,
160                                          NestedPropertySupport tag) {
161     boolean adjustProperty = true;
162     /* if the tag implements NestedNameSupport, set the name for the tag also */
163     if (tag instanceof NestedNameSupport) {
164       NestedNameSupport nameTag = (NestedNameSupport)tag;
165       if (nameTag.getName() == null|| Constants.BEAN_KEY.equals(nameTag.getName())) {
166         nameTag.setName(getCurrentName(request, (NestedNameSupport) tag));
167       } else {
168         adjustProperty = false;
169       }
170     }
171
172     /* get and set the relative property, adjust if required */
173     String JavaDoc property = tag.getProperty();
174     if (adjustProperty) {
175       property = getAdjustedProperty(request, property);
176     }
177     tag.setProperty(property);
178   }
179
180
181   /**
182    * Pulls the current nesting reference from the request object, and if there
183    * isn't one there, then it will create one and set it.
184    * @param request object to manipulate the reference into
185    * @return current nesting reference as stored in the request object
186    */

187   private static final NestedReference referenceInstance(HttpServletRequest JavaDoc request) {
188     /* get the old one if any */
189     NestedReference nr = (NestedReference) request.getAttribute(NESTED_INCLUDES_KEY);
190     // make a new one if required
191
if (nr == null) {
192       nr = new NestedReference();
193       request.setAttribute(NESTED_INCLUDES_KEY, nr);
194     }
195     // return the reference
196
return nr;
197   }
198
199   /* This property, providing the property to be appended, and the parent tag
200    * to append the property to, will calculate the stepping of the property
201    * and return the qualified nested property
202    *
203    * @param property the property which is to be appended nesting style
204    * @param parent the "dot notated" string representing the structure
205    * @return qualified nested property that the property param is to the parent
206    */

207   private static String JavaDoc calculateRelativeProperty(String JavaDoc property,
208                                                   String JavaDoc parent) {
209     if (parent == null) { parent = ""; }
210     if (property == null) { property = ""; }
211
212     /* Special case... reference my parent's nested property.
213        Otherwise impossible for things like indexed properties */

214     if ("./".equals(property) || "this/".equals(property)) {
215       return parent;
216     }
217
218     /* remove the stepping from the property */
219     String JavaDoc stepping;
220
221     /* isolate a parent reference */
222     if (property.endsWith("/")) {
223       stepping = property;
224       property = "";
225     } else {
226       stepping = property.substring(0, property.lastIndexOf('/') + 1);
227       /* isolate the property */
228       property = property.substring(property.lastIndexOf('/') + 1, property.length());
229     }
230
231     if (stepping.startsWith("/")) {
232       /* return from root */
233       return property;
234     } else {
235       /* tokenize the nested property */
236       StringTokenizer proT = new StringTokenizer(parent, ".");
237       int propCount = proT.countTokens();
238
239       /* tokenize the stepping */
240       StringTokenizer strT = new StringTokenizer(stepping, "/");
241       int count = strT.countTokens();
242
243       if (count >= propCount) {
244         /* return from root */
245         return property;
246
247       } else {
248         /* append the tokens up to the token difference */
249         count = propCount - count;
250         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
251         for (int i = 0; i < count; i++) {
252           result.append(proT.nextToken());
253           result.append('.');
254         }
255         result.append(property);
256
257         /* parent reference will have a dot on the end. Leave it off */
258         if (result.charAt(result.length()-1) == '.') {
259           return result.substring(0,result.length()-1);
260         } else {
261           return result.toString();
262         }
263       }
264     }
265   }
266 }
267
Popular Tags