KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > facelets > compiler > CompilationManager


1 /**
2  * Licensed under the Common Development and Distribution License,
3  * you may not use this file except in compliance with the License.
4  * You may obtain a copy of the License at
5  *
6  * http://www.sun.com/cddl/
7  *
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11  * implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */

14
15 package com.sun.facelets.compiler;
16
17 import java.util.ArrayList JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Stack JavaDoc;
20 import java.util.logging.Level JavaDoc;
21 import java.util.logging.Logger JavaDoc;
22
23 import com.sun.facelets.FaceletHandler;
24 import com.sun.facelets.tag.Tag;
25 import com.sun.facelets.tag.TagAttribute;
26 import com.sun.facelets.tag.TagAttributeException;
27 import com.sun.facelets.tag.TagAttributes;
28 import com.sun.facelets.tag.TagDecorator;
29 import com.sun.facelets.tag.TagException;
30 import com.sun.facelets.tag.TagLibrary;
31 import com.sun.facelets.tag.ui.ComponentRefHandler;
32 import com.sun.facelets.tag.ui.CompositionHandler;
33 import com.sun.facelets.tag.ui.UILibrary;
34
35 /**
36  * Compilation unit for managing the creation of a single FaceletHandler based
37  * on events from an XML parser.
38  *
39  * @see com.sun.facelets.compiler.Compiler
40  *
41  * @author Jacob Hookom
42  * @version $Id: CompilationManager.java,v 1.12.2.3 2006/03/28 07:31:11 jhook Exp $
43  */

