KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > xmla > XmlaUtil


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/xmla/XmlaUtil.java#20 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2003-2006 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 //
10 // jhyde, May 2, 2003
11 */

12 package mondrian.xmla;
13
14 import mondrian.olap.MondrianException;
15 import mondrian.util.Base64;
16 import org.apache.log4j.Logger;
17 import org.w3c.dom.*;
18 import org.xml.sax.InputSource JavaDoc;
19
20 import javax.xml.parsers.DocumentBuilder JavaDoc;
21 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
22 import javax.xml.transform.Transformer JavaDoc;
23 import javax.xml.transform.TransformerFactory JavaDoc;
24 import javax.xml.transform.dom.DOMSource JavaDoc;
25 import javax.xml.transform.stream.StreamResult JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.io.StringReader JavaDoc;
29 import java.io.StringWriter JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.List JavaDoc;
32
33 /**
34  * Utility methods for XML/A implementation.
35  *
36  * @author Gang Chen
37  * @version $Id: //open/mondrian/src/main/mondrian/xmla/XmlaUtil.java#20 $
38  */

39 public class XmlaUtil implements XmlaConstants {
40
41     private static final Logger LOGGER = Logger.getLogger(XmlaUtil.class);
42     /**
43      * Invalid characters for XML element name.
44      *
45      * XML element name:
46      *
47      * Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
48      * S ::= (#x20 | #x9 | #xD | #xA)+
49      * NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
50      * Name ::= (Letter | '_' | ':') (NameChar)*
51      * Names ::= Name (#x20 Name)*
52      * Nmtoken ::= (NameChar)+
53      * Nmtokens ::= Nmtoken (#x20 Nmtoken)*
54      *
55      */

56     private static final String JavaDoc[] CHAR_TABLE = new String JavaDoc[256];
57
58     static {
59         initCharTable(" \t\r\n(){}[]+/*%!,?");
60     }
61
62     private static void initCharTable(String JavaDoc charStr) {
63         char[] chars = charStr.toCharArray();
64         for (int i = 0; i < chars.length; i++) {
65             char c = chars[i];
66             CHAR_TABLE[c] = encodeChar(c);
67         }
68     }
69
70     private static String JavaDoc encodeChar(char c) {
71         StringBuilder JavaDoc buf = new StringBuilder JavaDoc();
72         buf.append("_x");
73         String JavaDoc str = Integer.toHexString(c);
74         for (int i = 4 - str.length(); i > 0; i--) {
75             buf.append("0");
76         }
77         return buf.append(str).append("_").toString();
78     }
79
80     /**
81      * This function is mainly for encode element names in result of Drill Through
82      * execute, because its element names come from database, we cannot make sure
83      * they are valid XML contents.
84      *
85      * <p>Quoth the <a HREF="http://xmla.org">XML/A specification</a>, version
86      * 1.1:
87      * <blockquote>
88      * XML does not allow certain characters as element and attribute names.
89      * XML for Analysis supports encoding as defined by SQL Server 2000 to
90      * address this XML constraint. For column names that contain invalid XML
91      * name characters (according to the XML 1.0 specification), the nonvalid
92      * Unicode characters are encoded using the corresponding hexadecimal
93      * values. These are escaped as _x<i>HHHH_</i> where <i>HHHH</i> stands for
94      * the four-digit hexadecimal UCS-2 code for the character in
95      * most-significant bit first order. For example, the name "Order Details"
96      * is encoded as Order_<i>x0020</i>_Details, where the space character is
97      * replaced by the corresponding hexadecimal code.
98      * </blockquote>
99      */

100     public static String JavaDoc encodeElementName(String JavaDoc name) {
101         StringBuilder JavaDoc buf = new StringBuilder JavaDoc();
102         char[] nameChars = name.toCharArray();
103         for (int i = 0; i < nameChars.length; i++) {
104             char ch = nameChars[i];
105             String JavaDoc encodedStr = (ch >= CHAR_TABLE.length ? null : CHAR_TABLE[ch]);
106             if (encodedStr == null) {
107                 buf.append(ch);
108             } else {
109                 buf.append(encodedStr);
110             }
111         }
112         return buf.toString();
113     }
114
115
116     public static String JavaDoc element2Text(Element elem)
117             throws XmlaException {
118         StringWriter JavaDoc writer = new StringWriter JavaDoc();
119         try {
120             TransformerFactory JavaDoc factory = TransformerFactory.newInstance();
121             Transformer JavaDoc transformer = factory.newTransformer();
122             transformer.transform(new DOMSource JavaDoc(elem), new StreamResult JavaDoc(writer));
123         } catch (Exception JavaDoc e) {
124             throw new XmlaException(
125                 CLIENT_FAULT_FC,
126                 USM_DOM_PARSE_CODE,
127                 USM_DOM_PARSE_FAULT_FS,
128                 e);
129         }
130         return writer.getBuffer().toString();
131     }
132
133     public static Element text2Element(String JavaDoc text)
134             throws XmlaException {
135         return _2Element(new InputSource JavaDoc(new StringReader JavaDoc(text)));
136     }
137
138     public static Element stream2Element(InputStream JavaDoc stream)
139             throws XmlaException {
140         return _2Element(new InputSource JavaDoc(stream));
141     }
142
143     private static Element _2Element(InputSource JavaDoc source)
144             throws XmlaException {
145         try {
146             DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
147             factory.setIgnoringElementContentWhitespace(true);
148             factory.setIgnoringComments(true);
149             factory.setNamespaceAware(true);
150             DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
151             Document doc = builder.parse(source);
152             Element elem = doc.getDocumentElement();
153             return elem;
154
155         } catch (Exception JavaDoc e) {
156             throw new XmlaException(
157                 CLIENT_FAULT_FC,
158                 USM_DOM_PARSE_CODE,
159                 USM_DOM_PARSE_FAULT_FS,
160                 e);
161         }
162     }
163
164     /**
165      * @return null if there is no child element.
166      */

167     public static Element firstChildElement(Element parent,
168                                             String JavaDoc ns,
169                                             String JavaDoc lname) {
170         if (LOGGER.isDebugEnabled()) {
171             StringBuilder JavaDoc buf = new StringBuilder JavaDoc(100);
172             buf.append("XmlaUtil.firstChildElement: ");
173             buf.append(" ns=\"");
174             buf.append(ns);
175             buf.append("\", lname=\"");
176             buf.append(lname);
177             buf.append("\"");
178             LOGGER.debug(buf.toString());
179         }
180         NodeList nlst = parent.getChildNodes();
181         for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) {
182             Node n = nlst.item(i);
183             if (n instanceof Element) {
184                 Element e = (Element) n;
185
186                 if (LOGGER.isDebugEnabled()) {
187                     StringBuilder JavaDoc buf = new StringBuilder JavaDoc(100);
188                     buf.append("XmlaUtil.firstChildElement: ");
189                     buf.append(" e.getNamespaceURI()=\"");
190                     buf.append(e.getNamespaceURI());
191                     buf.append("\", e.getLocalName()=\"");
192                     buf.append(e.getLocalName());
193                     buf.append("\"");
194                     LOGGER.debug(buf.toString());
195                 }
196
197                 if ((ns == null || ns.equals(e.getNamespaceURI())) &&
198                     (lname == null || lname.equals(e.getLocalName()))) {
199                     return e;
200                 }
201             }
202         }
203         return null;
204     }
205
206     public static Element[] filterChildElements(Element parent,
207                                                 String JavaDoc ns,
208                                                 String JavaDoc lname) {
209
210 /*
211 way too noisy
212         if (LOGGER.isDebugEnabled()) {
213             StringBuilder buf = new StringBuilder(100);
214             buf.append("XmlaUtil.filterChildElements: ");
215             buf.append(" ns=\"");
216             buf.append(ns);
217             buf.append("\", lname=\"");
218             buf.append(lname);
219             buf.append("\"");
220             LOGGER.debug(buf.toString());
221         }
222 */

223
224         List JavaDoc elems = new ArrayList JavaDoc();
225         NodeList nlst = parent.getChildNodes();
226         for (int i = 0, nlen = nlst.getLength(); i < nlen; i++) {
227             Node n = nlst.item(i);
228             if (n instanceof Element) {
229                 Element e = (Element) n;
230
231 /*
232                 if (LOGGER.isDebugEnabled()) {
233                     StringBuilder buf = new StringBuilder(100);
234                     buf.append("XmlaUtil.filterChildElements: ");
235                     buf.append(" e.getNamespaceURI()=\"");
236                     buf.append(e.getNamespaceURI());
237                     buf.append("\", e.getLocalName()=\"");
238                     buf.append(e.getLocalName());
239                     buf.append("\"");
240                     LOGGER.debug(buf.toString());
241                 }
242 */

243
244                 if ((ns == null || ns.equals(e.getNamespaceURI())) &&
245                     (lname == null || lname.equals(e.getLocalName()))) {
246                     elems.add(e);
247                 }
248             }
249         }
250         return (Element[]) elems.toArray(new Element[0]);
251     }
252
253     public static String JavaDoc textInElement(Element elem) {
254         StringBuilder JavaDoc buf = new StringBuilder JavaDoc(100);
255         elem.normalize();
256         NodeList nlst = elem.getChildNodes();
257         for (int i = 0, nlen = nlst.getLength(); i < nlen ; i++) {
258             Node n = nlst.item(i);
259             if (n instanceof Text) {
260                 final String JavaDoc data = ((Text) n).getData();
261                 buf.append(data);
262             }
263         }
264         return buf.toString();
265     }
266
267     /**
268      * Finds root MondrianException in exception chain if exists,
269      * otherwise the input throwable.
270      */

