KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > tools > struts > ValidatorTool


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.velocity.tools.struts;
18
19 import java.util.ArrayList JavaDoc;
20 import java.util.Comparator JavaDoc;
21 import java.util.Collections JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Locale JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import javax.servlet.ServletContext JavaDoc;
28 import javax.servlet.http.HttpServletRequest JavaDoc;
29 import javax.servlet.http.HttpSession JavaDoc;
30
31 import org.apache.commons.validator.Field;
32 import org.apache.commons.validator.Form;
33 import org.apache.commons.validator.ValidatorAction;
34 import org.apache.commons.validator.ValidatorResources;
35 import org.apache.commons.validator.ValidatorUtil;
36 import org.apache.commons.validator.Var;
37
38 import org.apache.struts.Globals;
39 import org.apache.struts.config.ActionConfig;
40 import org.apache.struts.config.ModuleConfig;
41 import org.apache.struts.util.MessageResources;
42 import org.apache.struts.util.RequestUtils;
43 import org.apache.struts.validator.Resources;
44 import org.apache.struts.validator.ValidatorPlugIn;
45
46 import org.apache.velocity.tools.view.context.ViewContext;
47 import org.apache.velocity.tools.view.tools.ViewTool;
48
49 /**
50  * <p>View tool that works with Struts Validator to
51  * produce client side javascript validation for your forms.</p>
52  * <p>Usage:
53  * <pre>
54  * Template example:
55  *
56  * $validator.getJavascript("nameOfYourForm")
57  *
58  * Toolbox configuration:
59  * &lt;tool&gt;
60  * &lt;key&gt;validator&lt;/key&gt;
61  * &lt;scope&gt;request&lt;/scope&gt;
62  * &lt;class&gt;org.apache.velocity.tools.struts.ValidatorTool&lt;/class&gt;
63  * &lt;/tool&gt;
64  * </pre>
65  * </p>
66  * <p>This is an adaptation of the JavascriptValidatorTag
67  * from the Struts 1.1 validator library.</p>
68  *
69  * @author David Winterfeldt
70  * @author David Graham
71  * @author <a HREF="mailto:marinoj@centrum.is">Marino A. Jonsson</a>
72  * @author <a HREF="mailto:nathan@esha.com">Nathan Bubna</a>
73  * @since VelocityTools 1.1
74  * @version $Revision: 1.9 $ $Date: 2004/02/18 23:34:50 $
75  */

