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