##### Coverage Report - org.webmacro.directive.DirectiveDescriptor

Classes in this File | Line Coverage | Branch Coverage | Complexity
DirectiveDescriptor |
92% | 39/42
82% | 34/41
| 6.5;6.5

1 |  |
     /*
2 |  |
      * Copyright (C) 1998-2000 Semiotek Inc.  All Rights Reserved.
3 |  |
      *
4 |  |
      * Redistribution and use in source and binary forms, with or without
5 |  |
      * modification, are permitted under the terms of either of the following
6 |  |
      * Open Source licenses:
7 |  |
      *
8 |  |
      * The GNU General Public License, version 2, or any later version, as
9 |  |
      * published by the Free Software Foundation
10 |  |
      * (http://www.fsf.org/copyleft/gpl.html);
11 |  |
      *
12 |  |
      *  or
13 |  |
      *
14 |  |
      * The Semiotek Public License (http://webmacro.org/LICENSE.)
15 |  |
      *
16 |  |
      * This software is provided "as is", with NO WARRANTY, not even the
17 |  |
      * implied warranties of fitness to purpose, or merchantability. You
18 |  |
      * assume all risks and liabilities associated with its use.
19 |  |
      *
20 |  |
      * See www.webmacro.org for more information on the WebMacro project.
21 |  |
      */
22 |  |
23 |  |
     package org.webmacro.directive;
24 |  |
25 |  |
     import org.webmacro.directive.Directive.ArgDescriptor;
26 |  |
     import org.webmacro.directive.Directive.Subdirective;
27 |  |
28 |  |
     /**
29 |  |
      * Each directive needs a DirectiveDescriptor to describe how it
30 |  |
      * should be parsed and built by the parser.  The directive descriptor
31 |  |
      * identifies the directive's name, the class of the underlying concrete
32 |  |
      * directive object, a list of directive argument descriptors, and a list
33 |  |
      * of subdirective descriptors.
34 |  |
      *
35 |  |
      * If the directive does not specify the class, the directive provider will
36 |  |
      * fill it in automatically.
37 |  |
      *
38 |  |
      * The args field is an array of Directive.ArgDescriptor objects.  There
39 |  |
      * are static nested classes within Directive for each type of argument
40 |  |
      * -- Condition, LValue, RValue, Keyword, Punctuation, Block, LiteralBlock,
41 |  |
      * and special argument descriptors for OptionalGroup and OptionalChoice.
42 |  |
      * These allow the directive writer to specify
43 |  |
      * a flexible syntax for directive arguments.
44 |  |
      * Each directive can have a set of subdirectives, and each subdirective
45 |  |
      * can have its own argument list.  Subdirectives can be required, optional,
46 |  |
      * or optional-repeating (multiple subdirectives of the same kind, like
47 |  |
      * #elseif.)  There are constructors for Subdirective in the Directive module
48 |  |
      * as well.
49 |  |
      *
50 |  |
      * @author Brian Goetz
51 |  |
      */
52 |  |
     public final class DirectiveDescriptor