76 public class ValidatorTool implements ViewTool {
77
78     /** A reference to the ViewContext */
79     protected ViewContext context;
80
81     /** A reference to the ServletContext */
82     protected ServletContext JavaDoc app;
83
84     /** A reference to the HttpServletRequest. */
85     protected HttpServletRequest JavaDoc request;
86
87     /** A reference to the HttpSession. */
88     protected HttpSession JavaDoc session;
89
90     /** A reference to the HttpSession. */
91     protected ValidatorResources resources;
92
93
94     private static final String JavaDoc HTML_BEGIN_COMMENT = "\n<!-- Begin \n";
95     private static final String JavaDoc HTML_END_COMMENT = "//End --> \n";
96
97     private boolean xhtml = false;
98
99     private boolean htmlComment = true;
100     private boolean cdata = true;
101     private String JavaDoc formName = null;
102     private String JavaDoc methodName = null;
103     private String JavaDoc src = null;
104     private int page = 0;
105
106
107     /**
108      * Default constructor. Tool must be initialized before use.
109      */

110     public ValidatorTool() {}
111
112
113     /**
114      * Initializes this tool.
115      *
116      * @param obj the current ViewContext
117      * @throws IllegalArgumentException if the param is not a ViewContext
118      */

119     public void init(Object JavaDoc obj)
120     {
121         if (!(obj instanceof ViewContext))
122         {
123             throw new IllegalArgumentException JavaDoc(
124                     "Tool can only be initialized with a ViewContext");
125         }
126
127         this.context = (ViewContext)obj;
128         this.request = context.getRequest();
129         this.session = request.getSession(false);
130         this.app = context.getServletContext();
131
132         Boolean JavaDoc b = (Boolean JavaDoc)context.getAttribute(ViewContext.XHTML);
133         if (b != null)
134         {
135             this.xhtml = b.booleanValue();
136         }
137
138         /* Is there a mapping associated with this request? */
139         ActionConfig config =
140                 (ActionConfig)request.getAttribute(Globals.MAPPING_KEY);
141         if (config != null)
142         {
143             /* Is there a form bean associated with this mapping? */
144             this.formName = config.getAttribute();
145         }
146
147         ModuleConfig mconfig = RequestUtils.getModuleConfig(request, app);
148         this.resources = (ValidatorResources)app.getAttribute(ValidatorPlugIn.
149                 VALIDATOR_KEY +
150                 mconfig.getPrefix());
151
152     }
153
154
155     /****************** get/set accessors ***************/
156
157     /**
158      * Gets the current page number of a multi-part form.
159      * Only field validations with a matching page number
160      * will be generated that match the current page number.
161      * Only valid when the formName attribute is set.
162      *
163      * @return the current page number of a multi-part form
164      */

165     public int getPage()
166     {
167         return page;
168     }
169
170     /**
171      * Sets the current page number of a multi-part form.
172      * Only field validations with a matching page number
173      * will be generated that match the current page number.
174      *
175      * @param page the current page number of a multi-part form
176      */

177     public void setPage(int page)
178     {
179         this.page = page;
180     }
181
182     /**
183      * Gets the method name that will be used for the Javascript
184      * validation method name if it has a value. This overrides
185      * the auto-generated method name based on the key (form name)
186      * passed in.
187      *
188      * @return the method name that will be used for the Javascript validation method
189      */

190     public String JavaDoc getMethod()
191     {
192         return methodName;
193     }
194
195     /**
196      * Sets the method name that will be used for the Javascript
197      * validation method name if it has a value. This overrides
198      * the auto-generated method name based on the key (form name)
199      * passed in.
200      *
201      * @param methodName the method name that will be used for the Javascript validation method name
202      */

203     public void setMethod(String JavaDoc methodName)
204     {
205         this.methodName = methodName;
206     }
207
208     /**
209      * Gets whether or not to delimit the
210      * JavaScript with html comments. If this is set to 'true', which
211      * is the default, html comments will surround the JavaScript.
212      *
213      * @return true if the JavaScript should be delimited with html comments
214      */

215     public boolean getHtmlComment()
216     {
217         return this.htmlComment;
218     }
219
220     /**
221      * Sets whether or not to delimit the
222      * JavaScript with html comments. If this is set to 'true', which
223      * is the default, html comments will surround the JavaScript.
224      *
225      * @param htmlComment whether or not to delimit the JavaScript with html comments
226      */

227     public void setHtmlComment(boolean htmlComment)
228     {
229         this.htmlComment = htmlComment;
230     }
231
232     /**
233      * Gets the src attribute's value when defining
234      * the html script element.
235      *
236      * @return the src attribute's value
237      */

238     public String JavaDoc getSrc()
239     {
240         return src;
241     }
242
243     /**
244      * Sets the src attribute's value (used to include
245      * an external script resource) when defining
246      * the html script element. The src attribute is only recognized
247      * when the formName attribute is specified.
248      *
249      * @param src the src attribute's value
250      */

251     public void setSrc(String JavaDoc src)
252     {
253         this.src = src;
254     }
255
256     /**
257      * Returns the cdata setting "true" or "false".
258      *
259      * @return boolean - "true" if JavaScript will be hidden in a CDATA section
260      */

261     public boolean getCdata()
262     {
263         return cdata;
264     }
265
266     /**
267      * Sets the cdata status.
268      * @param cdata The cdata to set
269      */

270     public void setCdata(boolean cdata)
271     {
272         this.cdata = cdata;
273     }
274
275
276     /****************** methods that aren't just accessors ***************/
277
278     /**
279      * Render both dynamic and static JavaScript to perform
280      * validations based on the form name attribute of the action
281      * mapping associated with the current request (if such exists).
282      *
283      * @return the javascript for the current form
284      * @throws Exception
285      */

286     public String JavaDoc getJavascript() throws Exception JavaDoc
287     {
288         return getJavascript(this.formName);
289     }
290
291     /**
292      * Render both dynamic and static JavaScript to perform
293      * validations based on the supplied form name.
294      *
295      * @param formName the key (form name)
296      * @return the Javascript for the specified form
297      * @throws Exception
298      */

299     public String JavaDoc getJavascript(String JavaDoc formName) throws Exception JavaDoc
300     {
301         this.formName = formName;
302         return getJavascript(formName, true);
303     }
304
305     /**
306      * Render just the dynamic JavaScript to perform validations based
307      * on the form name attribute of the action mapping associated
308      * with the current request (if such exists). Useful i.e. if the static
309      * parts are located in a seperate .js file.
310      *
311      * @return the javascript for the current form
312      * @throws Exception
313      */

314     public String JavaDoc getDynamicJavascript() throws Exception JavaDoc
315     {
316         return getDynamicJavascript(this.formName);
317     }
318
319
320     /**
321      * Render just the static JavaScript methods. Useful i.e. if the static
322      * parts should be located in a seperate .js file.
323      *
324      * @return all static Javascript methods
325      * @throws Exception
326      */

327     public String JavaDoc getStaticJavascript() throws Exception JavaDoc
328     {
329         StringBuffer JavaDoc results = new StringBuffer JavaDoc();
330
331         results.append(getStartElement());
332         if (this.htmlComment)
333         {
334             results.append(HTML_BEGIN_COMMENT);
335         }
336         results.append(getJavascriptStaticMethods(resources));
337         results.append(getJavascriptEnd());
338
339         return results.toString();
340     }
341
342
343     /**
344      * Render just the dynamic JavaScript to perform validations based
345      * on the supplied form name. Useful i.e. if the static
346      * parts are located in a seperate .js file.
347      *
348      * @param formName the key (form name)
349      * @return the dynamic Javascript for the specified form
350      * @throws Exception
351      */

352     public String JavaDoc getDynamicJavascript(String JavaDoc formName) throws Exception JavaDoc
353     {
354         this.formName = formName;
355         return getJavascript(formName, false);
356     }
357
358     /**
359      * Render both dynamic and static JavaScript to perform
360      * validations based on the supplied form name.
361      *
362      * @param formName the key (form name)
363      * @param getStatic indicates if the static methods should be rendered
364      * @return the Javascript for the specified form
365      * @throws Exception
366      */

367     protected String JavaDoc getJavascript(String JavaDoc formName, boolean getStatic) throws Exception JavaDoc
368     {
369         StringBuffer JavaDoc results = new StringBuffer JavaDoc();
370
371         Locale JavaDoc locale = StrutsUtils.getLocale(request, session);
372
373         Form form = resources.get(locale, formName);
374         if (form != null)
375         {
376             results.append(getDynamicJavascript(resources, locale, form));
377         }
378
379         if(getStatic)
380         {
381             results.append(getJavascriptStaticMethods(resources));
382         }
383
384         if (form != null)
385         {
386             results.append(getJavascriptEnd());
387         }
388
389         return results.toString();
390     }
391
392
393
394     /**
395      * Generates the dynamic JavaScript for the form.
396      *
397      * @param resources the validator resources
398      * @param locale the locale for the current request
399      * @param form the form to generate javascript for
400      * @return the dynamic javascript
401      */

402     protected String JavaDoc getDynamicJavascript(ValidatorResources resources,
403                                           Locale JavaDoc locale,
404                                           Form form)
405     {
406         StringBuffer JavaDoc results = new StringBuffer JavaDoc();
407
408         MessageResources messages =
409             StrutsUtils.getMessageResources(request, app);
410
411         List JavaDoc actions = createActionList(resources, form);
412
413         String JavaDoc methods = createMethods(actions);
414         results.append(getJavascriptBegin(methods));
415
416         for (Iterator JavaDoc i = actions.iterator(); i.hasNext();)
417         {
418             ValidatorAction va = (ValidatorAction)i.next();
419             String JavaDoc jscriptVar = null;
420             String JavaDoc functionName = null;
421
422             if (va.getJsFunctionName() != null && va.getJsFunctionName().length() > 0)
423             {
424                 functionName = va.getJsFunctionName();
425             }
426             else
427             {
428                 functionName = va.getName();
429             }
430
431             results.append(" function ");
432             results.append(functionName);
433             results.append(" () { \n");
434
435             for (Iterator JavaDoc x = form.getFields().iterator(); x.hasNext();)
436             {
437                 Field field = (Field)x.next();
438
439                 // Skip indexed fields for now until there is
440
// a good way to handle error messages (and the length
441
// of the list (could retrieve from scope?))
442
if (field.isIndexed()
443                     || field.getPage() != page
444                     || !field.isDependency(va.getName()))
445                 {
446                     continue;
447                 }
448
449                 String JavaDoc message =
450                     Resources.getMessage(messages, locale, va, field);
451
452                 if (message == null)
453                 {
454                     message = "";
455                 }
456
457                 jscriptVar = this.getNextVar(jscriptVar);
458
459                 results.append(" this.");
460                 results.append(jscriptVar);
461                 results.append(" = new Array(\"");
462                 results.append(field.getKey());
463                 results.append("\", \"");
464                 results.append(message);
465                 results.append("\", ");
466                 results.append("new Function (\"varName\", \"");
467
468                 Map JavaDoc vars = field.getVars();
469                 // Loop through the field's variables.
470
Iterator JavaDoc varsIterator = vars.keySet().iterator();
471                 while (varsIterator.hasNext())
472                 {
473                     String JavaDoc varName = (String JavaDoc)varsIterator.next();
474                     Var var = (Var)vars.get(varName);
475                     String JavaDoc varValue = var.getValue();
476                     String JavaDoc jsType = var.getJsType();
477
478                     // skip requiredif variables field, fieldIndexed, fieldTest, fieldValue
479
if (varName.startsWith("field"))
480                     {
481                         continue;
482                     }
483
484                     // these are appended no matter what jsType is
485
results.append("this.");
486                     results.append(varName);
487
488                     String JavaDoc escapedVarValue =
489                         ValidatorUtil.replace(varValue, "\\", "\\\\");
490
491                     if (Var.JSTYPE_INT.equalsIgnoreCase(jsType))
492                     {
493                         results.append("=");
494                         results.append(escapedVarValue);
495                         results.append("; ");
496                     }
497                     else if (Var.JSTYPE_REGEXP.equalsIgnoreCase(jsType))
498                     {
499                         results.append("=/");
500                         results.append(escapedVarValue);
501                         results.append("/; ");
502                     }
503                     else if (Var.JSTYPE_STRING.equalsIgnoreCase(jsType))
504                     {
505                         results.append("='");
506                         results.append(escapedVarValue);
507                         results.append("'; ");
508                     }
509                     // So everyone using the latest format
510
// doesn't need to change their xml files immediately.
511
else if ("mask".equalsIgnoreCase(varName))
512                     {
513                         results.append("=/");
514                         results.append(escapedVarValue);
515                         results.append("/; ");
516                     }
517                     else
518                     {
519                         results.append("='");
520                         results.append(escapedVarValue);
521                         results.append("'; ");
522                     }
523                 }
524                 results.append(" return this[varName];\"));\n");
525             }
526             results.append(" } \n\n");
527         }
528         return results.toString();
529     }
530
531
532     /**
533      * Creates the JavaScript methods list from the given actions.
534      * @param actions A List of ValidatorAction objects.
535      * @return JavaScript methods.
536      */

537     protected String JavaDoc createMethods(List JavaDoc actions)
538     {
539         String JavaDoc methodOperator = " && ";
540
541         StringBuffer JavaDoc methods = null;
542         for (Iterator JavaDoc i = actions.iterator(); i.hasNext();)
543         {
544             ValidatorAction va = (ValidatorAction)i.next();
545             if (methods == null)
546             {
547                 methods = new StringBuffer JavaDoc(va.getMethod());
548             }
549             else
550             {
551                 methods.append(methodOperator);
552                 methods.append(va.getMethod());
553             }
554             methods.append("(form)");
555         }
556         return methods.toString();
557     }
558
559
560     /**
561      * Get List of actions for the given Form.
562      *
563      * @param resources the validator resources
564      * @param form the form for which the actions are requested
565      * @return A sorted List of ValidatorAction objects.
566      */

567     protected List JavaDoc createActionList(ValidatorResources resources, Form form)
568     {
569         List JavaDoc actionMethods = new ArrayList JavaDoc();
570         // Get List of actions for this Form
571
for (Iterator JavaDoc i = form.getFields().iterator(); i.hasNext();)
572         {
573             Field field = (Field)i.next();
574             for (Iterator JavaDoc x = field.getDependencies().iterator(); x.hasNext();)
575             {
576                 Object JavaDoc o = x.next();
577                 if (o != null && !actionMethods.contains(o))
578                 {
579                     actionMethods.add(o);
580                 }
581             }
582         }
583
584         List JavaDoc actions = new ArrayList JavaDoc();
585
586         // Create list of ValidatorActions based on actionMethods
587
for (Iterator JavaDoc i = actionMethods.iterator(); i.hasNext();)
588         {
589             String JavaDoc depends = (String JavaDoc) i.next();
590             ValidatorAction va = resources.getValidatorAction(depends);
591
592             // throw nicer NPE for easier debugging
593
if (va == null)
594             {
595                 throw new NullPointerException JavaDoc(
596                     "Depends string \"" + depends +
597                     "\" was not found in validator-rules.xml.");
598             }
599
600             String JavaDoc javascript = va.getJavascript();
601             if (javascript != null && javascript.length() > 0)
602             {
603                 actions.add(va);
604             }
605             else
606             {
607                 i.remove();
608             }
609         }
610
611         //TODO? make an instance of this class a static member
612
Comparator JavaDoc comp = new ValidatorActionComparator();
613         Collections.sort(actions, comp);
614         return actions;
615     }
616
617
618     /**
619      * Returns the opening script element and some initial javascript.
620      *
621      * @param methods javascript validation methods
622      * @return the opening script element and some initial javascript
623      */

624     protected String JavaDoc getJavascriptBegin(String JavaDoc methods)
625     {
626         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
627         String JavaDoc name = formName.replace('/', '_'); // remove any '/' characters
628
name = name.substring(0, 1).toUpperCase() +
629                       name.substring(1, name.length());
630
631         sb.append(getStartElement());
632
633         if (this.xhtml && this.cdata)
634         {
635             sb.append("<![CDATA[\r\n");
636         }
637
638         if (!this.xhtml && this.htmlComment)
639         {
640             sb.append(HTML_BEGIN_COMMENT);
641         }
642         sb.append("\n var bCancel = false; \n\n");
643
644         if (methodName == null || methodName.length() == 0)
645         {
646             sb.append(" function validate");
647             sb.append(name);
648         }
649         else
650         {
651             sb.append(" function ");
652             sb.append(methodName);
653         }
654         sb.append("(form) {");
655         //FIXME? anyone know why all these spaces need to be here?
656
sb.append(" \n");
657         sb.append(" if (bCancel) \n");
658         sb.append(" return true; \n");
659         sb.append(" else \n");
660
661         // Always return true if there aren't any Javascript validation methods
662
if (methods == null || methods.length() == 0)
663         {
664             sb.append(" return true; \n");
665         }
666         else
667         {
668             sb.append(" return ");
669             sb.append(methods);
670             sb.append("; \n");
671         }
672         sb.append(" } \n\n");
673
674         return sb.toString();
675     }
676
677     /**
678      *
679      * @param resources the validation resources
680      * @return the static javascript methods
681      */

682     protected String JavaDoc getJavascriptStaticMethods(ValidatorResources resources)
683     {
684         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("\n\n");
685
686         Iterator JavaDoc actions = resources.getValidatorActions().values().iterator();
687         while (actions.hasNext())
688         {
689             ValidatorAction va = (ValidatorAction) actions.next();
690             if (va != null)
691             {
692                 String JavaDoc javascript = va.getJavascript();
693                 if (javascript != null && javascript.length() > 0)
694                 {
695                     sb.append(javascript + "\n");
696                 }
697             }
698         }
699         return sb.toString();
700     }
701
702
703     /**
704      * Returns the closing script element.
705      *
706      * @return the closing script element
707      */

708     protected String JavaDoc getJavascriptEnd()
709     {
710         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
711         sb.append("\n");
712
713         if (!this.xhtml && this.htmlComment)
714         {
715             sb.append(HTML_END_COMMENT);
716         }
717
718         if (this.xhtml && this.cdata)
719         {
720             sb.append("]]>\r\n");
721         }
722         sb.append("</script>\n\n");
723
724         return sb.toString();
725     }
726
727
728     /**
729      * The value <code>null</code> will be returned at the end of the sequence.
730      * ex: "zz" will return <code>null</code>
731      *
732      * @param input the string to process
733      * @return the next var
734      */

735     private String JavaDoc getNextVar(String JavaDoc input)
736     {
737         if (input == null)
738         {
739             return "aa";
740         }
741
742         input = input.toLowerCase();
743
744         for (int i = input.length(); i > 0; i--)
745         {
746             int pos = i - 1;
747
748             char c = input.charAt(pos);
749             c++;
750
751             if (c <= 'z')
752             {
753                 if (i == 0)
754                 {
755                     return c + input.substring(pos, input.length());
756                 }
757                 else if (i == input.length())
758                 {
759                     return input.substring(0, pos) + c;
760                 }
761                 else
762                 {
763                     return input.substring(0, pos) + c +
764                            input.substring(pos, input.length() - 1);
765                 }
766             }
767             else
768             {
769                 input = replaceChar(input, pos, 'a');
770             }
771         }
772         return null;
773      }
774
775
776     /**
777      * Replaces a single character in a <code>String</code>
778      *
779      * @param input the string to process
780      * @param pos the position of the caracter to replace
781      * @param c the substitute char
782      * @return the input string with the specified char replaced
783      */

784     private String JavaDoc replaceChar(String JavaDoc input, int pos, char c)
785     {
786         if (pos == 0)
787         {
788             return c + input.substring(pos, input.length());
789         }
790         else if (pos == input.length())
791         {
792             return input.substring(0, pos) + c;
793         }
794         else
795         {
796             return input.substring(0, pos) + c +
797                    input.substring(pos, input.length() - 1);
798         }
799     }
800
801
802     /**
803      * Constructs the beginning <script> element depending on xhtml status.
804      *
805      * @return the beginning <script> element depending on xhtml status
806      */

807     private String JavaDoc getStartElement()
808     {
809         StringBuffer JavaDoc start = new StringBuffer JavaDoc("<script type=\"text/javascript\"");
810
811         // there is no language attribute in xhtml
812
if (!this.xhtml)
813         {
814             start.append(" language=\"Javascript1.1\"");
815         }
816
817         if (this.src != null)
818         {
819             start.append(" SRC=\"" + src + "\"");
820         }
821
822         start.append("> \n");
823         return start.toString();
824     }
825
826
827     /**
828      * Inner class for use when creating dynamic javascript
829      */

830     protected class ValidatorActionComparator implements Comparator JavaDoc
831     {
832         /**
833          *
834          * @param o1 the first object to compare with regard to depends
835          * @param o2 the second object to compare with regard to depends
836          * @return -1, 0 or 1
837          */

838         public int compare(Object JavaDoc o1, Object JavaDoc o2)
839         {
840             ValidatorAction va1 = (ValidatorAction)o1;
841             ValidatorAction va2 = (ValidatorAction)o2;
842
843             String JavaDoc vad1 = va1.getDepends();
844             String JavaDoc vad2 = va2.getDepends();
845
846             if ((vad1 == null || vad1.length() == 0)
847                 && (vad2 == null || vad2.length() == 0))
848             {
849                 return 0;
850             }
851             else if ((vad1 != null && vad1.length() > 0)
852                      && (vad2 == null || vad2.length() == 0))
853             {
854                 return 1;
855             }
856             else if ((vad1 == null || vad1.length() == 0)
857                      && (vad2 != null && vad2.length() > 0))
858             {
859                 return -1;
860             }
861             else
862             {
863                 return va1.getDependencies().size() - va2.getDependencies().size();
864             }
865         }
866     }
867
868 }
869
Popular Tags