44 final class CompilationManager {
45
46     private final static Logger JavaDoc log = Logger.getLogger("facelets.compiler");
47
48     private final Compiler JavaDoc compiler;
49
50     private final TagLibrary tagLibrary;
51
52     private final TagDecorator tagDecorator;
53
54     private final NamespaceManager namespaceManager;
55
56     private final Stack JavaDoc units;
57
58     private int tagId;
59
60     private boolean finished;
61     
62     private final String JavaDoc alias;
63
64     public CompilationManager(String JavaDoc alias, Compiler JavaDoc compiler) {
65         
66         // this is our alias
67
this.alias = alias;
68
69         // grab compiler state
70
this.compiler = compiler;
71         this.tagDecorator = compiler.createTagDecorator();
72         this.tagLibrary = compiler.createTagLibrary();
73
74         // namespace management
75
this.namespaceManager = new NamespaceManager();
76
77         // tag uids
78
this.tagId = 0;
79
80         // for composition use
81
this.finished = false;
82
83         // our compilationunit stack
84
this.units = new Stack JavaDoc();
85         this.units.push(new CompilationUnit());
86     }
87     
88     public void writeInstruction(String JavaDoc value) {
89         if (this.finished) {
90             return;
91         }
92
93         // don't carelessly add empty tags
94
if (value.length() == 0) {
95             return;
96         }
97
98         TextUnit unit;
99         if (this.currentUnit() instanceof TextUnit) {
100             unit = (TextUnit) this.currentUnit();
101         } else {
102             unit = new TextUnit(this.alias);
103             this.startUnit(unit);
104         }
105         unit.writeInstruction(value);
106     }
107
108     public void writeText(String JavaDoc value) {
109
110         if (this.finished) {
111             return;
112         }
113
114         // don't carelessly add empty tags
115
if (value.length() == 0) {
116             return;
117         }
118
119         TextUnit unit;
120         if (this.currentUnit() instanceof TextUnit) {
121             unit = (TextUnit) this.currentUnit();
122         } else {
123             unit = new TextUnit(this.alias);
124             this.startUnit(unit);
125         }
126         unit.write(value);
127     }
128
129     public void writeComment(String JavaDoc text) {
130         if (this.compiler.isTrimmingComments())
131             return;
132
133         if (this.finished) {
134             return;
135         }
136           
137         // don't carelessly add empty tags
138
if (text.length() == 0) {
139             return;
140         }
141           
142         TextUnit unit;
143         if (this.currentUnit() instanceof TextUnit) {
144             unit = (TextUnit) this.currentUnit();
145         } else {
146             unit = new TextUnit(this.alias);
147             this.startUnit(unit);
148         }
149           
150         unit.writeComment(text);
151     }
152
153     public void writeWhitespace(String JavaDoc text) {
154         if (!this.compiler.isTrimmingWhitespace()) {
155             this.writeText(text);
156         }
157     }
158
159     private String JavaDoc nextTagId() {
160         return Integer.toHexString(Math.abs(this.alias.hashCode() ^ 13 * this.tagId++));
161     }
162
163     public void pushTag(Tag orig) {
164
165         if (this.finished) {
166             return;
167         }
168
169         if (log.isLoggable(Level.FINE)) {
170             log.fine("Tag Pushed: " + orig);
171         }
172
173         Tag t = this.tagDecorator.decorate(orig);
174         String JavaDoc[] qname = this.determineQName(t);
175         t = this.trimAttributes(t);
176
177         boolean handled = false;
178
179         if (isTrimmed(qname[0], qname[1])) {
180             log.fine("Composition Found, Popping Parent Tags");
181             this.units.clear();
182             NamespaceUnit nsUnit = this.namespaceManager
183                     .toNamespaceUnit(this.tagLibrary);
184             this.units.push(nsUnit);
185             this.startUnit(new TrimmedTagUnit(this.tagLibrary, qname[0], qname[1], t, this
186                     .nextTagId()));
187             log.fine("New Namespace and [Trimmed] TagUnit pushed");
188         } else if (isRemove(qname[0], qname[1])) {
189             this.units.push(new RemoveUnit());
190         } else if (this.tagLibrary.containsTagHandler(qname[0], qname[1])) {
191             this.startUnit(new TagUnit(this.tagLibrary, qname[0], qname[1], t, this.nextTagId()));
192         } else if (this.tagLibrary.containsNamespace(qname[0])) {
193             throw new TagException(orig, "Tag Library supports namespace: "+qname[0]+", but no tag was defined for name: "+qname[1]);
194         } else {
195             TextUnit unit;
196             if (this.currentUnit() instanceof TextUnit) {
197                 unit = (TextUnit) this.currentUnit();
198             } else {
199                 unit = new TextUnit(this.alias);
200                 this.startUnit(unit);
201             }
202             unit.startTag(t);
203         }
204     }
205
206     public void popTag() {
207
208         if (this.finished) {
209             return;
210         }
211
212         CompilationUnit unit = this.currentUnit();
213
214         if (unit instanceof TextUnit) {
215             TextUnit t = (TextUnit) unit;
216             if (t.isClosed()) {
217                 this.finishUnit();
218             } else {
219                 t.endTag();
220                 return;
221             }
222         }
223
224         unit = this.currentUnit();
225         if (unit instanceof TagUnit) {
226             TagUnit t = (TagUnit) unit;
227             if (t instanceof TrimmedTagUnit) {
228                 this.finished = true;
229                 return;
230             }
231         }
232
233         this.finishUnit();
234     }
235
236     public void popNamespace(String JavaDoc ns) {
237         this.namespaceManager.popNamespace(ns);
238         if (this.currentUnit() instanceof NamespaceUnit) {
239             this.finishUnit();
240         }
241     }
242
243     public void pushNamespace(String JavaDoc prefix, String JavaDoc uri) {
244
245         if (log.isLoggable(Level.FINE)) {
246             log.fine("Namespace Pushed " + prefix + ": " + uri);
247         }
248
249         this.namespaceManager.pushNamespace(prefix, uri);
250         NamespaceUnit unit;
251         if (this.currentUnit() instanceof NamespaceUnit) {
252             unit = (NamespaceUnit) this.currentUnit();
253         } else {
254             unit = new NamespaceUnit(this.tagLibrary);
255             this.startUnit(unit);
256         }
257         unit.setNamespace(prefix, uri);
258     }
259
260     public FaceletHandler createFaceletHandler() {
261         return ((CompilationUnit) this.units.get(0)).createFaceletHandler();
262     }
263
264     private CompilationUnit currentUnit() {
265         if (!this.units.isEmpty()) {
266             return (CompilationUnit) this.units.peek();
267         }
268         return null;
269     }
270
271     private void finishUnit() {
272         Object JavaDoc obj = this.units.pop();
273
274         if (log.isLoggable(Level.FINE)) {
275             log.fine("Finished Unit: " + obj);
276         }
277     }
278
279     private CompilationUnit searchUnits(Class JavaDoc type) {
280         CompilationUnit unit = null;
281         int i = this.units.size();
282         while (unit == null && --i >= 0) {
283             if (type.isAssignableFrom(this.units.get(i).getClass())) {
284                 unit = (CompilationUnit) this.units.get(i);
285             }
286         }
287         return unit;
288     }
289
290     private void startUnit(CompilationUnit unit) {
291
292         if (log.isLoggable(Level.FINE)) {
293             log.fine("Starting Unit: " + unit + " and adding it to parent: "
294                     + this.currentUnit());
295         }
296
297         this.currentUnit().addChild(unit);
298         this.units.push(unit);
299     }
300
301     private Tag trimAttributes(Tag tag) {
302         Tag t = this.trimJSFCAttribute(tag);
303         t = this.trimNSAttributes(t);
304         return t;
305     }
306
307     protected static boolean isRemove(String JavaDoc ns, String JavaDoc name) {
308         return UILibrary.Namespace.equals(ns)
309                 && "remove".equals(name);
310     }
311
312     protected static boolean isTrimmed(String JavaDoc ns, String JavaDoc name) {
313         return UILibrary.Namespace.equals(ns)
314                 && (CompositionHandler.Name.equals(name) || ComponentRefHandler.Name.equals(name));
315     }
316
317     private String JavaDoc[] determineQName(Tag tag) {
318         TagAttribute attr = tag.getAttributes().get("jsfc");
319         if (attr != null) {
320             if (log.isLoggable(Level.FINE)) {
321                 log.fine(attr + " JSF Facelet Compile Directive Found");
322             }
323             String JavaDoc value = attr.getValue();
324             String JavaDoc namespace, localName;
325             int c = value.indexOf(':');
326             if (c == -1) {
327                 namespace = this.namespaceManager.getNamespace("");
328                 localName = value;
329             } else {
330                 String JavaDoc prefix = value.substring(0, c);
331                 namespace = this.namespaceManager.getNamespace(prefix);
332                 if (namespace == null) {
333                     throw new TagAttributeException(tag, attr,
334                             "No Namespace matched for: " + prefix);
335                 }
336                 localName = value.substring(c + 1);
337             }
338             return new String JavaDoc[] { namespace, localName };
339         } else {
340             return new String JavaDoc[] { tag.getNamespace(), tag.getLocalName() };
341         }
342     }
343
344     private Tag trimJSFCAttribute(Tag tag) {
345         TagAttribute attr = tag.getAttributes().get("jsfc");
346         if (attr != null) {
347             TagAttribute[] oa = tag.getAttributes().getAll();
348             TagAttribute[] na = new TagAttribute[oa.length - 1];
349             int p = 0;
350             for (int i = 0; i < oa.length; i++) {
351                 if (!"jsfc".equals(oa[i].getLocalName())) {
352                     na[p++] = oa[i];
353                 }
354             }
355             return new Tag(tag, new TagAttributes(na));
356         }
357         return tag;
358     }
359
360     private Tag trimNSAttributes(Tag tag) {
361         TagAttribute[] attr = tag.getAttributes().getAll();
362         int remove = 0;
363         for (int i = 0; i < attr.length; i++) {
364             if (attr[i].getQName().startsWith("xmlns")
365                     && this.tagLibrary.containsNamespace(attr[i].getValue())) {
366                 remove |= 1 << i;
367                 if (log.isLoggable(Level.FINE)) {
368                     log.fine(attr[i] + " Namespace Bound to TagLibrary");
369                 }
370             }
371         }
372         if (remove == 0) {
373             return tag;
374         } else {
375             List JavaDoc attrList = new ArrayList JavaDoc(attr.length);
376             int p = 0;
377             for (int i = 0; i < attr.length; i++) {
378                 p = 1 << i;
379                 if ((p & remove) == p) {
380                     continue;
381                 }
382                 attrList.add(attr[i]);
383             }
384             attr = (TagAttribute[]) attrList.toArray(new TagAttribute[attrList
385                     .size()]);
386             return new Tag(tag.getLocation(), tag.getNamespace(), tag
387                     .getLocalName(), tag.getQName(), new TagAttributes(attr));
388         }
389     }
390 }
391
Popular Tags