001 /*
002 // $Id: //open/util/resgen/src/org/eigenbase/xom/XOMUtil.java#5 $
003 // Package org.eigenbase.xom is an XML Object Mapper.
004 // Copyright (C) 2005-2005 The Eigenbase Project
005 // Copyright (C) 2005-2005 Disruptive Tech
006 // Copyright (C) 2005-2005 LucidEra, Inc.
007 // Portions Copyright (C) 2001-2005 Kana Software, Inc. and others.
008 //
009 // This library is free software; you can redistribute it and/or modify it
010 // under the terms of the GNU Lesser General Public License as published by the
011 // Free Software Foundation; either version 2 of the License, or (at your
012 // option) any later version approved by The Eigenbase Project.
013 //
014 // This library is distributed in the hope that it will be useful,
015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017 // GNU Lesser General Public License for more details.
018 //
019 // You should have received a copy of the GNU Lesser General Public License
020 // along with this library; if not, write to the Free Software
021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022 //
023 // jhyde, 3 October, 2001
024 */
025
026 package org.eigenbase.xom;
027 import java.io.File;
028 import java.io.StringWriter;
029 import java.lang.reflect.Array;
030 import java.lang.reflect.Field;
031 import java.lang.reflect.InvocationTargetException;
032 import java.lang.reflect.Method;
033
034 /**
035 * Utility functions for the <code>org.eigenbase.xom</code> and
036 * <code>org.eigenbase.xom.wrappers</code> packages.
037 *
038 * @author jhyde
039 * @since 3 October, 2001
040 * @version $Id: //open/util/resgen/src/org/eigenbase/xom/XOMUtil.java#5 $
041 **/
042 public abstract class XOMUtil extends XMLUtil {
043
044 static final NodeDef[] emptyNodeArray = new NodeDef[0];
045
046 /**
047 * When the compiler is complaining that you are not using a variable, just
048 * call one of these routines with it.
049 **/
050 public static void discard(boolean b) {
051 }
052
053 public static void discard(byte b) {
054 }
055
056 public static void discard(char c) {
057 }
058
059 public static void discard(double d) {
060 }
061
062 public static void discard(float d) {
063 }
064
065 public static void discard(int i) {
066 }
067
068 public static void discard(long l) {
069 }
070
071 public static void discard(Object o) {
072 }
073
074 public static void discard(short s) {
075 }
076
077 /**
078 * Converts the first letter of <code>name</code> to upper-case.
079 */
080 static String capitalize(String name) {
081 if (name == null || name.length() < 1) {
082 return name;
083 }
084 return name.substring(0,1).toUpperCase() + name.substring(1);
085 }
086
087 /**
088 * Adds an object to the end of an array. The resulting array is of the
089 * same type (e.g. <code>String[]</code>) as the input array.
090 **/
091 public static Object[] addElement(Object[] a, Object o)
092 {
093 Class clazz = a.getClass().getComponentType();
094 Object[] a2 = (Object[]) Array.newInstance(clazz, a.length + 1);
095 System.arraycopy(a, 0, a2, 0, a.length);
096 a2[a.length] = o;
097 return a2;
098 }
099
100 /**
101 * Concatenates two arrays. The resulting array is of the
102 * same type (e.g. <code>String[]</code>) as the first array.
103 **/
104 public static Object[] concatenate(Object[] a0, Object[] a1)
105 {
106 Class clazz = a0.getClass().getComponentType();
107 Object[] a2 = (Object[]) Array.newInstance(
108 clazz, a0.length + a1.length);
109 System.arraycopy(a0, 0, a2, 0, a0.length);
110 System.arraycopy(a1, 0, a2, a0.length, a1.length);
111 return a2;
112 }
113
114 /**
115 * Adds a set of children to an object, using its best guess as to where to
116 * put them.
117 **/
118 public static void addChildren(ElementDef parent, NodeDef[] children)
119 throws XOMException
120 {
121 if (parent instanceof GenericDef) {
122 GenericDef xmlGeneric = (GenericDef) parent;
123 for (int i = 0; i < children.length; i++) {
124 xmlGeneric.addChild(children[i]);
125 }
126 } else if (parent instanceof Any) {
127 Any any = (Any) parent;
128 NodeDef[] currentChildren = any.getChildren();
129 if (currentChildren == null) {
130 if (children instanceof ElementDef[]) {
131 currentChildren = new ElementDef[0];
132 } else {
133 currentChildren = new NodeDef[0];
134 }
135 }
136 NodeDef[] newChildren = (NodeDef[]) concatenate(
137 currentChildren, children);
138 any.setChildren(newChildren);
139 } else {
140 // Use reflection. We presume that the children are stored in the
141 // first array field.
142 Field field = null;
143 Field[] fields = parent.getClass().getFields();
144 for (int i = 0; i < fields.length; i++) {
145 if (fields[i].getType().isArray()) {
146 field = fields[i];
147 break;
148 }
149 }
150 if (field == null) {
151 throw new XOMException(
152 "cannot add field to " + parent.getClass() +
153 ": it has no array field");
154 }
155 try {
156 Object[] a = (Object[]) field.get(parent);
157 Object[] b = concatenate(a, children);
158 field.set(parent, b);
159 } catch (IllegalAccessException e) {
160 throw new XOMException(e, "in XOMUtil.getChildren");
161 }
162 }
163 }
164
165 public static void addChild(ElementDef parent, ElementDef child)
166 throws XOMException
167 {
168 addChildren(parent, new ElementDef[] {child});
169 }
170
171 public static void addChild(ElementDef parent, NodeDef child)
172 throws XOMException
173 {
174 addChildren(parent, new NodeDef[] {child});
175 }
176
177 /**
178 * Creates a {@link Parser} of the default parser type.
179 **/
180 public static Parser createDefaultParser() throws XOMException
181 {
182 String className = "org.eigenbase.xom.wrappers.JaxpDOMParser";
183 try {
184 Class clazz = Class.forName(className);
185 return (Parser) clazz.newInstance();
186 } catch (ClassNotFoundException e) {
187 throw new XOMException(e, "Error while creating xml parser '" + className + "'");
188 } catch (IllegalAccessException e) {
189 throw new XOMException(e, "Error while creating xml parser '" + className + "'");
190 } catch (InstantiationException e) {
191 throw new XOMException(e, "Error while creating xml parser '" + className + "'");
192 } catch (VerifyError e) {
193 throw new XOMException(
194 e, "Error while creating xml parser '" + className + "' " +
195 "(If you are running Weblogic 6.1, try putting " +
196 "xml-apis.jar and xercesImpl.jar BEFORE weblogic.jar " +
197 "on CLASSPATH)");
198 }
199 }
200
201 /** * @see #makeParser **/
202 static final int MSXML = 1;
203 /** * @see #makeParser **/
204 static final int XERCES = 2;
205
206 /**
207 * Creates a parser of given type.
208 *
209 * @param parserType valid values are {@link #MSXML} and {@link #XERCES}.
210 **/
211 static Parser makeParser(
212 int parserType, boolean usesPlugins, String fileDirectory,
213 String dtdName, String docType) throws XOMException
214 {
215 try {
216 switch (parserType) {
217 case MSXML:
218 if (usesPlugins) {
219 // Use reflection to call
220 // MSXMLWrapper.createParser();
221 Class clazz = Class.forName(
222 "org.eigenbase.xom.wrappers.MSXMLWrapper");
223 Method method = clazz.getDeclaredMethod(
224 "createParser", new Class[] {});
225 return (Parser) method.invoke(null, new Object[] {});
226 } else {
227 // Use reflection to call
228 // MSXMLWrapper.createParser(docType, dtdPath);
229 File dtdPath = new File(fileDirectory, dtdName);
230 Class clazz = Class.forName(
231 "org.eigenbase.xom.wrappers.MSXMLWrapper");
232 Method method = clazz.getDeclaredMethod(
233 "createParser", new Class[] {
234 String.class, String.class});
235 return (Parser) method.invoke(null, new Object[] {
236 docType, dtdPath});
237 }
238 case XERCES:
239 return new org.eigenbase.xom.wrappers.XercesDOMParser(
240 !usesPlugins);
241 default:
242 throw new XOMException("Unknown parser type: " + parserType);
243 }
244 } catch (ClassNotFoundException e) {
245 throw new XOMException(e, "while creating xml parser");
246 } catch (IllegalAccessException e) {
247 throw new XOMException(e, "while creating xml parser");
248 } catch (NoSuchMethodException e) {
249 throw new XOMException(e, "while creating xml parser");
250 } catch (InvocationTargetException e) {
251 throw new XOMException(e, "while creating xml parser");
252 }
253 }
254
255 /**
256 * Returns the first member of an array of objects which is an instance of
257 * a given class, or null if there is no such.
258 **/
259 public static Object getFirstInstance(Object[] a, Class clazz)
260 {
261 for (int i = 0; i < a.length; i++) {
262 if (clazz.isInstance(a[i])) {
263 return a[i];
264 }
265 }
266 return null;
267 }
268
269 public static String wrapperToXml(DOMWrapper wrapper, boolean ignorePcdata)
270 {
271 try {
272 NodeDef node;
273 switch (wrapper.getType()) {
274 case DOMWrapper.ELEMENT:
275 node = new WrapperElementDef(wrapper,null,null);
276 break;
277 case DOMWrapper.CDATA:
278 node = new CdataDef(wrapper);
279 break;
280 case DOMWrapper.FREETEXT:
281 node = new TextDef(wrapper);
282 break;
283 case DOMWrapper.COMMENT:
284 node = new CommentDef(wrapper);
285 break;
286 default:
287 throw new Error(
288 "unknown node type " + wrapper.getType() +
289 " while converting node to xml");
290 }
291 StringWriter sw = new StringWriter();
292 XMLOutput out = new XMLOutput(sw);
293 out.setIgnorePcdata(ignorePcdata);
294 out.setGlob(true);
295 node.displayXML(out, 0);
296 return sw.toString();
297 } catch (XOMException e) {
298 throw new Error(
299 "[" + e.toString() + "] while converting node to xml");
300 }
301 }
302 }
303
304
305 // End XOMUtil.java