KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > language > markup > xsp > XSPExpressionFilter


1 /*
2  * Copyright 2005 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 package org.apache.cocoon.components.language.markup.xsp;
17
18 import org.apache.cocoon.components.language.markup.LogicsheetFilter;
19 import org.apache.cocoon.xml.AbstractXMLPipe;
20 import org.apache.cocoon.xml.AttributesImpl;
21 import org.apache.cocoon.xml.XMLConsumer;
22 import org.apache.cocoon.xml.XMLUtils;
23
24 import org.apache.commons.lang.StringUtils;
25 import org.xml.sax.Attributes JavaDoc;
26 import org.xml.sax.ContentHandler JavaDoc;
27 import org.xml.sax.SAXException JavaDoc;
28 import org.xml.sax.ext.LexicalHandler JavaDoc;
29
30 import java.util.LinkedList JavaDoc;
31
32 /**
33  * Filter attributes and text and expand {#expr} to xsp:attribute and xsp:expr
34  * elements.
35  *
36  * @version $Id: XSPExpressionFilter.java 306625 2005-10-06 13:07:58Z vgritsenko $
37  */

38 public class XSPExpressionFilter extends LogicsheetFilter
39                                  implements XSPExpressionParser.Handler {
40
41     public static class XMLPipeAdapter extends AbstractXMLPipe {
42         private XSPExpressionFilter expressionFilter;
43         private AbstractXMLPipe additionalFilter;
44
45         public XMLPipeAdapter(XSPExpressionFilter expressionFilter, AbstractXMLPipe additionalFilter) {
46             this.additionalFilter = additionalFilter;
47             this.expressionFilter = expressionFilter;
48             super.setLexicalHandler(additionalFilter);
49             super.setContentHandler(expressionFilter);
50             expressionFilter.setContentHandler(additionalFilter);
51         }
52
53         public void setConsumer(XMLConsumer consumer) {
54             additionalFilter.setConsumer(consumer);
55         }
56
57         public void setContentHandler(ContentHandler JavaDoc handler) {
58             additionalFilter.setContentHandler(handler);
59         }
60
61         public void setLexicalHandler(LexicalHandler JavaDoc handler) {
62             additionalFilter.setLexicalHandler(handler);
63         }
64     }
65
66
67     /** The markup language URI */
68     private String JavaDoc markupURI;
69
70     /** The markup language prefix */
71     private String JavaDoc markupPrefix;
72
73     /** Interpolation settings as nested properties */
74     private LinkedList JavaDoc interpolationStack = new LinkedList JavaDoc();
75
76     /** Default interpolation settings for given markup language */
77     private InterpolationSettings defaultInterpolationSettings;
78
79     /** The parser for XSP value templates */
80     private XSPExpressionParser expressionParser = new XSPExpressionParser(this);
81
82
83
84     public XSPExpressionFilter(XSPMarkupLanguage markup) {
85         this.markupURI = markup.getURI();
86         this.markupPrefix = markup.getPrefix();
87
88         // Initialize default interpolation settings.
89
defaultInterpolationSettings
90             = new InterpolationSettings(markup.hasAttrInterpolation(),
91                                         markup.hasTextInterpolation());
92     }
93
94     /**
95      * Create a new <code>{@link XSPExpressionFilter}</code>.
96      */

97     public void startDocument() throws SAXException JavaDoc {
98         interpolationStack.clear();
99         interpolationStack.addLast(defaultInterpolationSettings);
100         super.startDocument();
101     }
102
103     /**
104      * Start a new element. If attribute value templates are enabled and the element has attributes
105      * with templates, these are replaced by xsp:attribute tags.
106      *
107      * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String,
108      * java.lang.String, org.xml.sax.Attributes)
109      */

110     public void startElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qName, Attributes JavaDoc attribs)
111     throws SAXException JavaDoc {
112         expressionParser.flush();
113
114         // Check template for interpolation flags
115
attribs = pushInterpolationStack(attribs);
116
117         if (getInterpolationSettings().attrInterpolation) {
118             // Attribute value templates enabled => process attributes
119
AttributesImpl staticAttribs = new AttributesImpl();
120             AttributesImpl dynamicAttribs = new AttributesImpl();
121
122             // Gather attributes with and without templates separately
123
for (int i = 0; i < attribs.getLength(); ++i) {
124                 String JavaDoc value = attribs.getValue(i);
125
126                 if (value.indexOf("{#") != -1) {
127                     // The attribute contains templates
128
dynamicAttribs.addAttribute(attribs.getURI(i), attribs.getLocalName(i), attribs.getQName(i),
129                             attribs.getType(i), value);
130                 }
131                 else {
132                     // The attribute does not contain templates
133
staticAttribs.addAttribute(attribs.getURI(i), attribs.getLocalName(i), attribs.getQName(i),
134                             attribs.getType(i), value);
135                 }
136             }
137
138             // Start the element with template-free attributes
139
super.startElement(namespaceURI, localName, qName, staticAttribs);
140
141             // Generate xsp:attribute elements for the attributes containing templates
142
for (int i = 0; i < dynamicAttribs.getLength(); ++i) {
143                 AttributesImpl elemAttribs = new AttributesImpl();
144                 addAttribute(elemAttribs, "uri", dynamicAttribs.getURI(i));
145
146                 String JavaDoc qname = dynamicAttribs.getQName(i);
147
148                 if (qname != null) {
149                     addAttribute(elemAttribs, "prefix", StringUtils.left(qname, qname.indexOf(':')));
150                 }
151
152                 addAttribute(elemAttribs, "name", dynamicAttribs.getLocalName(i));
153
154                 super.startElement(markupURI, "attribute", markupPrefix + ":attribute", elemAttribs);
155                 expressionParser.consume(dynamicAttribs.getValue(i));
156                 expressionParser.flush();
157                 super.endElement(markupURI, "attribute", markupPrefix + ":attribute");
158             }
159         } else {
160             // Attribute value templates disabled => pass through element
161
super.startElement(namespaceURI, localName, qName, attribs);
162         }
163     }
164
165     /**
166      * Check attributes for presence of interpolation flags.
167      * Push current settings to stack.
168      * Remove interpolation attributes and return cleaned attribute list.
169      */