53 |  |
     {
54 |  |
55 |  |
         public String name;
56 |  |
         public Class dirClass;
57 |  |
         public ArgDescriptor[] args;
58 |  |
         public Subdirective[] subdirectives;
59 |  |
60 | 156 |
         public boolean valid = false,
61 |  |
         hasBreakingSubdirectives = false;
62 |  |
63 |  |
         public DirectiveDescriptor (String name,
64 |  |
                                     Class dirClass,
65 |  |
                                     ArgDescriptor[] args,
66 |  |
                                     Subdirective[] subdirectives)
67 | 156 |
         {
68 | 156 |
             this.name = name;
69 | 156 |
             this.dirClass = dirClass;
70 | 156 |
             this.args = args;
71 | 156 |
             this.subdirectives = subdirectives;
72 |  |
73 | 156 |
             completeArgs(this.args);
74 | 156 |
             valid = validateArgs(this.args);
75 |  |
76 | 156 |
             if (subdirectives != null)
77 |  |
             {
78 | 24 |
                 for (int i = 0; i < this.subdirectives.length; i++)
79 |  |
                 {
80 | 16 |
                     completeArgs(this.subdirectives[i].args);
81 | 16 |
                     valid &= validateArgs(this.subdirectives[i].args);
82 | 16 |
                     if (this.subdirectives[i].isBreaking)
83 | 16 |
                         hasBreakingSubdirectives = true;
84 |  |
                 }
85 |  |
             }
86 | 156 |
         }
87 |  |
88 |  |
         /**
89 |  |
          * Determines the index of the next argument following a given argument.
90 |  |
          * May return an index > args.length.
91 |  |
          */
92 |  |
         private static int nextArg (ArgDescriptor[] args, int i)
93 |  |
         {
94 | 1524 |
             if (args[i].type == Directive.ArgType_GROUP
95 |  |
                     || args[i].type == Directive.ArgType_CHOICE)
96 |  |
             {
97 | 370 |
                 int k = i + 1;
98 | 1006 |
                 for (int j = 0; j < args[i].subordinateArgs; j++)
99 | 636 |
                     k = nextArg(args, k);
100 | 370 |
                 return k;
101 |  |
             }
102 |  |
             else
103 | 1154 |
                 return i + 1;
104 |  |
         }
105 |  |
106 |  |
         /**
107 |  |
          * Set the nextArg, children[] fields as necessary.
108 |  |
          */
109 |  |
         private static void completeArgs (ArgDescriptor[] args)
110 |  |
         {
111 |  |
             int j, k;
112 |  |
113 | 1060 |
             for (int i = 0; i < args.length; i++)
114 | 888 |
                 args[i].nextArg = nextArg(args, i);
115 |  |
116 | 1060 |
             for (int i = 0; i < args.length; i++)
117 |  |
             {
118 | 888 |
                 switch (args[i].type)
119 |  |
                 {
120 |  |
                     case Directive.ArgType_GROUP:
121 |  |
                     case Directive.ArgType_CHOICE:
122 | 208 |
                         args[i].children = new int[args[i].subordinateArgs];
123 | 610 |
                         for (j = 0, k = i + 1; j < args[i].subordinateArgs; j++)
124 |  |
                         {
125 | 402 |
                             args[i].children[j] = k;
126 | 402 |
                             k = args[k].nextArg;
127 |  |
                         }
128 |  |
                         break;
129 |  |
130 |  |
                     default:
131 |  |
                         break;
132 |  |
                 }
133 |  |
             }
134 | 172 |
         }
135 |  |
136 |  |
         /**
137 |  |
          * Make sure that the structure of the arguments list is valid.
138 |  |
          * This means that
139 |  |
          *   GROUP arguments begin with a keyword, not optional
140 |  |
          *   Each of the children of a CHOICE argument is an OPTIONAL GROUP
141 |  |
          */
142 |  |
         private static boolean validateArgs (ArgDescriptor[] args)
143 |  |
         {
144 | 172 |
             boolean valid = true;
145 | 1060 |
             for (int i = 0; i < args.length; i++)
146 |  |
             {
147 | 888 |
                 if (args[i].type == Directive.ArgType_GROUP)
148 |  |
                 {
149 | 192 |
                     if (args[i].subordinateArgs == 0)
150 | 0 |
                         valid = false;
151 | 192 |
                     else if ((args[args[i].children[0]].type != Directive.ArgType_KEYWORD
152 |  |
                             && args[args[i].children[0]].type != Directive.ArgType_ASSIGN)
153 |  |
                             || args[args[i].children[0]].optional)
154 | 0 |
                         valid = false;
155 |  |
                 }
156 | 696 |
                 else if (args[i].type == Directive.ArgType_CHOICE)
157 |  |
                 {
158 | 72 |
                     for (int j = 0; j < args[i].subordinateArgs; j++)
159 |  |
                     {
160 | 56 |
                         if (args[args[i].children[j]].type != Directive.ArgType_GROUP
161 |  |
                                 || !args[args[i].children[j]].optional)
162 | 0 |
                             valid = false;
163 |  |
                     }
164 |  |
                 }
165 |  |
             }
166 |  |
167 | 172 |
             return valid;
168 |  |
         }
169 |  |
     }