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
026package org.eigenbase.xom;
027import java.io.File;
028import java.io.StringWriter;
029import java.lang.reflect.Array;
030import java.lang.reflect.Field;
031import java.lang.reflect.InvocationTargetException;
032import 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 **/
042public 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