271     public static Throwable JavaDoc rootThrowable(Throwable JavaDoc throwable) {
272         Throwable JavaDoc rootThrowable = throwable.getCause();
273         if (rootThrowable != null && rootThrowable instanceof MondrianException) {
274             return rootThrowable(rootThrowable);
275         }
276         return throwable;
277     }
278
279     /**
280      * Corrects for the differences between numeric strings arising because
281      * JDBC drivers use different representations for numbers
282      * ({@link Double} vs. {@link java.math.BigDecimal}) and
283      * these have different toString() behavior.
284      *
285      * <p>If it contains a decimal point, then
286      * strip off trailing '0's. After stripping off
287      * the '0's, if there is nothing right of the
288      * decimal point, then strip off decimal point.
289      */

290     public static String JavaDoc normalizeNumericString(String JavaDoc numericStr) {
291         int index = numericStr.indexOf('.');
292         if (index > 0) {
293             boolean found = false;
294             int p = numericStr.length();
295             char c = numericStr.charAt(p - 1);
296             while (c == '0') {
297                 found = true;
298                 p--;
299                 c = numericStr.charAt(p - 1);
300             }
301             if (c == '.') {
302                 p--;
303             }
304             if (found) {
305                 return numericStr.substring(0, p);
306             }
307         }
308         return numericStr;
309     }
310 }
311
312 // End XmlaUtil.java
313
Popular Tags