View Javadoc

1   /*
2    * Copyright 2002,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  package org.apache.commons.jelly.tags.xml;
17  
18  import org.apache.commons.jelly.JellyException;
19  import org.apache.commons.jelly.JellyTagException;
20  import org.apache.commons.jelly.TagSupport;
21  import org.apache.commons.jelly.XMLOutput;
22  import org.xml.sax.Attributes;
23  import org.xml.sax.SAXException;
24  import org.xml.sax.helpers.AttributesImpl;
25  
26  /*** A tag to produce an XML element which can contain other attributes
27    * or elements like the <code>&lt;xsl:element&gt;</code> tag.
28    *
29    * @author James Strachan
30    * @version $Revision: 219726 $
31    */
32  public class ElementTag extends TagSupport {
33  
34      /*** The namespace URI. */
35      private String namespace;
36  
37      /*** The qualified name. */
38      private String name;
39  
40      /*** The XML Attributes. */
41      private AttributesImpl attributes = new AttributesImpl();
42  
43      /*** flag set if attributes are output. */
44      private boolean outputAttributes;
45  
46      public ElementTag() {
47      }
48  
49      /***
50       * Sets the attribute of the given name to the specified value.
51       *
52       * @param name of the attribute
53       * @param value of the attribute
54       * @param uri namespace of the attribute
55       * @throws JellyTagException if the start element has already been output.
56       *   Attributes must be set on the outer element before any content
57       *   (child elements or text) is output
58       */
59      public void setAttributeValue(String name, String value, String uri) throws JellyTagException {
60          if (outputAttributes) {
61              throw new JellyTagException(
62                  "Cannot set the value of attribute: "
63                  + name + " as we have already output the startElement() SAX event"
64              );
65          }
66  
67          // ### we'll assume that all attributes are in no namespace!
68          // ### this is severely limiting!
69          // ### we should be namespace aware
70          // NAMESPACE FIXED:
71          int idx = name.indexOf(':');
72          final String localName = (idx >= 0)
73              ? name.substring(idx + 1)
74              : name;
75          final String nsUri = (uri != null)
76              ? uri
77              : "";
78  
79          int index = attributes.getIndex(nsUri, localName);
80          if (index >= 0) {
81              attributes.removeAttribute(index);
82          }
83          // treat null values as no attribute
84          if (value != null) {
85              attributes.addAttribute(nsUri, localName, name, "CDATA", value);
86          }
87      }
88  
89      // Tag interface
90      //-------------------------------------------------------------------------
91      public void doTag(XMLOutput output) throws JellyTagException {
92          int idx = name.indexOf(':');
93          final String localName = (idx >= 0)
94              ? name.substring(idx + 1)
95              : name;
96  
97          outputAttributes = false;
98  
99          XMLOutput newOutput = new XMLOutput(output) {
100 
101             // add an initialize hook to the core content-generating methods
102 
103             public void startElement(
104                 String uri,
105                 String localName,
106                 String qName,
107                 Attributes atts)
108                 throws SAXException {
109                 initialize();
110                 super.startElement(uri, localName, qName, atts);
111             }
112 
113             public void endElement(String uri, String localName, String qName)
114                 throws SAXException {
115                 initialize();
116                 super.endElement(uri, localName, qName);
117             }
118 
119             public void characters(char[] ch, int start, int length) throws SAXException {
120                 initialize();
121                 super.characters(ch, start, length);
122             }
123 
124             public void ignorableWhitespace(char[] ch, int start, int length)
125                 throws SAXException {
126                 initialize();
127                 super.ignorableWhitespace(ch, start, length);
128             }
129 
130             public void objectData(Object object)
131                 throws SAXException {
132                 initialize();
133                 super.objectData(object);
134             }
135 
136             public void processingInstruction(String target, String data)
137                 throws SAXException {
138                 initialize();
139                 super.processingInstruction(target, data);
140             }
141 
142             /***
143              * Ensure that the outer start element is generated
144              * before any content is output.
145              */
146             protected void initialize() throws SAXException {
147                 if (!outputAttributes) {
148                     super.startElement(namespace, localName, name, attributes);
149                     outputAttributes = true;
150                 }
151             }
152         };
153 
154         invokeBody(newOutput);
155 
156         try {
157             if (!outputAttributes) {
158                 output.startElement(namespace, localName, name, attributes);
159                 outputAttributes = true;
160             }
161 
162             output.endElement(namespace, localName, name);
163             attributes.clear();
164         } catch (SAXException e) {
165             throw new JellyTagException(e);
166         }
167     }
168 
169     // Properties
170     //-------------------------------------------------------------------------
171 
172     /***
173      * @return the qualified name of the element
174      */
175     public String getName() {
176         return name;
177     }
178 
179     /***
180      * Sets the qualified name of the element
181      */
182     public void setName(String name) {
183         this.name = name;
184     }
185 
186     /***
187      * @return the namespace URI of the element
188      */
189     public String getURI() {
190         return namespace;
191     }
192 
193     /***
194      * Sets the namespace URI of the element
195      */
196     public void setURI(String namespace) {
197         this.namespace = namespace;
198     }
199 }