170     private Attributes JavaDoc pushInterpolationStack(Attributes JavaDoc attribs) {
171         String JavaDoc valueAttr = attribs.getValue(markupURI, XSPMarkupLanguage.ATTR_INTERPOLATION);
172         String JavaDoc valueText = attribs.getValue(markupURI, XSPMarkupLanguage.TEXT_INTERPOLATION);
173
174         // Neither interpolation flag in attribute list: push tail to stack.
175
if (valueAttr == null && valueText == null ) {
176             interpolationStack.addLast(interpolationStack.getLast());
177             return attribs;
178         }
179
180         // Push new interpolation settings to stack and remove attributes.
181

182         InterpolationSettings lastSettings = (InterpolationSettings)interpolationStack.getLast();
183         boolean attrInterpolation = lastSettings.attrInterpolation;
184         boolean textInterpolation = lastSettings.textInterpolation;
185
186         AttributesImpl cleanedAttribs = new AttributesImpl(attribs);
187
188         if (valueAttr != null) {
189             attrInterpolation = Boolean.valueOf(valueAttr).booleanValue();
190             cleanedAttribs.removeAttribute(cleanedAttribs.getIndex(markupURI, XSPMarkupLanguage.ATTR_INTERPOLATION));
191         }
192
193         if (valueText != null) {
194             textInterpolation = Boolean.valueOf(valueText).booleanValue();
195             cleanedAttribs.removeAttribute(cleanedAttribs.getIndex(markupURI, XSPMarkupLanguage.TEXT_INTERPOLATION));
196         }
197
198         interpolationStack.addLast(new InterpolationSettings(attrInterpolation,
199                                                              textInterpolation));
200
201         return cleanedAttribs;
202     }
203
204     /**
205      * Flush the current expression.
206      */

207     public void endElement(String JavaDoc uri, String JavaDoc loc, String JavaDoc raw) throws SAXException JavaDoc {
208         expressionParser.flush();
209         super.endElement(uri, loc, raw);
210
211         // Pop stack of interpolation settings.
212
interpolationStack.removeLast();
213     }
214
215     /**
216      * Handle characters. If text templates are enabled, the text is parsed and expressions are
217      * replaced.
218      *
219      * @see org.xml.sax.ContentHandler#characters(char[], int, int)
220      */

221     public void characters(char[] ch, int start, int length) throws SAXException JavaDoc {
222         if (getInterpolationSettings().textInterpolation) {
223             // Text templated enabled => Replace text expressions
224
expressionParser.consume(ch, start, length);
225         }
226         else {
227             // Text templates disabled => pass through text
228
super.characters(ch, start, length);
229         }
230     }
231
232     /**
233      * Forward text to parent class.
234      *
235      * @see org.apache.cocoon.components.language.markup.xsp.XSPExpressionParser.Handler#handleText(char[],
236      * int, int)
237      */

238     public void handleText(char[] chars, int start, int length) throws SAXException JavaDoc {
239         super.characters(chars, start, length);
240     }
241
242     /**
243      * Wrap expressions in xsp:expr tags.
244      *
245      * @see org.apache.cocoon.components.language.markup.xsp.XSPExpressionParser.Handler#handleExpression(char[],
246      * int, int)
247      */

248     public void handleExpression(char[] chars, int start, int length) throws SAXException JavaDoc {
249         super.startElement(markupURI, "expr", markupPrefix + ":expr", XMLUtils.EMPTY_ATTRIBUTES);
250         super.characters(chars, start, length);
251         super.endElement(markupURI, "expr", markupPrefix + ":expr");
252     }
253
254     /**
255      * Add an attribute if it is neither <code>null</code> nor empty (length 0).
256      *
257      * @param attribs The attributes
258      * @param name The attribute name
259      * @param value The attribute value
260      */

261     protected void addAttribute(AttributesImpl attribs, String JavaDoc name, String JavaDoc value) {
262         if (value != null && value.length() > 0) {
263             attribs.addCDATAAttribute(name, value);
264         }
265     }
266
267     /**
268      * Return current interpolation settings.
269      */

270     private InterpolationSettings getInterpolationSettings() {
271         return (InterpolationSettings)interpolationStack.getLast();
272     }
273
274     /**
275      * Structure to hold settings for attribute and text interpolation.
276      */

277     private static class InterpolationSettings {
278         boolean attrInterpolation;
279         boolean textInterpolation;
280
281         InterpolationSettings(boolean attrInterpolation, boolean textInterpolation) {
282             this.attrInterpolation = attrInterpolation;
283             this.textInterpolation = textInterpolation;
284         }
285     }
286 }
287
Popular Tags